/*
 * Memory initialization and allocation for the translator.
 */

#include "itran.h"
#include "sym.h"
#include "tree.h"
#include "../h/memsize.h"

struct lentry **lhash;		/* hash area for local table */
struct gentry **ghash;		/* hash area for global table */
struct centry **chash;		/* hash area for constant table */
struct ientry **ihash;		/* hash area for identifier table */

nodeptr       tree;		/* parse tree space */
nodeptr       tend;		/* end of parse tree space */
struct lentry *ltable;		/* local table */
struct gentry *gtable;		/* global table */
struct centry *ctable;		/* constant table */
struct ientry *itable;		/* identifier table */

char *strings;			/* string space */
char *send;			/* end of string space */

nodeptr        tfree;		/* free pointer for parse tree space */
struct lentry *lfree;		/* free pointer for local table */
struct gentry *gfree;		/* free pointer for global table */
struct centry *ctfree;		/* free pointer to constant table */
struct ientry *ifree;		/* free pointer for identifier table */
char	      *strfree;		/* free pointer for string space */

int tsize  = TSize;		/* initial size of parse tree space */
int lsize  = LSize;		/* initial size of local table */
int gsize  = GSize;		/* initial size of global table */
int csize  = CSize;		/* initial size of constant table */
int isize  = ISize;		/* initial size of identifier table */
int ssize  = SSize;		/* initial size of string space */
int lhsize = LhSize;		/* initial size of local hash table */
int ghsize = GhSize;		/* initial size of global hash table */
int chsize = ChSize;		/* initial size of constant hash table */
int ihsize = IhSize;		/* initial size of identifier hash table */
int lmask;			/* mask for local table hash */
int gmask;			/* mask for global table hash */
int cmask;			/* mask for constant table hash */
int imask;			/* mask for identifier table hash */

int memsetd;

/*
 * meminit does per-file initialization of various data structures used
 *  by the translator.
 */
meminit()
   {
   register *p;

   if (!memsetd)
      memalloc();		/* allocate data regions for first file */
   /*
    * Reset the free pointer for each region.
    */
   lfree = ltable;
   gfree = gtable;
   ctfree = ctable;
   ifree = itable;
   strfree = strings;
   tfree = tree;
   /*
    * Zero out the hash tables.
    */
   for (p = (int *)lhash; p < (int *)&lhash[lhsize]; p++)
      *p = NULL;
   for (p = (int *)ghash; p < (int *)&ghash[ghsize]; p++)
      *p = NULL;
   for (p = (int *)chash; p < (int *)&chash[chsize]; p++)
      *p = NULL;
   for (p = (int *)ihash; p < (int *)&ihash[ihsize]; p++)
      *p = NULL;

   /*
    * Vestigial structures - these flags are only incremented after
    *  a call to syserr.  Idea was apparently to count number of
    *  entries in an overflowing table, but wasn't completely
    *  implemented.
    */
   alclflg = 0;
   alcgflg = 0;
   alccflg = 0;
   }

/*
 * allocate gets n*size bytes of storage and returns a pointer to it.
 */

char *allocate(n, size)
int n, size;
   {
#ifndef MSDOS
   return (char *)malloc(n*size);
#else MSDOS
   return (char *)calloc(n,size);
#endif MSDOS
   }

/*
 * memalloc computes sizes of data regions needed by the translator
 * obtains space for them, and initializes pointers to them
 */

memalloc()
{
   register int i;
   char *allocate();

   /*
    * Round sizes of hash tables for locals, globals, constants, and
    *  identifiers to next larger power of two.  The corresponding
    *  mask values are set to one less than the hash table size so that
    *  an integer value can be &'d with the mask to produce a hash value.
    *  (See [lgc]hasher in sym.h.)
    */
   for (i = 1; i < lhsize; i <<= 1) ;
   lhsize = i;
   lmask = i - 1;
   for (i = 1; i < ghsize; i <<= 1) ;
   ghsize = i;
   gmask = i - 1;
   for (i = 1; i < chsize; i <<= 1) ;
   chsize = i;
   cmask = i - 1;
   for (i = 1; i < ihsize; i <<= 1) ;
   ihsize = i;
   imask = i - 1;

   /*
    * Allocate the various data structures.
    */
   lhash = (struct lentry **)	allocate(lhsize, sizeof(struct lentry *));
   ghash = (struct gentry **)	allocate(ghsize, sizeof(struct gentry *));
   chash = (struct centry **)	allocate(chsize, sizeof(struct centry *));
   ihash = (struct ientry **)	allocate(ihsize, sizeof(struct ientry *));
   ltable = (struct lentry *)	allocate(lsize, sizeof(struct lentry));
   gtable = (struct gentry *)	allocate(gsize, sizeof(struct gentry));
   ctable = (struct centry *)	allocate(csize, sizeof(struct centry));
   itable = (struct ientry *)	allocate(isize, sizeof(struct ientry));
   tree = (nodeptr)		allocate(tsize, sizeof(int));
   strings =			allocate(ssize, sizeof(char));
   tend = (nodeptr)((int *)tree + tsize);
   send = strings + ssize;
   /*
    * Check to see if there was enough memory.  This assumes that the
    *  allocation for strings fails if any of the other allocations
    *  failed.  Apparent bug - That assumption is not necessarily valid.
    */
   if (strings == NULL) {
      fprintf(stderr, "Can't get enough memory\n");
      exit(ErrorExit);
      }

}
