static char *SccsId = "@(#)main.c 4.6 (TU-Delft) 07/28/92";
/**********************************************************

Name/Version      : func_mkdb/4.6

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

Author(s)         : O. Hol
Creation date     : 05-Nov-1987
Modified by       : S. de Graaf
Modification date : 25-Apr-1988
Modified by       : P.E. Menchen
Modification date : 24-Sep-1991


        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) 1987-1991, All rights reserved
**********************************************************/
#include "func_parse.h"
#ifdef ESE
#include "eseOption.h"
#include "tversion.h"
#endif

#define EQUI_TOOL "relate"

FILE * yyin, *yyout;
char   *infile;
char   *outfile;
char   baseinfile[200];

DM_CELL *key, *dkey;           /* dkey and ddes are for a dummy circuit cell */
DM_STREAM *fdes, *ddes;
DM_PROJECT *dmproject;

#ifdef ESE
char   *argv0 = "putfunc";	/* Program Name */
#else
char   *argv0 = "func_mkdb";	/* Program Name */
#endif

int     verbose = 1;
int     cflag = 0;
int     dummy = 0;
int     cirflag = 0;
char    viewtype[BUFSIZ];
char    cmdstr[BUFSIZ];
char    C_options[BUFSIZ];
extern char Func_name[BUFSIZ];

static int     ncppflag = 0;
static int     fpflag = 0;
#ifdef ESE
static int     pcsave;
static char    * C_optionsTmp = NULL;
static char ** arguments;
#endif


#ifdef ESE
OptionSpec optionSpecs[] = {
    { "usage", NO, eseHelp, (void *) optionSpecs,
            "usage:     putfunc [options] file\nOptions (may be abbreviated) are: "},
    { "%etext", NO, eseText, (void *) NULL,
            "    -%etext:                 print the '(int) & etext' number" },
    { "%help", NO, eseHelpAll, (void *) optionSpecs,
            "    -%help:                  print this list" },
    { "help", NO, eseHelp, (void *) optionSpecs,
            "    -help:                   print this list" },
    { "nocpre", NO, eseTurnOn, (void *) & ncppflag,
            "    -nocpre:                 do not run the C preprocessor" },
    { "release", NO, esePrintString, (void *) TOOLVERSION,
            "    -release:                print the release number of this tool " },
    { "save", NO, eseTurnOn, (void *) & pcsave,
            "    -save:                   save the '.p' and the '.c' file" },
    { "silent", NO, eseTurnOff, (void *) & verbose,
            "    -silent:                 silent mode" },
#if NCF_RELEASE >= 400
    { "dummy", NO, eseTurnOn, (void *) & dummy,
	    "    -dummy:                  generate dummy circuit object with equivalence"},
#endif
    { "C", YES, eseAssignArgument, (void *) & C_optionsTmp,
            "    -C xxx:                  use the following options for the C compiler"},
    { (char *) 0, (char) 0, (IFP) 0, (void *) 0, (char *) 0 },
};
#endif

main (argc, argv)
int     argc;
char   *argv[];
{
/*  int     cursflag = 0; */
    int     i = 0;
    int     k;
    char    tmp[BUFSIZ];
    char    cppoutfile[BUFSIZ];
    struct stat buf;

    infile = NULL;
    outfile = NULL;
    yyin = NULL;
    yyout = NULL;

    sprintf (C_options, "");

#if NCF_RELEASE < 400
    strcpy (viewtype, "circuit");
#else
    strcpy (viewtype, FUNCTIONAL);
#endif

#ifdef ESE
    pcsave = 0;
#endif

#ifndef ESE
    while (--argc && ++argv) {
	if ((*argv)[0] == '-') {
	    i = 1;
	    if ((*argv)[i] == 'C') {
		strcat (C_options, "-");
		strcat (C_options, (*argv) + 2);
		strcat (C_options, " ");
	    }
	    else
		do {
		    switch ((*argv)[i]) {
#if NCF_RELEASE >= 400
			case 'd':
			    i++;
			    dummy = 1;
			    break;
#endif
			case 'k':
			    i++;
			    fpflag = 1;
			    cflag = 1;
			    break;
			case 'p':
			    i++;
			    ncppflag = 1;
			    break;
			case 's':
			    i++;
			    verbose = 0;
			    break;
			case 'y':
			    i++;
			    yydebug = 1;
			    break;
			default:
			    usage ("bad option:", (*argv)[i]);
			    i++;
			    break;
		    }
		} while ((*argv)[i] != '\0');
	}
	else
	    if (infile == NULL) {
		infile = *argv;
	    }
	    else {
		usage ("too many arguments", ' ');
	    }
    }
#else
    arguments = (char **) calloc (1, sizeof (char *));
    if ((eseOptionHandler (argc, argv, optionSpecs, 1, arguments) > 0)) {
        usage ("", ' ');
        exit (1);
    }
    infile = arguments[0];
    if (C_optionsTmp != NULL) {
        sprintf (C_options, "-%s ", C_optionsTmp);
    }
    if (pcsave) {
	fpflag = 1;
	cflag = 1;
    }
#endif

    if (infile) {
	if (stat (infile, &buf) != 0)
	    usage ("cannot find input file", ' ');
    }
    else {
	usage ("no input file present", ' ');
    }

    strcpy (baseinfile, infile);

    i = strlen (baseinfile);
    while (i > 0 && baseinfile[i - 1] != '/' && baseinfile[i - 1] != '.') {
	i--;
    }
    if (baseinfile[i - 1] == '.') {
	baseinfile[i - 1] = '\0';
    }
    else {
	usage ("input file does not end with an extension", ' ');
    }

    i = strlen (baseinfile); 
    while (i > 0 && baseinfile[i - 1] != '/') {
        i--;
    }

#ifdef FILENAME_MAX
    /* FILENAME_MAX should be defined in stdio.h, but may not be on Suns */
#if (FILENAME_MAX < DM_MAXNAME)
#define NOEXT_MAX FILENAME_MAX
#else
#define NOEXT_MAX DM_MAXNAME
#endif
#else
#define NOEXT_MAX DM_MAXNAME
#endif

    k = strlen (baseinfile) - i;
    if (k > (NOEXT_MAX-2)) {
        baseinfile[i + (NOEXT_MAX-2)] = '\0';
    }

    if (ncppflag == 0) {
	sprintf (cppoutfile, "%s.p", baseinfile);
	sprintf (tmp, "%s.c", baseinfile);
	cppexec (infile, cppoutfile, tmp);
	yyin = fopen (cppoutfile, "r");
        if (!yyin) die (2, cppoutfile, "");
    }
    else {
	yyin = fopen (infile, "r");
        if (!yyin) die (2, infile, "");
    }

    sprintf (tmp, "%s.c", baseinfile);
    outfile = tmp;
    yyout = fopen (outfile, "w");

    if (!yyout) die (2, outfile, "");

/*
    fprintf (yyout, "#include <stdio.h>\n");
    if (cursflag != 0)
	fprintf (yyout, "#include <curses.h>\n");
*/
    dmInit (argv0);   /* to obtain icdpath */

    fprintf (yyout, "#include \"%s/lib/sls/func.h\"\n", icdpath);
    if (ncppflag != 0)
	lineno (1);

    if (outfile && verbose) {
	if (ncppflag)
	    fprintf (stderr, "Parsing %s ; making %s\n", infile, outfile);
	else
	    fprintf (stderr, "Parsing %s ; making %s\n", cppoutfile, outfile);
    }

    yyparse ();
    fclose (yyin);
    fclose (yyout);

    if (ncppflag == 0 && fpflag == 0)
	rmexec (cppoutfile);

    dmproject = dmOpenProject (DEFAULT_PROJECT, DEFAULT_MODE);

#if NCF_RELEASE >= 400
    {

	/* Unfortunately, 

	if ((int)dmGetMetaDesignData (EXISTVIEW, dmproject, FUNCTIONAL) != 1) {
        }

	   does not work since it calls dmError if the view does not exist.
	*/

        data **view_list;
        int view_entry;
        int exist_funcview = 0;

	view_list = dmproject -> views;
	for (view_entry = 0; view_list[view_entry] != NULL; ++view_entry) {
	    if (strcmp (FUNCTIONAL, view_list[view_entry][0].point) == 0) {
                exist_funcview = 1;
	    }
	}
	if (!exist_funcview) {
	    cirflag = 1;    /* circuit view only mode, for old projects */
	    strcpy(viewtype, CIRCUIT);
	    if (dummy)
#ifndef ESE
		usage( "-d option is invalid for project without 'functional' viewtype", ' ');
#else
		usage("-dummy option is invalid for project without 'functional' viewtype", ' ');
#endif
        }
    }
#endif

    key = dmCheckOut (dmproject, Func_name, WORKING,
                      DONTCARE, viewtype, UPDATE);
    if (dummy) {
	dkey = dmCheckOut (dmproject, Func_name, WORKING, /* only one stream */
			   DONTCARE, CIRCUIT, UPDATE);    /* used, so opened */
	ddes = dmOpenStream (dkey, "term", "w");      /* here to cut down on */
    }                                               /* if (dummy) statements */

    addfun_term (ftrm_list);
    addfun_obj (baseinfile);

    dmCheckIn (key, COMPLETE);
    if (dummy) {
        dmCloseStream (ddes, COMPLETE);
        dmCheckIn (dkey, COMPLETE);
        sprintf(cmdstr, "%s -s %s", EQUI_TOOL, Func_name);
        system(cmdstr);
    }

    dmQuit ();

    exit (0);
}

void    usage (s1, c)
char   *s1, c;
{
    fprintf (stderr, "%s: %s %c\n", argv0, s1, c);
#ifndef ESE
#if NCF_RELEASE >= 400
    fprintf (stderr,
	"\nUsage: %s [-cdkps] [-C\"cc options\"] infile\n\n", argv0);
#else
    fprintf (stderr,
	"\nUsage: %s [-kps] [-C\"cc options\"] infile\n\n", argv0);
#endif
#else
    fprintf (stderr,
	"\nUsage: %s [options] infile\n\n", argv0);
#endif
    exit (1);
}

void    yyerror (s)
char   *s;
{
    fprintf (stderr, "%s: %s, in line %d: %s\n",
	argv0, infile, yylineno, s);
    if (yydebug == 0) die (5, "", "");
}

void    lineno (line)
int     line;
{
    fprintf (yyout, "#line %d ", line);
    if (infile)
	fprintf (yyout, "\"%s\"", infile);
    fprintf (yyout, "\n");
}

dmError (s)
char   *s;
{
#if NCF_RELEASE < 400
    fprintf (stderr, "%s: ", argv0);
#endif
    dmPerror (s);
    if (!strcmp(dmerrlist[dmerrno],"Bad viewtype 'functional'"))
        fprintf(stderr,
            "Create project with viewtype 'functional'\n");
    die (0, "", "");
}

char *errlist[] = {
/* 0 */  "error in DMI function",
/* 1 */  "cannot allocate memory",
/* 2 */  "cannot open file '%s'",
/* 3 */  "no successful compilation of '%s'",
/* 4 */  "C preprocessor on '%s' unsuccesfull",
/* 5 */  "yyerror exit",
/* 6 */  "index of terminal '%s' must be an integer",
/* 7 */  "terminal name '%s' is already used",
/* 8 */  "terminal '%s' in routine delay is not output or inout",
/* 9 */  "terminal '%s', illegal call of routine %s",
/* 10 */ "cannot find terminal '%s' in routine %s",
/* 11 */ "terminal '%s' in routine cap_add is not input or inread",
/* 12 */ "terminal '%s' in routine %s_val is not a terminal",
/* 13 */ "terminal '%s', illegal call of routine %s_val",
/* 14 */ "internal error in evaluating routine %s",
/* 15 */ "unknown error"
};

die (nr, s1, s2)
int  nr;
char *s1, *s2;
{
    if (nr < 0 || nr > 15) nr = 15;
    fprintf (stderr, "%s: ", argv0);
    fprintf (stderr, errlist[nr], s1, s2);
    fprintf (stderr, "\n%s: -- program aborted --\n", argv0);
    dmQuit ();
    exit (1);
}
