#!/usr/local/bin/icmake -qi
/*                              build

*/

string                                      // contain options for
    libxxxa,				    // expanded lib-name
    libs,	                            // extra libs, e.g., "-lrss -licce"
    libpath;			   	    // extra lib-paths, eg, "-L../rss"

int
    relink;                                 // internally used: != 0 to relink

string
    copt,				// extra C-options
    lopt,				// extra link-options
    wild,                               // wildcard of extension
    current;                            // contains name of current dir.

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
        objfile = change_ext(file, "o");    // make obj-filename
        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);
}

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
}

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

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

    return (files);
}

void link(string library, string exe)
{
    if
    (
        relink                           // new library, new main.obj
        ||
        !exists(exe)                     // final program doesn't exist
    )
    {
        printf("\n");
        exec("gcc", "-o", exe, "-l" + library, libs, "-L.", libpath, lopt);
        printf("ok: ", exe, "\n");
    }
}

void c_compile(list cfiles)
{
	string
		nextfile;
	int
		i;

	if (sizeof(cfiles))			// files to compile ?
	{
	        printf("\ncompiling: ", current, "\n\n");
						// compile all files separately
		for (i = 0; nextfile = element(i, cfiles); i++)
			exec("gcc",
				"-c -m486 -Wall -funsigned-char " +
				copt + " " + nextfile);
        	relink = 1;
		printf("\n");
	}
	printf("ok: ", current, "\n");
}

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 std_cpp(string library)
{
    list
        cfiles;

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

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

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

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

    wild = "*.cc";

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

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

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


    current = "auxiliary *.cc files";
    std_cpp (libxxxa);                    // compile all files in current dir

    for (index = 0; index < sizeof(classes); index++)
    {
        current = element(index, classes);  // determine class name
        chdir( current);                  // chdir to a class directory.
	prefix_class((string)index);	  // prefix class-number for .o files
        updatelib(libxxxa);
        chdir( "..");                     // go back to parent dir
    }

    current = "";                           // no class anymore

    updatelib(libxxxa);			    // update lib in current dir

    if (mainfile != "")                     // mainfile -> do link
    {
        link(library, exe);
        printf
	(
	    "\nProgram construction completed.\n"
	    "\n"
	);
    }
}

void main()
{
    libs    = "-lcclib";		// the libname (no lib, .a)

	copt = "-O2";
	lopt = "-s";
	
//	copt = "-DDEBUG";		// Debug-flag set

//  remove the echo() statement if you want to see the execed commands
//    echo(OFF);			// do not show commands

    cpp_make
    (
        "xd.cc",             // program source
        "xd",                // program library
        "xd",                // exe program
	(list)"Command" +	// classes
	(list)"Match" 	+
	(list)"Config" 	+
	(list)"Arbiter"
    );
}
