
#define COPT               "-Wall -O2 --std=c++0x"

#define ECHO_REQUEST       1

#define LIBS               "bobcat"
#define LIBPATH            ""


string                  // contain options for
    g_cwd,              // current WD
    libs,               // extra libs, e.g., "-lrss -licce"
    libpath,            // extra lib-paths, eg, "-L../rss"
    g_sources,          // sources to be used
    g_binary,           // the name of the program to create
    g_strip;            // "-s" strips the binary  
int
    g_nClasses;         // number of classes/subdirectories
list
    g_classes;          // list of classes/directories

void setClasses()
{
    list class;

    while (sizeof(class = fgets("CLASSES", (int)element(1, class))))
        g_classes += (list)element(0, strtok(element(0, class), " \t\n"));
  
    g_nClasses = sizeof(g_classes);
}

void static_lib(string ofiles, string library)
{
    if (sizeof(makelist(ofiles)))
    {
        run("ar crsu " + library + " " + ofiles);
        run("rm " + ofiles);
    }
}

void static_library(string library)
{
    static_lib("*/o/*.o", library);
    static_lib("o/*.o", library);
}

void initialize()
{
//    system(P_NOCHECK, "tput clear");
    echo(ECHO_REQUEST);
    g_sources = "*.cc";

    g_binary = "tmp/bin/stealth";

    g_cwd = chdir(".");

    setClasses();                           // remaining classes
}

void link(string library)
{
    exec(COMPILER, "-o", g_binary,
            "-l" + library, libs, "-L.", libpath, g_strip);
}


list inspect(int prefix, list srcList, string library)
{
    int idx;
    string ofile;
    string oprefix;
    string file;

    oprefix = "./o/" + (string)prefix;

    for (idx = sizeof(srcList); idx--; )
    {
        file  = element(idx, srcList);   
        ofile   = oprefix + change_ext(file, "o");    // make o-filename

        // A file s must be recompiled if it's newer than its object
        // file o or newer than its target library l, or if neither o nor l
        // exist. 
        // Since `a newer b' is true if a is newer than b, or if a exists and
        // b doesn't exist s must be compiled if s newer o and s newer l.
        // So, it doesn't have to be compiled if s older o or s older l.
                                            // redo if file has changed
        if (file older ofile || file older library)
            srcList -= (list)file;
    }
    return srcList;
}


void c_compile(int prefix, string srcDir, list cfiles)
{
    int idx;
    string compiler;
    string file;

    compiler = COMPILER + " -c -o " + srcDir + "/o/" + (string)prefix;
    md(srcDir + "/o");

    for (idx = sizeof(cfiles); idx--; )
    {
        file = element(idx, cfiles);
        
        run(compiler + change_ext(file, "o") + " " + 
                COPT + " " + srcDir + "/" + file);
    }
}

void std_cpp(int prefix, string srcDir, string library)
{
    list files;

    chdir(srcDir);
                                                      // make list of all files
    files = inspect(prefix, makelist(g_sources), library);  
    chdir(g_cwd);

    if (sizeof(files))
        c_compile(prefix, srcDir, files);             // compile files
}


void cpp_make(string mainfile, string library)
{
    int idx;
    string class;
    string fullLibname;

    fullLibname = "lib" + library + ".a";

    for (idx = g_nClasses; idx--; )
        std_cpp(idx, element(idx, g_classes), "../" + fullLibname);
        
    std_cpp(g_nClasses, ".", fullLibname);  // compile all files in current dir

    static_library(fullLibname);            // make the library

    link(library);
    printf("\n"
            "ok: ", g_binary, "\n");
}

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);

        cut = strtok(LIBPATH, " ");     // cut up the paths
        n = sizeof(cut);
        for (index = 0; index < n; index++)
            libpath += " -L" + element(index, cut);
}

void program()
{
    initialize();
    setlibs();
    
    md("tmp/bin tmp/o");
    
    special();

    cpp_make
    (
        "stealth.cc",      // program source
        "stealth"          // static program library base name
    );

    exit(0);
}





