// Copyright, 2001-2003, Astra Network Inc.  All Rights Reserved

// This source code has been published by Astra Network Inc. However, any
// use, reproduction, modification, distribution or transfer of this
// software, or any software which includes or is based upon any of this
// code, is only permitted if expressly authorized by a written license
// agreement from Astra. Contact your Astra representative directly for
// more information.

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "defines.h"
#include "version.h"

system_t *sys;

bool quiet = FALSE;
unsigned int verbosity = 0;
static short int yyerrors = 0;

extern int yyleng;
extern char yylinebuf[500];
extern FILE *yyin;

int
main (int argc, char *argv[])
{
  FILE *scrfile = stdin;
  FILE *asmfile = stdout;
  int c;

  while ((c = getopt (argc, argv, "f:o:I:q")) != -1)
    {
      switch (c)
	{
	case 'f':
	  scrfile = fopen (optarg, "r");
	  if (!scrfile)
	    {
	      fprintf (stderr, "Unable to open script \"%s\"!", optarg);
	      exit (EXIT_FAILURE);
	    }
	  yyin = scrfile;
	  break;

	case 'o':
	  asmfile = fopen (optarg, "w");
	  if (!asmfile)
	    {
	      fprintf (stderr, "Unable to open file \"%s\" for write!",
		       optarg);
	      exit (EXIT_FAILURE);
	    }
	  break;

	case 'I':
	  add_include_dir (optarg);
	  break;

	case 'q':
	  quiet = TRUE;
	  break;

	case 'v':
	  verbosity++;
	  break;

	case '?':
	  fprintf (stderr,
		   "%s [-f script] [-o outputfile] [-q | -v] [-I includedir]\n",
		   argv[0]);
	  fprintf (stderr, "Options:\n");
	  fprintf (stderr,
		   " -f    Script file to parse, stdin if unspecified\n");
	  fprintf (stderr,
		   " -o    PCode assembler file to output, stdout if unspecified\n");
	  fprintf (stderr, " -q    Quiet mode\n");
	  fprintf (stderr, " -v    Add extra verbosity\n");
	  fprintf (stderr, " -I    Directory to search for included files\n");
	  fprintf (stderr,
		   "\nInclude file directories may also be placed, colon-seperated, in the\n");
	  fprintf (stderr, "OLCINCLUDE environment variable.\n");
	  exit (EXIT_FAILURE);
	}
    }

  add_include_dir (getenv ("OLCINCLUDE"));
  add_include_dir (".");	// Always search current directory.
  add_include_dir ("/opt/hafta/include");

  if (quiet == 0)
    {
#ifdef BETA
      fprintf (stderr,
	       "HAFTA Overlord Compiler v%d.%02d %s (Build %s)\n",
	       VERSION / 100, VERSION % 100, BETA, BUILD);
      fprintf (stderr, "This is a beta version. It is not for use in"
	       " production evironments.\n");
#else
      fprintf (stderr,
	       "HAFTA Overlord Compiler v%d.%02d (Build: %s)\n",
	       VERSION / 100, VERSION % 100, BUILD);
#endif /* #ifdef BETA */
      fprintf (stderr,
	       "Copyright 2002-2003, Astra Network Inc., "
	       "All rights reserved.\n");
    }

  yyparse ();

  if (yyerrors == 0)
    generate_system (asmfile, sys);

  return (0);
}

void
yyfatalerror (char *msg, ...)
{
  va_list arg;

  fprintf (stderr, "%d: ", yylineno);
  va_start (arg, msg);
  (void) vfprintf (stderr, msg, arg);
  va_end (arg);
  fprintf (stderr, ":\n%s\n%*s\n", yylinebuf, yytokenpos - yyleng, "^");

  fprintf (stderr, "Fatal error, aborting compile\n");
  exit (EXIT_FAILURE);
}

void
yyerror (char *msg, ...)
{
  va_list arg;

  fprintf (stderr, "%d: ", yylineno);
  va_start (arg, msg);
  (void) vfprintf (stderr, msg, arg);
  va_end (arg);
  fprintf (stderr, ":\n%s\n%*s\n", yylinebuf, yytokenpos - yyleng, "^");

  yyerrors++;
  if (yyerrors >= 10)
    {
      fprintf (stderr, "Too many errors, aborting compile\n");
      exit (EXIT_FAILURE);
    }
}

void
yywarning (char *msg, ...)
{
  va_list arg;

  fprintf (stderr, "%d: ", yylineno);
  va_start (arg, msg);
  (void) vfprintf (stderr, msg, arg);
  va_end (arg);
  fprintf (stderr, ":\n%s\n%*s\n", yylinebuf, yytokenpos - yyleng, "^");
}
