home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / icont / lsym.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  11KB  |  451 lines

  1. /*
  2.  * lsym.c -- functions for symbol table manipulation.
  3.  */
  4.  
  5. #include "link.h"
  6. #include "tproto.h"
  7. #include "tglobals.h"
  8.  
  9. /*
  10.  * Prototypes.
  11.  */
  12.  
  13. hidden struct     fentry *alcfhead
  14.    Params((struct fentry *blink,word name, int fid, struct rentry *rlist));
  15. hidden struct     rentry *alcfrec    
  16.    Params((struct rentry *link,struct gentry *gp, int fnum));
  17. hidden struct     gentry *alcglobal
  18.    Params((struct gentry *blink, word name, int flag,int nargs,int procid));
  19. hidden struct     ientry *alcident    Params((char *nam,int len));
  20.  
  21. int dynoff;            /* stack offset counter for locals */
  22. int argoff;            /* stack offset counter for arguments */
  23. int static1;            /* first static in procedure */
  24. int lstatics = 0;        /* static variable counter */
  25.  
  26. int nlocal;            /* number of locals in local table */
  27. int nconst;            /* number of constants in constant table */
  28. int nfields = 0;        /* number of fields in field table */
  29.  
  30. /*
  31.  * instid - copy the string s to the start of the string free space
  32.  *  and call putident with the length of the string.
  33.  */
  34. word instid(s)
  35. char *s;
  36.    {
  37.    register int l;
  38.    register word indx;
  39.    register char *p;
  40.  
  41.    indx = lsfree;
  42.    p = s;
  43.    l = 0;
  44.    do {
  45.       if (indx >= stsize)
  46.          lsspace = (char *)trealloc(lsspace, NULL, &stsize, 1, 1,
  47.             "string space");
  48.       l++;
  49.  
  50. #if SCCX_MX
  51.       /* Avoid compiler warning */
  52.       } while( (lsspace[indx++] = *p++) != 0);
  53. #else
  54.       } while (lsspace[indx++] = *p++);
  55. #endif                    /* SCCX_MX */
  56.  
  57.    return putident(l, 1);
  58.    }
  59.  
  60. /*
  61.  * putident - install the identifier named by the string starting at lsfree
  62.  *  and extending for len bytes.  The installation entails making an
  63.  *  entry in the identifier hash table and then making an identifier
  64.  *  table entry for it with alcident.  A side effect of installation
  65.  *  is the incrementing of lsfree by the length of the string, thus
  66.  *  "saving" it.
  67.  *
  68.  * Nothing is changed if the identifier has already been installed.
  69.  *
  70.  * If "install" is 0, putident returns -1 for a nonexistent identifier,
  71.  * and does not install it.
  72.  */
  73. word putident(len, install)
  74. int len, install;
  75.    {
  76.    register int hash;
  77.    register char *s;
  78.    register struct ientry *ip;
  79.    int l;
  80.  
  81.    /*
  82.     * Compute hash value by adding bytes and masking result with imask.
  83.     *  (Recall that imask is ihsize-1.)
  84.     */
  85.    s = &lsspace[lsfree];
  86.    hash = 0;
  87.    l = len;
  88.    while (l--)
  89.       hash += *s++;
  90.    l = len;
  91.    s = &lsspace[lsfree];
  92.    hash &= imask;
  93.    /*
  94.     * If the identifier hasn't been installed, install it.
  95.     */
  96.    if ((ip = lihash[hash]) != NULL) {     /* collision */
  97.       for (;;) { /* work down i_blink chain until id is found or the
  98.                      end of the chain is reached */
  99.          if (l == ip->i_length && lexeql(l, s, &lsspace[ip->i_name]))
  100.             return (ip->i_name); /* id is already installed, return it */
  101.          if (ip->i_blink == NULL) { /* end of chain */
  102.             if (install == 0)
  103.                return -1;
  104.             ip->i_blink = alcident(s, l);
  105.             lsfree += l;
  106.             return ip->i_blink->i_name;
  107.             }
  108.          ip = ip->i_blink;
  109.          }
  110.       }
  111.    /*
  112.     * Hashed to an empty slot.
  113.     */
  114.    if (install == 0)
  115.       return -1;
  116.    lihash[hash] = alcident(s, l);
  117.    lsfree += l;
  118.    return lihash[hash]->i_name;
  119.    }
  120.  
  121. /*
  122.  * lexeql - compare two strings of given length.  Returns non-zero if
  123.  *  equal, zero if not equal.
  124.  */
  125. int lexeql(l, s1, s2)
  126. register int l;
  127. register char *s1, *s2;
  128.    {
  129.    while (l--)
  130.       if (*s1++ != *s2++)
  131.          return 0;
  132.    return 1;
  133.    }
  134.  
  135. /*
  136.  * alcident - get the next free identifier table entry, and fill it in with
  137.  *  the specified values.
  138.  */
  139. static struct ientry *alcident(nam, len)
  140. char *nam;
  141. int len;
  142.    {
  143.    register struct ientry *ip;
  144.  
  145.    ip = NewStruct(ientry);
  146.    ip->i_blink = NULL;
  147.    ip->i_name = (word)(nam - lsspace);
  148.    ip->i_length = len;
  149.    return ip;
  150.    }
  151.  
  152. /*
  153.  * locinit -  clear local symbol table.
  154.  */
  155. novalue locinit()
  156.    {
  157.    dynoff = 0;
  158.    argoff = 0;
  159.    nlocal = -1;
  160.    nconst = -1;
  161.    static1 = lstatics;
  162.    }
  163.  
  164. /*
  165.  * putlocal - make a local symbol table entry.
  166.  */
  167. novalue putlocal(n, id, flags, imperror, procname)
  168. int n;
  169. word id;
  170. register int flags;
  171. int imperror;
  172. word procname;
  173.    {
  174.    register struct lentry *lp;
  175.    union {
  176.       struct gentry *gp;
  177.       int bn;
  178.       } p;
  179.  
  180.    if (n >= lsize)
  181.       lltable  = (struct lentry *) trealloc(lltable, NULL, &lsize,
  182.          sizeof(struct lentry), 1, "local symbol table");
  183.    if (n > nlocal)
  184.       nlocal = n;
  185.    lp = &lltable[n];
  186.    lp->l_name = id;
  187.    lp->l_flag = flags;
  188.    if (flags == 0) {                /* undeclared */
  189.       if ((p.gp = glocate(id)) != NULL) {    /* check global */
  190.          lp->l_flag = F_Global;
  191.          lp->l_val.global = p.gp;
  192.          }
  193.  
  194.       else if ((p.bn = blocate(id)) != 0) {    /* check for function */
  195.          lp->l_flag = F_Builtin | F_Global;
  196.          lp->l_val.global = putglobal(id, F_Builtin | F_Proc, -1, p.bn);
  197.          }
  198.  
  199.       else {                    /* implicit local */
  200.          if (imperror)
  201.             lwarn(&lsspace[id], "undeclared identifier, procedure ", 
  202.                &lsspace[procname]);
  203.          lp->l_flag = F_Dynamic;
  204.          lp->l_val.offset = ++dynoff;
  205.          }
  206.       }
  207.    else if (flags & F_Global) {            /* global variable */
  208.       if ((p.gp = glocate(id)) == NULL)
  209.          quit("putlocal: global not in global table");
  210.       lp->l_val.global = p.gp;
  211.       }
  212.    else if (flags & F_Argument)            /* procedure argument */
  213.       lp->l_val.offset = ++argoff;
  214.    else if (flags & F_Dynamic)            /* local dynamic */
  215.       lp->l_val.offset = ++dynoff;
  216.    else if (flags & F_Static)            /* local static */
  217.       lp->l_val.staticid = ++lstatics;
  218.    else
  219.       quit("putlocal: unknown flags");
  220.    }
  221.  
  222. /*
  223.  * putglobal - make a global symbol table entry.
  224.  */
  225. struct gentry *putglobal(id, flags, nargs, procid)
  226. word id;
  227. int flags;
  228. int nargs;
  229. int procid;
  230.    {
  231.    register struct gentry *p;
  232.  
  233.    flags |= F_Global;
  234.    if ((p = glocate(id)) == NULL) {    /* add to head of hash chain */
  235.       p = lghash[ghasher(id)];
  236.       lghash[ghasher(id)] = alcglobal(p, id, flags, nargs, procid);
  237.       return lghash[ghasher(id)];
  238.       }
  239.    p->g_flag |= flags;
  240.    p->g_nargs = nargs;
  241.    p->g_procid = procid;
  242.    return p;
  243.    }
  244.  
  245. /*
  246.  * putconst - make a constant symbol table entry.
  247.  */
  248. novalue putconst(n, flags, len, pc, valp)
  249. int n;
  250. int flags, len;
  251. word pc;
  252. union xval *valp;
  253.  
  254.    {
  255.    register struct centry *p;
  256.    if (n >= csize)
  257.       lctable  = (struct centry *) trealloc(lctable, NULL, &csize,
  258.          sizeof(struct centry), 1, "constant table");
  259.    if (nconst < n)
  260.       nconst = n;
  261.    p = &lctable[n];
  262.    p->c_flag = flags;
  263.    p->c_pc = pc;
  264.    if (flags & F_IntLit) {
  265.       p->c_val.ival = valp->ival;
  266.       }
  267.    else if (flags & F_StrLit) {
  268.       p->c_val.sval = valp->sval;
  269.       p->c_length = len;
  270.       }
  271.    else if (flags & F_CsetLit) {
  272.       p->c_val.sval = valp->sval;
  273.       p->c_length = len;
  274.       }
  275.    else    if (flags & F_RealLit)
  276.  
  277. #ifdef Double
  278. /* access real values one word at a time */
  279.     {  int *rp, *rq;    
  280.        rp = (int *) &(p->c_val.rval);
  281.        rq = (int *) &(valp->rval);
  282.        *rp++ = *rq++;
  283.        *rp   = *rq;
  284.     }
  285. #else                    /* Double */
  286.       p->c_val.rval = valp->rval;
  287. #endif                    /* Double */
  288.  
  289.    else
  290.       fprintf(stderr, "putconst: bad flags: %06o %011lo\n", flags, valp->ival);
  291.    }
  292.  
  293. /*
  294.  * putfield - make a record/field table entry.
  295.  */
  296. novalue putfield(fname, gp, fnum)
  297. word fname;
  298. struct gentry *gp;
  299. int fnum;
  300.    {
  301.    register struct fentry *fp;
  302.    register struct rentry *rp, *rp2;
  303.    word hash;
  304.  
  305.    fp = flocate(fname);
  306.    if (fp == NULL) {        /* create a field entry */
  307.       nfields++;
  308.       hash = fhasher(fname);
  309.       fp = lfhash[hash];
  310.       lfhash[hash] = alcfhead(fp, fname, nfields, alcfrec((struct rentry *)NULL,
  311.          gp, fnum));
  312.       return;
  313.       }
  314.    rp = fp->f_rlist;                /* found field entry; */
  315.    if (rp->r_gp->g_procid > gp->g_procid) {    /* find spot in record list */
  316.       fp->f_rlist = alcfrec(rp, gp, fnum);
  317.       return;
  318.       }
  319.    while (rp->r_gp->g_procid < gp->g_procid) {    /* keep record list ascending */
  320.       if (rp->r_link == NULL) {
  321.          rp->r_link = alcfrec((struct rentry *)NULL, gp, fnum);
  322.          return;
  323.          }
  324.       rp2 = rp;
  325.       rp = rp->r_link;
  326.       }
  327.    rp2->r_link = alcfrec(rp, gp, fnum);
  328.    }
  329.  
  330. /*
  331.  * glocate - lookup identifier in global symbol table, return NULL
  332.  *  if not present.
  333.  */
  334. struct gentry *glocate(id)
  335. word id;
  336.    {
  337.    register struct gentry *p;
  338.  
  339.    p = lghash[ghasher(id)];
  340.    while (p != NULL && p->g_name != id)
  341.       p = p->g_blink;
  342.    return p;
  343.    }
  344.  
  345. /*
  346.  * flocate - lookup identifier in field table.
  347.  */
  348. struct fentry *flocate(id)
  349. word id;
  350.    {
  351.    register struct fentry *p;
  352.  
  353.    p = lfhash[fhasher(id)];
  354.    while (p != NULL && p->f_name != id)
  355.       p = p->f_blink;
  356.    return p;
  357.    }
  358.  
  359. /*
  360.  * alcglobal - create a new global symbol table entry.
  361.  */
  362. static struct gentry *alcglobal(blink, name, flag, nargs, procid)
  363. struct gentry *blink;
  364. word name;
  365. int flag;
  366. int nargs;
  367. int procid;
  368.    {
  369.    register struct gentry *gp;
  370.  
  371.    gp = NewStruct(gentry);
  372.    gp->g_blink = blink;
  373.    gp->g_name = name;
  374.    gp->g_flag = flag;
  375.    gp->g_nargs = nargs;
  376.    gp->g_procid = procid;
  377.    gp->g_next = NULL;
  378.    if (lgfirst == NULL) {
  379.       lgfirst = gp;
  380.       gp->g_index = 0;
  381.       }
  382.    else {
  383.       lglast->g_next = gp;
  384.       gp->g_index = lglast->g_index + 1;
  385.       }
  386.    lglast = gp;
  387.    return gp;
  388.    }
  389.  
  390. /*
  391.  * alcfhead - allocate a field table header.
  392.  */
  393. static struct fentry *alcfhead(blink, name, fid, rlist)
  394. struct fentry *blink;
  395. word name;
  396. int fid;
  397. struct rentry *rlist;
  398.    {
  399.    register struct fentry *fp;
  400.  
  401.    fp = NewStruct(fentry);
  402.    fp->f_blink = blink;
  403.    fp->f_name = name;
  404.    fp->f_fid = fid;
  405.    fp->f_rlist = rlist;
  406.    fp->f_nextentry = NULL;
  407.    if (lffirst == NULL)
  408.       lffirst = fp;
  409.    else
  410.       lflast->f_nextentry = fp;
  411.    lflast = fp;
  412.    return fp;
  413.    }
  414.  
  415. /*
  416.  * alcfrec - allocate a field table record list element.
  417.  */
  418. static struct rentry *alcfrec(link, gp, fnum)
  419. struct rentry *link;
  420. struct gentry *gp;
  421. int fnum;
  422.    {
  423.    register struct rentry *rp;
  424.  
  425.    rp = NewStruct(rentry);
  426.    rp->r_link = link;
  427.    rp->r_gp = gp;
  428.    rp->r_fnum = fnum;
  429.    return rp;
  430.    }
  431.  
  432. /*
  433.  * blocate - search for a function. The search is linear to make
  434.  *  it easier to add/delete functions. If found, returns index+1 for entry.
  435.  */
  436.  
  437. int blocate(s_indx)
  438. word s_indx;
  439.    {
  440. register char *s;
  441.    register int i;
  442.    extern char *ftable[];
  443.    extern int ftbsize;
  444.  
  445.    s = &lsspace[s_indx];
  446.    for (i = 0; i < ftbsize; i++)
  447.       if (strcmp(ftable[i], s) == 0)
  448.          return i + 1;
  449.    return 0;
  450.    }
  451.