home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / icon / dos / src / icont / lsym.c < prev    next >
C/C++ Source or Header  |  1992-02-10  |  10KB  |  419 lines

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