home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / calc / part02 / label.c < prev   
C/C++ Source or Header  |  1992-05-09  |  4KB  |  177 lines

  1. /*
  2.  * Copyright (c) 1992 David I. Bell
  3.  * Permission is granted to use, distribute, or modify this source,
  4.  * provided that this copyright notice remains intact.
  5.  *
  6.  * Label handling routines.
  7.  */
  8.  
  9. #include "calc.h"
  10. #include "token.h"
  11. #include "label.h"
  12. #include "string.h"
  13. #include "opcodes.h"
  14. #include "func.h"
  15.  
  16. static long labelcount;            /* number of user labels defined */
  17. static STRINGHEAD labelnames;        /* list of user label names */
  18. static LABEL labels[MAXLABELS];        /* list of user labels */
  19.  
  20.  
  21. /*
  22.  * Initialize the table of labels for a function.
  23.  */
  24. void
  25. initlabels()
  26. {
  27.     labelcount = 0;
  28.     initstr(&labelnames);
  29. }
  30.  
  31.  
  32. /*
  33.  * Define a user named label to have the offset of the next opcode.
  34.  */
  35. void
  36. definelabel(name)
  37.     char *name;            /* label name */
  38. {
  39.     register LABEL *lp;        /* current label */
  40.     long i;                /* current label index */
  41.  
  42.     i = findstr(&labelnames, name);
  43.     if (i >= 0) {
  44.         lp = &labels[i];
  45.         if (lp->l_offset) {
  46.             scanerror(T_NULL, "Label \"%s\" is multiply defined",
  47.                 name);
  48.             return;
  49.         }
  50.         setlabel(lp);
  51.         return;
  52.     }
  53.     if (labelcount >= MAXLABELS) {
  54.         scanerror(T_NULL, "Too many labels in use");
  55.         return;
  56.     }
  57.     lp = &labels[labelcount++];
  58.     lp->l_chain = 0;
  59.     lp->l_offset = curfunc->f_opcodecount;
  60.     lp->l_name = addstr(&labelnames, name);
  61.     clearopt();
  62. }
  63.  
  64.  
  65. /*
  66.  * Add the offset corresponding to the specified user label name to the
  67.  * opcode table for a function. If the label is not yet defined, then a
  68.  * chain of undefined offsets is built using the offset value, and it
  69.  * will be fixed up when the label is defined.
  70.  */
  71. void
  72. addlabel(name)
  73.     char *name;            /* user symbol name */
  74. {
  75.     register LABEL *lp;        /* current label */
  76.     long i;                /* counter */
  77.  
  78.     for (i = labelcount, lp = labels; --i >= 0; lp++) {
  79.         if (strcmp(name, lp->l_name))
  80.             continue;
  81.         uselabel(lp);
  82.         return;
  83.     }
  84.     if (labelcount >= MAXLABELS) {
  85.         scanerror(T_NULL, "Too many labels in use");
  86.         return;
  87.     }
  88.     lp = &labels[labelcount++];
  89.     lp->l_offset = 0;
  90.     lp->l_chain = curfunc->f_opcodecount;
  91.     lp->l_name = addstr(&labelnames, name);
  92.     addop(0);
  93. }
  94.  
  95.  
  96. /*
  97.  * Check to make sure that all labels are defined.
  98.  */
  99. void
  100. checklabels()
  101. {
  102.     register LABEL *lp;        /* label being checked */
  103.     long i;                /* counter */
  104.  
  105.     for (i = labelcount, lp = labels; --i >= 0; lp++) {
  106.         if (lp->l_offset > 0)
  107.             continue;
  108.         scanerror(T_NULL, "Label \"%s\" was never defined",
  109.             lp->l_name);
  110.     }
  111. }
  112.  
  113.  
  114. /*
  115.  * Clear an internal label for use.
  116.  */
  117. void
  118. clearlabel(lp)
  119.     register LABEL *lp;    /* label being cleared */
  120. {
  121.     lp->l_offset = 0;
  122.     lp->l_chain = 0;
  123.     lp->l_name = NULL;
  124. }
  125.  
  126.  
  127. /*
  128.  * Set any label to have the value of the next opcode in the current
  129.  * function being defined.  If there were forward references to it,
  130.  * all such references are patched up.
  131.  */
  132. void
  133. setlabel(lp)
  134.     register LABEL *lp;    /* label being set */
  135. {
  136.     register FUNC *fp;    /* current function */
  137.     long curfix;        /* offset of current location being fixed */
  138.     long nextfix;        /* offset of next location to fix up */
  139.     long offset;        /* offset of this label */
  140.  
  141.     fp = curfunc;
  142.     offset = fp->f_opcodecount;
  143.     nextfix = lp->l_chain;
  144.     while (nextfix > 0) {
  145.         curfix = nextfix;
  146.         nextfix = fp->f_opcodes[curfix];
  147.         fp->f_opcodes[curfix] = offset;
  148.     }
  149.     lp->l_chain = 0;
  150.     lp->l_offset = offset;
  151.     clearopt();
  152. }
  153.  
  154.  
  155. /*
  156.  * Use the specified label at the current location in the function
  157.  * being compiled.  This adds one word to the current function being
  158.  * compiled.  If the label is not yet defined, a patch chain is built
  159.  * so the reference can be fixed when the label is defined.
  160.  */
  161. void
  162. uselabel(lp)
  163.     register LABEL *lp;        /* label being used */
  164. {
  165.     long offset;            /* offset being added */
  166.  
  167.     offset = curfunc->f_opcodecount;
  168.     if (lp->l_offset > 0) {
  169.         addop(lp->l_offset);
  170.         return;
  171.     }
  172.     addop(lp->l_chain);
  173.     lp->l_chain = offset;
  174. }
  175.  
  176. /* END CODE */
  177.