static char *SccsId = "@(#)mksim.c 4.12 (TU-Delft) 06/15/92";
/**********************************************************

Name/Version      : sls_exp/4.3

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
Creation date     : 25-Sep-1986
Modified by       : A.J. van Genderen
Modification date : 16-Feb-1987


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1986 , All rights reserved
**********************************************************/
#include "extern.h"

#define  SLSFUNF  "sls.funlist"
#define  FUNCC    "deffunc.c"
#define  FUNCOBJ  "deffunc.o"
#define  CCCOM    "cc -c -I"
#define  CCCOMG   "cc -g -c -I"
#define  LDCOM    "cc" 
#define  LDCOMG   "cc -g" 
#define  SIMOBJ   "*.o -ll"
#define  LDARGF   "sls.ld_arg"

/* If neccessary, mksim makes a new simulator executable.
   When a new one is made 1 will be returned, otherwise 0.
*/

extern int debugcomp;
   
int mksim ()
{
    struct stat buf;
    int strend;
    int make;
    int i;
    int j;
    int found;
    int unknown;
    int endreached;
    char fname[NAMESIZE];
    FILE * fp;
    char c;
    char *syscom;
    int syscom_size;
    int len;
    char libsls[128];
    char dmlib[128];
    char libfunc[128];
#ifdef ESE
    char *simname = "funcsls";
#else
    char *simname = "sls";
#endif

    if (FD_cnt == 0)
        return (0);        /* no functions in network */

    if (!force_exp && stat (simname, &buf) == 0) {
        if (buf.st_mtime <= newest_ftime)
            make = TRUE;
        else {
            if ((fp = fopen (SLSFUNF, "r")) == NULL) {
                fprintf (stderr, "Can't read %s\n", SLSFUNF);
                make = TRUE;
            }
            else {
                unknown = FALSE;
                for (i = 0; i < FD_cnt && ! unknown; i++) {
                    rewind ((FILE *)fp);
                    found = FALSE;
                    fname[0] = 'a';
                    while (! found && fscanf (fp, "%s", fname) == 1) {
                        if (strcmp_quick (FD[i].name, fname) == 0)
                            found = TRUE;
                    }
                    if (! found)
                        unknown = TRUE;
                }
                if (unknown)
                    make = TRUE;
                else
                    make = FALSE;
            }
            fclose (fp);
        }
    }
    else
        make = TRUE;

    if (make) {
        if (! silent)
            fprintf (stderr, "Making %s\n", simname);

        OPENW (fp, FUNCC);

#if NCF_RELEASE < 400
	fprintf (fp, "#include \"gndefine.h\"\n\n");
	fprintf (fp, "#include \"gntype.h\"\n\n");
#else
        fprintf (fp, "#include <stdio.h>\n\n");
        fprintf (fp, "#include \"gndefine.h\"\n\n");
        fprintf (fp, "#include \"dmi.h\"\n\n");
        fprintf (fp, "#include \"gntype.h\"\n\n");
#endif

        fprintf (fp, "FUNCDESCR FD[] = {\n");
        for (i = 0; i < FD_cnt; i++) {
            endreached = FALSE;
            for (j = 0; j < NAMESIZE; j++) {
                if (endreached || FD[i].name[j] == '\0') {
                    fprintf (fp, "0,"); 
                    endreached = TRUE;
                }
                else {
                    fprintf (fp, "'%c',", FD[i].name[j]); 
                }
            }
#if NCF_RELEASE < 400
            endreached = FALSE;
            for (j = 0; j < MAXDMPATH + 1; j++) {
                if (endreached || FD[i].dmpath[j] == '\0') {
                    fprintf (fp, "0,"); 
                    endreached = TRUE;
                }
                else {
                    fprintf (fp, "'%c',", FD[i].dmpath[j]); 
                }
            }
#endif
#if NCF_RELEASE >= 400
            fprintf (fp, "0,");  /* FD[i].key */
            fprintf (fp, "0,");  /* FD[i].streamkey */
#endif
            fprintf (fp, "0,");  /* FD[i].help */
            fprintf (fp, "%d,", FD[i].fvx);
            fprintf (fp, "%d,", FD[i].fvx_cnt);
            fprintf (fp, "%d", FD[i].offsx);
            if (i != FD_cnt - 1)
                fprintf (fp, ",");
            fprintf (fp, "\n");
        }
        fprintf (fp, "};\n");

        fprintf (fp, "\nFUNCVAR FV[] = {\n");
        for (i = 0; i < FV_cnt; i++) {
            endreached = FALSE;
            for (j = 0; j < NAMESIZE; j++) {
                if (endreached || FV[i].name[j] == '\0') {
                    fprintf (fp, "0,"); 
                    endreached = TRUE;
                }
                else {
                    fprintf (fp, "'%c',", FV[i].name[j]); 
                }
            }
            fprintf (fp, "0,");
            fprintf (fp, "%d,", FV[i].type);
            fprintf (fp, "%d,%d", FV[i].ind[0], FV[i].ind[1]);
            if (i != FV_cnt - 1)
                fprintf (fp, ",");
            fprintf (fp, "\n");
        }
        fprintf (fp, "};\n");

        fprintf (fp, "\nint FD_cnt = %d;\n", FD_cnt);
        fprintf (fp, "int FV_cnt = %d;\n", FV_cnt);

        fprintf (fp, "\nloaddf (fx, S)\n");
        fprintf (fp, "int fx;\n");
        fprintf (fp, "char * S;\n");
        fprintf (fp, "{\n");
        fprintf (fp, "switch (fx) {\n");
        for (i = 0; i < FD_cnt; i++) {
            fprintf (fp, "case %d:\n", i);
            fprintf (fp, "L%s (S);\n", FD[i].name);
            fprintf (fp, "break;\n");
        }
        fprintf (fp, "}\n");
        fprintf (fp, "}\n");
            
        fprintf (fp, "\ninitdf (fx, S)\n");
        fprintf (fp, "int fx;\n");
        fprintf (fp, "char * S;\n");
        fprintf (fp, "{\n");
        fprintf (fp, "switch (fx) {\n");
        for (i = 0; i < FD_cnt; i++) {
            fprintf (fp, "case %d:\n", i);
            fprintf (fp, "I%s (S);\n", FD[i].name);
            fprintf (fp, "break;\n");
        }
        fprintf (fp, "}\n");
        fprintf (fp, "}\n");
            
        fprintf (fp, "\nevaldf (fx, S)\n");
        fprintf (fp, "int fx;\n");
        fprintf (fp, "char * S;\n");
        fprintf (fp, "{\n");
        fprintf (fp, "switch (fx) {\n");
        for (i = 0; i < FD_cnt; i++) {
            fprintf (fp, "case %d:\n", i);
            fprintf (fp, "E%s (S);\n", FD[i].name);
            fprintf (fp, "break;\n");
        }
        fprintf (fp, "}\n");
        fprintf (fp, "}\n");
            
        CLOSE (fp);

        syscom_size = 1200 + FD_cnt * 80;
	PALLOC (syscom, syscom_size, char);

#if NCF_RELEASE < 400
	if ( debugcomp )
	    sprintf (syscom, "%s%s/lib/sls %s", CCCOMG, icdpath, FUNCC);
	else
	    sprintf (syscom, "%s%s/lib/sls %s", CCCOM, icdpath, FUNCC);
#else
	if ( debugcomp )
            sprintf (syscom, 
		     "%s%s/lib/sls -I%s/lib/include -DNCF_RELEASE=%d %s",
		     CCCOMG, icdpath, icdpath, NCF_RELEASE, FUNCC);
	else
            sprintf (syscom, 
		     "%s%s/lib/sls -I%s/lib/include -DNCF_RELEASE=%d %s",
		     CCCOM, icdpath, icdpath, NCF_RELEASE, FUNCC);
#endif

        if (! silent)
            fprintf (stderr, "%s\n", syscom);

        if (system (syscom) != 0) {
            fprintf (stderr, "\nNo successful compilation of %s\n\n", FUNCC);
            die (1);
        }
        
	if ( debugcomp ) {

	    sprintf (syscom, "%s %s %s/lib/sls/%s %s", 
		     LDCOMG, LDFLSLS, icdpath, SIMOBJ, FUNCOBJ);

            /* remove the -s option if it is present */

	    len = strlen (syscom);
	    for (i = 0; i < len; i++) {
		if (syscom[i] == '-' && syscom[i+1] == 's') {
		    while (i + 3 <= len) {
			syscom[i] = syscom[i+3];
			i++;
		    }   
		}
	    }
	}
	else
	    sprintf (syscom, "%s %s %s/lib/sls/%s %s", 
		     LDCOM, LDFLSLS, icdpath, SIMOBJ, FUNCOBJ);

#ifndef ESE
        strend = strlen (syscom);
        sprintf (syscom + strend, " %s/lib/libddm.a", icdpath);
#endif

        for (i = 0; i < FD_cnt; i++) {
            strend = strlen (syscom);
#if NCF_RELEASE < 400
	    sprintf (syscom + strend, " %s/circuit/%s/sls.o",
		     FD[i].dmpath, FD[i].name);
#else
#if NCF_RELEASE >= 430
            /* This is the new code that is used for the version of
	       libddm that contains 'dmGetPathOfStream' and 
	       'streamkey -> dmpath'.
	       (SEE ALSO below with dmCloseStream (FD[i].streamkey, COMPLETE);)
	    */

	    FD[i].streamkey = dmGetPathOfStream (FD[i].key, "sls.o");
	    sprintf (syscom + strend, " %s", FD[i].streamkey -> dmpath); 
            /*
	    sprintf (syscom + strend, " %s/%s/%s/sls.o", 
		     FD[i].dmpath, FD[i].key->view,FD[i].key->old_object);
	    */
#else
            /* This is code for NCF_RELEASE < 430 */

	    sprintf (syscom + strend, " %s/%s/%s/sls.o", 
		     FD[i].key->dmproject->TMPath,
		     FD[i].key->view,FD[i].key->old_object);
#endif
#endif
        }

#ifndef ESE
        strend = strlen (syscom);
        sprintf (syscom + strend, " %s/lib/libfunc.a", icdpath);
#endif

        if ((fp = fopen (LDARGF, "r")) != NULL) {
            strend = strlen (syscom);
            *(syscom + strend) = ' ';
            strend++;
            while ((c = fgetc (fp)) != EOF) {
                if (c == '\n') 
                    c = ' ';
                if (c != ' ' || *(syscom + strend - 1) != ' ') {
                    *(syscom + strend) = c;
                    strend++;
                }
            }
            if (*(syscom + strend - 1) == ' ')
                *(syscom + strend - 1) = '\0';
            else
                *(syscom + strend) = '\0';
        }

        strend = strlen (syscom);
        sprintf (syscom + strend, " -o %s", simname);

        if (! silent)
            fprintf (stderr, "%s\n", syscom);

        if (system (syscom) != 0) {
            fprintf (stderr, "\nNo successful linking of %s\n\n", simname);
            die (1);
        }
        
        OPENW (fp, SLSFUNF);
        for (i = 0; i < FD_cnt; i++) {
             fprintf (fp, "%s\n", FD[i].name);
#if NCF_RELEASE >= 400
#if NCF_RELEASE >= 430
             /* see also above */

             dmCloseStream (FD[i].streamkey, COMPLETE);
#endif
	     dmCheckIn (FD[i].key, COMPLETE);
#endif
        }
        CLOSE (fp);
    }

    if (make)
	return (1);
    else
	return (0);
}
