/******************************************************
 *      om.c: Lambda Beta CAST builder
 ******************************************************/
/***********************************
   (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: om.c,v $
 * Revision 1.9  1993/06/16  14:07:34  lotos
 * ]code cleaning and tabulating
 * spread use of set_first_son
 * fix construction of exit_offer_list
 * complains about unknown options
 * LBM.spe well indented
 * colours c_light y c_from become public
 *
 * Revision 1.8  1993/01/18  18:13:04  lotos
 * revise user interface (command line): make it more robust
 *
 * Revision 1.7  1993/01/12  20:20:38  lotos
 * portability issues
 *
 * Revision 1.6  1992/11/17  17:29:25  lotos
 * adapt names: lsaf -> lsf
 *
 * Revision 1.5  1992/10/20  17:57:46  lotos
 * flag -f to read .lsaf, rather than .lsa
 *
 * Revision 1.4  1992/10/20  17:54:42  lotos
 * add colour c_va: max number of variables in the spec
 *
 * Revision 1.3  1992/09/11  16:48:14  lotos
 * bug fixing
 *
 * Revision 1.2  1992/09/02  17:12:58  lotos
 * colour c_pr is included in 'colours.c'
 * so, deleted from here.
 *
 * Revision 1.1  1992/09/02  16:09:59  lotos
 * Initial revision
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: om.c,v 1.9 1993/06/16 14:07:34 lotos Exp $";
#endif

# include "swbus.h"

PUBLIC char *progname = NULL;
PUBLIC AT   *ATable = NULL;

/* Lambda Beta variables */

PUBLIC IT	*gl;
PUBLIC IAT	*omgrnl;

PRIVATE TNODE	*lbmroot  = NULL;
PRIVATE FILE	*specfile = NULL;
PRIVATE FILE	*alfile   = NULL;

PRIVATE	TIOCOLOURS iocolours [] = {
# include "colours.c"

	"lbm",		c_lbm,				IO_ign,
	"state",	c_state,			IO_ign,
	"BUT_def_list",	c_BUT_def_list,			IO_ign,
	"BUT_list",	c_BUT_list,			IO_ign,
	"BUT_def",	c_BUT_def,			IO_ign,
	"gate_id",	c_gate_id,			IO_int,
	"annot_list",	c_annot_list,			IO_ign,
	"last_annot_l",	c_last_annot_list,		IO_ign,
	"annot",	c_annot,			IO_ign,
	"experiment_l",	c_experiment_list,		IO_ign,
	"gate_list",	c_gate_list,			IO_IL,
	"gate_decl",	c_gate_decl,			IO_IL,
	"var_list",	c_var_list,			IO_IL,
	"gte_var_list",	c_gte_var_list,			IO_ign,
	"val_exp_list",	c_val_exp_list,			IO_ign,
	"value_exp",	c_value_exp,			IO_ign,
	"value_exp2",	c_value_exp2,			IO_ign,
	"var_id",	c_var_id,			IO_int,
	"var_id_node",	c_var_id_node,			IO_ign,
	"BUT_number",	c_BUT_number,			IO_int,
	"predicate",	c_predicate,			IO_ign,
	"exit_off_l",	c_exit_offer_list,		IO_ign,
	"ident_eq_l",	c_ident_equation_list,		IO_ign,
	"ident_eq",	c_ident_equation,		IO_ign,
	"var_dmn_l",	c_var_domain_list,		IO_ign,
	"gate_dmn_l",	c_gate_domain_list,		IO_ign,
	"gate_domain",	c_gate_domain,			IO_ign,
	"is_exp",	c_is_experiment,		IO_ign,

		/* Auxiliar to differentiate the parallels */
	"par_type",	c_par_type,			IO_ign,

	NULL,		others,				IO_ign
};

PRIVATE void
help ()
{
  (void) fprintf (stderr, "usage: %s [options] [filename]\n", progname);
  (void) fprintf (stderr, "\toptions:\n");
  (void) fprintf (stderr, "\t\t-d debugging. The CAST is dumped to stderr\n");
  (void) fprintf (stderr, "\t\t-f read from .lsf rather than .lsa\n");
  (void) fprintf (stderr, "\t\t-s statistics. Prints number of nodes\n");
  (void) fprintf (stderr, "\t\t-h help\n");
}

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

  if ((fp= fopen (filename, mode)) == NULL) {
    (void) fprintf (stderr, "%s: cannot open file %s mode %s\n",
		    progname, filename, mode);
    exit (1);
  }
  return fp;
}

PRIVATE char*
emalloc (i)
  int i;
{
  char *p;

  p = malloc ((unsigned) i);
  if (p == NULL) {
    (void)fprintf (stderr, "%s: Out of memory\n", progname);
    exit (1);
  }
  return p;
}

PRIVATE int
number_nodes (r)
  TNODE *r;
{
  int i=0;

  for (; r != NULL; r= r->brothers) {
    i++;			     /* counts the brothers */
    if (r->sons)
      i += number_nodes (r->sons);     /* and adds the sons */
  }
  return i;
}

/* KJT 20/01/23: added "int" type */
int main (argc, argv)
  int argc;
  char* argv[];
{
  char	 *specname = NULL, *alname = NULL, *lname = NULL;
  TNODE  *astroot = NULL;		/* AST root creation*/
  TNODE  *alroot = NULL;
  int    debugging = FALSE, statistics = FALSE, lsf = FALSE;

  progname = argv[0];
  while (argc > 1) {
    if (argv[1][0] == '-')
      switch (argv[1][1]) {
      case 'd' : debugging = TRUE; break;
      case 'f' : lsf = TRUE; break;
      case 's' : statistics = TRUE; break;
      case 'h' : help(); exit (0);
      default  :
	(void)fprintf (stderr, "%s: unknown option %s\n", progname, argv[1]);
	help(); exit (1);
      }
    else {
      if (specname == NULL)        /* Still not initialized */
	specname = argv[1];
      else {
	(void)fprintf (stderr, "%s: only one file at a time\n");
	help ();
	exit (1);
      }
    }
    argc--;
    argv++;
  }

  if (specname == NULL) {
    help (); exit (1);
  }

  gl = ITcreate (4, 2, 1);
  omgrnl = IATcreate (100, 10, 1);

  cast_init (iocolours);

  if (strlen (specname) != 0) {
      alname = emalloc ((strlen (specname) + 6)*sizeof(char));
      lname  = emalloc ((strlen (specname) + 6)*sizeof(char));

      if (lsf) {
	(void)sprintf (lname, "%s.lsf", specname);
	(void)sprintf (alname, "%s.agf", specname);
      }
      else {
	(void)sprintf (lname, "%s.ls", specname);
	(void)sprintf (alname, "%s.as", specname);
      }

      specfile = efopen (lname, "r");
      alfile = efopen (alname, "r");

      astroot = restore (specfile);
      grnl = (IAT*) find_attr (c_grnl, astroot)->value;
      grnl->class = 1;
      alroot = restore (alfile);
      SymbolTable= (ST*) find_attr (c_ll, alroot)->value;
      ATable = (AT*) find_attr (c_at, alroot)->value;
  }
  else {
    help ();
    exit (1);
  }

  rag (astroot);

  lbmroot = (TNODE*)find_attr (c_lbm, astroot)->value;

  set_attr (c_name, lbmroot, find_attr (c_name, astroot)->value);
  set_attr (c_grnl, lbmroot, (CLR_TYPE) omgrnl);
  set_attr (c_luid, lbmroot, find_attr (c_luid, astroot)->value);
  set_attr (c_pr,   lbmroot, find_attr (c_pr, astroot)->value);
  set_attr (c_va,   lbmroot, find_attr (c_va, astroot)->value);

  name2clr("L")      ->put=NULL;
  name2clr("sidref") ->put=NULL;

  if (statistics) {
    (void)printf ("There are %d nodes in the AST\n", number_nodes (astroot));
    (void)printf ("There are %d nodes in the LBM\n", number_nodes (lbmroot));
  }
  else
    if (debugging)
      save_tree (stderr, astroot);
    else
      save_tree (stdout, lbmroot);

  exit (0);
  return 0;
}
