home *** CD-ROM | disk | FTP | other *** search
- /*
- * tsym.c -- functions for symbol table management.
- */
-
- #include "../h/gsupport.h"
- #include "tproto.h"
- #include "globals.h"
- #include "trans.h"
- #include "token.h"
- #include "tsym.h"
-
- #ifndef VarTran
- #include "lfile.h"
- #endif /* VarTran */
-
- /*
- * Prototypes.
- */
-
- hidden struct tgentry *alcglob
- Params((struct tgentry *blink, char *name,int flag,int nargs));
- hidden struct tientry *alcid Params((char *nam,int len));
- hidden struct tcentry *alclit
- Params((struct tcentry *blink, char *name, int len,int flag));
- hidden struct tlentry *alcloc
- Params((struct tlentry *blink, char *name,int flag));
- hidden struct tcentry *clookup Params((char *id,int flag));
- hidden struct tgentry *glookup Params((char *id));
- hidden struct tlentry *llookup Params((char *id));
- hidden novalue putglob
- Params((char *id,int id_type, int n_args));
- hidden int streq Params((int len,char *s1,char *s2));
-
- #ifdef DeBugTrans
- novalue cdump Params((noargs));
- novalue gdump Params((noargs));
- novalue ldump Params((noargs));
- #endif /* DeBugTrans */
-
-
- /*
- * putid - install the identifier named by the string starting at strf
- * and extending for len bytes. The installation entails making an
- * entry in the identifier hash table and then making an identifier
- * table entry for it with alcid. A side effect of installation
- * is the incrementing of strf by the length of the string, thus
- * "saving" it.
- *
- * Nothing is changed if the identifier has already been installed.
- */
- char *putid(len)
- int len;
- {
- register int hash;
- register char *s;
- register struct tientry *ip;
- int l;
-
- /*
- * Compute hash value by adding bytes and masking result with imask.
- * (Recall that imask is ihsize-1.)
- */
- s = strf;
- hash = 0;
- l = len;
- while (l--)
- hash += *s++ & 0377;
- s = strf;
- l = len;
- hash &= imask;
- /*
- * If the identifier hasn't been installed, install it.
- */
- if ((ip = ihash[hash]) != NULL) { /* collision */
- for (;;) { /* work down i_blink chain until id is found or the
- end of the chain is reached */
- if (l == ip->i_length && streq(l, s, ip->i_name))
- return (ip->i_name); /* id is already installed */
- if (ip->i_blink == NULL) { /* end of chain */
- ip->i_blink = alcid(s,l);
- strf += l;
- return s;
- }
- ip = ip->i_blink;
- }
- }
- /*
- * Hashed to an empty slot.
- */
- ihash[hash] = alcid(s,l);
- strf += l;
- return s;
- }
-
- /*
- * streq - compare s1 with s2 for len bytes, and return 1 for equal,
- * 0 for not equal.
- */
- static int streq(len, s1, s2)
- register int len;
- register char *s1, *s2;
- {
- while (len--)
- if (*s1++ != *s2++)
- return 0;
- return 1;
- }
-
- /*
- * alcid - get the next free identifier table entry, and fill it in with
- * the specified values.
- */
- static struct tientry *alcid(nam, len)
- char *nam;
- int len;
- {
- register struct tientry *ip;
-
- if (ifree >= &itable[isize])
- tsyserr("out of identifier table space");
- ip = ifree++;
- ip->i_blink = NULL;
- ip->i_name = nam;
- ip->i_length = len;
- return ip;
- }
-
- #ifndef VarTran
-
- /*
- * loc_init - clear the local symbol table.
- */
-
- novalue loc_init()
- {
- register struct tlentry **lp;
- register struct tcentry **cp;
- static int maxlfree = 0;
- static int maxcfree = 0;
- /* clear local table */
- maxlfree = (maxlfree > lfree-ltable) ? maxlfree : lfree-ltable;
- for (lp = lhash; lp < &lhash[lhsize]; lp++)
- *lp = NULL;
- lfree = ltable;
- /* clear constant table */
- maxcfree = (maxcfree > ctfree-ctable) ? maxcfree : ctfree-ctable;
- for (cp = chash; cp < &chash[chsize]; cp++)
- *cp = NULL;
- ctfree = ctable;
- }
-
- /*
- * install - put an identifier into the global or local symbol table.
- * The basic idea here is to look in the right table and install
- * the identifier if it isn't already there. Some semantic checks
- * are performed.
- */
- novalue install(name, flag, argcnt)
- char *name;
- int flag, argcnt;
- {
- union {
- struct tgentry *gp;
- struct tlentry *lp;
- } p;
-
- switch (flag) {
- case F_Global: /* a variable in a global declaration */
- if ((p.gp = glookup(name)) == NULL)
- putglob(name, flag, argcnt);
- else
- p.gp->g_flag |= flag;
- break;
-
- case F_Proc|F_Global: /* procedure declaration */
- case F_Record|F_Global: /* record declaration */
- case F_Builtin|F_Global: /* external declaration */
- if ((p.gp = glookup(name)) == NULL)
- putglob(name, flag, argcnt);
- else if ((p.gp->g_flag & (~F_Global)) == 0) { /* superfluous global
- declaration for
- record or proc */
- p.gp->g_flag |= flag;
- p.gp->g_nargs = argcnt;
- }
- else /* the user can't make up his mind */
- tfatal("inconsistent redeclaration", name);
- break;
-
- case F_Static: /* static declaration */
- case F_Dynamic: /* local declaration (possibly implicit?) */
- case F_Argument: /* formal parameter */
- if ((p.lp = llookup(name)) == NULL)
- putloc(name,flag);
- else if (p.lp->l_flag == flag) /* previously declared as same type */
- tfatal("redeclared identifier", name);
- else /* previously declared as different type */
- tfatal("inconsistent redeclaration", name);
- break;
-
- default:
- tsyserr("install: unrecognized symbol table flag.");
- }
- }
-
- /*
- * putloc - make a local symbol table entry and return the index
- * of the entry in lhash. alcloc does the work if there is a collision.
- */
- int putloc(id,id_type)
- char *id;
- int id_type;
- {
- register struct tlentry *ptr;
-
- if ((ptr = llookup(id)) == NULL) { /* add to head of hash chain */
- ptr = lhash[lhasher(id)];
- lhash[lhasher(id)] = alcloc(ptr, id, id_type);
- return (lhash[lhasher(id)] - ltable);
- }
- return (ptr - ltable);
- }
-
- /*
- * putglob makes a global symbol table entry. alcglob does the work if there
- * is a collision.
- */
-
- static novalue putglob(id, id_type, n_args)
- char *id;
- int id_type, n_args;
- {
- register struct tgentry *ptr;
-
- if ((ptr = glookup(id)) == NULL) { /* add to head of hash chain */
- ptr = ghash[ghasher(id)];
- ghash[ghasher(id)] = alcglob(ptr, id, id_type, n_args);
- }
- }
-
- /*
- * putlit makes a constant symbol table entry and returns the index
- * of the entry in chash. alclit does the work if there is a collision.
- */
- int putlit(id, idtype, len)
- char *id;
- int len, idtype;
- {
- register struct tcentry *ptr;
-
- if ((ptr = clookup(id,idtype)) == NULL) { /* add to head of hash chain */
- ptr = chash[chasher(id)];
- chash[chasher(id)] = alclit(ptr, id, len, idtype);
- return (chash[chasher(id)] - ctable);
- }
- return (ptr - ctable);
- }
-
- /*
- * llookup looks up id in local symbol table and returns pointer to
- * to it if found or NULL if not present.
- */
-
- static struct tlentry *llookup(id)
- char *id;
- {
- register struct tlentry *ptr;
-
- ptr = lhash[lhasher(id)];
- while (ptr != NULL && ptr->l_name != id)
- ptr = ptr->l_blink;
- return ptr;
- }
-
- /*
- * glookup looks up id in global symbol table and returns pointer to
- * to it if found or NULL if not present.
- */
- static struct tgentry *glookup(id)
- char *id;
- {
- register struct tgentry *ptr;
-
- ptr = ghash[ghasher(id)];
- while (ptr != NULL && ptr->g_name != id) {
- ptr = ptr->g_blink;
- }
- return ptr;
- }
-
- /*
- * clookup looks up id in constant symbol table and returns pointer to
- * to it if found or NULL if not present.
- */
- static struct tcentry *clookup(id,flag)
- char *id;
- int flag;
- {
- register struct tcentry *ptr;
-
- ptr = chash[chasher(id)];
- while (ptr != NULL && (ptr->c_name != id || ptr->c_flag != flag))
- ptr = ptr->c_blink;
-
- return ptr;
- }
-
- /*
- * klookup looks up keyword named by id in keyword table and returns
- * its number (keyid).
- */
- int klookup(id)
- register char *id;
- {
- register struct keyent *kp;
-
- for (kp = keytab; kp->keyid >= 0; kp++)
- if (strcmp(kp->keyname,id) == 0)
- return (kp->keyid);
-
- return 0;
- }
-
- #ifdef DeBugTrans
- /*
- * ldump displays local symbol table to stdout.
- */
-
- novalue ldump()
- {
- register int i;
- register struct tlentry *lptr;
-
- fprintf(stderr,"Dump of local symbol table (%d entries)\n",lfree-ltable);
- fprintf(stderr," loc blink id (name) flags\n");
- for (i = 0; i < lhsize; i++)
- for (lptr = lhash[i]; lptr != NULL; lptr = lptr->l_blink)
- fprintf(stderr,"%5d %5d %5d %20s %7o\n", lptr-ltable,
- lptr->l_blink, lptr->l_name, lptr->l_name, lptr->l_flag);
- fflush(stderr);
-
- }
-
- /*
- * gdump displays global symbol table to stdout.
- */
-
- novalue gdump()
- {
- register int i;
- register struct tgentry *gptr;
-
- fprintf(stderr,"Dump of global symbol table (%d entries)\n",
- (int)(gfree-gtable));
- fprintf(stderr," loc blink id (name) flags nargs\n");
- for (i = 0; i < ghsize; i++)
- for (gptr = ghash[i]; gptr != NULL; gptr = gptr->g_blink)
- fprintf(stderr,"%5d %5d %5d %20s %7o %8d\n", gptr-gtable,
- gptr->g_blink, gptr->g_name, gptr->g_name,
- gptr->g_flag, gptr->g_nargs);
- fflush(stderr);
- }
-
- /*
- * cdump displays constant symbol table to stdout.
- */
-
- novalue cdump()
- {
- register int i;
- register struct tcentry *cptr;
-
- fprintf(stderr,"Dump of constant symbol table (%d entries)\n",ctfree-ctable);
- fprintf(stderr," loc blink id (name) flags\n");
- for (i = 0; i < chsize; i++)
- for (cptr = chash[i]; cptr != NULL; cptr = cptr->c_blink)
- fprintf(stderr,"%5d %5d %5d %20s %7o\n", cptr-ctable,
- cptr->c_blink, cptr->c_name, cptr->c_name, cptr->c_flag);
- fflush(stderr);
- }
- #endif /* DeBugTrans */
-
- /*
- * alcloc allocates a local symbol table entry, fills in fields with
- * specified values and returns offset of new entry.
- */
- static struct tlentry *alcloc(blink, name, flag)
- struct tlentry *blink;
- char *name;
- int flag;
- {
- register struct tlentry *lp;
-
- if (lfree >= <able[lsize])
- tsyserr("out of local symbol table space");
- lp = lfree++;
- lp->l_blink = blink;
- lp->l_name = name;
- lp->l_flag = flag;
- return lp;
- }
-
- /*
- * alcglob allocates a global symbol table entry, fills in fields with
- * specified values and returns offset of new entry.
- */
- static struct tgentry *alcglob(blink, name, flag, nargs)
- struct tgentry *blink;
- char *name;
- int flag, nargs;
- {
- register struct tgentry *gp;
-
- if (gfree >= >able[gsize])
- tsyserr("out of global symbol table space");
- gp = gfree++;
- gp->g_blink = blink;
- gp->g_name = name;
- gp->g_flag = flag;
- gp->g_nargs = nargs;
- return gp;
- }
-
- /*
- * alclit allocates a constant symbol table entry, fills in fields with
- * specified values and returns offset of new entry.
- */
- static struct tcentry *alclit(blink, name, len, flag)
- struct tcentry *blink;
- char *name;
- int len, flag;
- {
- register struct tcentry *cp;
-
- if (ctfree >= &ctable[csize])
- tsyserr("out of constant table space");
- cp = ctfree++;
- cp->c_blink = blink;
- cp->c_name = name;
- cp->c_length = len;
- cp->c_flag = flag;
- return cp;
- }
-
- /*
- * lout dumps local symbol table to fd, which is a .u1 file.
- */
- novalue lout(fd)
- FILE *fd;
- {
- register int i;
- register struct tlentry *lp;
-
- i = 0;
- for (lp = ltable; lp < lfree; lp++)
- writecheck(fprintf(fd, "\tlocal\t%d,%06o,%s\n",
- i++, lp->l_flag, lp->l_name));
- }
-
- /*
- * cout dumps constant symbol table to fd, which is a .u1 file.
- */
- novalue cout(fd)
- FILE *fd;
- {
- register int l;
- register char *c;
- register struct tcentry *cp;
- int i;
-
- i = 0;
- for (cp = ctable; cp < ctfree; cp++) {
- writecheck(fprintf(fd, "\tcon\t%d,%06o", i++, cp->c_flag));
- if (cp->c_flag & F_IntLit)
- writecheck(fprintf(fd, ",%d,%s\n", strlen(cp->c_name), cp->c_name));
- else if (cp->c_flag & F_RealLit)
- writecheck(fprintf(fd, ",%s\n", cp->c_name));
- else {
- c = cp->c_name;
- l = cp->c_length - 1;
- writecheck(fprintf(fd, ",%d", l));
- while (l--)
- writecheck(fprintf(fd, ",%03o", *c++ & 0377));
- writecheck(putc('\n', fd));
- }
- }
- }
-
- /*
- * rout dumps a record declaration for name to file fd, which is a .u2 file.
- */
- novalue rout(fd,name)
- FILE *fd;
- char *name;
- {
- register int i;
- register struct tlentry *lp;
-
- writecheck(fprintf(fd, "record\t%s,%d\n", name, (int)(lfree-ltable)));
- i = 0;
- for (lp = ltable; lp < lfree; lp++)
- writecheck(fprintf(fd, "\t%d,%s\n", i++, lp->l_name));
- }
-
- /*
- * gout writes various items to fd, which is a .u2 file. These items
- * include: implicit status, tracing activation, link directives,
- * and the global table.
- */
- novalue gout(fd)
- FILE *fd;
- {
- register int i;
- register char *name;
- register struct tgentry *gp;
- struct lfile *lfl;
-
- if (uwarn)
- name = "error";
- else
- name = "local";
- writecheck(fprintf(fd, "impl\t%s\n", name));
- if (trace)
- writecheck(fprintf(fd, "trace\n"));
-
- lfl = lfiles;
- while (lfl) {
-
- #if MVS
- writecheck(fprintf(fd,"link\t%s\n",lfl->lf_name));
- #else /* MVS */
- writecheck(fprintf(fd,"link\t%s.u1\n",lfl->lf_name));
- #endif /* MVS */
-
- lfl = lfl->lf_link;
- }
- lfiles = 0;
- writecheck(fprintf(fd, "global\t%d\n", (int)(gfree-gtable)));
- i = 0;
- for (gp = gtable; gp < gfree; gp++)
- writecheck(fprintf(fd, "\t%d,%06o,%s,%d\n", i++, gp->g_flag,
- gp->g_name, gp->g_nargs));
- }
- #endif /* VarTran */
-