/*
 * trans.c - main control of the translation process.
 */

#include "..\h\config.h"
#include "general.h"
#include "tproto.h"
#include "..\h\version.h"
#include "globals.h"
#include "trans.h"
#include "tsym.h"
#include "tree.h"
#include "token.h"

/*
 * Prototypes.
 */

hidden	FILE	*preprocess	Params((char *filename));
hidden	novalue	trans1		Params((char *filename));

char *comfile = NULL;

int tfatals;			/* total number of fatal errors */
int nocode;			/* non-zero to suppress code generation */
int in_line;			/* current input line number */
int incol;			/* current input column number */
int peekc;			/* one-character look ahead */

FILE *srcfile;			/* current input file */
FILE *codefile;			/* current ucode output file */
FILE *globfile;			/* current global table output file */

/*
 * translate a number of files, returning an error count
 */
int trans(ifiles)
char **ifiles;
   {
   tmalloc();			/* allocate memory for translation */

#ifdef MultipleRuns
   yylexinit();			/* initialize lexical analyser */
   tcodeinit();			/* initialize code generator */
#endif					/* Multiple Runs */

   while (*ifiles)
      trans1(*ifiles++);	/* translate each file in turn */
   tmfree();			/* free memory used for translation */

   /*
    * Report information about errors and warnings and be correct about it.
    */
   if (tfatals == 1)
      fprintf(stderr, "1 error\n");
   else if (tfatals > 1)
      fprintf(stderr, "%d errors\n", tfatals);
   else if (!silent)
      fprintf(stderr, "No errors\n");

   return tfatals;
   }

/*
 * translate one file.
 */
static novalue trans1(filename)
char *filename;
{
   char oname[MaxFileName];	/* buffer for constructing file names */

   comfile = filename;
   tfatals = 0;	/* reset error counts */
   nocode = 0;			/* allow code generation/*
   in_line = 1;			/* start with line 1, column 0 */
   incol = 0;
   peekc = 0;			/* clear character lookahead */

   if (m4pre)
      srcfile = preprocess(filename);
   else if (strcmp(filename,"-") == 0) {
      srcfile = stdin;
      filename = "stdin";
      }
   else
      srcfile = fopen(filename,ReadText);
   if (srcfile == NULL)
      quitf("cannot open %s",filename);
   if (!silent)
      fprintf(stderr, "%s:\n",filename);

#ifndef VarTran
   /*
    * Form names for the .u1 and .u2 files and open them.
    *  Write the ucode version number to the .u2 file.
    */

   makename(oname, TargetDir, filename, U1Suffix);

#if MVS || VM
/*
 * Even though the ucode data is all reasonable text characters, use
 *  of text I/O may cause problems if a line is larger than LRECL.
 *  This is likely to be true with any compiler, though the precise
 *  disaster which results may vary.
 */
   codefile = fopen(oname, WriteBinary);   /* avoid line splits */
#else					/* MVS || VM */
   codefile = fopen(oname, WriteText);
#endif					/* MVS || VM */

   if (codefile == NULL)
      quitf("cannot create %s", oname);

   makename(oname, TargetDir, filename, U2Suffix);

#if MVS || VM
   globfile = fopen(oname, WriteBinary);
#else					/* MVS || VM */
   globfile = fopen(oname, WriteText);
#endif					/* MVS || VM */

   if (globfile == NULL)
      quitf("cannot create %s", oname);
   writecheck(fprintf(globfile,"version\t%s\n",UVersion));
#endif					/* VarTran */

   tok_loc.n_file = filename;
   in_line = 1;

   tminit();				/* Initialize data structures */
   yyparse();				/* Parse the input */

   /*
    * Close the output files and the input file.
    */

#ifndef VarTran
   if (fclose(codefile) != 0 || fclose(globfile) != 0)
      quit("cannot close ucode file");
#endif					/* VarTran */

   if (!m4pre) 
      fclose(srcfile);
   /* "else" is below in conditional */

#if UNIX
   else if (pclose(srcfile) != 0)
      quit("m4 terminated abnormally");
#endif					/* UNIX */
   }

/*
 * writecheck - check the return code from a stdio output operation
 */
novalue writecheck(rc)
   {
   if (rc < 0)
      quit("cannot write to ucode file");
   }

/*
 * open a pipe to the preprocessor.
 */
static FILE *preprocess(filename)
char *filename;
{

#if MACINTOSH
#if MPW
/* #pragma unused(filename) */
   return NULL;			/* to prevent compiler warning */
#endif					/* MPW */
#endif					/* MACINTOSH */

#if UNIX
      {
      FILE *f, *popen();
      char *s = alloc((unsigned int)(4+strlen(filename)));
      sprintf(s,"m4 %s",filename);
      f = popen(s,ReadText);
      free(s);
      return f;
      }
#endif					/* UNIX */
}
