1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)pccaseop.c 1.1 08/27/80";
4 
5 #include "whoami.h"
6 #ifdef PC
7     /*
8      *	and the rest of the file
9      */
10 #include "0.h"
11 #include "tree.h"
12 #include "objfmt.h"
13 #include "pcops.h"
14 #include "pc.h"
15     /*
16      *	tcase	[0]	T_CASE
17      *		[1]	lineof "case"
18      *		[2]	expression
19      *		[3]	list of cased statements
20      *			cstat	[0]	T_CSTAT
21      *				[1]	lineof ":"
22      *				[2]	constant list
23      *				[3]	statement
24      */
25 
26 struct ct {
27     long	clong;
28     int		cline;
29 };
30 
31 pccaseop( tcase )
32     int	*tcase;
33     {
34 	struct nl	*exprtype;
35 	struct nl	*rangetype;
36 	long		low;
37 	long		high;
38 	long		exproff;
39 	long		exprctype;
40 	long		count;
41 	long		*cstatlp;
42 	long		*cstatp;
43 	struct ct	*ctab;
44 	long		endlabel;
45 	long		nextlabel;
46 	long		firsttime;
47 	long		*casep;
48 	long		i;
49 	long		nr;
50 	long		goc;
51 
52 	goc = gocnt;
53 	    /*
54 	     *	find out the type of the case expression
55 	     */
56 	line = tcase[1];
57 	codeoff();
58 	exprtype = rvalue( (int *) tcase[2] , NIL  , RREQ );
59 	codeon();
60 	if ( exprtype != NIL ) {
61 	    if ( isnta( exprtype , "bcsi" ) ) {
62 		error("Case selectors cannot be %ss" , nameof( exprtype ) );
63 		exprtype = NIL;
64 	    } else {
65 		if ( exprtype -> class != RANGE ) {
66 		    rangetype = exprtype -> type;
67 		} else {
68 		    rangetype = exprtype;
69 		}
70 		if ( rangetype == NIL ) {
71 		    exprtype = NIL;
72 		} else {
73 		    low = rangetype -> range[0];
74 		    high = rangetype -> range[1];
75 		}
76 	    }
77 	}
78 	if ( exprtype != NIL ) {
79 		/*
80 		 * allocate temporary for case expression
81 		 */
82 	    sizes[cbn].om_off -= sizeof( long );
83 	    exproff = sizes[cbn].om_off;
84 	    putlbracket( ftnno , -sizes[cbn].om_off );
85 	    if ( sizes[cbn].om_off < sizes[cbn].om_max ) {
86 		sizes[cbn].om_max = sizes[cbn].om_off;
87 	    }
88 		/*
89 		 * compute and save the expression
90 		 */
91 	    exprctype = p2type( exprtype );
92 	    putRV( 0 , cbn , exproff , P2INT );
93 	    rvalue( (int *) tcase[2] , NIL  , RREQ );
94 	    putop( P2ASSIGN , exprctype );
95 	    putdot( filename , line );
96 	}
97 	    /*
98 	     *	count the number of cases
99 	     *	and allocate table for cases and lines
100 	     */
101 	count = 0;
102 	for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) {
103 	    cstatp = cstatlp[1];
104 	    if ( cstatp == NIL ) {
105 		continue;
106 	    }
107 	    for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) {
108 		count++;
109 	    }
110 	}
111 	ctab = (struct ct *) malloc( count * sizeof( struct ct ) );
112 	if ( ctab == (struct ct *) -1 ) {
113 	    error("Ran out of memory (case)");
114 	    pexit( DIED );
115 	}
116 	    /*
117 	     * generate code for each case
118 	     */
119 	endlabel = getlab();
120 	nextlabel = getlab();
121 	count = 0;
122 	nr = 1;
123 	for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) {
124 	    cstatp = cstatlp[1];
125 	    if ( cstatp == NIL ) {
126 		continue;
127 	    }
128 	    line = cstatp[1];
129 	    putlab( nextlabel );
130 	    nextlabel = getlab();
131 		/*
132 		 * if it's not any of these, then go to next
133 		 */
134 	    firsttime = 1;
135 	    for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) {
136 		gconst( casep[1] );
137 		if( exprtype == NIL || con.ctype == NIL ) {
138 		    continue;
139 		}
140 		if ( incompat( con.ctype , exprtype , NIL ) ) {
141 		    cerror("Case label type clashed with case selector expression type");
142 		    continue;
143 		}
144 		if ( con.crval < low || con.crval > high ) {
145 		    error("Case label out of range");
146 		    continue;
147 		}
148 		ctab[ count ].clong = con.crval;
149 		ctab[ count ].cline = line;
150 		    /*
151 		     *	check for duplicates
152 		     */
153 		for ( i = 0 ; i < count ; i++ ) {
154 		    if ( ctab[ i ].clong == con.crval ) {
155 			error("Multiply defined label in case, lines %d and %d"
156 				, ctab[ i ].cline , line );
157 		    }
158 		}
159 		putRV( 0 , cbn , exproff , exprctype , 0 );
160 		putleaf( P2ICON , ctab[ count ].clong , 0 , exprctype , 0 );
161 		putop( P2EQ , exprctype );
162 		if ( ! firsttime ) {
163 			/*
164 			 * note the use of !! to get short circuiting
165 			 */
166 		    putop( P2OROR , P2CHAR );
167 		}
168 		firsttime = 0;
169 	    }
170 	    putleaf( P2ICON , nextlabel , 0 , P2INT , 0 );
171 	    putop( P2CBRANCH , P2INT );
172 	    putdot( filename , line );
173 		/*
174 		 * if we get here, we must be in this case
175 		 */
176 	    putcnt();
177 	    level++;
178 	    statement( cstatp[3] );
179 	    nr &= noreach;
180 	    noreach = 0;
181 	    putjbr( endlabel );
182 	    level--;
183 	    if (gotos[cbn]) {
184 		    ungoto();
185 	    }
186 	}
187 	    /*
188 	     *	default action is to call error
189 	     */
190 	putlab( nextlabel );
191 	putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ERROR" );
192 	putleaf( P2ICON , ECASE , 0 , P2INT , 0 );
193 	putRV( 0 , cbn , exproff , P2INT );
194 	putop( P2LISTOP , P2INT );
195 	putop( P2CALL , P2INT );
196 	putdot( filename , line );
197 	putlab( endlabel );
198 	noreach = nr;
199 	if ( goc != gocnt ) {
200 		putcnt();
201 	}
202     }
203 
204 #endif PC
205