/******************************************************
 *      omlba.c: Lambda Beta to Ada compiler
 ******************************************************/
/***********************************
   (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: omlb.c,v $
 * Revision 2.13  1994/01/10  09:23:48  lotos
 * function main typed
 *
 * Revision 2.12  1993/09/20  10:35:18  lotos
 * corregido help (donde ponia options poen flags)
 * Admite modificar extensiones de los ficheros .at y .lbm.
 *   Por defecto, son ".agf" y ".lbm"
 *
 * Revision 2.11  1993/07/08  16:01:24  lotos
 * no rag call, when transformation option is ON
 * bug fixed: light coroutines parameters
 *
 * Revision 2.10  1993/06/25  13:15:58  lotos
 * fix generation of TSsort%d y TSsorts
 * data structures TSsort%d, TSvar%s y TSgate%s, now static
 *
 * Revision 2.9  1993/06/23  18:50:41  lotos
 * corrected max_var calculation.
 * fix unique names generation
 *
 * Revision 2.8  1993/06/16  14:11:11  lotos
 * colours c_light y c_from become public
 * remove option -i
 * add #line (and option -l to inhibit it)
 * transformation phase becomes independent: no global variables
 * data names pay attention to annotation CALL
 *
 * Revision 2.7  1993/05/07  14:46:10  lotos
 * Para arreglar los errores de indices en las trazas de depuracion:
 *     - Se ha anyadido un array de listas de puertas para simplificar la
 *     impresion de las tablas
 * - el Array de procesos se ha cambiado a char**
 * - la impresion de las tablas se ha modificado. Se han eliminado los
 *   arrays intermedios (gates1, gates2, etc)
 * -pequenya mejora del 'look' del codigo producido.
 *
 * Revision 2.6  1993/02/22  16:13:24  lotos
 * preserve memory
 *
 * Revision 2.5  1993/01/18  18:14:46  lotos
 * revise user interface
 *
 * Revision 2.4  1993/01/12  20:20:46  lotos
 * portability issues
 *
 * Revision 2.3  1993/01/11  18:33:09  lotos
 * overall bug fixing
 * new variable specpar: # of parameters in the lotos spec
 * formal parameters in processes are not compacted any longer
 * reverse -i meaning
 * add -C to remove would-be-generated files
 * generates code for if and use annotations
 * it is valid to split into 1 piece (no effect, really)
 * remove tbil.hh, replaced by conf.h
 *
 * Revision 2.2  1992/11/19  11:41:54  lotos
 * fix file naming
 * close brackets in code generated for guards and predicates
 *
 * Revision 2.1  1992/11/17  17:37:29  lotos
 * variables are compacted per sort
 * split generated code into several files
 * generates *.hh
 * admit option to change basename
 * adapted to use c_cui's
 * modify sort tables
 * code generation is more rational (needs further polishing ...)
 * adapted to new data type conventions
 * adopt new naming convention
 * include var declaration list in light BUTs
 *
 * Revision 1.4  1992/11/17  17:09:30  lotos
 * use colours from OM (shared)
 *
 * Revision 1.3  1992/09/11  16:48:44  lotos
 * bug fixing
 *
 * Revision 1.2  1992/09/02  17:15:10  lotos
 * colour c_pr is included in 'colours.h'. Delted from here.
 *
 * Revision 1.1  1992/09/02  16:58:07  lotos
 * Initial revision
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: omlb.c,v 2.13 1994/01/10 09:23:48 lotos Exp $";
#endif

# include "swbus.h"

PUBLIC TNODE   *lbmroot  = NULL;                             /* AST root */
PUBLIC char    *progname = NULL, *specname = NULL,
               *basename = NULL, *codename = NULL,
               *incname  = NULL, *ldcname  = NULL;
PUBLIC AT      *ATable   = NULL;
PUBLIC IT      *pred_tbl = NULL;
PUBLIC IAT     *sort_tbl = NULL;  /* sort list for experiments and exits */
PUBLIC INTlist *paramtbl = NULL;          /* parameters of all corutines */
PUBLIC int     lastBUTnumber;
PUBLIC int     lastVARnumber;
PUBLIC int     luid;
PUBLIC int     debuging = FALSE;
PUBLIC int     debug_code = FALSE;
PUBLIC int     genline = TRUE;        /* by default, #LINE are generated */
PUBLIC int     split_flag = FALSE;    /* If the output should be splited */
PUBLIC int     split_parts = 0; /* Parts in which output will be splited */
PUBLIC int     split_counter = 0;           /* Counter of splitted parts */
PUBLIC int     split_digits = 0;    /* Number of digits of 'split_parts' */
PUBLIC int     but_counter = 0;          /* Counter of printed corutines */
PUBLIC int     but_per_part = 1;              /* Coroutines in each part */
PUBLIC int     but_redundant = 0;                  /* coroutines % parts */

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

"lbc_id",	c_lbc_id,			IO_int,
"entry",	c_entry,			IO_int,
"lentry",	c_lentry,			IO_int,
"gate_decl_l",	c_gate_decl_list,		IO_IL,
"gate_actl_l",	c_gate_actual_list,		IO_IL,
"var_decl_l",	c_var_decl_list,		IO_IL,
"local_var_d",	c_local_var_decl,		IO_IL,
"decl_gate",	c_decl_gate,			IO_IL,
"decl_var",	c_decl_var,			IO_IL,
"number_exp",	c_number_exp,			IO_int,
"number_off",	c_number_off,			IO_int,
"number_var",	c_number_var,			IO_int,
"pred_number",	c_pred_number,			IO_int,
"product",	c_product,			IO_int,
"sort_code",	c_sort_code,			IO_int,
"sort_list",	c_sort_list,			IO_IL,
"val_exp_used",	c_value_exp_used,		IO_IL,
"num_delays",	c_num_delays,			IO_int,
"num_waits",	c_num_waits,			IO_int,
"this_BUT_ui",	c_this_BUT_ui,			IO_int,
"sort_decl_l",	c_sort_decl_list,		IO_IL,

NULL,		others,				IO_ign
};

PRIVATE void
help ()
{
  (void)fprintf (stderr,
		 "usage: %s -D <name> -o <base> [options] [filename]\n",
		 progname);
  (void)fprintf (stderr, "\t-D <name> data types declarations ");
  (void)fprintf (stderr, "include file name\n");
  (void)fprintf (stderr, "\t-o <base> output to \"base\"\n");
  (void)fprintf (stderr, "\t   flags -o, -D required\n");
  (void)fprintf (stderr, "\toptions:\n");
  (void)fprintf (stderr, "\t\t-C Clean. It removes all files produced.\n");
  (void)fprintf (stderr, "\t\t\t  It takes into account other options.\n");
  (void)fprintf (stderr, "\t\t-T <lbm_extension> Extension for the lbm\n");
  (void)fprintf (stderr, "\t\t-a <at_extension> Extension for the .at\n");
  (void)fprintf (stderr, "\t\t-d debuging\n");
  (void)fprintf (stderr, "\t\t-g produces code for debug\n");
  (void)fprintf (stderr, "\t\t-l do not generate numbered line directives\n");
  (void)fprintf (stderr, "\t\t-s n split the output in 'n' parts.");
  (void)fprintf (stderr, " 0 < n < 1000.\n");
  (void)fprintf (stderr, "\t\t-t only transformation\n");
  (void)fprintf (stderr, "\t\t-h help\n");
}

PUBLIC int
main (argc, argv)
  int argc;
  char* argv[];
{
  char	*atname = NULL, *lname = NULL, *lbmext = NULL, *atext = NULL;
  TNODE	*atroot = NULL;
  FILE	*specfile;
  FILE	*atfile;
  int	i;
  int	transformation = FALSE,
        delete = FALSE;

  progname = argv[0];
  while (argc > 1) {
    if (argv[1][0] == '-') {
      switch (argv[1][1]) {
      case 'C': delete= TRUE; break;
      case 'D':
	if (argc > 2) {
	  ldcname = argv[2];
	  argc--;
	  argv++;
	}
	else {
	  help (); exit (1);
	}
	break;
      case 'T':
	if (argc > 2) {
	  lbmext = argv[2];
	  argc--;
	  argv++;
	}
	else {
	  help (); exit (1);
	}
	break;
      case 'a':
	if (argc > 2) {
	  atext = argv[2];
	  argc--;
	  argv++;
	}
	else {
	  help (); exit (1);
	}
	break;
      case 'd' :
	debuging = TRUE; break;
      case 'g' :
	debug_code = TRUE; break;
      case 'h' :
	help(); exit (0);
      case 'l' :
	genline = FALSE; break;
      case 'o' :
	if (argc > 2) {
	  basename= argv[2];
	  argc--;
	  argv++;
	}
	else {
	  help (); exit (1);
	}
	break;
      case 's' :
	split_flag = TRUE;
	if (argc > 2) {               /* there are more arguments */
	  split_parts = atoi (argv[2]);
	  argc--;
	  argv++;
	  if (split_parts <= 0) {     /* No conversion has token place */
	    (void) fprintf (stderr, "Bad argument in option -s\n");
	    help (); exit (1);
	  }
	}
	else {
	  help (); exit (1);
	}
	if (split_parts == 1) {
	  split_flag = FALSE;
	  split_parts = 0;
	}
	break;
      case 't' :
	transformation = TRUE;
	break;
      default :
	(void)fprintf (stderr, "%s: unknown option %s\n", progname, argv[1]);
	help(); exit (1);
      }
    }
    else {
      specname = argv[1];
    }
    argc--;
    argv++;
  }

  if (basename == NULL) {
    (void)fprintf (stderr, "%s: no basename supplied\n", progname);
    help ();
    exit (1);
  }

  if (split_flag && ((split_parts < 1) || (split_parts > 1000))) {
    (void)fprintf (stderr, "bad range in splitting\n");
    help ();
    exit (1);
  }

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

  if (delete) {
    remove_files ();
    exit (0);
  }

  cast_init (iocolours);

  if (strlen (specname) != 0) {
    if (atext != NULL) {
      atname = emalloc ((strlen (specname) + strlen (atext) + 2)*sizeof(char));
      (void)sprintf (atname, "%s.%s", specname, atext);
    }
    else {
      atname = emalloc ((strlen (specname) + 6)*sizeof(char));
      (void)sprintf (atname, "%s.agf", specname);
    }

    if (lbmext != NULL) {
      lname = emalloc ((strlen (specname) + strlen (lbmext) + 2)*sizeof(char));
      (void)sprintf (lname, "%s.%s", specname, lbmext);
    }
    else {
      lname  = emalloc ((strlen (specname) + 6)*sizeof(char));
      (void)sprintf (lname, "%s.lbm", specname);
    }

    specfile = efopen (lname, "r");
    atfile = efopen (atname, "r");

    lbmroot = restore (specfile);
    grnl = (IAT*) find_attr (c_grnl, lbmroot)->value;
    grnl->incr = 16;
    grnl->class = 1;
    atroot = restore (atfile);
    SymbolTable= (ST*) find_attr (c_ll, atroot)->value;
    SymbolTable->incr = 16;
    SymbolTable->class = 1;
    ATable = (AT*) find_attr (c_at, atroot)->value;
    (void)fclose (specfile);
    (void)fclose (atfile);
  }
  else {
    help ();
    exit (1);
  }

  if (ldcname == NULL) {
    (void)fprintf (stderr, "option -D missing or wrong\n");
    help ();
    exit (1);
  }

  max_val = 0;
  pred_tbl = ITcreate (100, 10, 1);
  sort_tbl = IATcreate (100, 10, 1);
  lastBUTnumber = (int)find_attr (c_pr, lbmroot)->value;
  lastVARnumber = (int)find_attr (c_va, lbmroot)->value;
  luid = (int)find_attr(c_luid, lbmroot)->value;

  lastBUTnumber = do_transform (lbmroot, ATable, SymbolTable,
				lastBUTnumber, grnl);
  find_attr (c_pr, lbmroot)->value = (CLR_TYPE)lastBUTnumber;
  find_attr (c_luid, lbmroot)->value = (CLR_TYPE)luid;

  if (transformation) {
    save_tree (stdout, lbmroot);
    atfile = efopen (atname, "w");
    save_tree (atfile, atroot);
    (void)fclose (atfile);
    exit (0);
  }

  tvs = (tvarsort**) emalloc ((lastBUTnumber)*sizeof (tvarsort*));
  for (i = 0; i < lastBUTnumber; i++)
    tvs[i] = NULL;
  paramtbl = (INTlist*) emalloc ((lastBUTnumber)*sizeof (INTlist));
  for (i = 0; i < lastBUTnumber; i++)
    paramtbl[i] = NULL;

  rag (lbmroot);
  gencode ();
  exit (0);
  return 0;
}
