// These two defines are the C compiler and the flags. -c is needed to 
// ensure compilation-only; -O or -g may be selected to turn debugging
// off or on. The flag -funsigned-char makes gcc use 'unsigned char's rather
// than 'signed chars'. 
#define CC 		"gcc"
#define CFLAGS		"-c -g -Wall -O -funsigned-char"

// The following two macros are the library manager. That program must
// is started as "AR ARFLAGS library-name object-files".
#define AR		"ar"
#define ARFLAGS		"vrs"

// A remove program..
#define RM		"rm"

// The destination directory to copy executables to, and your install
// program ("cp" for a poor man's solution).
#define BINDIR		"/usr/local/bin"
#define CP		"cp"

// The strip program, to remove debugging information
#define STRIP		"strip"

// The 'cat1' directory of your ready-to-cat man pages. Used when you 
// "make unix -- doc2man"
#define CATDIR 		"/usr/man/cat1"

// You've edited enough now. Try making it.

#define LIB_ICRSS	"libicrss.a"
#define LIB_ICMAKE	"libicmake.a"
#define LIB_ICMPP	"libicmpp.a"
#define LIB_ICMCOMP	"libicmcomp.a"
#define LIB_ICMEXEC	"libicmexec.a"
#define LIB_ICMUN	"libicmun.a"
#define ZIP		"icmake.zip"
#define VERSION		"6.07"
#define EXAMPLES	(list)"r"+(list)"idir"+(list)"tolower"+(list)"keep"

void makelib (string dir, string lib)
{
    list
    	cfiles,
    	ofiles;
    string
    	ofile,
    	cfile;
    int
    	i;

    printf ("---- Directory: ", dir, " ----\n");
    chdir (dir);

    printf ("Checking .c files against library ", lib, "\n");    	
    cfiles = makelist ("*.c");
    for (i = sizeof (cfiles) - 1; i >= 0; i--)
    {
    	cfile = element (i, cfiles);
    	ofile = change_ext (cfile, ".o");
    	if (cfile older lib ||
    	    (exists (ofile) && ofile younger cfile)
    	   )
    	    cfiles -= (list) cfile;
    }
    for (i = 0; i < sizeof (cfiles); i++)
        exec (CC, CFLAGS, element (i, cfiles));
    
    printf ("Checking .o files against library ", lib, "\n");
    ofiles = makelist ("*.o");
    if (ofiles)
    {
    	exec (AR, ARFLAGS, lib, "*.o");
	exec (RM, "*.o");
    }
    
    chdir ("..");
}

void makelibs ()
{
    printf ("\nMaking Run Time Support System library\n");
    makelib ("rss", LIB_ICRSS);
    
    printf ("\nMaking lib for shell program icmake\n");
    makelib ("make", LIB_ICMAKE);
    
    printf ("\nMaking lib for preprocessor icm-pp\n");
    makelib ("pp", LIB_ICMPP);
    
    printf ("\nMaking lib for compiler icm-comp\n");
    makelib ("comp", LIB_ICMCOMP);
    
    printf ("\nMaking lib for executor icm-exec\n");
    makelib ("exec", LIB_ICMEXEC);
    
    printf ("\nMaking lib for unassembler icmun\n");
    makelib ("un", LIB_ICMUN);
}

void makeprog (string dir, string lib, string prog)
{
    string
    	rsslib;
    	
    rsslib = "../rss/libicrss.a";

    printf ("---- Directory: ", dir, " ----\n");
    chdir (dir);
    
    printf ("Checking prog ", prog, " against libs ", lib, 
            " and ", rsslib, "\n");
    if (lib younger prog || rsslib younger prog)
    	exec (CC, "-o " + prog, lib, rsslib);
    	
    chdir ("..");
}

void makeprogs ()
{
    makelibs ();
    
    printf ("\nMaking shell program icmake\n");
    makeprog ("make", LIB_ICMAKE, "icmake");
    
    printf ("\nMaking unassembler program icmun\n");
    makeprog ("un", LIB_ICMUN, "icmun");

    printf ("\nMaking unassembler program icm-pp\n");
    makeprog ("pp", LIB_ICMPP, "icm-pp");
    
    printf ("\nMaking compiler program icm-comp\n");
    makeprog ("comp", LIB_ICMCOMP, "icm-comp");
    
    printf ("\nMaking executor program icm-exec\n");
    makeprog ("exec", LIB_ICMEXEC, "icm-exec");
}

void inst (string dir, string prog)
{
    string
    	dest;

    printf ("---- Directory: ", dir, " ----\n");
    chdir (dir);
    dest = BINDIR + "/" + prog;
    
    if (dest older prog)
	if (prog == "icm-exec")
	    printf ("Since icm-exec itself is running, it has to be "
	    					"installed by hand.\n"
	    	    "PLEASE EXECUTE THE FOLLOWING COMMANDS WHEN ICMAKE "
						"IS DONE:\n"
	    	    "  > ", CP, " exec/icm-exec ", BINDIR, "\n"
	    	    "  > ", STRIP, " ", dest, "\n\n");
	else
	{
	    exec (CP, prog, BINDIR);
	    exec (STRIP, dest);
    	}
    
    chdir ("..");
}

void install ()
{
    makeprogs ();
    
    printf ("\nInstalling shell program icmake\n");
    inst ("make", "icmake");
    
    printf ("\nInstalling unassembler program icmun\n");
    inst ("un", "icmun");
    
    printf ("\nInstalling unassembler program icm-pp\n");
    inst ("pp", "icm-pp");
    
    printf ("\nInstalling compiler program icm-comp\n");
    inst ("comp", "icm-comp");
    
    printf ("\nInstalling executor program icm-exec\n");
    inst ("exec", "icm-exec");
    
}

void clean (string dir, string lib, string prog)
{
    printf ("---- Directory: ", dir, " ----\n");
    chdir (dir);
    if (exists (lib))
    	exec (RM, lib);
    if (prog && exists (prog))
    	exec (RM, prog);
    chdir ("..");
}

void cleanup ()
{
    clean ("rss", LIB_ICRSS, "");
    clean ("make", LIB_ICMAKE, "icmake");
    clean ("pp", LIB_ICMPP, "icm-pp");
    clean ("comp", LIB_ICMCOMP, "icm-comp");
    clean ("exec", LIB_ICMEXEC, "icm-exec");
    clean ("un", LIB_ICMUN, "icmun");
}

void zip ()
{
    cleanup ();
    exec (RM, "-f", "*.tar", "*.tar.z", "*.tar.gz");
    exec ("zip", "-ur", ZIP, "*");
}

void makedist ()
{
    string
    	tar,
    	tarz,
    	example;
    list
    	examples;
    int
    	i;
    	
    printf ("Have you updated the version number (if things have changed)?");
    if (getch () != "y")
    	return;
    printf ("\nOk..\n");
    
    examples = EXAMPLES;
    chdir ("examples");
    for (i = 0; i < sizeof (examples); i++)
    {
    	example = element (i, examples);
    	if ("/home/karel/bin/" + example younger example)
    	    exec (CP, "/home/karel/bin/" + example, example);
    }
    chdir ("..");
    
    tar = "icmake-" + VERSION + ".tar";
    tarz = tar + ".z";
    
    exec ("tar", "-c -v --exclude-from distrib.no -f", tar, ".");
    exec ("gzip", tar);
    exec ("mv", tarz, change_ext (tarz, ".gz"));
}

void doc2man ()
{
    string
    	src,
    	dest;
    	
    src  = "doc"   + "/" + "icmake.1";
    dest = CATDIR  + "/" + "icmake.1";
    
    if (dest older src)
    	exec (CP, src, dest);
}

void main (int argc, list argv)
{
    string
    	av1;
    	
    av1 = element (1, argv);
    if (av1 == "libs")
    	makelibs ();
    else if (av1 == "progs")
    	makeprogs ();
    else if (av1 == "install")
    	install ();
    else if (av1 == "clean")
    	cleanup ();
    else if (av1 == "doc2man")
    	doc2man ();
    else if (av1 == "zip")
    	zip ();
    else if (av1 == "dist")
	makedist ();
    else
    	printf ("Make what?\n"
    		"Select one of the following:\n"
    		"    \"icmake unix -- libs\" to make libraries\n"
    		"    \"icmake unix -- progs\" to make programs\n"
    		"    \"icmake unix -- install\" to install programs to ",
		    					BINDIR, "\n"
		"    \"icmake unix -- clean\" to remove old mush\n"
		"    \"icmake unix -- doc2man\" to copy crude docs to cat\n"
		"\n"
		"    \"icmake unix -- zip\" to clean up and zip it up\n"
		"    \"icmake unix -- dist\" to make distribution\n"
    		"\n");
}
