#!/usr/bin/icmake -qt/tmp/driver

// script generated by the C++ icmake script version 1.62

string
    CLASSES;

void setClasses()
{
//  ADD ADDITIONAL DIRECTORIES CONTAINING SOURCES OF CLASSES HERE
//  Use the construction `CLASSES += "classname1 classname2";' etc.

    CLASSES += " ";
}

#define COMPILER "g++"

// COPT: the set of C-options (-m486 with the 2.95 g++ compiler)
#define COPT "-Wall  -I../../inc"

#define ECHO_REQUEST ON

// #define GDB

#define LIBS "bobcat"
#define LIBPATH "../../lib"

#define PROGRAM

#define RELINK

//      DO NOT ALTER THINGS BELOW THIS LINE
string                                      // contain options for
    libs,                                   // extra libs, e.g., "-lrss -licce"
    libpath,                                // extra lib-paths, eg, "-L../rss"
    copt,
    lopt,
    libxxxa;                                // expanded lib-name
int
    relink;                                 // internally used: != 0 to relink

string
    ofiles,                             // wildcards for o-files
    sources,                            // sources to be used
    wild,                               // wildcard of extension
    current;                            // contains name of current dir.
/*
                                O B J F I L E S . I M
*/

list objfiles(list files)
{
    string
        file,
        objfile;
    int
        i;

    for (i = 0; i < sizeof(files); i++)
    {
        file = element(i, files);           // determine element of the list
#ifdef USE_LIBRARY
        objfile = change_ext(file, "o");    // make obj-filename
#else
        objfile = "./o/" + change_ext(file, "o");    // make obj-filename
#endif
        if (objfile younger file)           // objfile is younger
        {
            files -= (list)file;            // remove the file from the list
            i--;                            // reduce i to test the next
        }
    }
    return (files);
}
/*
                                A L T E R E D . I M
*/

list altered(list files, string target)
{
    int
        i;
    string
        file;

    for (i = 0; i < sizeof(files); i++)     // try all elements of the list
    {
        file = element(i, files);           // use element i of the list
            
        if (file older target)              // a file is older than the target
        {
            files -= (list)file;            // remove the file from the list
            i--;                            // reduce i to inspect the next
        }                                   // file of the list
    }
    return (files);                         // return the new list
}
/*
                            F I L E L I S T . I M
*/

list file_list(string type, string library)
{
    list
        files;

    files = makelist(type);                 // make all files of certain type
#ifdef USE_LIBRARY
    files = altered(files, library);        // keep all files newer than lib.
#endif
    files = objfiles(files);                // remove if younger .obj exist

    return (files);
}
/*
                        L I N K . I M
*/

void link(string library, string exe)
{
    printf("\n");
    system("mv ../../lib/libbobcat.so ../../lib/libbobcat.OFF");
    exec(COMPILER, "-o", exe, 
        ofiles,
        libs, "-L.", libpath, lopt
#ifndef GDB
        , "-s"
#endif                                
    );
    system("mv ../../lib/libbobcat.OFF ../../lib/libbobcat.so");
    printf("ok: ", exe, "\n");
}

/*
                            C C O M P I L E . I M
*/

void c_compile(list cfiles)
{
        string
                nextfile;
        int
                i;
                
#ifndef USE_LIBRARY
    if (!exists("o"))
        system("mkdir o");

#endif
                                                      
    if (sizeof(cfiles))                 // files to compile ?
    {
        printf("\ncompiling: ", current, "\n\n");
        
                                        // compile all files separately
        for (i = 0; nextfile = element(i, cfiles); i++)
        {
#ifdef USE_LIBRARY
                exec(COMPILER,
                "-c "
                COPT + " " +
                copt + " " + nextfile);
#else
                exec(COMPILER,
                "-c -o o/" + change_ext(nextfile, "o") + " "
                COPT + " " +
                copt + " " + nextfile);
#endif
        }
        relink = 1;
        printf("\n");
    }
    printf("ok: ", current, "\n");
}
/*
                            U P D A T E L I . I M
*/

void updatelib(string library)
{
    list
        arlist,
        objlist;
    string
        to,
        from;

    objlist = makelist("*.o");

    if (!sizeof(objlist))
        return;

    printf("\n");
    relink = 1;

    exec("ar", "rvs", library, "*.o");
    exec("rm", "*.o");

    printf("\n");
}

void prefix_class(string class_id)
{
    list
        o_files;
    string
        o_file;
    int
        i;

    o_files = makelist("*.o");

    for (i = 0; o_file = element(i, o_files); i++)
        exec("mv", o_file, class_id + o_file);
}
/*
                                S T D C P P . I M
*/

void std_cpp(string library)
{
    list
        cfiles;

    cfiles = file_list(wild, library);      // make list of all cpp-files

    c_compile(cfiles);                      // compile cpp-files
}

/*
                                C P P M A K E . C

    CPP files are processed by stdmake.

    Arguments of CPPMAKE:

    cpp_make(
        string mainfile,    : name of the main .cpp file, or "" for library
                              maintenance
        string library,     : name of the local library to use/create
                                (without lib prefix, .a suffix
                                 if main is given here, libmain.a is created)
        string exe,         : (path) name of the exe file to create
        )

    Both mainfile and library MUST be in the current directory
*/

void cpp_make(string mainfile, string library, string exe)
{
    int
        n,
        index;
    list
        classes;
    string
        cwd;

#ifdef BISON++
    CLASSES += "parser ";
    if (exists("parser"))                  // subdir parser exists
        parser(); 
#endif

#ifdef FLEX++
    CLASSES += "scanner ";
    if (exists("scanner"))                  // subdir scannerexists
        scanner(); 
#endif
    
    setClasses();                           // remaining classes

    cwd = chdir(".");
        
    ofiles = "o/*.o";                       // std set of o-files

    classes = strtok(CLASSES, " ");         // list of classes

    if (n = sizeof(classes))
        ofiles += " */o/*.o";               // set ofiles for no LIBRARY use

    wild = sources;
                                            // make library name
    libxxxa = chdir(".") + "lib" + library + ".a";

                                            // first process all classes
    for (index = 0; index < n; index++)
    {                   
        current = element(index, classes);  // next class to process
        chdir(current);                     // change to directory

        current = "subdir " + current;
        std_cpp (libxxxa);                // compile all files
        chdir( cwd);                      // go back to parent dir
    }


    current = "auxiliary " + wild + " files";
    std_cpp (libxxxa);                    // compile all files in current dir
    
    for (index = 0; index < n; index++)
    {
        current = element(index, classes);  // determine class name
        chdir( current);                  // chdir to a class directory.
#ifdef USE_LIBRARY
        prefix_class((string)index);      // prefix class-number for .o files
        updatelib(libxxxa);
#endif
        chdir(cwd);                       // go back to parent dir
    }

    current = "";                           // no class anymore

#ifdef USE_LIBRARY
    updatelib(libxxxa);                     // update lib in current dir
#endif 

    if (mainfile != "")                     // mainfile -> do link
    {
        link(library, exe);
        printf
        (
            "\nProgram construction completed.\n"
            "\n"
        );
    }
}
/*
                        S E T L I B S . I M
*/
void setlibs()
{       
    int
        n,
        index;
    list
        cut;
        
    cut = strtok(LIBS, " ");        // cut op libraries
    n = sizeof(cut);
    for (index = 0; index < n; index++)
        libs += " -l" + element(index, cut);
    
#ifdef FLEX++
    libs += " -lfl";
#endif
    
    cut = strtok(LIBPATH, " ");     // cut up the paths
    n = sizeof(cut);
    for (index = 0; index < n; index++)
        libpath += " -L" + element(index, cut);
}


void main()
{

    echo(ECHO_REQUEST);

    sources = "*.cc";

    setlibs();

#ifdef GDB
    copt = "-g";
#endif

#ifdef PROGRAM
    cpp_make
    (
        "driver.cc",          // program source
        "driver",                    // program library
        "driver"                     // binary program
    );
#else
    cpp_make
    (
        "",
        "driver",                    // program library
        ""
    );
#endif
}
