mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
1059 lines
34 KiB
Plaintext
1059 lines
34 KiB
Plaintext
1File: EXPR.C Page 1
|
|
1 /*#define DEBUG*/
|
|
2 /*
|
|
3 Copyright 1982
|
|
4 Alcyon Corporation
|
|
5 8716 Production Ave.
|
|
6 San Diego, Ca. 92121
|
|
7 */
|
|
8
|
|
9 #include "parser.h"
|
|
10 int opdontop;
|
|
11 int strassign;
|
|
12
|
|
13 /*
|
|
14 * expr - expression evaluator
|
|
15 * This handles all the expression syntax in C. This is a straight-
|
|
16 * forward operator-stack/oppri scheme for translating infix into
|
|
17 * a binary expression tree.
|
|
18 */
|
|
19 char *expr() /* returns 0 or ptr to node*/
|
|
20 {
|
|
21 register char *p;
|
|
22 register char *opdsave, *oprsave;
|
|
23 register int token, op, oppri, i, opdotsave;
|
|
24 int type, sc;
|
|
25 long size;
|
|
26
|
|
27 opdsave = opdp;
|
|
28 strassign = 0;
|
|
29 oprsave = opp;
|
|
30 opdotsave = opdontop;
|
|
31 if( !opp || !opdp ) {
|
|
32 opp = opstack;
|
|
33 opdp = opdstack;
|
|
34 }
|
|
35 else
|
|
36 opp++;
|
|
37 opp->o_op = STACKEND;
|
|
38 opp->o_pri = STKPRI;
|
|
39 opap = exprp;
|
|
40 opdontop = 0;
|
|
41
|
|
42 while( (token=gettok()) != EOF ) {
|
|
43 switch( token ) {
|
|
44 /*
|
|
45 * the following are the terminal nodes of the expresion tree,
|
|
46 * note that when we see a terminal node, we push it and then go
|
|
47 * and get the next token. When we see an operator, we need to
|
|
48 * check the operator stack to see if we can do a reduction.
|
|
49 */
|
|
50 case CINT:
|
|
51 if( doopd(cnalloc(INT,cvalue)) ) {
|
|
52 exprerr:
|
|
53 if( token == SEMI || token == RCURBR )
|
|
54 pbtok(token);
|
|
55 error("invalid expression");
|
|
56 opdp = opdsave;
|
|
57 opp = oprsave;
|
|
58 opdontop = opdotsave;
|
|
59 return(0);
|
|
1File: EXPR.C Page 2
|
|
60 }
|
|
61 continue;
|
|
62
|
|
63 case CFLOAT: /*[vlh] 3.4*/
|
|
64 if( doopd(fpcnalloc(FLOAT,clvalue)) )
|
|
65 goto exprerr;
|
|
66 continue;
|
|
67
|
|
68 case CLONG:
|
|
69 if( doopd(lcnalloc(LONG,clvalue)) )
|
|
70 goto exprerr;
|
|
71 continue;
|
|
72
|
|
73 case SYMBOL:
|
|
74 if( !((p=csp)->s_attrib&SDEFINED) ) {
|
|
75 if( peek(LPAREN) ) { /*assume function call*/
|
|
76 p->s_sc = EXTERNAL;
|
|
77 p->s_type = FUNCTION|INT;
|
|
78 }
|
|
79 else if( commastop ) /*in initialization?*/
|
|
80 p->s_sc = EXTERNAL;
|
|
81 else
|
|
82 error("undefined symbol: %.8s",p->s_symbol);
|
|
83 p->s_attrib =| SDEFINED;
|
|
84 }
|
|
85 if (p->s_sc==EXTERNAL || function(p->t_type)) {
|
|
86 if (!reducep || p->s_sc==EXTERNAL || peek(LPAREN)) {
|
|
87 p = enalloc(p);
|
|
88 p->t_sc = EXTERNAL;
|
|
89 }
|
|
90 else { /* [vlh] 3.4 if (main).... */
|
|
91 p = cnalloc(CINT,1); /* eval function name */
|
|
92 }
|
|
93 }
|
|
94 else
|
|
95 p=snalloc(p->s_type,p->s_sc,p->s_offset,p->s_dp,p->s_ssp);
|
|
96 if( doopd(p) )
|
|
97 goto exprerr;
|
|
98 continue;
|
|
99
|
|
100 case STRING:
|
|
101 outtstr(cvalue);
|
|
102 if( doopd(snalloc(ARRAY|CHAR,STATIC,cvalue,0,0)) )
|
|
103 goto exprerr;
|
|
104 continue;
|
|
105 /*
|
|
106 * do special checking for unary ops and operators that can be
|
|
107 * either unary or binary operators, such as -, &, *, etc.
|
|
108 */
|
|
109 case RESWORD:
|
|
110 if( cvalue != R_SIZEOF ) {
|
|
111 goto exprerr;
|
|
112 }
|
|
113 token = SIZEOF;
|
|
114 case COMPL:
|
|
115 case NOT:
|
|
116 if( opdontop ) /*can't have: operand unary-op*/
|
|
117 goto exprerr;
|
|
118 break;
|
|
1File: EXPR.C Page 3
|
|
119
|
|
120 case LBRACK:
|
|
121 opdontop = 0;
|
|
122 break;
|
|
123
|
|
124 case RBRACK:
|
|
125 case RPAREN:
|
|
126 if( !opdontop ) /*can't be: operator )*/
|
|
127 goto exprerr;
|
|
128 break;
|
|
129
|
|
130 case PREINC:
|
|
131 if( opdontop ) /*assume its lvalue++*/
|
|
132 token = POSTINC;
|
|
133 break;
|
|
134
|
|
135 case PREDEC:
|
|
136 if( opdontop ) /*assume its lvalue--*/
|
|
137 token = POSTDEC;
|
|
138 break;
|
|
139
|
|
140 case SUB:
|
|
141 if(!opdontop) { /*if no operand, assume unary*/
|
|
142 if( peek(CINT) ) {
|
|
143 cvalue = -cvalue;
|
|
144 continue;
|
|
145 }
|
|
146 if( peek(CLONG) ) {
|
|
147 clvalue = -clvalue;
|
|
148 continue;
|
|
149 }
|
|
150 if( peek(CFLOAT) ) { /*[vlh] 3.4*/
|
|
151 if (!fflag) { /* IEEE format */
|
|
152 if (clvalue & 0x80000000)
|
|
153 clvalue =& 0x7fffffff;
|
|
154 else
|
|
155 clvalue =| 0x80000000;
|
|
156 }
|
|
157 else /* FFP format */
|
|
158 if (clvalue & 0x80)
|
|
159 clvalue =& 0xffffff7f;
|
|
160 else
|
|
161 clvalue =| 0x80;
|
|
162 continue;
|
|
163 }
|
|
164 token = UMINUS;
|
|
165 }
|
|
166 break;
|
|
167
|
|
168 case AND:
|
|
169 if(!opdontop)
|
|
170 token = ADDR;
|
|
171 break;
|
|
172
|
|
173 case MULT:
|
|
174 if( !opdontop )
|
|
175 token = INDR;
|
|
176 break;
|
|
177 /*
|
|
1File: EXPR.C Page 4
|
|
178 * for left parenthesis, we need to see if this is a casting operator.
|
|
179 */
|
|
180
|
|
181 case LPAREN:
|
|
182 if( !opdontop ) { /*see if casting or abstract declarator*/
|
|
183 sc = type = 0;
|
|
184 if( gettype(&sc,&type,&size) ) {
|
|
185 sc = (type == STRUCT) ? dalloc(size) : cdp;
|
|
186 p = snalloc(type,STATIC,0,sc,sc);
|
|
187 p->t_type =| declarator(1);
|
|
188 if( !next(RPAREN) )
|
|
189 goto exprerr;
|
|
190 if( tdp )
|
|
191 p->t_type=addtdtype(tdp,p->t_type,p->t_dp,
|
|
192 &(p->t_ssp));
|
|
193 pushopd(p);
|
|
194 token = CAST;
|
|
195 if( opp->o_op == SIZEOF ) {
|
|
196 opdontop++;
|
|
197 continue;
|
|
198 }
|
|
199 }
|
|
200 }
|
|
201 else /*we've seen (), look for NACALL*/
|
|
202 token = (next(RPAREN)) ? MPARENS : CALL;
|
|
203 break;
|
|
204
|
|
205 case PERIOD:
|
|
206 case APTR:
|
|
207 smember++; /*next token needs to be struct membr*/
|
|
208 strucptr[smember+instruct] = csp->s_struc;
|
|
209 break;
|
|
210
|
|
211 }
|
|
212 /*
|
|
213 * we have seen an operator, get its info and then check the operator
|
|
214 * stack.
|
|
215 */
|
|
216 if( binop(token) ) {
|
|
217 /*
|
|
218 * handle special binary operators, such as CAST and post-inc and
|
|
219 * post-dec.
|
|
220 */
|
|
221 if(!opdontop) {
|
|
222 if( token != PREDEC && token != PREINC && token != CAST )
|
|
223 goto exprerr;
|
|
224 }
|
|
225 if( token != POSTDEC && token != POSTINC && token != MPARENS )
|
|
226 opdontop = 0; /*this fixes x++ op problem.*/
|
|
227 }
|
|
228 oppri = oppriority(token);
|
|
229 if( commastop && token == COMMA ) /*need to stop at comma(init)*/
|
|
230 oppri = COLPRI;
|
|
231 if( colonstop && token == COLON ) /*need to stop at colon(case)*/
|
|
232 oppri = COLPRI;
|
|
233 while( 1 ) {
|
|
234 if( oppri > opp->o_pri ||
|
|
235 (oppri == opp->o_pri && rasop(token)) ) {
|
|
236 /*
|
|
1File: EXPR.C Page 5
|
|
237 * we have encountered a higher priority (or right-associative)
|
|
238 * operator, hence we need to stack it.
|
|
239 */
|
|
240 if( ++opp >= &opstack[OPSSIZE] )
|
|
241 ferror("expression too complex");
|
|
242 if( token == POSTINC || token == POSTDEC )
|
|
243 oppri = PSTPRI;
|
|
244 else if( token == LPAREN || token == LBRACK ||
|
|
245 token == CALL )
|
|
246 oppri = CALPRI;
|
|
247 opp->o_op = token;
|
|
248 opp->o_pri = oppri;
|
|
249 break;
|
|
250 }
|
|
251 /*
|
|
252 * we have encountered a lower priority operator, hence we need to
|
|
253 * do a reduction.
|
|
254 */
|
|
255 op = opp->o_op;
|
|
256 opp--;
|
|
257 type = CINT;
|
|
258 switch( op ) {
|
|
259
|
|
260 case STACKEND: /*we accept the expression...*/
|
|
261 pbtok(token);
|
|
262 if (!strassign) {
|
|
263 if (!maketree(0))
|
|
264 goto exprerr;
|
|
265 }
|
|
266 if (!(p=popopd()))
|
|
267 goto exprerr;
|
|
268 opdp = opdsave;
|
|
269 opp = oprsave;
|
|
270 opdontop = opdotsave;
|
|
271 return(p);
|
|
272
|
|
273 case LPAREN: /*assure these have matching )*/
|
|
274 case CALL:
|
|
275 if( token != RPAREN )
|
|
276 goto exprerr;
|
|
277 break;
|
|
278
|
|
279 case MPARENS:
|
|
280 if( !maketree(NACALL) )
|
|
281 goto exprerr;
|
|
282 continue;
|
|
283
|
|
284 case LBRACK:
|
|
285 if( token != RBRACK )
|
|
286 goto exprerr;
|
|
287 if(!maketree(ADD)) /*array[index]->*(array+index)*/
|
|
288 goto exprerr;
|
|
289 op = INDR;
|
|
290 break;
|
|
291
|
|
292 case PREINC: /*turn these into binary operators*/
|
|
293 case POSTINC: /*which in reality they are...*/
|
|
294 case PREDEC:
|
|
295 case POSTDEC:
|
|
1File: EXPR.C Page 6
|
|
296 pushopd(cnalloc(INT,1));
|
|
297 default:
|
|
298 if(!maketree(op))
|
|
299 goto exprerr;
|
|
300 continue; /*see if we can reduce some more...*/
|
|
301 }
|
|
302 if( op != LPAREN && !maketree(op) )
|
|
303 goto exprerr;
|
|
304 break;
|
|
305 }
|
|
306 }
|
|
307 error("unexpected EOF");
|
|
308 return(0);
|
|
309 }
|
|
310
|
|
311 /* talloc - expression area tree node allocation
|
|
312 * Allocates area and checks for overflow.*/
|
|
313 char *talloc(size) /* returns pointer to node*/
|
|
314 int size; /* size of node to alloc*/
|
|
315 {
|
|
316 register char *p;
|
|
317
|
|
318 p = opap;
|
|
319 if( p + size >= &exprarea[EXPSIZE] )
|
|
320 ferror("expression too complex");
|
|
321 opap = p + size;
|
|
322 return(p);
|
|
323 }
|
|
324
|
|
325 /*
|
|
326 * enalloc - external name alloc
|
|
327 * Allocates an expression tree node for an external name and
|
|
328 * copies symbol table info and symbol into tree node.
|
|
329 */
|
|
330 char *enalloc(sp) /* returns - none*/
|
|
331 struct symbol *sp; /* pointer to symbol table entry*/
|
|
332 {
|
|
333 register struct extnode *ep;
|
|
334
|
|
335 ep = talloc(sizeof(*ep));
|
|
336 ep->t_op = SYMBOL;
|
|
337 ep->t_sc = sp->s_sc;
|
|
338 ep->t_type = sp->s_type;
|
|
339 ep->t_dp = sp->s_dp;
|
|
340 ep->t_ssp = sp->s_ssp;
|
|
341 ep->t_offset = sp->s_offset;
|
|
342 symcopy(sp->s_symbol,ep->t_symbol);
|
|
343 return(ep);
|
|
344 }
|
|
345
|
|
346 /* cnalloc - constant node allocation
|
|
347 * Allocates a constant tree node and fills the info fields.*/
|
|
348 char *cnalloc(type,value) /* returns pointer to node*/
|
|
349 int type; /* data type*/
|
|
350 int value; /* constant value*/
|
|
351 {
|
|
352 register struct conode *cp;
|
|
353
|
|
354 cp = talloc(sizeof(*cp));
|
|
1File: EXPR.C Page 7
|
|
355 cp->t_op = CINT;
|
|
356 cp->t_type = type;
|
|
357 cp->t_dp = 0;
|
|
358 cp->t_ssp = 0;
|
|
359 cp->t_value = value;
|
|
360 return(cp);
|
|
361 }
|
|
362
|
|
363 /* lcnalloc - long constant node allocation*/
|
|
364 /* Allocates a constant tree node and fills the info fields.*/
|
|
365 char *lcnalloc(type,value) /* returns pointer to node*/
|
|
366 int type; /* data type*/
|
|
367 long value; /* constant value*/
|
|
368 {
|
|
369 register struct lconode *cp;
|
|
370
|
|
371 cp = talloc(sizeof(*cp));
|
|
372 cp->t_op = CLONG;
|
|
373 cp->t_type = type;
|
|
374 cp->t_dp = 0;
|
|
375 cp->t_ssp = 0;
|
|
376 cp->t_lvalue = value;
|
|
377 return(cp);
|
|
378 }
|
|
379
|
|
380 /* fpcnalloc - floating point constant node allocation*/
|
|
381 /* Allocates a constant tree node and fills the info fields.*/
|
|
382 char *fpcnalloc(type,value) /*[vlh] 3.4 returns pointer to node*/
|
|
383 int type; /* data type*/
|
|
384 long value; /* constant value*/
|
|
385 {
|
|
386 register struct lconode *cp;
|
|
387
|
|
388 cp = talloc(sizeof(*cp));
|
|
389 cp->t_op = CFLOAT;
|
|
390 cp->t_type = type;
|
|
391 cp->t_dp = 0;
|
|
392 cp->t_ssp = 0;
|
|
393 cp->t_lvalue = value;
|
|
394 return(cp);
|
|
395 }
|
|
396
|
|
397 /* tnalloc - tree node allocation*/
|
|
398 /* Allocates an operator tree node and fills the info fields*/
|
|
399 char *tnalloc(op,type,dp,ssp,left,right) /* returns pointer to node*/
|
|
400 int op; /* operator*/
|
|
401 int type; /* operator type*/
|
|
402 int dp; /* dimension pointer or other info*/
|
|
403 int ssp; /* structure length pointer*/
|
|
404 char *left; /* left subtree*/
|
|
405 char *right; /* right subtree*/
|
|
406 {
|
|
407 register struct tnode *tp;
|
|
408
|
|
409 tp = talloc(sizeof(*tp));
|
|
410 tp->t_op = op;
|
|
411 tp->t_type = type;
|
|
412 tp->t_dp = dp;
|
|
413 tp->t_ssp = ssp;
|
|
1File: EXPR.C Page 8
|
|
414 tp->t_left = left;
|
|
415 tp->t_right = right;
|
|
416 return(tp);
|
|
417 }
|
|
418
|
|
419 /* pushopd - put operand node onto operand stack*/
|
|
420 /* Checks for operand stack overflow.*/
|
|
421 pushopd(tp) /* returns - none*/
|
|
422 struct tnode *tp; /* pointer to tree node to push*/
|
|
423 {
|
|
424 #ifdef DEBUG
|
|
425 error("pushopd %d",tp->t_op);
|
|
426 #endif
|
|
427 if( opdp >= &opdstack[OPDSIZE] )
|
|
428 ferror("expression too complex");
|
|
429 *opdp++ = tp;
|
|
430 }
|
|
431
|
|
432 /* popopd - pop operand stack*/
|
|
433 /* Checks for stack underflow*/
|
|
434 char *popopd() /* returns ptr to top operand*/
|
|
435 {
|
|
436 register struct tnode *tp;
|
|
437
|
|
438 if( opdp <= &opdstack[0] )
|
|
439 return(0);
|
|
440 tp = *--opdp;
|
|
441 #ifdef DEBUG
|
|
442 error("popopd: %d",tp->t_op);
|
|
443 #endif
|
|
444 return(tp);
|
|
445 }
|
|
446
|
|
447 /* doopd - handle constant or symbol node operand*/
|
|
448 /* Pushes node onto operand stack and handles opdontop flag.*/
|
|
449 doopd(tp) /* returns 1 if syntax error, 0 for ok*/
|
|
450 struct tnode *tp; /* pointer to tree node*/
|
|
451 {
|
|
452 pushopd(tp);
|
|
453 if( opdontop )
|
|
454 return(1);
|
|
455 opdontop++;
|
|
456 return(0);
|
|
457 }
|
|
458
|
|
459 /*
|
|
460 * This indicates if a conversion operator is needed given the types
|
|
461 * of the two operands. The upper diagonal is applied ONLY if this
|
|
462 * is an assignment operator and the indexes are swapped so the lower
|
|
463 * diagonal is used otherwise.
|
|
464 * INT UNSN LONG DOUB PTR
|
|
465 */
|
|
466 char cvmap[5][5] {
|
|
467 0, UNSN_INT, LONG_INT, DOUB_INT, PTR_INT, /*INT*/
|
|
468 INT_UNSN, 0, LONG_UNSN, DOUB_UNSN, PTR_UNSN, /*UNSN*/
|
|
469 INT_LONG, UNSN_LONG, 0, DOUB_LONG, PTR_LONG, /*LONG*/
|
|
470 INT_DOUB, UNSN_DOUB, LONG_DOUB, 0, BADCONV, /*DOUB*/
|
|
471 INT_PTR, UNSN_PTR, LONG_PTR, BADCONV, PTR_PTR, /*PTR*/
|
|
472 };
|
|
1File: EXPR.C Page 9
|
|
473
|
|
474 /*
|
|
475 * maketree - given operator, takes operands and builds up tree
|
|
476 * This takes the given operator, allocates a node for it
|
|
477 * and links up the subtrees on the operand stack. A lot of
|
|
478 * work is in inserting the proper conversions.
|
|
479 */
|
|
480 maketree(op) /* returns success or failure */
|
|
481 int op; /* new root operator*/
|
|
482 {
|
|
483 register struct tnode *ltp, *rtp, *p;
|
|
484 register int type, ltype, rtype, lconv, conv, pconv, ilen;
|
|
485
|
|
486 #ifdef DEBUG
|
|
487 error("maketree: op = %d",op);
|
|
488 #endif
|
|
489 if( binop(op) ) {
|
|
490 if(!(rtp=popopd()))
|
|
491 return(0);
|
|
492 rtype = (rtp=funcref(arrayref(rtp)))->t_type;
|
|
493 }
|
|
494 if(!(ltp=popopd()))
|
|
495 return(0);
|
|
496 if( op == SIZEOF ) { /* [vlh] 3.4 ilen */
|
|
497 ilen = dsize(ltp->t_type,ltp->t_dp,ltp->t_ssp);
|
|
498 pushopd(cnalloc(INT,ilen));
|
|
499 return(1);
|
|
500 }
|
|
501 if( op != ADDR ) {
|
|
502 ltp = arrayref(ltp);
|
|
503 if( op != CALL && op != NACALL )
|
|
504 ltp = funcref(ltp);
|
|
505 }
|
|
506 if( specops(op,ltp,rtp) )
|
|
507 return( 1 );
|
|
508 ltype = ltp->t_type;
|
|
509 if( lintegral(op) )
|
|
510 integral(ltp,LONG);
|
|
511 if( rintegral(op) )
|
|
512 integral(rtp,LONG);
|
|
513 if( lvalop(op) && ltp->t_op != SYMBOL && ltp->t_op != INDR &&
|
|
514 ltp->t_op != BFIELD )
|
|
515 error("assignable operand required");
|
|
516 if( unaryop(op) ) {
|
|
517 if(!unopeval(op,ltp))
|
|
518 pushopd(tnalloc(op,ltype,ltp->t_dp,ltp->t_ssp,ltp));
|
|
519 return;
|
|
520 }
|
|
521 if( ltype == STRUCT || rtype == STRUCT ) {
|
|
522 if (ltype==STRUCT && rtype==STRUCT && op==ASSIGN) { /*[vlh]*/
|
|
523 pushopd(ltp);
|
|
524 maketree(ADDR);
|
|
525 pushopd(rtp);
|
|
526 maketree(ADDR);
|
|
527 maketree(STASSIGN);
|
|
528 strassign = 1;
|
|
529 return(1);
|
|
530 }
|
|
531 ltype = rtype = INT;
|
|
1File: EXPR.C Page 10
|
|
532 error("illegal structure operation");
|
|
533 }
|
|
534 type = ltype;
|
|
535 if( rtype == TYPELESS ) {
|
|
536 rtp->t_type = rtype = INT;
|
|
537 lconv = conv = 0;
|
|
538 }
|
|
539 else {
|
|
540 lconv = ttoconv(ltype);
|
|
541 conv = ttoconv(rtype);
|
|
542 if (!asgop(op) && conv > lconv) {
|
|
543 conv = cvmap[conv][lconv];
|
|
544 lconv = 1;
|
|
545 type = rtype;
|
|
546 }
|
|
547 else {
|
|
548 conv = cvmap[lconv][conv];
|
|
549 lconv = 0;
|
|
550 }
|
|
551 }
|
|
552 if( asgop(op) ) {
|
|
553 if( (op == ASSIGN || op == FRETURN) && (conv == INT_PTR ||
|
|
554 conv == UNSN_PTR) && rtp->t_op != CINT )
|
|
555 error("short assigned to pointer");
|
|
556 if( op == ASSIGN || op == CAST ) {
|
|
557 switch( conv ) {
|
|
558
|
|
559 case INT_PTR:
|
|
560 case UNSN_PTR:
|
|
561 case PTR_PTR:
|
|
562 case PTR_LONG:
|
|
563 case LONG_PTR:
|
|
564 conv = 0;
|
|
565 break;
|
|
566 }
|
|
567 }
|
|
568 }
|
|
569 else if( op == COLON && suptype(ltype) != 0 && ltype == rtype )
|
|
570 conv = 0;
|
|
571 else if( relop(op) && conv == PTR_PTR )
|
|
572 conv = 0;
|
|
573 pconv = 0;
|
|
574 if ((relop(op) || op==FRETURN) && alltype(ltype) == (STRUCT | POINTER)
|
|
575 && (conv == INT_PTR || conv == LONG_PTR)) /* [vlh] 3.4 */
|
|
576 conv = 0; /* int compare to struct pointer, no conversion */
|
|
577 if( conv == PTR_PTR ) {
|
|
578 conv = 0;
|
|
579 if( op == SUB ) {
|
|
580 type = LONG;
|
|
581 pconv++;
|
|
582 }
|
|
583 else if(op != FRETURN && ( (alltype(ltype) != alltype(rtype) ||
|
|
584 alltype(ltype) != (POINTER|CHAR)) ) )
|
|
585 conv = BADCONV;
|
|
586 }
|
|
587 if( conv ) {
|
|
588 if( conv == BADCONV )
|
|
589 error("illegal type conversion");
|
|
590 else if( lconv ) {
|
|
1File: EXPR.C Page 11
|
|
591 ltp = cvopgen(ltp,type,conv,psize(rtp),op);
|
|
592 }
|
|
593 else {
|
|
594 rtp = cvopgen(rtp,type,conv,psize(ltp),op);
|
|
595 }
|
|
596 }
|
|
597 else if( op == CAST && rtp->t_type != CHAR ) {
|
|
598 rtp->t_type = ltp->t_type;
|
|
599 rtp->t_ssp = ltp->t_ssp; /* [vlh] 3.4 */
|
|
600 rtp->t_dp = ltp->t_dp; /* [vlh] 3.4 */
|
|
601 }
|
|
602 if( relop(op) )
|
|
603 type = INT;
|
|
604 if( op == CAST )
|
|
605 pushopd(rtp);
|
|
606 else if(!binopeval(op,ltp,rtp)) {
|
|
607 if( btype(ltype) == STRUCT || btype(rtype) != STRUCT )
|
|
608 p = ltp;
|
|
609 else
|
|
610 p = rtp;
|
|
611 pushopd(tnalloc(op,type,p->t_dp,p->t_ssp,ltp,rtp));
|
|
612 }
|
|
613 if( pconv && ltype != (POINTER|CHAR) ) {
|
|
614 if(!(ltp=popopd()))
|
|
615 return(0);
|
|
616 pushopd(cvopgen(ltp,LONG,PTR_LONG,psize(ltp->t_left),op));
|
|
617 }
|
|
618 return(1);
|
|
619 }
|
|
620
|
|
621 /* specops - handle special operators in building tree*/
|
|
622 specops(op,ltp,rtp) /* returns 1 if op special, 0 otherwise*/
|
|
623 int op; /* operator*/
|
|
624 struct tnode *ltp; /* left subtree pointer*/
|
|
625 struct tnode *rtp; /* right subtree pointer*/
|
|
626 {
|
|
627 register int type, sr_size, sl_size;
|
|
628
|
|
629 type = ltp->t_type;
|
|
630 switch (op) {
|
|
631
|
|
632 case 0:
|
|
633 break;
|
|
634
|
|
635 default:
|
|
636 return(0);
|
|
637
|
|
638 case APTR: /*expr -> name*/
|
|
639 integral(ltp,LONG); /*we need to turn expr into a*/
|
|
640 ltp->t_type = POINTER|STRUCT; /*pointer to a struct, then use*/
|
|
641 pushopd(ltp); /*expr . name stuff*/
|
|
642 maketree(INDR);
|
|
643 ltp = popopd(); /*ltp cannot be 0*/
|
|
644 case PERIOD: /*expr . name*/
|
|
645 if( !(isstel(rtp)) )
|
|
646 error("invalid structure member name");
|
|
647 type = rtp->t_type;
|
|
648 if( array(type) ) {
|
|
649 type = delspchk(type);
|
|
1File: EXPR.C Page 12
|
|
650 rtp->t_dp++;
|
|
651 }
|
|
652 tadjust(ltp,type,rtp->t_dp,rtp->t_ssp);
|
|
653 pushopd(ltp);
|
|
654 maketree(ADDR);
|
|
655 pushopd(cnalloc(TYPELESS,rtp->t_offset));
|
|
656 maketree(ADD);
|
|
657 if( notarray(rtp->t_type) )
|
|
658 maketree(INDR);
|
|
659 ltp = popopd();
|
|
660 if( rtp->t_sc == BFIELDCL ) /*ltp cannot be 0*/
|
|
661 ltp = tnalloc(BFIELD,type,rtp->t_dp,rtp->t_ssp,ltp);
|
|
662 break;
|
|
663
|
|
664 case QMARK:
|
|
665 if( rtp->t_op != COLON )
|
|
666 error("invalid ?: operator syntax");
|
|
667 if( ltp->t_op == CINT && rtp->t_left->t_op == CINT &&
|
|
668 rtp->t_right->t_op == CINT )
|
|
669 ltp->t_value = (ltp->t_value ? rtp->t_left->t_value :
|
|
670 rtp->t_right->t_value);
|
|
671 else
|
|
672 ltp = tnalloc(op,rtp->t_type,0,0,ltp,rtp);
|
|
673 break;
|
|
674
|
|
675 case LAND:
|
|
676 case LOR:
|
|
677 case COMMA: /*don't need conversions here*/
|
|
678 ltp = tnalloc(op,INT,0,0,ltp,rtp);
|
|
679 break;
|
|
680
|
|
681 case INDR:
|
|
682 if( ltp->t_op == ADDR ) /**& is null op*/
|
|
683 ltp = ltp->t_left;
|
|
684 else {
|
|
685 if( function(type) )
|
|
686 error("indirection on function invalid");
|
|
687 ltp = tnalloc(INDR,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp);
|
|
688 }
|
|
689 break;
|
|
690
|
|
691 case STASSIGN: /*[vlh]*/
|
|
692 sr_size = psize(rtp);
|
|
693 sl_size = psize(ltp);
|
|
694 if( sl_size >= sr_size )
|
|
695 ltp = tnalloc(STASSIGN,sr_size,0,0,ltp,rtp);
|
|
696 else
|
|
697 error("invalid structure assignment");
|
|
698 break;
|
|
699
|
|
700 case NACALL:
|
|
701 case CALL:
|
|
702 if( notfunction(type) )
|
|
703 error("illegal call");
|
|
704 ltp = tnalloc(op,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp,rtp);
|
|
705 break;
|
|
706
|
|
707 case ADDR:
|
|
708 if( ltp->t_op == INDR ) { /*&* is null op*/
|
|
1File: EXPR.C Page 13
|
|
709 /* ltp->t_left->t_type = addsp(type,POINTER);*/
|
|
710 /* ltp->t_left->t_dp = ltp->t_dp;*/
|
|
711 /* ltp->t_left->t_ssp = ltp->t_ssp;*/
|
|
712 ltp = ltp->t_left;
|
|
713 }
|
|
714 else {
|
|
715 if( ltp->t_op != SYMBOL )
|
|
716 error("& operand illegal");
|
|
717 else if( ltp->t_sc == REGISTER )
|
|
718 error("address of register");
|
|
719 ltp = tnalloc(ADDR,addsp(type,POINTER),ltp->t_dp,ltp->t_ssp,
|
|
720 ltp);
|
|
721 }
|
|
722 break;
|
|
723 }
|
|
724 pushopd(ltp);
|
|
725 return(1);
|
|
726 }
|
|
727
|
|
728 /* cvopgen - generate a conversion operator*/
|
|
729 /* Generates conversions necessary for integers, pointers and longs.*/
|
|
730 char *cvopgen(tp,type,conv,len,op) /* returns pointer to conv node*/
|
|
731 struct tnode *tp; /* pointer to node to do conversion*/
|
|
732 int type; /* type to convert to*/
|
|
733 int conv; /* specified conversion*/
|
|
734 long len; /* object length [vlh] 3.4 i=>l */
|
|
735 int op; /* for cast operator*/
|
|
736 {
|
|
737 register struct tnode *rtp;
|
|
738 register int cop, ilen;
|
|
739
|
|
740 switch(conv) {
|
|
741
|
|
742 case INT_PTR:
|
|
743 case UNSN_PTR:
|
|
744 if( op == CAST || op == FRETURN ) {
|
|
745 cop = INT2L; /*of the ptd to objects length plus*/
|
|
746 if( len != 1L ) { /*an integer to long covnversion*/
|
|
747 ilen = len;
|
|
748 rtp = cnalloc(INT,ilen);
|
|
749 tp = tnalloc(MULT,type,0,0,tp,rtp);
|
|
750 }
|
|
751 break;
|
|
752 }
|
|
753 case PTR_LONG: /*need to generate mult or div*/
|
|
754 case LONG_PTR: /*of the ptd to objects length*/
|
|
755 if( len == 1 )
|
|
756 return(tp);
|
|
757 ilen = len;
|
|
758 cop = (conv == PTR_LONG ? DIV : MULT);
|
|
759 rtp = cnalloc(INT,ilen);
|
|
760 break;
|
|
761
|
|
762 case INT_LONG:
|
|
763 case UNSN_LONG:
|
|
764 cop = INT2L;
|
|
765 break;
|
|
766
|
|
767 case INT_DOUB: /*[vlh] 3.4*/
|
|
1File: EXPR.C Page 14
|
|
768 case UNSN_DOUB:
|
|
769 cop = INT2F;
|
|
770 break;
|
|
771
|
|
772 case LONG_DOUB: /*[vlh] 3.4*/
|
|
773 cop = LONG2F;
|
|
774 break;
|
|
775
|
|
776 case DOUB_LONG: /*[vlh] 3.4*/
|
|
777 cop = FLOAT2L;
|
|
778 break;
|
|
779
|
|
780 case DOUB_INT: /*[vlh] 3.4*/
|
|
781 case DOUB_UNSN:
|
|
782 cop = FLOAT2I;
|
|
783 break;
|
|
784
|
|
785 case LONG_INT:
|
|
786 case LONG_UNSN:
|
|
787 cop = LONG2I;
|
|
788 break;
|
|
789
|
|
790 default:
|
|
791 error("invalid conversion");
|
|
792 return(tp);
|
|
793 }
|
|
794 return( tnalloc(cop,type,0,0,tp,rtp) );
|
|
795 }
|
|
796
|
|
797 /* tadjust - expression tree type adjustment*/
|
|
798 /* Adjusts the types of subtrees to agree with the top of the tree.*/
|
|
799 tadjust(tp,type,dp,ssp) /* returns - none*/
|
|
800 struct tnode *tp; /* pointer to tree*/
|
|
801 int type; /* type to adjust to*/
|
|
802 int dp; /* dimension pointer or info*/
|
|
803 int ssp; /* structure pointer*/
|
|
804 {
|
|
805 register int op;
|
|
806
|
|
807 tp->t_type = type;
|
|
808 if( dp >= 0 ) {
|
|
809 tp->t_dp = dp;
|
|
810 tp->t_ssp = ssp;
|
|
811 }
|
|
812 if( (op=tp->t_op) == ADDR )
|
|
813 type = delspchk(type);
|
|
814 else if( op == INDR )
|
|
815 type = addsp(type,POINTER);
|
|
816 else if( op != ADD && op != SUB )
|
|
817 return;
|
|
818 tadjust(tp->t_left,type,dp,ssp);
|
|
819 }
|
|
820
|
|
821 /* funcref - handle tree function reference*/
|
|
822 /* Turns a reference to a function into the address of the function.*/
|
|
823 char *funcref(tp) /* returns pointer to node*/
|
|
824 struct tnode *tp; /* pointer to old node*/
|
|
825 {
|
|
826 if( function(tp->t_type) )
|
|
1File: EXPR.C Page 15
|
|
827 tp = tnalloc(ADDR,addsp(tp->t_type,POINTER),tp->t_dp,tp->t_ssp,tp);
|
|
828 return(tp);
|
|
829 }
|
|
830
|
|
831 /* arrayref - handle tree array reference*/
|
|
832 /* Turns a reference to an array into the address of the array.*/
|
|
833 char *arrayref(tp) /* returns pointer to tree node*/
|
|
834 struct tnode *tp; /* tree node pointer*/
|
|
835 {
|
|
836 if( array(tp->t_type) && !(isstel(tp)) ) {
|
|
837 tp->t_dp++;
|
|
838 pushopd(tp);
|
|
839 tadjust(tp,delspchk(tp->t_type),-1,0);
|
|
840 maketree(ADDR);
|
|
841 tp = popopd(); /*tp cannot be 0*/
|
|
842 }
|
|
843 return(tp);
|
|
844 }
|
|
845
|
|
846 /* integral - checks operand for integral type*/
|
|
847 /* This checks for needing an integral operand.*/
|
|
848 integral(tp,atype) /* returns - none*/
|
|
849 struct tnode *tp; /* pointer to tree node*/
|
|
850 int atype; /* alternate type allowable*/
|
|
851 {
|
|
852 register int type;
|
|
853
|
|
854 if( (type=tp->t_type) != INT && type != UNSIGNED && type != CHAR &&
|
|
855 !suptype(type) && type != atype )
|
|
856 error("invalid operand type");
|
|
857 }
|
|
858
|
|
859 /* ttoconv - maps normal type into conversion table type*/
|
|
860 ttoconv(type) /* returns conversion type*/
|
|
861 int type; /* type to convert*/
|
|
862 {
|
|
863 switch(type) {
|
|
864
|
|
865 case CHAR:
|
|
866 case INT:
|
|
867 return(0);
|
|
868
|
|
869 case UNSIGNED:
|
|
870 return(1);
|
|
871
|
|
872 case LONG:
|
|
873 return(2);
|
|
874
|
|
875 case FLOAT:
|
|
876 case DOUBLE:
|
|
877 return(3);
|
|
878
|
|
879 default:
|
|
880 return(4);
|
|
881 }
|
|
882 }
|
|
883
|
|
884 /* binopeval - does binary operator constant expression evaluation*/
|
|
885 /* Does the constant expression evaluation for binary operators.*/
|
|
1File: EXPR.C Page 16
|
|
886 binopeval(op,ltp,rtp) /* returns 1 if done, 0 if not*/
|
|
887 int op; /* operator to evaluate*/
|
|
888 struct tnode *ltp; /* pointer to left subtree*/
|
|
889 struct tnode *rtp; /* pointer to right subtree*/
|
|
890 {
|
|
891 register int lvalue, rvalue;
|
|
892
|
|
893 if( ltp->t_op != CINT )
|
|
894 return(0);
|
|
895 lvalue = ltp->t_value;
|
|
896 if( rtp->t_op != CINT )
|
|
897 return(0);
|
|
898 rvalue = rtp->t_value;
|
|
899 switch (op) {
|
|
900
|
|
901 case ADD:
|
|
902 lvalue =+ rvalue;
|
|
903 break;
|
|
904
|
|
905 case SUB:
|
|
906 lvalue =- rvalue;
|
|
907 break;
|
|
908
|
|
909 case MULT:
|
|
910 lvalue =* rvalue;
|
|
911 break;
|
|
912
|
|
913 case DIV:
|
|
914 lvalue =/ rvalue;
|
|
915 break;
|
|
916
|
|
917 case MOD:
|
|
918 lvalue =% rvalue;
|
|
919 break;
|
|
920
|
|
921 case AND:
|
|
922 lvalue =& rvalue;
|
|
923 break;
|
|
924
|
|
925 case OR:
|
|
926 lvalue =| rvalue;
|
|
927 break;
|
|
928
|
|
929 case XOR:
|
|
930 lvalue =^ rvalue;
|
|
931 break;
|
|
932
|
|
933 case LSH:
|
|
934 lvalue =<< rvalue;
|
|
935 break;
|
|
936
|
|
937 case RSH:
|
|
938 lvalue =>> rvalue;
|
|
939 break;
|
|
940
|
|
941 case EQUALS:
|
|
942 lvalue = (lvalue == rvalue);
|
|
943 break;
|
|
944
|
|
1File: EXPR.C Page 17
|
|
945 case NEQUALS:
|
|
946 lvalue = (lvalue != rvalue);
|
|
947 break;
|
|
948
|
|
949 case GREAT:
|
|
950 lvalue = (lvalue > rvalue);
|
|
951 break;
|
|
952
|
|
953 case LESS:
|
|
954 lvalue = (lvalue < rvalue);
|
|
955 break;
|
|
956
|
|
957 case GREATEQ:
|
|
958 lvalue = (lvalue >= rvalue);
|
|
959 break;
|
|
960
|
|
961 case LESSEQ:
|
|
962 lvalue = (lvalue <= rvalue);
|
|
963 break;
|
|
964
|
|
965 default:
|
|
966 return(0);
|
|
967 }
|
|
968 ltp->t_value = lvalue;
|
|
969 pushopd(ltp);
|
|
970 return(1);
|
|
971 }
|
|
972
|
|
973 /* unopeval - unary operator constant expression evaluation*/
|
|
974 /* Does constant expression evaluation for unary operators.*/
|
|
975 unopeval(op,tp) /* returns 1 if done, 0 otherwise*/
|
|
976 int op; /* operator to evaluate*/
|
|
977 struct tnode *tp; /* pointer to subexpression*/
|
|
978 {
|
|
979 register int value;
|
|
980
|
|
981 if( tp->t_op != CINT )
|
|
982 return(0);
|
|
983 value = tp->t_value;
|
|
984 switch( op ) {
|
|
985
|
|
986 case COMPL:
|
|
987 value = ~ value;
|
|
988 break;
|
|
989
|
|
990 case UMINUS:
|
|
991 value = - value;
|
|
992 break;
|
|
993
|
|
994 case NOT:
|
|
995 value = ! value;
|
|
996 break;
|
|
997
|
|
998 default:
|
|
999 return(0);
|
|
1000 }
|
|
1001 tp->t_value = value;
|
|
1002 pushopd(tp);
|
|
1003 return(1);
|
|
1File: EXPR.C Page 18
|
|
1004 }
|
|
1005
|
|
1006 /* cexpr - evaluate a constant integer expression*/
|
|
1007 /* Used in evaluating array bounds, bit field numbers, etc.*/
|
|
1008 cexpr()
|
|
1009 {
|
|
1010 register struct tnode *tp;
|
|
1011 register char *savep;
|
|
1012
|
|
1013 savep = exprp;
|
|
1014 exprp = opap;
|
|
1015 commastop++;
|
|
1016 if( (tp=expr()) && tp->t_op != CINT )
|
|
1017 error("constant required");
|
|
1018 commastop--;
|
|
1019 exprp = savep;
|
|
1020 return( tp->t_value );
|
|
1021 }
|
|
1022
|
|
1023 /* delspchk - delete one special reference and check if non-zero*/
|
|
1024 delspchk(type) /*returns new special type*/
|
|
1025 int type; /* type to modify*/
|
|
1026 {
|
|
1027 if(!(suptype(type)))
|
|
1028 error("bad indirection");
|
|
1029 return( delsp(type) );
|
|
1030 }
|
|
1031
|
|
1032 /* psize - return size of object ptd at by pointer*/
|
|
1033 long /* [vlh] 3.4 int => long */
|
|
1034 psize(tp) /* returns size of object in bytes*/
|
|
1035 struct tnode *tp; /* pointer to tree node*/
|
|
1036 {
|
|
1037 if ( !(suptype(tp->t_type)) ) /* what case ??? */
|
|
1038 return(1);
|
|
1039 return( dsize(delsp(tp->t_type),tp->t_dp,tp->t_ssp) );
|
|
1040 }
|