/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: lag.c,v $
 * Revision 2.7  1995/01/12  14:52:18  eps
 * force numbers for %tokens
 *
 * Revision 2.6  1993/01/12  16:36:18  eps
 * portability issues
 *
 * Revision 2.5  1992/11/17  11:49:11  eps
 * fix definition of *alloc for PC portability
 * fix declaration of static functions for portability
 *
 * Revision 2.4  1992/01/14  15:44:31  eps
 * distribution issues
 *
 * Revision 2.3  92/01/14  15:27:51  eps
 * adapt to case independent cast
 *
 * Revision 2.2  91/04/10  10:05:15  eps
 * adapted for HP
 *
 * Revision 2.1  90/10/30  08:41:17  eps
 * lag + rag -> lag
 * allowed productions are simplified (i.e. reduced)
 *
 **********************************************/

#ifndef lint
static char rcsid[]= "$Id: lag.c,v 2.7 1995/01/12 14:52:18 eps Exp $";
#endif

# include <ctype.h>
# include <string.h>
# include "swbus.h"

int      flagd= FALSE;
int      flagl= FALSE;
int      flagn= TRUE;
int      flaga= FALSE;
int      flagb= FALSE;
char*    progname= "input";
int	 errorcount= 0;
int	 nrules= 0;

/* KJT 18/05/02: removed non-constant initialisations */

FILE*    sfp /* = stdin */;
FILE*    lfp /* = stdout */;
FILE*    fast /* = stdout */;
FILE*    fgrm /* = stdout */;
FILE*    fndl /* = stdout */;
FILE*    fgrc /* = stdout */;

PRIVATE char    sfile[BUFSIZ];          /* store input filename */
PRIVATE char    afile[BUFSIZ];          /* store ast filename */
PRIVATE char    lfile[BUFSIZ];          /* output listing filename */
PRIVATE char    nfile[BUFSIZ];          /* store ndl filename */
PRIVATE char    gfile[BUFSIZ];          /* store grc.h filename */

char	filename[BUFSIZ];
int	nfname;
ST*	blocktbl;
char*	block;

HT	hidtbl;
IT*	term_lis;
IT*	ndl;
ST*	grcl;

PRIVATE TIOCOLOURS iocolours [] = {
	"L",        c_lexv,     IO_int,
	"N",        c_line,     IO_I2,
	"LL",       c_ll,       IO_ST,
	"GL",       c_grnl,     IO_IAT,
	"nrule",    c_nrule,    IO_int,
	"type",     c_type,     IO_int,
	"nterms",   c_nterms,   IO_int,
	"nsec",     c_nsec,     IO_int,
	"intid",    c_intid,    IO_str,
	"tndx",     c_tndx,     IO_int,
	"ndid",     c_ndid,     IO_int,
	"ngrc",     c_ngrc,     IO_int,
	"idgrc",    c_idgrc,    IO_int,
	"rlhs",     c_rlhs,     IO_int,
	"start",    c_start,    IO_int,
	"block",    c_block,    IO_str,
	NULL,       others,     IO_ign
	};


/*-------------------------------------------------------------------*/

PRIVATE void    makenames ();
PRIVATE void    help	();

/*-------------------------------------------------------------------*/
PRIVATE void
makenames ()
{
	char *p1;

  nfname= -1;

  if (strlen (sfile) == 0)
       (void)strcpy (filename, progname);
  else{
       (void)strcpy (filename, sfile);
       p1 = strrchr (sfile, '/');
       if (p1) (void)strcpy (filename, ++p1);
       p1 = strrchr (filename, '.');
       if (p1)
       {
	    if (strcmp (p1, ".spe") == 0) *p1 = '\0';
       }
       else (void)strcat (sfile, ".spe");
  }
  (void)strcpy(afile, filename);
  (void)strcat(afile, ".ast");
  (void)strcpy(lfile, filename);
  (void)strcat(lfile, ".lis");
  (void)strcpy(nfile, filename);
  (void)strcat(nfile, ".ndl");
  (void)strcpy(gfile, filename);
  (void)strcat(gfile, ".grc");
}

PRIVATE	FILE*
efopen(file, mode, tool)
     char* file;
     char* mode;
     char* tool;
{
  FILE* fp;
  FILE* fopen();

  if ((fp= fopen (file, mode)) == NULL) {
    (void) fprintf (stderr,
		    "%s: cannot open file %s mode %s\n",
		    tool, file, mode);
    exit (1);
  }
  return fp;
} /* end of efopen */

PRIVATE void
help ()
{
  (void) fprintf (stderr, "usage: %s [-daln] [source[.spe]]\n", progname);
  (void) fprintf (stderr, "  -d : produce debugging information\n");
  (void) fprintf (stderr, "  -a : produce input grammar ast file\n");
  (void) fprintf (stderr, "  -l : produce output listing file\n");
  (void) fprintf (stderr, "  -n : remove grammar nodes file\n");
  fputs("stdout      output yacc grammar file\n", stderr);
  fputs("source.ast  input grammar ast file\n", stderr);
  fputs("source.lis  listing and debugging messages file\n", stderr);
  fputs("source.ndl  grammar nodes file\n", stderr);

} /* end of help */


PUBLIC int
main    (argc, argv)
	int     argc;
	char*   argv[];
{
  TNODE*	tree;
  /* KJT 22/01/23: added "int" type */
  register int i;
  register int c;

    while (argc > 1)
    {
	if (argv[1][0] == '-')
	{
	  i = 0;
	  while ((c = argv[1][++i]) != '\0')
	    switch (c)
	    {
	      case 'l' : flagl = TRUE; break;
	      case 'n' : flagn = FALSE; break;
	      case 'a' : flaga = TRUE; flagb= FALSE; break;
	      case 'b' : flagb = TRUE; flaga= FALSE; break;
	      case 'd' : flagd = TRUE; break;
	      default :  help (); exit (1);
	    }
	}
	else (void) strcpy (sfile, argv[1]);
	argc--;
	argv++;
    }
    cast_init(iocolours);
    stinit(ST_SIZE);
    blocktbl= STcreate (BUFSIZ, 2, 0, 1);
    SymbolTable= STcreate (20, 4, 1, 1);
    hidtbl= STHinit (SymbolTable, 5119);
    grnl= IATcreate (100, 10, 1);
    term_lis= ITcreate(20, 4, 1);
    ndl= ITcreate (20, 4, 2);
    grcl= STcreate (20, 4, 0, 1);

    makenames ();
    if (strlen (sfile) == 0)
	 sfp= stdin;
    else sfp= efopen (sfile, "r", argv[0]);
    fgrm= stdout;
    if (flagl)
	 lfp= efopen (lfile, "w", argv[0]);
    else lfp= efopen ("/dev/null", "w", argv[0]);
    if (flaga || flagb)
	 fast= efopen (afile, "w", argv[0]);
    if (flagn){
	 fndl= efopen (nfile, "w", argv[0]);
	 fgrc= efopen(gfile, "w", argv[0]);
    }

    tree= bast();
    if (tree == NULL) {
     (void) fprintf (stderr, "near   end:\tIt cannot  build a complete ast\n");
     exit (1);
    }
    set_attr(c_ll, tree, (CLR_TYPE) SymbolTable);
    set_attr(c_grnl, tree, (CLR_TYPE) grnl);
    if (flaga)
    {
	save_tree(fast, tree);
	(void)fclose(fast);
    }
    if (errorcount != 0){
     if (errorcount == 1)
	  (void) fprintf (stderr, "near   end:\t1 error found\n");
     else (void) fprintf (stderr, "near   end:\t%d errors found\n", errorcount);
     if (flagl) (void) fclose(lfp);
     exit (2);
    }
    rag(tree);
    visit(tree);
    if (flagb)
    {
	save_tree(fast, tree);
	(void)fclose(fast);
    }
    if (flagn)
    {
       fprintf(fndl, "# define tNULL -1\n");
       for (i= 0; i < term_lis->size; i++)
	  fprintf(fndl, "# define %s %d\n",
		  SymbolTable->data[term_lis->data[i]],
		  260 + i);
       for (i= 0; i < ndl->size; i++)
	  fprintf(fndl, "# define t%s %d\n",
		  SymbolTable->data[ndl->data[i]],
		  -(2 + i));
       (void)fclose(fndl);
       for (i= 0; i < grcl->size; i++)
	  fprintf(fgrc, "%s", grcl->data[i]);
       (void)fclose(fgrc);
    }
    exit (0);
}
