#include "c.h"

static char rcsid[] = "$Name: v4_0 $($Id: main.nw,v 4.15 1997/06/03 01:02:12 drh Exp $)";

static void typestab(Symbol, void *);

Interface *IR = NULL;

int Aflag;              /* >= 0 if -A specified */
int Pflag;              /* != 0 if -P specified */
int glevel;             /* == [0-9] if -g[0-9] specified */
int xref;               /* != 0 for cross-reference data */
Symbol YYnull;          /* _YYnull  symbol if -n or -nvalidate specified */
Symbol YYcheck;         /* _YYcheck symbol if -nvalidate,check specified */

int main(int argc, char *argv[]) {
        int i, j;
	for (i = argc - 1; i > 0; i--)
	        if (strncmp(argv[i], "-target=", 8) == 0)
	                break;
	if (i > 0) {
	        char *s = strchr(argv[i], '\\');
	        if (s != NULL)
	                *s = '/';
	        for (j = 0; bindings[j].name && bindings[j].ir; j++)
	                if (strcmp(&argv[i][8], bindings[j].name) == 0) {
	                        IR = bindings[j].ir;
	                        break;
	                }
	        if (s != NULL)
	                *s = '\\';
	}
	if (!IR) {
	        fprint(stderr, "%s: unknown target", argv[0]);
	        if (i > 0)
	                fprint(stderr, " `%s'", &argv[i][8]);
	        fprint(stderr, "; must specify one of\n");
	        for (i = 0; bindings[i].name; i++)
	                fprint(stderr, "\t-target=%s\n", bindings[i].name);
	        exit(EXIT_FAILURE);
	}
	init(argc, argv);
	t = gettok();
	(*IR->progbeg)(argc, argv);
	if (glevel && IR->stabinit)
	        (*IR->stabinit)(firstfile, argc, argv);
	program();
	if (events.end)
	        apply(events.end, NULL, NULL);
	memset(&events, 0, sizeof events);
	if (glevel || xref) {
	        Symbol symroot = NULL;
	        Coordinate src;
	        foreach(types,       GLOBAL, typestab, &symroot);
	        foreach(identifiers, GLOBAL, typestab, &symroot);
	        src.file = firstfile;
	        src.x = 0;
	        src.y = lineno;
	        if ((glevel > 2 || xref) && IR->stabend)
	                (*IR->stabend)(&src, symroot,
	                        ltov(&loci,    PERM),
	                        ltov(&symbols, PERM), NULL);
	        else if (IR->stabend)
	                (*IR->stabend)(&src, NULL, NULL, NULL, NULL);
	}
	finalize();
	(*IR->progend)();
	deallocate(PERM);
        return errcnt > 0;
}
/* main_init - process program arguments */
void main_init(int argc, char *argv[]) {
        char *infile = NULL, *outfile = NULL;
        int i;
        static int inited;

        if (inited)
                return;
        inited = 1;
        type_init(argc, argv);
        for (i = 1; i < argc; i++)
                if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
		        glevel = 2;
		else if (strcmp(argv[i], "-x") == 0)
		        xref++;
		else if (strcmp(argv[i], "-A") == 0) {
		        ++Aflag;
		} else if (strcmp(argv[i], "-P") == 0)
		        Pflag++;
		else if (strcmp(argv[i], "-w") == 0)
		        wflag++;
		else if (strcmp(argv[i], "-n") == 0) {
		        if (!YYnull) {
		                YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM);
		                YYnull->type = func(voidptype, NULL, 1);
		                YYnull->sclass = EXTERN;
		                (*IR->defsymbol)(YYnull);
		        }
		} else if (strncmp(argv[i], "-n", 2) == 0) {    /* -nvalid[,check] */
		        char *p = strchr(argv[i], ',');
		        if (p) {
		                YYcheck = install(string(p+1), &globals, GLOBAL, PERM);
		                YYcheck->type = func(voidptype, NULL, 1);
		                YYcheck->sclass = EXTERN;
		                (*IR->defsymbol)(YYcheck);
		                p = stringn(argv[i]+2, p - (argv[i]+2));
		        } else
		                p = string(argv[i]+2);
		        YYnull = install(p, &globals, GLOBAL, PERM);
		        YYnull->type = func(voidptype, NULL, 1);
		        YYnull->sclass = EXTERN;
		        (*IR->defsymbol)(YYnull);
		} else if (strcmp(argv[i], "-v") == 0)
		        fprint(stderr, "%s %s\n", argv[0], rcsid);
		else if (strncmp(argv[i], "-s", 2) == 0)
		        density = strtod(&argv[i][2], NULL);
		else if (strncmp(argv[i], "-errout=", 8) == 0) {
		        FILE *f = fopen(argv[i]+8, "w");
		        if (f == NULL) {
		                fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8);
		                exit(EXIT_FAILURE);
		        }
		        fclose(f);
		        f = freopen(argv[i]+8, "w", stderr);
		        assert(f);
		} else if (strncmp(argv[i], "-e", 2) == 0) {
		        int x;
		        if ((x = strtol(&argv[i][2], NULL, 0)) > 0)
		                errlimit = x;
		} else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
		        if (infile == NULL)
		                infile = argv[i];
		        else if (outfile == NULL)
		                outfile = argv[i];
		}

        if (infile != NULL && strcmp(infile, "-") != 0
        && freopen(infile, "r", stdin) == NULL) {
                fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
                exit(EXIT_FAILURE);
        }
        if (outfile != NULL && strcmp(outfile, "-") != 0
        && freopen(outfile, "w", stdout) == NULL) {
                fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile);
                exit(EXIT_FAILURE);
        }
}
/* typestab - emit stab entries for p */
static void typestab(Symbol p, void *cl) {
        if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF)
                *(Symbol *)cl = p;
        if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
                (*IR->stabtype)(p);
}
