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