home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / pi1 / case.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  3KB  |  190 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #
  3. /*
  4.  * pi - Pascal interpreter code translator
  5.  *
  6.  * Charles Haley, Bill Joy UCB
  7.  * Version 1.2 January 1979
  8.  */
  9.  
  10. #include "0.h"
  11. #include "tree.h"
  12. #include "opcode.h"
  13.  
  14. /*
  15.  * The structure used to
  16.  * hold information about
  17.  * each case label.
  18.  */
  19. struct ct {
  20.     long    clong;
  21.     int    cline;
  22. };
  23.  
  24. /*
  25.  * Caseop generates the
  26.  * pascal case statement code
  27.  */
  28. caseop(r)
  29.     int *r;
  30. {
  31.     register struct nl *p;
  32.     register struct ct *ctab;
  33.     register *cs;
  34.     int *cl;
  35.     double low, high;
  36.     int *brtab;
  37.     char *brtab0;
  38.     char *csend;
  39.     int w, i, j, m, n;
  40.     int nr, goc;
  41.  
  42.     goc = gocnt;
  43.     /*
  44.      * Obtain selector attributes:
  45.      *    p    type
  46.      *    w    width
  47.      *    low    lwb(p)
  48.      *    high    upb(p)
  49.      */
  50.     p = rvalue(r[2], NIL);
  51.     if (p != NIL) {
  52.         if (isnta(p, "bcsi")) {
  53.             error("Case selectors cannot be %ss", nameof(p));
  54.             p = NIL;
  55.         } else {
  56.             cl = p;
  57.             if (p->class != RANGE)
  58.                 cl = p->type;
  59.             if (cl == NIL)
  60.                 p = NIL;
  61.             else {
  62.                 w = width(p);
  63. #ifdef DEBUG
  64.                 if (hp21mx)
  65.                     w = 2;
  66. #endif
  67.                 low = cl->range[0];
  68.                 high = cl->range[1];
  69.             }
  70.         }
  71.     }
  72.     /*
  73.      * Count # of cases
  74.      */
  75.     n = 0;
  76.     for (cl = r[3]; cl != NIL; cl = cl[2]) {
  77.         cs = cl[1];
  78.         if (cs == NIL)
  79.             continue;
  80.         for (cs = cs[2]; cs != NIL; cs = cs[2])
  81.             n++;
  82.     }
  83.     /*
  84.      * Allocate case table space
  85.      */
  86.     ctab = i = alloc(n * sizeof *ctab);
  87.     if (i == -1) {
  88.         error("Ran out of memory (case)");
  89.         pexit(DIED);
  90.     }
  91.     /*
  92.      * Check the legality of the
  93.      * labels and count the number
  94.      * of good labels
  95.      */
  96.     m = 0;
  97.     for (cl = r[3]; cl != NIL; cl = cl[2]) {
  98.         cs = cl[1];
  99.         if (cs == NIL)
  100.             continue;
  101.         line = cs[1];
  102.         for (cs = cs[2]; cs != NIL; cs = cs[2]) {
  103.             gconst(cs[1]);
  104.             if (p == NIL || con.ctype == NIL)
  105.                 continue;
  106.             if (incompat(con.ctype, p, NIL)) {
  107.                 cerror("Case label type clashed with case selector expression type");
  108.                 continue;
  109.             }
  110.             if (con.crval < low || con.crval > high) {
  111.                 error("Case label out of range");
  112.                 continue;
  113.             }
  114.             ctab[m].clong = con.crval;
  115.             ctab[m].cline = line;
  116.             m++;
  117.         }
  118.     }
  119.  
  120.     /*
  121.      * Check for duplicate labels
  122.      */
  123.     for (i = 0; i < m; i++)
  124.         for (j = 0; j < m; j++)
  125.             if (ctab[i].clong == ctab[j].clong) {
  126.                 if (i == j)
  127.                     continue;
  128.                 if (j < i)
  129.                     break;
  130.                 error("Multiply defined label in case, lines %d and %d", ctab[i].cline, ctab[j].cline);
  131.             }
  132.     /*
  133.      * Put out case operator and
  134.      * leave space for the
  135.      * branch table
  136.      */
  137.     if (p != NIL) {
  138.         put2(O_CASE1OP + (w >> 1), n);
  139.         brtab = brtab0 = lc;
  140.         putspace(n * 2);
  141.         put1(O_CASEBEG);
  142.         for (i=0; i<m; i++)
  143.             put3(O_CASE1 + (w >> 1), ctab[i].clong);
  144.         put1(O_CASEEND);
  145.     }
  146.     csend = getlab();
  147.     put2(O_TRA, csend);
  148.     /*
  149.      * Free the case
  150.      * table space.
  151.      */
  152.     free(ctab);
  153.     /*
  154.      * Generate code for each
  155.      * statement. Patch branch
  156.      * table to beginning of each
  157.      * statement and follow each
  158.      * statement with a branch back
  159.      * to the TRA above.
  160.      */
  161.     nr = 1;
  162.     for (cl = r[3]; cl != NIL; cl = cl[2]) {
  163.         cs = cl[1];
  164.         if (cs == NIL)
  165.             continue;
  166.         if (p != NIL)
  167.             for (cs = cs[2]; cs != NIL; cs = cs[2]) {
  168.                 patchfil(brtab - 1, lc - brtab0);
  169.                 brtab++;
  170.             }
  171.         cs = cl[1];
  172.         putcnt();
  173.         level++;
  174.         statement(cs[3]);
  175.         nr =& noreach;
  176.         noreach = 0;
  177.         put2(O_TRA, csend);
  178.         level--;
  179.         if (gotos[cbn])
  180.             ungoto();
  181.     }
  182.     /*
  183.      * Patch the termination branch
  184.      */
  185.     patch(csend);
  186.     noreach = nr;
  187.     if (goc != gocnt)
  188.         putcnt();
  189. }
  190.