/***********************************
  (C) Copyright 1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: topo.c,v $
 * Revision 2.18  1995/01/20  14:43:21  lotos
 * new function -main & -compiler
 *
 * Revision 2.17  1995/01/17  10:00:03  lotos
 * no per system COPY MOVE TYPE
 * automatic [re]generation of libraries
 *
 * Revision 2.16  1994/12/19  16:54:19  lotos
 * adapted to new lsa conventions
 *
 * Revision 2.15  1994/12/19  15:09:46  lotos
 * prototypes integrated into topo
 * new pieces convention, and integrated into topo
 * clean objects
 *
 * Revision 2.14  1994/11/22  15:07:01  lotos
 * compatibility with lola for reusage
 *
 * Revision 2.13  1994/11/21  16:32:39  lotos
 * port to msdos
 *
 * Revision 2.12  1994/10/17  16:37:18  lotos
 * fix adtxr call
 *
 * Revision 2.11  1994/10/03  18:34:38  lotos
 * ada code may be splitted into pieces
 *
 * Revision 2.10  1994/07/19  18:40:41  lotos
 * remove standard library automatic recompilation
 *
 * Revision 2.9  1993/11/08  17:19:03  lotos
 * omlbADA has no means to break code into pieces (TPCS)
 *
 * Revision 2.8  1993/10/16  09:59:52  lotos
 * add xlola
 *
 * Revision 2.7  1993/09/30  13:17:15  lotos
 * context file may be explicit
 * make may work on a user makefile
 * emit a warning on unused arguments
 * use COPY for MSDOS (insted of REN)
 *
 * Revision 2.6  1993/08/02  16:57:10  lotos
 * add option -syntax
 *
 * Revision 2.5  1993/07/01  19:19:00  lotos
 * forward -verbose to library actualization
 *
 * Revision 2.4  1993/06/23  17:35:49  lotos
 * Ada prototypes
 *
 * Revision 2.3  1993/06/23  16:06:35  lotos
 * new option -verbose
 *
 * Revision 2.2  1993/06/15  12:51:12  lotos
 * add code to tidy-out topomain.o
 *
 * Revision 2.1  1993/06/10  14:10:24  lotos
 * extract context common part
 * extract C and Ada generation and cleaning functions
 * lots of bugs fixed
 *
 * Revision 1.2  1993/02/23  17:03:41  lotos
 * fix minor details to port to pc
 *
 * Revision 1.1  1993/02/22  16:09:39  lotos
 * Initial revision
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: topo.c,v 2.18 1995/01/20 14:43:21 lotos Exp $";
#endif

#include "context.h"

char* getenv ();

char args[BUFSIZ];
int FlagDebug= 0;
int UserMake= 0;
int FlagTemporal= 0;

#define PF(text) (void) fprintf (stderr, text)

PRIVATE void
help ()
{
  PF ("usage: topo SPEC [topo_options] [action [action_options]]");
  PF ("  topo options:\n");
  PF ("     -verbose    echo activity\n");
  PF ("     -context F  use F.ctx as context [SPEC.ctx]\n");
  PF ("  actions\n");
  PF ("     -syntax     syntax analysis\n");
  PF ("     -s          semantics analysis (default)\n");
  PF ("     -behaviour  temporal part compiler\n");
  PF ("        [-g]       [debugging code]\n");
  PF ("     -data       data part compiler\n");
  PF ("     -p          make a prototype\n");
  PF ("     -main       generate a main program (if needed)\n");
  PF ("     -compiler   generate a compiler caller (if needed)\n");
  PF ("     -ildi       Interactive Lotos Data Interpreter\n");
  PF ("     -rdtts ...  Real Data Types Testing Specification\n");
  PF ("     -ltg ...    Lotos Test case Generator\n");
  PF ("     -lola       run LOLA (LOtos LAboratory)\n");
#ifndef MSDOS
  PF ("     -xlola      X version of LOLA (LOtos LAboratory)\n");
#endif
  PF ("     -cr         generates CR (for LITE)\n");
  PF ("     -pp ...     pretty printer       [topo -pph for further help]\n");
  PF ("     -a ...      adt cross references [topo -ah  for further help]\n");
  PF ("     -r ...      cross references     [topo -rh  for further help]\n");
  PF ("     -listmake   dumps makefile\n");
  PF ("     -clean      clean directory\n");
  PF ("     -tidy       more drastic cleaning\n");
}

PRIVATE void
recollect (argc, argv)
  int argc;
  char* argv[];
{
  (void) strcpy (args, "");
  while (argc > 1) {
    (void) strcat (args, " ");
    (void) strcat (args, argv[1]);
    shift;
  }
}

PRIVATE void
ignore (argc, argv)
  int argc;
  char* argv[];
{
  if (argc <= 1)
    return;
  (void) fprintf (stderr, "extra options ignored: ");
  while (argc > 1) {
    (void) fprintf (stderr, " %s", argv[1]);
    shift;
  }
  (void) fprintf (stderr, "\n");
}

PRIVATE void
genmake (file)
  FILE* file;
{
  if (file == NULL && UserMake)
    return;

  if (file == NULL) {
    if ((file= fopen (MAKE, "w")) == NULL) {
      (void) fprintf (stderr, "can't open %s (w)\n", MAKE);
      exit (1);
    }
  }

  if (! FlagVerbose)
    fprintf (file, ".SILENT:\n\n");

  fprintf(file,"%s.lfe:\t%s.lot\n", SPEC, SPEC);
  fprintf(file,"\tlfe %s %s.lot > %s\n", TOPOF_LFE, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  if (strcmp (LIB, "") != 0 &&
      strncmp (LIB, TOPOSTDLIB, strlen (TOPOSTDLIB)) != 0 &&
      read_ok (LIBLOT)) {
    fprintf(file,"%s:\t%s\n", LIBLSA, LIBLOT);
    fprintf(file,"\t@echo topo warning: %s is out of date!\n", LIBLSA);
    fprintf(file,"\tlfe %s > %s\n", LIBLOT, TMP);
    fprintf(file,"\tlsa -p %s %s\n", LIB, TMP);
    /*
    fprintf(file,"\ttopo %s\n", LIB);
    */
    fprintf(file,"\n");
  }

  fprintf(file,"%s.ls %s.as:\t%s.lfe %s\n", SPEC, SPEC, SPEC, LIBLSA);
  fprintf(file,"\t%s %s -p %s %s.lfe\n", LSA, TOPOF_LSA, SPEC, SPEC);
  fprintf(file,"\n");

  fprintf(file,"%s.lss %s.ass:\t%s.lfe %s\n", SPEC, SPEC, SPEC, LIBLSA);
  fprintf(file,"\t%s -s %s -p %s %s.lfe\n", LSA, TOPOF_LSA, SPEC, SPEC);
  fprintf(file,"\n");

  fprintf(file,"%s.lsf %s.asf:\t%s.lfe %s\n", SPEC, SPEC, SPEC, LIBLSA);
  fprintf(file,"\t%s -f -C %s -p %s %s.lfe\n", LSA, TOPOF_LSA, SPEC, SPEC);
  fprintf(file,"\n");

  fprintf(file,"%s.lsc %s.asc %s.lcr:\t%s.lfe %s\n",
	  SPEC, SPEC, SPEC, SPEC, LIBLSA);
  fprintf(file,"\t%s -c %s -p %s %s.lfe\n", LSA, TOPOF_LSA, SPEC, SPEC);
  fprintf(file,"\n");

  fprintf(file,"%s.agf:\t%s.asf %s\n", SPEC, SPEC, GLDLIB);
  fprintf(file,"\t%s %s %s < %s.asf > %s\n", GLAD, TOPOF_GLAD, GLDLIB, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  fprintf(file,"%s.aif:\t%s.asf %s\n", SPEC, SPEC, GLDLIB);
  fprintf(file,"\t%s %s -s %s < %s.asf > %s\n", GLAD, TOPOF_GLAD, GLDLIB, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  fprintf(file,"%s.cr:\t%s.lsc %s.asc %s.lcr\n", SPEC, SPEC, SPEC, SPEC);
  fprintf(file,"\tast2cr -n%s > %s\n", SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  fprintf(file,"%s.idl:\t%s.lsf %s.agf\n", SPEC, SPEC, SPEC);
  fprintf(file,"\t%s -c %s -t%s.agf < %s.lsf > %s\n",
	  IDLE, TOPOF_IDLE, SPEC, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  fprintf(file,"%s.ldi:\t%s.lsf %s.aif\n", SPEC, SPEC, SPEC);
  fprintf(file,"\tidle -r %s -t%s.aif < %s.lsf > %s\n",
	  TOPOF_IDLE, SPEC, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  fprintf(file,"%s.lbm:\t%s.lsf %s.agf\n", SPEC, SPEC, SPEC);
  fprintf(file,"\tom -f %s %s > %s\n", TOPOF_OM, SPEC, TMP);
#ifdef MSDOS
  fprintf(file,"\ttype %s > $@\n", TMP);
#else
  fprintf(file,"\tmv %s $@\n", TMP);
#endif
  fprintf(file,"\n");

  if (strcmp (LANGUAGE, "C") == 0)
    Cgenmake (file);
  else /* Ada */
    Adagenmake (file);

  (void) fclose (file);
}

PRIVATE void
clean ()
{
  if (FlagVerbose)
    (void) fprintf (stderr,
		    "remove %s.lfe %s.ls %s.lss %s.lsf %s.lsc %s.lcr\n",
		    SPEC, SPEC, SPEC, SPEC, SPEC, SPEC);
  (void) sprintf (filename, "%s.lfe", SPEC);
  (void) unlink (filename);

  (void) sprintf (filename, "%s.ls", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.lss", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.lsf", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.lsc", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.lcr", SPEC);
  (void) unlink (filename);

  if (FlagVerbose)
    (void) fprintf (stderr,
		    "remove %s.as %s.ass %s.asf %s.asc %s.agf %s.aif\n",
		    SPEC, SPEC, SPEC, SPEC, SPEC, SPEC);
  (void) sprintf (filename, "%s.as", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.ass", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.asf", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.asc", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.agf", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.aif", SPEC);
  (void) unlink (filename);

  if (FlagVerbose)
    (void) fprintf (stderr,
		    "remove %s.lbm %s.idl %s.ldi\n",
		    SPEC, SPEC, SPEC);
  (void) sprintf (filename, "%s.lbm", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.idl", SPEC);
  (void) unlink (filename);
  (void) sprintf (filename, "%s.ldi", SPEC);
  (void) unlink (filename);
}

PRIVATE void
tidy ()
{
  clean ();

  (void) sprintf (filename, "%s.com", SPEC);
  if (FlagVerbose)
    (void) fprintf (stderr, "remove %s\n", filename);
  (void) unlink (filename);

  if (strcmp (LANGUAGE, "C") == 0) {
    CCleanBehaviour ();
    CCleanData ();
    CCleanObject ();
  }
  else /* Ada */ {
    AdaCleanBehaviour ();
    AdaCleanData ();
    AdaCleanObject ();
  }
}

PRIVATE int
cstrcmp (s1, s2)
  char *s1, *s2;
{
  register char ls1, ls2;

  while (*s1 && *s2) {
    ls1= isupper (*s1) ? tolower (*s1) : *s1;
    ls2= isupper (*s2) ? tolower (*s2) : *s2;
    if (ls1 < ls2)
      return -1;
    else if (ls1 > ls2)
      return 1;
    s1++; s2++;
  }
  if (*s1 == *s2)
    return 0;
  else if (*s1)
    return 1;
  else
    return -1;
}

typedef enum option {
  opthelp, debug, listmake, verbose, context, temporal,
  adtxr, adtxrhelp,
  ildi, rdtts, ltg, lxref, lxrefhelp, prettyprinter, prettyprinterhelp,
  syntax, semantics,
  data, behaviour, prototype,
  xmain, compiler,
  lola, xlola, plola,
  cr,
  force, optclean, opttidy,
  noopt, unknown
} option;

PRIVATE struct {
  char*   keyword;
  option  kopt;
} kwtable [] = {
  "-a",		adtxr,
  "-ah",	adtxrhelp,
  "-behaviour",	behaviour,
  "-c",		optclean,
  "-clean",	optclean,
  "-context",   context,
  "-compiler",	compiler,
  "-cr",	cr,
  "-d",		data,
  "-data",	data,
  "-debug",	debug,
  "-f",		force,
  "-force",	force,
  "-h",		opthelp,
  "-help",	opthelp,
  "-ildi",	ildi,
  "-listmake",	listmake,
  "-lola",	lola,
  "-ltg",	ltg,
  "-main",	xmain,
  "-p",		prototype,
  "-plola",	plola,
  "-pp",	prettyprinter,
  "-pph",	prettyprinterhelp,
  "-r",		lxref,
  "-rdtts",	rdtts,
  "-rh",	lxrefhelp,
  "-s",		semantics,
  "-syntax",	syntax,
  "-t",		behaviour,
  "-temporal",  temporal,
  "-tidy",	opttidy,
  "-v",		verbose,
  "-verbose",	verbose,
  "-x",		syntax,
  "-xlola",	xlola,
  "-xref",	lxref,
  NULL
};

PRIVATE option
Classify (arg)
  char* arg;
{
  int i;

  if (arg == NULL)
    return noopt;
  for (i= 0; kwtable[i].keyword != NULL; i++)
    if (cstrcmp (arg, kwtable[i].keyword) == 0)
      return kwtable[i].kopt;
  if (*arg == '-')
    return unknown;
  return noopt;
}

#ifdef LOLACODE
topomain (argc, argv)
#else
/* KJT 20/01/23: added "int" type */
int main (argc, argv)
#endif
  int   argc;
  char* argv[];
{
  char* s;
  int status= 0;

  read_env ();

  if ((s= getenv ("TOPOF_LFE")) != NULL)
    (void) strcpy (TOPOF_LFE, s);

  if ((s= getenv ("TOPOF_LSA")) != NULL)
    (void) strcpy (TOPOF_LSA, s);

  if ((s= getenv ("TOPOF_GLAD")) != NULL)
    (void) strcpy (TOPOF_GLAD, s);

  if ((s= getenv ("TOPOF_OM")) != NULL)
    (void) strcpy (TOPOF_OM, s);

  if ((s= getenv ("TOPOF_OMLBC")) != NULL)
    (void) strcpy (TOPOF_OMLBC, s);

  if ((s= getenv ("TOPOF_IDLE")) != NULL)
    (void) strcpy (TOPOF_IDLE, s);

  if ((s= getenv ("TOPOF_D2H")) != NULL)
    (void) strcpy (TOPOF_D2H, s);

  if ((s= getenv ("TOPOF_D2C")) != NULL)
    (void) strcpy (TOPOF_D2C, s);

  if ((s= getenv ("TOPOF_OMLBADA")) != NULL)
    (void) strcpy (TOPOF_OMLBADA, s);

  if ((s= getenv ("TOPOF_D2ADA")) != NULL)
    (void) strcpy (TOPOF_D2ADA, s);

  if ((s= getenv ("TOPOF_D2ADA_B")) != NULL)
    (void) strcpy (TOPOF_D2ADA_B, s);

  if ((s= getenv ("TOPOF_ADACPL")) != NULL)
    (void) strcpy (TOPOF_ADACPL, s);

  if ((s= getenv ("TOPOF_ADARTS")) != NULL)
    (void) strcpy (TOPOF_ADARTS, s);

  if (argc == 1) {
    help ();
    exit (0);
  }

	/* this is out of usage instructions
	** but helps a lot for common pitfalls
	*/

  switch (Classify (argv[1])) {
  case opthelp:
    help ();
    shift;
    ignore (argc, argv);
    exit (0);
  case prettyprinterhelp:
    (void) system ("pl -h");
    shift;
    ignore (argc, argv);
    exit (0);
  case adtxrhelp:
    (void) system ("adtxr -h");
    shift;
    ignore (argc, argv);
    exit (0);
  case lxrefhelp:
    (void) system ("lxref -h");
    shift;
    ignore (argc, argv);
    exit (0);
  case noopt:
    break;
  case unknown:
  default:
    help ();
    shift;
    ignore (argc, argv);
    exit (1);
  }

  (void) strcpy (SPEC, argv[1]);
  if (s= strrchr (SPEC, '.')) {
    if (strcmp (s, ".lot") == 0)
      *s= '\0';
  }
  shift;

  if (strcmp (SPEC, "") == 0) {
    help ();
    exit (1);
  }

  /***  topo options  ***/

  for (;;) {
    int leave= FALSE;

    if (argc <= 1)
      break;
    if (argv[1][0] != '-')
      break;
    switch (Classify (argv[1])) {
    case verbose:
      FlagVerbose++;
      shift;
      break;

    case context:
      if (argc < 3) {
	(void) fprintf (stderr, "option -context requires one argument\n");
	exit (1);
      }
      (void) strcpy (CONTEXT, argv[2]);
      if ((s= strchr (CONTEXT, '.')) != 0) {
	if (strcmp (s, ".ctx") == 0)
	  *s= '\0';
      }
      shift; shift;
      break;

    case temporal:
      if (argc < 3) {
	(void) fprintf (stderr, "option -temporal requires one argument\n");
	exit (1);
      }
      (void) strcpy (TMP, argv[2]);
      FlagTemporal++;
      shift; shift;
      break;

    case debug:
      FlagDebug++;
      shift;
      break;

    default:
      leave= TRUE;
    }

    if (leave)
      break;
  }

  read_ctx ();
  UserMake= strcmp (MAKEFILE, "") != 0;
  /* KJT 20/01/23: changed "mktemp" to "mkstemp" */
  if (! FlagTemporal)
    (void) mkstemp (TMP);
  if (UserMake) {
    (void) strcpy (MAKE, MAKEFILE);
    if (FlagVerbose)
      (void)  fprintf (stderr, "using %s\n", MAKE);
  }
  else
    (void) mkstemp (MAKE);

  if (strcmp (LIB, "") != 0) {
    (void) sprintf (LIBLOT, "%s.lot", LIB);
    (void) sprintf (LIBLSA, "%s.ls", LIB);
    (void) strcat (LSA, " -l ");
    (void) strcat (LSA, LIB);
    (void) strcat (LOLA, " -l");
    (void) strcat (LOLA, LIB);
    (void) strcat (XLOLA, " -l");
    (void) strcat (XLOLA, LIB);
  }

  if (strcmp (GLDLIB, "") == 0) {
    (void) strcat (GLAD, " ");
    (void) strcat (GLAD, DEVNULL);
  }

  if (atoi (TPCS) > 1) {
    (void) strcat (OMLBC, " -s ");
    (void) strcat (OMLBC, TPCS);
    (void) strcat (OMLBADA, " -s ");
    (void) strcat (OMLBADA, TPCS);
  }

  if (atoi (DPCS) > 1) {
    (void) strcat (D2C, " -s");
    (void) strcat (D2C, DPCS);
    (void) strcat (D2ADA_B, " -s");
    (void) strcat (D2ADA_B, DPCS);
  }

  /***  action  ***/

  if (argc > 1)
    switch (Classify (argv[1])) {
    case opthelp:
      help ();
      shift;
      ignore (argc, argv);
      exit (0);
    case listmake:
      shift;
      ignore (argc, argv);
      genmake (stdout);
      exit (0);
    case optclean:
      if (FlagVerbose)
	(void)  fprintf (stderr, "clean directory ...\n");
      shift;
      ignore (argc, argv);
      clean ();
      exit (0);
    case opttidy:
      if (FlagVerbose)
	(void) fprintf (stderr, "tidying up directory ...\n");
      shift;
      ignore (argc, argv);
      tidy ();
      exit (0);
    }

  if (argc == 1) {
    if (FlagVerbose)
      fprintf (stderr, "semantics analysis ...\n");
    shift;
    ignore (argc, argv);
    genmake ((FILE*) NULL);
    sprintf (command, "make -f %s %s.ls %s", MAKE, SPEC, REDIR);
    status= my_system (command);
  }
  else {
    switch (Classify (argv[1])) {
    case opthelp:

    case ildi:
      if (FlagVerbose)
	fprintf (stderr, "Interactive Lotos Data Interpreter ...\n");
      shift;
      recollect (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command,"make -f %s %s.ldi %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      if (status == 0) {
	sprintf (command,"ildi %s %s", args, SPEC);
	status= my_system (command);
      }
      break;

    case rdtts:
      if (FlagVerbose)
	fprintf (stderr, "Real Data Types Test Specification ...\n");
      shift;
      recollect (argc, argv);
      sprintf (command, "rdtts %s %s", args, SPEC);
      status= my_system (command);
      break;

    case ltg:
      if (FlagVerbose)
	fprintf (stderr, "Lotos Test case Generation ...\n");
      shift;
      recollect (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.lbm %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      if (status == 0) {
	sprintf (command, "ltg -s %s %s", SPEC, args);
	status= my_system (command);
      }
      break;

    case plola:
      if (FlagVerbose)
	fprintf (stderr, "LOtos LAboratory preprocessing ...\n");
      shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.lsf %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      break;

    case lola:
      if (FlagVerbose)
	fprintf (stderr, "LOtos LAboratory ...\n");
      shift;
      recollect (argc, argv);
      sprintf (command, "%s %s %s", LOLA, args, SPEC);
      status= my_system (command);
      break;

    case xlola:
      if (FlagVerbose)
	fprintf (stderr, "LOtos LAboratory ...\n");
      shift;
      recollect (argc, argv);
      sprintf (command, "%s %s %s", XLOLA, args, SPEC);
      status= my_system (command);
      break;

    case prettyprinter:
      if (FlagVerbose)
	fprintf (stderr, "pretty printing ...\n");
      shift;
      recollect (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.lfe %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      if (status == 0) {
	sprintf (command, "pl %s %s.lfe", args, SPEC);
	status= my_system (command);
      }
      break;

    case force:
      if (FlagVerbose)
	fprintf (stderr, "forcing tool %s ...\n", argv[2]);
      (void) sprintf (filename, "%s.%s", SPEC, argv[2]);
      if (FlagVerbose)
	fprintf (stderr, "delete %s\n", filename);
      (void) unlink (filename);
      shift; shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s %s", MAKE, filename, REDIR);
      status= my_system (command);
      break;

    case prototype:
      if (FlagVerbose)
	fprintf (stderr, "try to make a prototype ...\n");
      shift;
      ignore (argc, argv);
      if (strcmp (LANGUAGE, "C") == 0) {
	if (atoi (DPCS) > 1 || atoi (TPCS) > 1) {
	  (void) fprintf (stderr,
	    "C code splitting and prototype generation are incompatible\n");
	  exit (1);
	}
      }
      else {
	if (atoi (DPCS) > 1 || atoi (TPCS) > 1) {
	  (void) fprintf (stderr,
	    "Ada code splitting and prototype generation are incompatible\n");
	  exit (1);
	}
	if (getenv ("TOPOF_ADACPL") == NULL ||
	    getenv ("TOPOF_ADARTS") == NULL) {
	  (void) fprintf (stderr,
	    "variables TOPOF_ADACPL and TOPOF_ADARTS must be in the environment\n");
	  exit (1);
	}
      }
      (void) strcat (OMLBC, " -g");
      (void) strcat (OMLBADA, " -g");
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      break;

    case xmain:
      if (FlagVerbose)
	fprintf (stderr, "main program generation ...\n");
      shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      if (strcmp (LANGUAGE, "C") == 0)
	status= CBuildMain ();
      else
	status= AdaBuildMain ();
      break;

    case compiler:
      if (FlagVerbose)
	fprintf (stderr, "compiler caller generation ...\n");
      shift;
      ignore (argc, argv);
      if (strcmp (LANGUAGE, "C") == 0) {
	(void) fprintf (stderr,
	  "C compiler caller generation not needed, so not provided\n");
	exit (1);
      }
      else {
	if (getenv ("TOPOF_ADACPL") == NULL) {
	  (void) fprintf (stderr,
	    "variable TOPOF_ADACPL must be in the environment\n");
	  exit (1);
	}
      }
      genmake ((FILE*) NULL);
      if (strcmp (LANGUAGE, "C") == 0)
	status= CBuildCompiler ();
      else
	status= AdaBuildCompiler ();
      break;

    case syntax:
      if (FlagVerbose)
	fprintf (stderr, "syntax analysis ...\n");
      shift;
      recollect (argc, argv);
      (void) strcat (TOPOF_LFE, " ");
      (void) strcat (TOPOF_LFE, args);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.lfe %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      break;

    case semantics:
      if (FlagVerbose)
	fprintf (stderr,"semantics analysis ...\n");
      shift;
      recollect (argc, argv);
      (void) strcat (TOPOF_LSA, " ");
      (void) strcat (TOPOF_LSA, args);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.ls %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      break;

    case adtxr:
      if (FlagVerbose)
	fprintf (stderr, "ADT cross references ...\n");
      shift;
      recollect (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.ls %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      if (status == 0) {
	if (strlen (LIB) == 0)
	  sprintf (command, "adtxr -o%s %s", SPEC, args);
	else
	  sprintf (command, "adtxr -o%s -l%s %s", SPEC, LIB, args);
	status= my_system (command);
      }
      break;

    case lxref:
      if (FlagVerbose)
	fprintf (stderr, "cross references ...\n");
      shift;
      recollect (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.ls %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      if (status == 0) {
	sprintf (command, "lxref -n%s %s", SPEC, args);
	status= my_system (command);
      }
      break;

    case behaviour:
      if (FlagVerbose)
	fprintf (stderr, "behaviour compiler ...\n");
      shift;
      if (argc > 1 && strcmp (argv[1], "-g") == 0) {
	(void) strcat (OMLBC, " -g");
	shift;
      }
      (void) strcat (OMLBADA, " -g");
      shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      if (strcmp (LANGUAGE, "C") == 0)
	status= CBuildBehaviour ();
      else
	status= AdaBuildBehaviour ();
      break;

    case data:
      if (FlagVerbose)
	fprintf (stderr, "data types compiler ...\n");
      shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      if (strcmp (LANGUAGE, "C") == 0)
	status= CBuildData ();
      else
	status= AdaBuildData ();
      break;

    case cr:
      if (FlagVerbose)
	fprintf (stderr, "CR generation ...\n");
      shift;
      ignore (argc, argv);
      genmake ((FILE*) NULL);
      sprintf (command, "make -f %s %s.cr %s", MAKE, SPEC, REDIR);
      status= my_system (command);
      break;

    case unknown:
      (void) fprintf (stderr, "unknown option %s\n", argv[1]);
      help ();
      shift;
      ignore (argc, argv);
      exit (1);
      break;

    case noopt:
      (void) fprintf (stderr, "I do not understand %s\n", argv[1]);
      help ();
      shift;
      ignore (argc, argv);
      exit (1);
    }
  }

  if (FlagDebug == 0)
    (void) unlink (TMP);
  if (! UserMake) {
    if (FlagDebug == 0)
      (void) unlink (MAKE);
    else
      (void) fprintf (stderr, "makefile left in %s\n", MAKE);
  }

#ifndef LOLACODE
  exit (status);
#endif
  return status;
}

