home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / pascal / src / case.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  6.2 KB  |  269 lines

  1. /*-
  2.  * Copyright (c) 1980 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)case.c    5.3 (Berkeley) 4/16/91";
  36. #endif /* not lint */
  37.  
  38. #include "whoami.h"
  39. #include "0.h"
  40. #include "tree.h"
  41. #include "opcode.h"
  42. #include "tree_ty.h"
  43.  
  44. /*
  45.  * The structure used to
  46.  * hold information about
  47.  * each case label.
  48.  */
  49. struct ct {
  50.     long    clong;
  51.     int    cline;
  52. };
  53.  
  54. #ifdef OBJ
  55. /*
  56.  * Caseop generates the
  57.  * pascal case statement code
  58.  */
  59. caseop(rnode)
  60.     WHI_CAS *rnode;
  61. {
  62.     register struct nl *p;
  63.     register struct ct *ctab;
  64.     register struct tnode *cs;
  65.     extern char *lc;
  66.     double low, high;
  67.     short *brtab;
  68.     char *brtab0;
  69.     char *csend;
  70.     int w, j, m, n;
  71.     int goc;
  72.     bool nr;
  73.  
  74.     goc = gocnt;
  75.     /*
  76.      * Obtain selector attributes:
  77.      *    p    type
  78.      *    w    width
  79.      *    low    lwb(p)
  80.      *    high    upb(p)
  81.      */
  82.     p = rvalue(rnode->expr, NLNIL , RREQ );
  83.  
  84.     {
  85.         register struct nl    *cl;
  86.  
  87.     if (p != NLNIL) {
  88.         if (isnta(p, "bcsi")) {
  89.             error("Case selectors cannot be %ss", nameof(p));
  90.             p = NLNIL;
  91.         } else {
  92.             cl = p;
  93.             if (p->class != (char) RANGE)
  94.                 cl = p->type;
  95.             if (cl == NLNIL)
  96.                 p = NLNIL;
  97.             else {
  98.                 w = width(p);
  99. #ifdef DEBUG
  100.                 if (hp21mx)
  101.                     w = 2;
  102. #endif
  103.                 low = cl->range[0];
  104.                 high = cl->range[1];
  105.             }
  106.         }
  107.     }
  108.     } /* local declaration */
  109.     {
  110.         struct tnode    *cl;    /* list node */
  111.     /*
  112.      * Count # of cases
  113.      */
  114.     n = 0;
  115.     for (cl = rnode->stmnt_list; cl != TR_NIL;
  116.         cl = cl->list_node.next) {
  117.         cs = cl->list_node.list;;
  118.         if (cs == TR_NIL)
  119.             continue;
  120.         for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
  121.                 cs = cs->list_node.next)
  122.             n++;
  123.     }
  124.     } /* local declaration */
  125.     /*
  126.      * Allocate case table space
  127.      */
  128.     {
  129.         char *i;
  130.     i = malloc((unsigned) n * sizeof *ctab);
  131.     if (i == 0) {
  132.         error("Ran out of memory (case)");
  133.         pexit(DIED);
  134.     }
  135.     ctab = (struct ct *) i;
  136.     }
  137.     /*
  138.      * Check the legality of the
  139.      * labels and count the number
  140.      * of good labels
  141.      */
  142.     {
  143.         register struct tnode *cl;
  144.     m = 0;
  145.     for (cl = rnode->stmnt_list; cl != TR_NIL;
  146.         cl = cl->list_node.next) {
  147.         cs = cl->list_node.list;
  148.         if (cs == TR_NIL)
  149.             continue;
  150.         line = cs->c_stmnt.line_no;
  151.         for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
  152.                 cs =  cs->list_node.next) {
  153.             gconst(cs->list_node.list);
  154.             if (p == NLNIL || con.ctype == NIL)
  155.                 continue;
  156.             if (incompat(con.ctype, p, TR_NIL )) {
  157.                 cerror("Case label type clashed with case selector expression type");
  158.                 continue;
  159.             }
  160.             if (con.crval < low || con.crval > high) {
  161.                 error("Case label out of range");
  162.                 continue;
  163.             }
  164.             ctab[m].clong = con.crval;
  165.             ctab[m].cline = line;
  166.             m++;
  167.         }
  168.     }
  169.     } /* decl of cl */
  170.     {
  171.         register int i;
  172.     /*
  173.      * Check for duplicate labels
  174.      */
  175.     for (i = 0; i < m; i++)
  176.         for (j = 0; j < m; j++)
  177.             if (ctab[i].clong == ctab[j].clong) {
  178.                 if (i == j)
  179.                     continue;
  180.                 if (j < i)
  181.                     break;
  182.                 error("Multiply defined label in case, lines %d and %d", (char *) ctab[i].cline, (char *) ctab[j].cline);
  183.             }
  184.     }
  185.     /*
  186.      * Put out case operator and
  187.      * leave space for the
  188.      * branch table
  189.      */
  190.     if (p != NLNIL) {
  191.         (void) put(2, O_CASE1OP + (w >> 1), n);
  192.         brtab0 = lc;
  193.         brtab = ((short *) brtab0);
  194.         putspace(n * 2);
  195.         (void) put(1, O_CASEBEG);
  196.         {
  197.             int i;
  198.         for (i=0; i<m; i++)
  199.             if (w <= 2)
  200.                 (void) put(2 ,O_CASE1 + (w >> 1), (int)ctab[i].clong);
  201.             else
  202.                 (void) put(2 ,O_CASE4, ctab[i].clong);
  203.         }
  204.         (void) put(1, O_CASEEND);
  205.     }
  206.     csend = getlab();
  207.     (void) put(2, O_TRA, csend);
  208.     /*
  209.      * Free the case
  210.      * table space.
  211.      */
  212.     free((char *) ctab);
  213.     /*
  214.      * Generate code for each
  215.      * statement. Patch branch
  216.      * table to beginning of each
  217.      * statement and follow each
  218.      * statement with a branch back
  219.      * to the TRA above.
  220.      */
  221.     {
  222.         register struct tnode *cl;
  223.     nr = TRUE;
  224.     for (cl = rnode->stmnt_list; cl != TR_NIL;
  225.             cl = cl->list_node.next) {
  226.         cs = cl->list_node.list;
  227.         if (cs == TR_NIL)
  228.             continue;
  229.         if (p != NLNIL)
  230.             for (cs = cs->c_stmnt.const_list; cs != TR_NIL;
  231.                 cs =  cs->list_node.next) {
  232. #ifdef ADDR16
  233.                 patchfil(((char *) (brtab - 1)),
  234.                     (long)(lc - brtab0), 1);
  235. #endif ADDR16
  236. #ifdef ADDR32
  237.                 
  238.                 patchfil( ((unsigned long) (brtab - 1)),
  239.                     (long)(lc - brtab0), 1);
  240. #endif ADDR32
  241.                 brtab++;
  242.             }
  243.         cs = cl->list_node.list;
  244.         putcnt();
  245.         level++;
  246.         statement(cs->c_stmnt.stmnt);
  247.         nr = (bool)(noreach && nr);
  248.         noreach = FALSE;
  249.         (void) put(2, O_TRA, csend);
  250.         level--;
  251.         if (gotos[cbn])
  252.             ungoto();
  253.     }
  254.     } /* decl of cl */
  255.     /*
  256.      * Patch the termination branch
  257.      */
  258. #ifdef ADDR16
  259.     patch((char *) csend);
  260. #endif ADDR16
  261. #ifdef ADDR32
  262.     patch((unsigned long) csend);
  263. #endif ADDR32
  264.     noreach = nr;
  265.     if (goc != gocnt)
  266.         putcnt();
  267. }
  268. #endif OBJ
  269.