/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: idle.c,v $
 * Revision 1.17  1993/06/10  14:00:13  lotos
 * new annotation CALL
 *
 * Revision 1.16  1993/05/28  10:41:43  lotos
 * opcion -c tiene niveles
 *
 * Revision 1.15  1993/03/29  18:09:10  lotos
 * add constructor verification/s
 *
 * Revision 1.14  1993/03/24  17:51:24  lotos
 * annotations lcd, and ldcinit go into ATable
 * unused attribute handling functions (now in glad)
 *
 * Revision 1.13  1993/01/18  18:12:15  lotos
 * distribution issues
 *
 * Revision 1.12  1993/01/12  20:20:21  lotos
 * portability issues
 *
 * Revision 1.11  1993/01/12  14:22:09  lotos
 * use conf.h for portability
 *
 * Revision 1.10  1992/10/14  17:42:52  lotos
 * forget about ophuscation
 *
 * Revision 1.9  1992/09/02  15:44:44  lotos
 * new option to remove externa annotations
 * new option to print and label the equations
 * new debugging options: save modified CAST
 * overall debugging and improvements
 *
 * Revision 1.8  92/05/06  18:49:25  lotos
 * avoid lint complaints w.r.t. exit()
 * 
 * Revision 1.7  92/01/14  15:25:07  lotos
 * distribution issues
 * 
 * Revision 1.6  92/01/13  19:24:23  lotos
 * adaptec to ophuscate
 * 
 * Revision 1.5  91/11/20  13:08:43  lotos
 * ATable is read from a separate file
 * 
 * Revision 1.4  91/05/03  19:50:48  lotos
 * system V adaptation
 * 
 * Revision 1.3  91/04/19  21:15:31  lotos
 * exit code is 0 if no error
 * 
 * Revision 1.2  91/04/11  18:31:13  lotos
 * cosmetics
 * 
 * Revision 1.1  91/02/06  20:12:49  lotos
 * Initial revision
 * 
 ***********************************/

#include "version.h"
#ifndef lint
static char rcsid[]= "$Id: idle.c,v 1.17 1993/06/10 14:00:13 lotos Exp $";
#endif

/***********************************************************************

     "idle": Intermediate Data LanguagE generator.

***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "idle.h"
#include "tabop.h"
#include "LDM.h"
#include "preproc.h"
#include "gendecl.h"
#include "gendef.h"


char *NomProg= NULL;		/* Nombre del programa. */
EstOpcProg OpcProg= {		/* Opciones del programa. */
		      0,
		      FALSE,
		      0,
		      NULL,
		      NULL
		    };

/* Tamano del nivel de sangrado por defecto. */
#define SANG_DEF	2

/* Tamano maximo del nivel de sangrado. */
#define SANG_MAX	16


void *emalloc(n)
unsigned n;
{ void *p;

  p= (void *) ALIN(malloc(n));
  if (p == NULL)
    Error(ERR_NO_HAY_MEM);
  return p;
}

void efree(p)
void *p;
{
  free((char *) p);
}

static void EscUso()
/* Escribe la forma de uso del programa. */
{
  (void) fprintf(stderr, "usage: %s", NomProg);
  (void) fprintf(stderr, " [ -h ]");
  (void) fprintf(stderr, " [ -i[num] ]");
  (void) fprintf(stderr, " [ -c[0-2] ]");
  (void) fprintf(stderr, " [ -r ]");
  (void) fprintf(stderr, " [ -t<file> ]");
  (void) fprintf(stderr, " [ -d<file> ]");
  (void) fprintf(stderr, "\n");
}

static void EscAyuda()
/* Escribe un mensaje de ayuda sobre el programa. */
{
  EscUso();
  (void) fprintf(stderr,
		 "       -h        this help message\n");
  (void) fprintf(stderr,
		 "       -i[num]   indentation level size ");
  (void) fprintf(stderr,
		 "(range 0-%u, default %u)\n", SANG_MAX, SANG_DEF);
  (void) fprintf(stderr,
		 "       -c[0-2]   comment insertion level ");
  (void) fprintf(stderr,
		 "(default 1)\n");
  (void) fprintf(stderr,
		 "       -r        adds labels to rules\n");
  (void) fprintf(stderr,
		 "       -t<file>  specification table file\n");
  (void) fprintf(stderr,
		 "       -d<file>  for debugging, save AST in file\n");
}

static void ProcArg(argc, argv)
/* Procesa los argumentos de la linea de comandos. */
int argc;
char *argv[];
{ int i, j;
  int Ayuda= FALSE;
  int HayErr= FALSE;
  char FinBusq;
  int DiagBusq;

  NomProg= strrchr (argv[0], '/');
  if (NomProg == NULL)
    NomProg= argv[0];
  else
    ++NomProg;
  for (i= 1; !HayErr && i < argc; ++i)
    if (argv[i][j= 0] == '-')
      switch (argv[i][++j])
      { case 'c':
	  DiagBusq= sscanf(&argv[i][++j], "%u %c", &OpcProg.InsCom,
			   &FinBusq);
	  if (DiagBusq == EOF)
	    OpcProg.InsCom= 1;
	  else if (DiagBusq != 1 ||
		   OpcProg.InsCom > 2)
	    HayErr= TRUE;
	  break;
	case 'r':
	  OpcProg.EtiqReg= TRUE;
	  if (argv[i][++j] != '\0')
	    HayErr= TRUE;
	  break;
	case 'i':
	  DiagBusq= sscanf(&argv[i][++j], "%u %c", &OpcProg.TamSang,
			   &FinBusq);
	  if (DiagBusq == EOF)
	    OpcProg.TamSang= SANG_DEF;
	  if (DiagBusq != EOF &&
	      DiagBusq != 1 ||
	      OpcProg.TamSang > SANG_MAX)
	    HayErr= TRUE;
	  break;
	case 't':
	  OpcProg.FichTab= &argv[i][++j];
	  if (*OpcProg.FichTab == '\0')
	    HayErr= TRUE;
	  break;
	case 'd':
	  OpcProg.FichAST= &argv[i][++j];
	  if (*OpcProg.FichAST == '\0')
	    HayErr= TRUE;
	  break;
	case 'h':
	  Ayuda= TRUE;
	  if (argv[i][++j] != '\0')
	    HayErr= TRUE;
	  break;
	default:
	  HayErr= TRUE;
	  break;
      }
    else
      HayErr= TRUE;
  if (HayErr)
  { EscUso();
    exit(2);
  }
  if (Ayuda)
  { EscAyuda();
    exit(0);
  }
}

int main(argc, argv)
int argc;
char *argv[];
{ int HayErr= FALSE;
  FILE *PuntTab= NULL;
  FILE *PuntAST= NULL;

  ProcArg(argc, argv);
  if (OpcProg.FichTab != NULL)
  { PuntTab= fopen(OpcProg.FichTab, "r");
    if (PuntTab == NULL)
      Error(ERR_NO_ABR_FICH, OpcProg.FichTab);
  }
  if (OpcProg.FichAST != NULL)
  { PuntAST= fopen(OpcProg.FichAST, "w");
    if (PuntAST == NULL)
      Error(ERR_NO_ABR_FICH, OpcProg.FichAST);
  }
  InicTabOp(load_spec(stdin, PuntTab));
  if (OpcProg.FichTab != NULL)
    (void) fclose(PuntTab);
  if (OpcProg.EtiqReg)
    AsigEtiqEc();
  aborta_si(!VerifAnotTipo())
  HayErr= !CorrExpExtMIEc() || HayErr;
  HayErr= !CorrRepVarMIEc() || HayErr;
  HayErr= !EnVarMIEc() || HayErr;
  HayErr= !VerifConsTipo() || HayErr;
  if (HayErr)
    Error(ERR_COMPIL_ABORT);
  ComplTabOp();
  InicSang(OpcProg.TamSang);
  GenDeclTipo();
  GenDefTipo();
  if (OpcProg.FichAST != NULL)
    save_spec(PuntAST, RaizEspec());
  exit (0);
  return 0;
}
