/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: lfe.c,v $
 * Revision 2.14  1993/06/15  12:49:18  lotos
 * fix grammar w.r.t. mandatory equations after ofsort ...
 *
 * Revision 2.13  1993/01/18  18:04:54  lotos
 * distribution issues
 *
 * Revision 2.12  1993/01/12  20:18:42  lotos
 * portability issues
 *
 * Revision 2.11  1993/01/12  14:10:06  lotos
 * use conf.h for portability
 * remove tbil.hh
 *
 * Revision 2.10  1992/11/19  18:27:18  lotos
 * bug fix
 *
 * Revision 2.9  1992/09/08  13:15:29  lotos
 * revise help information
 *
 * Revision 2.8  1992/09/02  14:47:27  lotos
 * keep annotations as independent (and sorted!) nodes in AST
 *
 * Revision 2.7  92/02/21  17:10:19  lotos
 * flags -t -w -n
 *
 * Revision 2.6  92/01/14  15:22:41  lotos
 * distribution issues
 *
 * Revision 2.5  92/01/13  16:23:54  lotos
 * make SymbloTable case insensitive
 *
 * Revision 2.4  92/01/10  14:59:53  lotos
 * add colour name to cast root, holding fine name
 *
 * Revision 2.3  91/04/12  11:32:03  lotos
 * make sprintf compatible for System V
 *
 * Revision 2.2  91/02/28  17:17:46  lotos
 * rule 'premiss ::= _value_expression' removed
 * consequences: colours c_bool, c_rectrue, c_true removed
 * unique identifier per class generated
 *
 *
 * Revision 2.1  90/10/30  14:12:31  lotos
 * compressed AST
 * use of hardwired colours
 * compressed value expressions
 * annotations to colours
 *
 * Revision 1.5  90/06/04  15:23:47  lotos
 * if then else fi, removed
 * final match, removed
 * last ';' of eqns, made optional
 * executable comments are always lists
 * minor changes to shut lint up
 * adclr -> set_attr
 *
 * Revision 1.4  90/03/16  17:39:04  lotos
 * cosmetics
 *
 * Revision 1.3  90/01/29  16:20:43  lotos
 * delete sccs identifiers
 *
 * Revision 1.2  90/01/29  13:06:37  lotos
 * fixing license details
 *
 * Revision 1.1  90/01/24  14:38:01  lotos
 * Initial revision
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: lfe.c,v 2.14 1993/06/15 12:49:18 lotos Exp $";
#endif

# include "swbus.h"

/* KJT 20/01/23: added function prototypes */
int unlink(const char *pathname);

PUBLIC char	sfile[BUFSIZ];
PUBLIC char	lfile[BUFSIZ];
PUBLIC char	cfile[BUFSIZ];

PUBLIC int nfname;
PRIVATE char filename[BUFSIZ];

PUBLIC FILE*	sfp;
PUBLIC FILE*	lfp;
PUBLIC FILE*	cfp;

PUBLIC HT	hidtbl;

PUBLIC int     flagc= FALSE;
PUBLIC int     flage= FALSE;
PUBLIC int     flagl= FALSE;
PUBLIC int     flagd= 0;
PUBLIC int     flagt= FALSE;
PUBLIC int     flagw= FALSE;
PUBLIC int     flagn= FALSE;

int	errorcount= 0;
PRIVATE void    makenames ();
PRIVATE void    help ();
PRIVATE FILE*   efopen();

PRIVATE TIOCOLOURS iocolours [] = {
# include "colours.c"
	"tree",     c_tree,     NULL, save_tree, NULL, NULL,
	"troo",     c_troo,     NULL, save_tree, NULL, NULL,
	"ckey",     c_ckey,     IO_str,
	"cval",     c_cval,     IO_str,
	"vclrs",    c_vclrs,    IO_IL,
	"preserve", c_preserve, IO_int,

	"keylist",  c_keylist,  IO_IL,
	"vallist",  c_vallist,  IO_SL,
	OTHERS
	};

PRIVATE void
makenames ()
{
  char *p1;

  nfname= -1;
  if (strlen (sfile) == 0)
    (void) strcpy (filename, "lfe");
  else {
    (void) strcpy (filename, sfile);
    p1 = strrchr (sfile, '/');
    if (p1)
      (void) strcpy (filename, ++p1);
    p1= strrchr (filename, '.');
    if (p1) {
      if (strcmp (p1, ".lot") == 0)
	*p1 = '\0';
    }
    else
      (void) strcat (sfile, ".lot");
    nfname= STHadd (sfile, SymbolTable, hidtbl, FALSE);
  }
  (void) strcpy (cfile, filename);
  (void) strcat (cfile, ".com");
  (void) strcpy (lfile, filename);
  (void) strcat (lfile, ".lis");
}

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

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

PRIVATE void
help    ()
{
#define ph(msg) (void) fprintf (stderr, msg);
  ph ("usage: lfe [-celtwn] [source[.lot]]\n");
  ph ("       lfe    source : lotos spec. from 'source.lot'\n");
  ph ("       lfe           : lotos spec. from the input\n");
  ph ("           -e        : warns on LOTOS extensions\n");
  ph ("           -w        : report on case dissonances\n");
  ph ("           -t        : lower case identifiers\n");
  ph ("           -l        : listing to 'source.lis'\n");
  ph ("           -c        : comments to 'source.com'\n");
  ph ("           -n        : forget source line numbers\n");
  ph ("           -d        : debugging\n");
}

PUBLIC int
main (argc, argv)
     int argc;
     char* argv[];
{
  int i, c;
  TNODE* tree;
  TNODE *this, *next, *new,
	*thefather, *leftbrother, *rightbrother;

  while (argc > 1) {
    if (argv[1][0] == '-') {
      i= 0;
      while ((c= argv[1][++i]) != '\0')
	switch (c) {
	case 'c':
	  flagc= TRUE;
	  break;
	case 'e':
	  flage= TRUE;
	  break;
	case 'l':
	  flagl= TRUE;
	  break;
	case 'd':
	  flagd++;
	  break;
	case 't':
	  flagt= TRUE;
	  break;
	case 'w':
	  flagw= TRUE;
	  break;
	case 'n':
	  flagn= TRUE;
	  break;
	default:
	  help ();
	  exit (1);
	}
    }
    else
      (void) strcpy (sfile, argv[1]);
    argc--;
    argv++;
  }
  cast_init(iocolours);
  stinit(5000);
  SymbolTable= STcreate(100, 0, 1, flagt);
  hidtbl= STHinit (SymbolTable, 5119);
  grnl= IATcreate (100, 10, 1);

  makenames ();
  if (strlen (sfile) == 0)
    sfp = stdin;
  else sfp = efopen (sfile, "r");
  if (flagl)
    lfp = efopen (lfile, "w");
  if (flagc || !flage)
    cfp = efopen (cfile,"w");

  tree= bast();

  if ((flagc || !flage) && (ftell (cfp) == 0)) {
    (void) fclose (cfp);
    if (unlink (cfile) == -1)
      (void) fprintf (stderr, "cannot unlink %s\n", cfile);
  }
  else
    (void) fclose(cfp);
  if (errorcount > 0 || tree == NULL) {
    if (flagl) {
      if (errorcount == 1)
	(void) fprintf (lfp, "1 error found\n");
      else
	(void) fprintf (lfp, "%d errors found\n", errorcount);
    }
    if (errorcount == 1)
      (void) fprintf (stderr, "1 error found\n");
    else
      (void) fprintf (stderr, "%d errors found\n", errorcount);
    if (flagl)
      (void) fclose(lfp);
    exit (1);
  }

  if (errorcount == 0 && tree != NULL) {
    if (flagc || !flage) {
      comm= malloc((unsigned)(strlen(cfile)+5));
      (void) sprintf (comm, "%d %s", BCOMM, cfile);
      set_attr (c_comm, tree, (CLR_TYPE)comm);
    }
    set_attr(c_name, tree, (CLR_TYPE) filename);
    set_attr(c_ll, tree, (CLR_TYPE) SymbolTable);
    set_attr(c_grnl, tree, (CLR_TYPE) grnl);
    rag(tree);
    if (ragerrors != 0) {
      (void) fprintf (stderr, "***  lfe: errors detected\n");
      if (flagd > 0)
	save_tree (stdout, tree);
      exit (1);
    }

    for (this= tree; this != NULL; this= next) {
      if (find_attr (c_tree, this)) {
	new= (TNODE*)find_attr (c_tree, this)->value;
	thefather= gt_ft (this);
	leftbrother= gt_lb (this);
	rightbrother= gt_rb (this);

	this->sons= NULL;
	next= succ (this, PREORDER);

	if (new) {
	  if (leftbrother)
	    leftbrother->brothers= new;
	  else
	    thefather->sons= new;
	  new->father= thefather;
	  new->brothers= rightbrother;
	}
	else {
	  if (leftbrother)
	    leftbrother->brothers= rightbrother;
	  else
	    thefather->sons= rightbrother;
	}
      }
      else
	next= succ (this, PREORDER);
    }

    for (this= tree; this != NULL; this= succ (this, PREORDER)) {
      if (this->type == teqn_list) {
	if (this->sons == NULL) {
	  report (this->father, c_line);
	  (void) fprintf (stderr, "syntax error\n");
	}
      }
    }

    for (this= tree; this != NULL; this= succ (this, PREORDER))
      visit (this);

    if (ragerrors != 0) {
      (void) fprintf (stderr, "***  lfe: errors detected\n");
      if (flagd > 0)
	save_tree (stdout, tree);
      exit (1);
    }
  }
  if (flagl)
    (void) fclose(lfp);
  if (flagd < 1) {
    name2clr("tree")	->put= NULL;
    name2clr("troo")	->put= NULL;
    name2clr("ckey")	->put= NULL;
    name2clr("cval")	->put= NULL;
    name2clr("vclrs")	->put= NULL;
    name2clr("preserve")	->put= NULL;
    name2clr("keylist")	->put= NULL;
    name2clr("vallist")	->put= NULL;
  }
  if (flagn)
    name2clr("N")	->put= NULL;
  save_tree(stdout, tree);
  exit (0);
  return 0;
}
