int isEmpty(string line)        // needs stripped line
{
    return !line || line[0] == "#" || strfind(line, "//") == 0;
}
    
int lineRead()
{
    g_classLine = fgets("CLASSES", g_classLine);
    return listlen(g_classLine) && g_classLine[2] == "OK";
}

list nextCLASSESline() // return entries of CLASSES as a list
{
    string ret;

            // get the next line from CLASSES:
    while (lineRead())
    {
        string line = trim(g_classLine[0]);     // remove blanks

        if (isEmpty(line))                      // nothing there
        {
            if (strlen(ret) != 0)               // ret already contains txt
                break;                          // so we're done
        }
        else                                    // the next line isn't empty
        {
            int last = strlen(line) - 1;
            int backslash = line[last] == "\\";

            if (backslash)                      // its last char is backsl.
                line = trimright(resize(line, last));    // remove it and
                                                // trim rhs blanks

            ret += line + " ";                  // append line

            if (! backslash)                    // done unless backslash
                break;
        }
    }

    if (!isEmpty(ret))
        g_classLines += (list)ret;

    return strtok(ret, " \t");
}

void setClasses()
{
#ifdef SCANNER_DIR                      // scanner/parser directories must be
                                        // first, to avoid reordering
    if (SCANNER_DIR != "")
        g_classes = (list)SCANNER_DIR;  // add the scanner-dir
#endif

#ifdef PARSER_DIR
    if (PARSER_DIR != "")
        g_classes += (list)PARSER_DIR;
#endif

    list class;
    while (listlen(class = nextCLASSESline()))      // add remaining classes
        g_classes = listunion(g_classes, class[0]);

    // g_classLines contains the full lines of the CLASSES file, and thus
    // stores its dependencies.

    g_nClasses = listlen(g_classes);
}
