/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
/* File: main.c */
/* Author: David F. Bacon */
#ifndef lint
static char sccsinfo[] = "@(#)main.c	1.12 3/13/90";
#endif

/*
 1.  COPYRIGHT
 
     Program Name: Hermes
 
     (C) Copyright International Business Machines Corporation 23 January 1990.
     All Rights Reserved.
 
 
 2.  RESEARCH SOFTWARE DISCLAIMER
 
     As experimental, research software, this program is provided free of
     charge on an "as is" basis without warranty of any kind, either expressed
     or implied, including but not limited to implied warranties of
     merchantability and fitness for a particular purpose.  IBM does not
     warrant that the functions contained in this program will meet the user's
     requirements or that the operation of this program will be uninterrupted
     or error-free.  Acceptance and use of this program constitutes the user's
     understanding that he will have no recourse to IBM for any actual or
     consequential damages, including, but not limited to, lost profits or
     savings, arising out of the use or inability to use this program.  Even if
     the user informs IBM of the possibility of such damages, IBM expects the
     user of this program to accept the risk of any harm arising out of the use
     of this program, or the user shall not attempt to use this program for any
     purpose.
 
 
 3.  USER AGREEMENT
 
     BY ACCEPTANCE AND USE OF THIS EXPERIMENTAL PROGRAM THE USER AGREES TO THE
     FOLLOWING:
 
     a.  This program is provided for the user's personal, non-commercial,
         experimental use and the user is granted permission to copy this
         program to the extent reasonably required for such use.
 
     b.  All title, ownership and rights to this program and any copies remain
         with IBM, irrespective of the ownership of the media on which the
         program resides.
 
     c.  The user is permitted to create derivative works to this program.
         However, all copies of the program and its derivative works must
         contain the IBM copyright notice, the EXPERIMENTAL SOFTWARE DISCLAIMER
         and this USER AGREEMENT.
 
     d.  By furnishing this program to the user, IBM does NOT grant either
         directly or by implication, estoppel, or otherwise any license under
         any patents, patent applications, trademarks, copyrights or other
         rights belonging to IBM or to any third party, except as expressly
         provided herein.
 
     e.  The user understands and agrees that this program and any derivative
         works are to be used solely for experimental uses and are not to be
         sold, distributed to a commercial organization, or be commercially
         exploited in any manner.
 
     f.  IBM requests that the user supply to IBM a copy of any changes,
         enhancements, or derivative works which the user may create.  The user
         grants IBM and its subsidiaries an irrevocable, nonexclusive,
         worldwide and royalty-free license to use, execute, reproduce,
         display, perform, prepare derivative works based upon, and distribute,
         (INTERNALLY AND EXTERNALLY) copies of any and all such materials and
         derivative works thereof, and to sublicense others to do any, some, or
         all of the foregoing, (including supporting documentation).
 
         Copies of these modifications should be sent to:

                        SOFTWARE@YKTVMV.BITNET
			Hermes@IBM.Com
*/

#include <stdio.h>
#include <varargs.h>

#include "li.h"
#include "storage.h"

#include "lex-yacc.h"
#include "resolve.h"

#include "errors.cd"

#define YYBUFSIZE 256

char yytext[YYBUFSIZE];


static struct 
{
    char *filename;

} gram;

static JumpBuf fatal_catch;	/* catch for bad errors */
static error_severity max_error; /* maximum error encountered */
static counter error_counts[ERROR_LEVELS];

/* main() function for running front end as a standalone program */
femain(argc, argv)
int argc;
char *argv[];
{
    void make_quopy_datareps();
    void init_storage();
    void init_cherm();
    void init_debug();		/* Li-level debugging stuff */
    void felex_setinput();

    int argindex;
    int retcode;
    FILE *infile;		/* input source for parsing */


    make_quopy_datareps();
    init_storage();
    init_cherm();		/* initialize c-hermes call stuff. */
    init_debug();		/* init the Li debug info stuff */
    
    max_error = No_Error;

    argindex = 1;
    do {
				/* always gets done at least once */
	if (argc > 1) {
	    if ((infile = fopen(argv[argindex], "r")) is NULL) {
		fprintf(stderr, "Couldn't open %s\n", argv[1]);
		exit(1);
	    }
	    gram.filename = argv[argindex];
	} else {
	    gram.filename = NULL;
	    infile = stdin;
	}

	felex_setinput(infile, nil);

	retcode = fe_imain();
	
	if (max_error is Information)
	  max_error = No_Error; /* not really an "error" */
	
	if (max_error isnt No_Error) {
	    if (retcode isnt 0)
	      fprintf(stderr, "Syntax errors detected.\n");
	    else switch (max_error) {
	      case Warning: {
		  fprintf(stderr, "Resolution warnings issued.\n");
		  break;
	      }
	      case Fatal: {
		  fprintf(stderr, "INTERNAL CONSISTENCY PROBLEMS.\n");
		  exit((int) Fatal);
		  /*NOTREACHED*/
		  break;
	      }
	      case Stop_Now: {
		  fprintf(stderr,
			  "I can't take it any more.  I'm leaving.\n");
		  break;
	      }
	      default: {
		  fprintf(stderr, "Resolution errors detected.\n");
		  break;
	      }
	    }
	}

	if (gram.filename)
	  fclose(infile);

	argindex++;
    } while (argindex < argc);

    exit((int) max_error);
}


/* internal main function.  does not make unix references, does not do IO */
int
fe_imain()
{
    void lexinit();

    int retcode;
    counter i;


    max_error = No_Error;
    for (i = 0; i < ERROR_LEVELS; i++)
      error_counts[i] = 0;

    if (SetJmp(fatal_catch) is 0) {
	lexinit();		/* initialize the lexer. */

	retcode = yyparse();	/* do it up!!!!! */

    }
    else {			/* longjmp here on Stop_Now or Fatal */
	retcode = 0;
    }

    tempfree();
    return(retcode);
}


char *
get_srcfile_name()
{
  if (gram.filename is nil)
    return("");
  else
    return(gram.filename);
}

void
set_srcfile_name(name)
char *name;
{
  gram.filename = name;
}

static void
abort_fe()
{
    LongJmp(fatal_catch);
}



void
yyerror(s)
char *s;
{
    fe_error(Stop_Now, errorcode__general_error, "%s", s);
}


/*VARARGS2*/
void
fe_error(va_alist)
va_dcl
{
    void printerror();
    extern globinfo global;

    va_list argv;
    error_severity severity;
    int code;

    va_start(argv);
    severity = va_arg(argv, error_severity);
    code = va_arg(argv, int);
    printerror(severity, code, global.lineno, argv);
}


/*VARARGS2*/
void
fe_error_at(va_alist)
va_dcl
{
    void printerror();

    va_list argv;
    error_severity severity;
    int code;
    int lineno;


    va_start(argv);
    severity = va_arg(argv, error_severity);
    code = va_arg(argv, int);
    lineno = va_arg(argv, int);

    printerror(severity, code, lineno, argv);
}


static void
printerror(severity, code, lineno, argv)
error_severity severity;
int code, lineno;
va_list argv;
{
    void io_printerror();

    char *fmt;
    char *buggy_routine;
    char errbuf[4096];		/* fix later... this is just prayerful. */
    char severitybuf[1024];


    fmt = va_arg(argv, char *);

    switch (severity) {
      case Warning:
	sprintf(severitybuf, "Warning: ");
	break;
      case Information:
	sprintf(severitybuf, "Information: ");
	break;
      case Fatal:
	buggy_routine = fmt;
	fmt = va_arg(argv, char *);
	sprintf(severitybuf, "Fatal (%s): ", buggy_routine);
	break;
      default:
	sprintf(severitybuf, "");
    }
		

    (void) vsprintf(errbuf, fmt, argv);
    va_end(argv);

    io_printerror(gram.filename, code, lineno, severitybuf, errbuf);

    if (severity is Fatal)
      /* fix later: append info to error log file */ ;

    error_counts[(int) severity]++;
    max_error = (error_severity) max((int) max_error, (int) severity);

    if (severity is Fatal or severity is Stop_Now)
      abort_fe();
}


