#include <../../nmodlconf.h>
/* /local/src/master/nrn/src/modlunit/model.c,v 1.6 1998/07/12 13:19:02 hines Exp */

/*
 * int main(int argc, char *argv[]) --- returns 0 if translation is
 * successful. Diag will exit with 1 if error. 
 *
 * ---The overall strategy of the translation consists of three phases. 
 *
 * 1) read in the whole file as a sequence of tokens, building a parse tree.
 * The entire file can be printed exactly by printing the intoken list. No
 * translation is done here but the symbol table is constructed.
 * 2) Manipulate the blocks.
 * 3) Output the lists. 
 *
 * void openfiles(int argc, char *argv[]) parse the argument list, and open
 * files. Print usage message and exit if no argument 
 *
 */

/*
 * In order to interface this process with merge, a second argument is
 * allowed which gives the complete input filename.  The first argument
 * still gives the prefix of the .c and .var files.
 */
 
#include "model.h"
#include "parse1.h"

extern int yyparse();

FILE
	* fin,			/* input file descriptor for filename.mod */
				/* or file2 from the second argument */
	*fparout,		/* output file descriptor for filename.var */
	*fcout;			/* output file descriptor for filename.c */

char            finname[200];	/* filename.mod  or second argument */
Item	*parseroot;
Item	*title;

#if LINT
char           *clint;
int             ilint;
Item           *qlint;
#endif

static char pgm_name[] =	"model";
extern char *RCS_version;
extern char *RCS_date;
static void openfiles();
static void debug_item();
#if MAC
#include <sioux.h>
#endif

int
main(argc, argv)
	int             argc;
	char           *argv[]; {
	/*
	 * arg 1 is the prefix to the input file and output .c and .par
	 * files 
	 * We first look for a .mrg file and then a .mod file
	 */
#if MAC
	SIOUXSettings.asktosaveonclose = false;
#endif
	Fprintf(stderr, "%s   %s   %s\n",
		pgm_name, RCS_version, RCS_date);
	
							
	init();			/* keywords into symbol table, initialize
				 * lists, etc. */
	unit_init();
	nrn_unit_init();
#if MAC
	mac_cmdline(&argc, &argv);
#endif
	openfiles(argc, argv);	/* .mrg else .mod,  .var, .c */
	Fprintf(stderr, "Checking units of %s\n", finname);

	lex_start();
	/* declare all used variables */
	parsepass(1);
	IGNORE(yyparse());
	declare_implied();
	/* At this point The input file is in the intoken list */
#if 0
	printlist(intoken);
	debug_item((Item *)intoken, 0, fparout);
#endif	
	/* give all names their proper units */
	/* all variables used consistently (arrays) */
	parsepass(2);
	yyparse();
	/* 
	 * NAME's can be used in many cases before they were declared and
	 * no checking up to this point has been done to make sure that
	 * names have been used in only one way.
	 *
	 */
	consistency();
	/* check unit consistency */
	parsepass(3);
	yyparse();
#if MAC
	printf("Units consistent in %s\n", finname);
	SIOUXSettings.autocloseonquit = true;
#endif
#if 0
	parout();		/* print .var file.
				 * Also #defines which used to be in defs.h
				 * are printed into .c file at beginning.
				 */
	cout();			/* print .c file */
#endif
#if 0
	IGNORE(fclose(fparout));
	IGNORE(fclose(fcout));
	memory_usage();
#endif
#if LINT
	{			/* for lex */
		extern int      yytchar, yylineno;
		extern FILE    *yyin;
		IGNORE(yyin);
		IGNORE(yytchar);
		IGNORE(yylineno);
		IGNORE(yyinput());
		yyunput(ilint);
		yyoutput(ilint);
	}
#endif
	return 0;
}

static void openfiles(argc, argv)
	int             argc;
	char           *argv[];
{
	char *cp, modprefix[200];
	if (argc > 1) {
		sprintf(modprefix, "%s", argv[1]);
		cp = strstr(modprefix, ".mod");
		if (cp) {
			*cp = '\0';
		}
	}
	if (argc == 2) {
		Sprintf(finname, "%s.mrg", modprefix);
	} else if (argc == 3) {
		Sprintf(finname, "%s", argv[2]);
	} else {
		diag("Usage:", "modl prefixto.mod [inputfile]");
	}
	if ((fin = fopen(finname, "r")) == (FILE *) 0) {
		Sprintf(finname, "%s.mod", modprefix);
		if ((fin = fopen(finname, "r")) == (FILE *) 0) {
			diag("Can't open input file: ", finname);
		}
	}
}

void printlist(list)
	List *list;
{
	Item *q;

	ITERATE(q, list) {
		printitem(q, fcout);
	}
}

void printitems(q1, q2)
	Item *q1, *q2;
{
	Item *q;

	for (q = q1; q->prev != q2; q = q->next) {
		printitem(q, stderr);
	}
}

void printitem(q, fp)
	Item *q;
	FILE *fp;
{
		switch (q->itemtype) {

		case SYMBOL:
			Fprintf(fp, "%s", SYM(q)->name);
			break;
		case STRING:
			Fprintf(fp, "%s", STR(q));
			break;
		case NEWLINE:
			Fprintf(fp, "\n");
			break;
		default:
			Fprintf(stderr, "\nq->itemtype = %d\n", q->itemtype);
			diag("printlist handles only a few types of items",
				(char *)0);
			break;
		}
	fflush(fp);
}

void debugitem(q)
	Item *q;
{
	debug_item(q, 0, stderr);
}

static void debug_item(q, indent, file)
	Item *q;
	int indent;
	FILE *file;
{
	int i;
	List *list;
	Item *q1;
	
	for (i=0; i<indent; i++) {
		Fprintf(file, " ");
	}
	if (!q) {
		Fprintf(file, "NULL ITEM\n");
	}else
	switch (q->itemtype) {
		case SYMBOL:
		Fprintf(file, "SYMBOL |%s| %p\n", SYM(q)->name, SYM(q));
		break;
	case STRING:
		Fprintf(file, "STRING |%s|\n", STR(q));
		break;
	case LIST:
		Fprintf(file, "LIST\n");
		list = LST(q);
		ITERATE(q1, list) {
			debug_item(q1, indent+2, file);
		}
		break;
	case 0:
		list = (List *)q;
		Fprintf(file, "HEAD/TAIL of list\n");
		ITERATE(q1, list) {
			debug_item(q1, indent, file);
		}
		break;
	case ITEM:
		Fprintf(file, "ITEM\n");
		debug_item(ITM(q), indent+2, file);
		break;
	case ITEMARRAY: {Item **qa; int i; long n;
		qa = ITMA(q);
		n = (size_t)qa[-1];
		Fprintf(file, "ITEMARRAY %ld\n", n);
		for (i=0; i<n; i++) {
			debug_item(qa[i], indent+2, file);
		}
		}
		break;
	case NEWLINE:
		Fprintf(file, "NEWLINE %d\n", q->itemsubtype);
		break;
	default:
		Fprintf(stderr, "\nq->itemtype = %d\n", q->itemtype);
		diag("unknown itemtype",
			(char *)0);
			break;
	}
	fflush(file);
}

/* model.c,v
 * Revision 1.6  1998/07/12  13:19:02  hines
 * error when no args to modelunit fixed
 *
 * Revision 1.5  1997/12/01  14:51:39  hines
 * mac port to codewarrior pro2 more complete
 *
 * Revision 1.4  1997/11/28  14:57:52  hines
 * more changes for port to mac of modlunit
 *
 * Revision 1.3  1997/11/24  16:19:12  hines
 * modlunit port to MAC (not complete)
 *
 * Revision 1.2  1997/10/20  14:58:07  hines
 * modlunit file.mod accepted (ie suffix allowed)
 *
 * Revision 1.1.1.1  1994/10/12  17:22:49  hines
 * NEURON 3.0 distribution
 *
 * Revision 1.6  1994/05/18  18:08:13  hines
 * INCLUDE "file"
 * tries originalpath/file ./file MODL_INCLUDEpaths/file
 *
 * Revision 1.5  1993/02/01  15:15:48  hines
 * static functions should be declared before use
 *
 * Revision 1.4  91/02/09  16:39:35  hines
 * special neuron variables checked for correct units.
 * 
 * Revision 1.3  91/01/07  14:17:10  hines
 * in kinunit, wrong itemsubtype.  Fix lint messages
 * 
 * Revision 1.2  90/11/16  07:53:34  hines
 * take out the .c and .var file
 * 
 * Revision 1.1  90/11/13  16:10:21  hines
 * Initial revision
 *  */

