#include "c.h"

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

#define LCCVERS		"4.0"

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: ANSI C Compiler version %s (%s) Fraser & Hanson\n", argv[0], LCCVERS, __DATE__);
    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);
}
