home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 163_01 / cc31.c < prev    next >
Text File  |  1990-11-20  |  9KB  |  310 lines

  1. /*
  2. ** lval[0] - symbol table address, else 0 for constant
  3. ** lval[1] - type of indirect obj to fetch, else 0 for static
  4. ** lval[2] - type of pointer or array, else 0 for all other
  5. ** lval[3] - true if constant expression
  6. ** lval[4] - value of constant expression
  7. ** lval[5] - true if secondary register altered
  8. ** lval[6] - function address of highest/last binary operator
  9. ** lval[7] - stage address of "oper 0" code, else 0
  10. */
  11.  
  12. /*
  13. ** skim over terms adjoining || and && operators
  14. */
  15. skim(opstr, testfunc, dropval, endval, heir, lval)
  16.   char *opstr;
  17.   int testfunc, dropval, endval, heir, lval[]; {
  18.   int k, hits, droplab, endlab;
  19.   hits=0;
  20.   while(1) {
  21.     k=plunge1(heir, lval);
  22.     if(nextop(opstr))  {
  23.       bump(opsize);
  24.       if(hits==0)  {
  25.         hits=1;
  26.         droplab=getlabel();
  27.         }
  28.       dropout(k, testfunc, droplab, lval);
  29.       }
  30.     else if(hits)  {
  31.       dropout(k, testfunc, droplab, lval);
  32.       const(endval);
  33.       jump(endlab=getlabel());
  34.       postlabel(droplab);
  35.       const(dropval);
  36.       postlabel(endlab);
  37.       lval[1]=lval[2]=lval[3]=lval[7]=0;
  38.       return 0;
  39.       }
  40.     else return k;
  41.     }
  42.   }
  43.  
  44. /*
  45. ** test for early dropout from || or && evaluations
  46. */
  47. dropout(k, testfunc, exit1, lval) int k, testfunc, exit1, lval[];  {
  48.   if(k) rvalue(lval);
  49.   else if(lval[3]) const(lval[4]);
  50.   testfunc(exit1); /* jumps on false */
  51.   }
  52.  
  53. /*
  54. ** plunge to a lower level
  55. */
  56. plunge(opstr, opoff, heir, lval)
  57.   char *opstr;
  58.   int opoff, heir, lval[];  {
  59.   int k, lval2[8];
  60.   k=plunge1(heir, lval);
  61.   if(nextop(opstr)==0) return k;
  62.   if(k) rvalue(lval);
  63.   while(1)  {
  64.     if(nextop(opstr))  {
  65.       bump(opsize);
  66.       opindex=opindex+opoff;
  67.       plunge2(op[opindex], op2[opindex], heir, lval, lval2);
  68.       }
  69.     else return 0;
  70.     }
  71.   }
  72.  
  73. /*
  74. ** unary plunge to lower level
  75. */
  76. plunge1(heir, lval) int heir, lval[];  {
  77.   char *before, *start;
  78.   int k;
  79.   setstage(&before, &start);
  80.   k=heir(lval);
  81.   if(lval[3]) clearstage(before,0); /* load constant later */
  82.   return k;
  83.   }
  84.  
  85. /*
  86. ** binary plunge to lower level
  87. */
  88. plunge2(oper, oper2, heir, lval, lval2)
  89.   int oper, oper2, heir, lval[], lval2[];  {
  90.   char *before, *start;
  91.   setstage(&before, &start);
  92.   lval[5]=1;           /* flag secondary register used */
  93.   lval[7]=0;           /* flag as not "... oper 0" syntax */
  94.   if(lval[3])  {       /* constant on left side not yet loaded */
  95.     if(plunge1(heir, lval2)) rvalue(lval2);
  96.     if(lval[4]==0) lval[7]=stagenext;
  97.     const2(lval[4]<<dbltest(lval2, lval));
  98.     }
  99.   else {  /* non-constant on left side */
  100.     push();
  101.     if(plunge1(heir, lval2)) rvalue(lval2);
  102.     if(lval2[3]) {     /* constant on right side */
  103.       if(lval2[4]==0) lval[7]=start;
  104.       if(oper==add)  { /* may test other commutative operators */
  105.         csp=csp+2;
  106.         clearstage(before,0);
  107.         const2(lval2[4]<<dbltest(lval, lval2)); /* load secondary */
  108.         }
  109.       else  {
  110.         const(lval2[4]<<dbltest(lval, lval2));  /* load primary */
  111.         pop();
  112.         }
  113.       }
  114.     else {             /* non-constants on both sides */
  115.       pop();
  116.       if((oper==add)|(oper==sub)) {
  117.         if(dbltest(lval,lval2)) doublereg();
  118.         if(dbltest(lval2,lval)) {
  119.           swap();
  120.           doublereg();
  121.           if(oper==sub) swap();
  122.           }
  123.         }
  124.       }
  125.     }
  126.   if(oper) {
  127.     if(lval[3]=lval[3]&lval2[3]) {
  128.       lval[4]=calc(lval[4], oper, lval2[4]);
  129.       clearstage(before, 0);
  130.       lval[5]=0;
  131.       }
  132.     else {
  133.       if((lval[2]==0)&(lval2[2]==0)) {
  134.         oper();
  135.         lval[6]=oper;   /* identify the operator */
  136.         }
  137.       else {
  138.         oper2();
  139.         lval[6]=oper2;  /* identify the operator */
  140.         }
  141.       }
  142.     if(oper==sub) {
  143.       if((lval[2]==CINT)&(lval2[2]==CINT)) {
  144.         swap();
  145.         const(1);
  146.         asr();  /** div by 2 **/
  147.         }
  148.       }
  149.     if((oper==sub)|(oper==add)) result(lval, lval2);
  150.     }
  151.   }
  152.  
  153. calc(left, oper, right) int left, oper, right; {
  154.        if(oper ==  or) return (left  |  right);
  155.   else if(oper == xor) return (left  ^  right);
  156.   else if(oper == and) return (left  &  right);
  157.   else if(oper ==  eq) return (left  == right);
  158.   else if(oper ==  ne) return (left  != right);
  159.   else if(oper ==  le) return (left  <= right);
  160.   else if(oper ==  ge) return (left  >= right);
  161.   else if(oper ==  lt) return (left  <  right);
  162.   else if(oper ==  gt) return (left  >  right);
  163.   else if(oper == asr) return (left  >> right);
  164.   else if(oper == asl) return (left  << right);
  165.   else if(oper == add) return (left  +  right);
  166.   else if(oper == sub) return (left  -  right);
  167.   else if(oper ==mult) return (left  *  right);
  168.   else if(oper == div) return (left  /  right);
  169.   else if(oper == mod) return (left  %  right);
  170.   else return 0;
  171.   }
  172.  
  173. expression(const, val) int *const, *val; {
  174.   int lval[8];
  175.   if(heir1(lval)) rvalue(lval); /* if only lvalue returned, fetch rvalue */
  176.   if(lval[3]) { /* if result is a constant expression . . . */
  177.     *const=1; /* say so */
  178.     *val=lval[4]; /* return its value */
  179.     }
  180.   else *const=0; /* not a constant expression */
  181.   }
  182.  
  183. /*
  184. ** expr ? expr : expr implemented per A. Macpherson letter, DDJ #81
  185. ** (UNIX flavor)
  186. */
  187. heir1(lval)  int lval[];  { /* expect <lvalue> <assignment op> <rvalue> */
  188.   int k,lval2[8], oper;
  189.   k=plunge1(heir2, lval);
  190.   if(lval[3]) const(lval[4]); /* if constant expression, generate the value */
  191.        if(match("|="))  oper=or;
  192.   else if(match("^="))  oper=xor;
  193.   else if(match("&="))  oper=and;
  194.   else if(match("+="))  oper=add;
  195.   else if(match("-="))  oper=sub;
  196.   else if(match("*="))  oper=mult;
  197.   else if(match("/="))  oper=div;
  198.   else if(match("%="))  oper=mod;
  199.   else if(match(">>=")) oper=asr;
  200.   else if(match("<<=")) oper=asl;
  201.   else if(match("="))   oper=0;
  202.   else return k; /* not followed by assignment operator */
  203.   if(k==0) { /* lvalue must be to left of assignment operator:  post error */
  204.     needlval(); /* "must be lvalue" */
  205.     return 0;
  206.     }
  207.   if(lval[1]) { /* if lvalue is not static */
  208.     if(oper) { /* and if operator is not pure assignment */
  209.       push(); /* save the lvalue (address) */
  210.       rvalue(lval); /* fetch the rvalue (value) */
  211.       }
  212.     plunge2(oper, oper, heir1, lval, lval2); /* evaluate right-hand side */
  213.     if(oper) pop(); /* if operator is not pure assignment retrieve lvalue */
  214.     }
  215.   else { /* if lvalue is static */
  216.     if(oper) { /* and if operator is not pure assignment */
  217.       rvalue(lval); /* fetch the rvalue */
  218.       plunge2(oper, oper, heir1, lval, lval2); /* evaluate right-hand side */
  219.       }
  220.     else { /* lvalue is static and operator is pure assignment */
  221.       if(heir1(lval2)) rvalue(lval2); /* evaluate right-hand side */
  222.       lval[5]=lval2[5]; /* copy sec reg status */
  223.       }
  224.     }
  225.   store(lval); /* store the result */
  226.   return 0;
  227.   }
  228.  
  229. /*
  230. ** expr ? expr : expr implemented per A. Macpherson letter, DDJ #81
  231. ** (UNIX flavor)
  232. */
  233. heir2(lval)  int lval[];  { /* expect <lvalue> <assignment op> <rvalue> */
  234.   int k;
  235.   k = plunge1(heir3, lval);
  236.   if(match("?")) {
  237.     int falselab, endlab, val;
  238.     char reg2used, selconst, explconst, sel2;
  239.     falselab = getlabel();
  240.     reg2used = 0;
  241.     if(k) rvalue(lval);
  242.     if(selconst = lval[3]) { /* selector is a constant */
  243.       if(sel2= lval[4]) jump(falselab);
  244.       }
  245.     else {
  246.       testjump(falselab);
  247.       reg2used = lval[5];
  248.       }
  249.     dropout(plunge1(heir3, lval), jump, endlab = getlabel(), lval);
  250.     if(explconst = lval[3]) val = lval[4];
  251.     else reg2used |= lval[5];
  252.     postlabel(falselab);
  253.     needtoken(":");
  254.     if(plunge1(heir3, lval)) rvalue(lval);
  255.     if(lval[3]) {
  256.       const(lval[4]);
  257.       if(selconst && sel2) val = lval[4];
  258.       }
  259.     else reg2used |= lval[5];
  260.     lval[5] = reg2used;
  261.     lval[4] = val;
  262.     lval[3] = selconst && ((!sel2 && explconst) || (sel2 && lval[3]));
  263.     postlabel(endlab);
  264.     return 0;
  265.     }
  266.   return k;
  267.   }
  268.  
  269. heir3(lval)  int lval[];  {
  270.   return skim("||", eq0, 1, 0, heir4, lval);
  271.   }
  272.  
  273. heir4(lval)  int lval[];  {
  274.   return skim("&&", ne0, 0, 1, heir5, lval);
  275.   }
  276.  
  277. heir5(lval)  int lval[];  {
  278.   return plunge("|", 0, heir6, lval);
  279.   }
  280.  
  281. heir6(lval)  int lval[];  {
  282.   return plunge("^", 1, heir7, lval);
  283.   }
  284.  
  285. heir7(lval)  int lval[];  {
  286.   return plunge("&", 2, heir8, lval);
  287.   }
  288.  
  289. heir8(lval)  int lval[];  {
  290.   return plunge("== !=", 3, heir9, lval);
  291.   }
  292.  
  293. heir9(lval)  int lval[];  {
  294.   return plunge("<= >= < >", 5, heir10, lval);
  295.   }
  296.  
  297. heir10(lval)  int lval[];  {
  298.   return plunge(">> <<", 9, heir11, lval);
  299.   }
  300.  
  301. heir11(lval)  int lval[];  {
  302.   return plunge("+ -", 11, heir12, lval);
  303.   }
  304.  
  305. heir12(lval)  int lval[];  {
  306.   return plunge("* / %", 13, heir13, lval);
  307.   }
  308.  
  309.  
  310.