/*
 * lgloc.c -- routines for processing .u2 files.
 */

#include "..\h\config.h"
#include "general.h"
#include "tproto.h"
#include "link.h"
#include "opcode.h"
#include "..\h\version.h"

int nrecords = 0;		/* number of records in program */

/*
 * readglob reads the global information from infile (.u2) and merges it with
 *  the global table and record table.
 */
novalue readglob()
   {
   register char *id;
   register int n, op;
   int k;
   int implicit;
   char *name;
   struct gentry *gp;
   extern char *progname;

   if (getopc(&name) != Op_Version)
      quitf("ucode file %s has no version identification",inname);
   id = getid();		/* get version number of ucode */
   newline();
   if (strcmp(id,UVersion)) {
      fprintf(stderr,"version mismatch in ucode file %s\n",inname);
      fprintf(stderr,"\tucode version: %s\n",id);
      fprintf(stderr,"\texpected version: %s\n",UVersion);

      exit(ErrorExit);

      }
   while ((op = getopc(&name)) != EOF) {
      switch (op) {
         case Op_Record:	/* a record declaration */
            id = getid();	/* record name */
            n = getdec();	/* number of fields */
            newline();
            gp = glocate(id);
            /*
             * It's ok if the name isn't already in use or if the
             *  name is just used in a "global" declaration.  Otherwise,
             *  it is an inconsistent redeclaration.
             */
            if (gp == NULL || (gp->g_flag & ~F_Global) == 0) {
               putglobal(id, F_Record, n, ++nrecords);
               while (n--) {	/* loop reading field numbers and names */
                  k = getdec();
                  putfield(getid(), nrecords, k);
                  newline();
                  }
               }
            else {
               lfatal(id, "inconsistent redeclaration");
               while (n--)
                  newline();
               }
            break;

         case Op_Impl:		/* undeclared identifiers should be noted */
            if (getopc(&name) == Op_Local)
               implicit = 0;
            else
               implicit = F_ImpError;
            break;

         case Op_Trace:		/* turn on tracing */
            trace = -1;
            break;

         case Op_Global:	/* global variable declarations */
            n = getdec();	/* number of global declarations */
            newline();
            while (n--) {	/* process each declaration */
               getdec();	/* throw away sequence number */
               k = getoct();	/* get flags */
               if (k & (F_Proc & ~F_Global))
                  k |= implicit;
               id = getid();	/* get variable name */
               gp = glocate(id);
               /*
                * Check for conflicting declarations and install the
                *  variable.
                */
               if (gp != NULL &&
                   (k & (F_Proc & ~F_Global)) && gp->g_flag != F_Global)
                  lfatal(id, "inconsistent redeclaration");
               else if (gp == NULL || (k & (F_Proc & ~F_Global)))
                  putglobal(id, k, getdec(), 0);
               newline();
               }
            break;

         case Op_Link:		/* link the named file */
            name = getrest();	/* get the name and */
/*          name = getstr();	/* get the name and */
            alsolink(name);	/*  put it on the list of files to link */
            newline();
            break;

         default:
	    quitf("ill-formed global file %s",inname);
         }
      }
   }
