Quick Search:

View

Revision:
Expand:  
Changeset: BSD_44:ragge:20020324105723

Diff

Diff from 1.1.1.1 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/ccom/trees.c

Annotated File View

ragge
1.1
1 #ifndef lint
2 static char *sccsid ="@(#)trees.c       4.37 (Berkeley) 6/18/90";
3 #endif
4
5 # include "pass1.h"
6
7 # include <setjmp.h>
8
9 int bdebug = 0;
10 int adebug = 0;
11 extern ddebug;
12 extern eprint();
13
14             /* corrections when in violation of lint */
15
16 /*      some special actions, used in finding the type of nodes */
17 # define NCVT 01
18 # define PUN 02
19 # define TYPL 04
20 # define TYPR 010
21 # define TYMATCH 040
22 # define LVAL 0100
23 # define CVTO 0200
24 # define CVTL 0400
25 # define CVTR 01000
26 # define PTMATCH 02000
27 # define OTHER 04000
28 # define NCVTR 010000
29
30 #ifndef BUG1
31 printact(tacts)
32         NODE *t;
33         int acts;
34 {
35         static struct actions {
36                 int     a_bit;
37                 char    *a_name;
38         } actions[] = {
39                 { PUN,          "PUN" },
40                 { CVTL,         "CVTL" },
41                 { CVTR,         "CVTR" },
42                 { TYPL,         "TYPL" },
43                 { TYPR,         "TYPR" },
44                 { TYMATCH,      "TYMATCH" },
45                 { PTMATCH,      "PTMATCH" },
46                 { LVAL,         "LVAL" },
47                 { CVTO,         "CVTO" },
48                 { NCVT,         "NCVT" },
49                 { OTHER,        "OTHER" },
50                 { NCVTR,        "NCVTR" },
51                 { 0 }
52         };
53         register struct actions *p;
54         char *sep = " ";
55
56         printf("actions");
57         for (p = actionsp->a_namep++)
58                 if (p->a_bit & acts) {
59                         printf("%s%s"sepp->a_name);
60                         sep = "|";
61                 }
62         if (!bdebug) {
63                 printf(" for:\n");
64                 fwalk(teprint0);
65         } else
66                 putchar('\n');
67 }
68 #endif
69
70 /* node conventions:
71
72         NAME:   rval>0 is stab index for external
73                 rval<0 is -inlabel number
74                 lval is offset in bits
75         ICON:   lval has the value
76                 rval has the STAB index, or - label number,
77                         if a name whose address is in the constant
78                 rval = NONAME means no name
79         REG:    rval is reg. identification cookie
80
81         */
82
83 NODE *
84 buildtreeolr ) register NODE *l, *r; {
85         register NODE *p, *q;
86         register actions;
87         register opty;
88         register struct symtab *sp;
89         register NODE *lr, *ll;
90         NODE *fixargs();
91         int i;
92
93 # ifndef BUG1
94         ifbdebug ) printf"buildtree( %s, %o, %o )\n"opst[o], lr );
95 # endif
96         opty = optype(o);
97
98         /* check for constants */
99
100         ifopty == UTYPE && l->in.op == ICON ){
101
102                 switcho ){
103
104                 case NOT:
105                         ifhflag ) werror"constant argument to NOT" );
106                 case UNARY MINUS:
107                 case COMPL:
108                         ifconvallol ) ) return(l);
109                         break;
110
111                         }
112                 }
113
114         else ifopty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
115
116                 switcho ){
117
118                 case NOT:
119                         ifhflag ) werror"constant argument to NOT" );
120                         ifl->in.op == FCON )
121                                 l->tn.lval = l->fpn.fval == 0.0;
122                         else
123                                 l->tn.lval = l->dpn.dval == 0.0;
124                         l->tn.rval = NONAME;
125                         l->in.op = ICON;
126                         l->fn.csiz = l->in.type = INT;
127                         l->fn.cdim = 0;
128                         return(l);
129                 case UNARY MINUS:
130                         ifl->in.op == FCON )
131                                 l->fpn.fval = -l->fpn.fval;
132                         else
133                                 l->dpn.dval = -l->dpn.dval;
134                         return(l);
135                         }
136                 }
137
138         else ifo==QUEST && l->in.op==ICON ) {
139                 l->in.op = FREE;
140                 r->in.op = FREE;
141                 ifl->tn.lval ){
142                         tfreer->in.right );
143                         returnr->in.left );
144                         }
145                 else {
146                         tfreer->in.left );
147                         returnr->in.right );
148                         }
149                 }
150
151         else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
152
153         else ifopty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
154
155                 switcho ){
156
157                 case ULT:
158                 case UGT:
159                 case ULE:
160                 case UGE:
161                 case LT:
162                 case GT:
163                 case LE:
164                 case GE:
165                 case EQ:
166                 case NE:
167                         ifl->in.type == ENUMTY && r->in.type == ENUMTY ){
168                                 p = blockolrINT0INT );
169                                 chkpunp );
170                                 p->in.op = FREE;
171                                 }
172
173                 case ANDAND:
174                 case OROR:
175                 case CBRANCH:
176
177                 ccwarn:
178                         ifhflag ) werror"constant in conditional context" );
179
180                 case PLUS:
181                 case MINUS:
182                 case MUL:
183                 case DIV:
184                 case MOD:
185                 case AND:
186                 case OR:
187                 case ER:
188                 case LS:
189                 case RS:
190                         ifconvallor ) ) {
191                                 r->in.op = FREE;
192                                 return(l);
193                                 }
194                         break;
195                         }
196                 }
197         else if (opty == BITYPE &&
198                 (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
199                 (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
200                         if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
201                                 extern int fpe_count;
202                                 extern jmp_buf gotfpe;
203
204                                 fpe_count = 0;
205                                 if (setjmp(gotfpe))
206                                         goto treatfpe;
207                                 if (l->in.op == ICON)
208                                         l->dpn.dval = l->tn.lval;
209                                 else if (l->in.op == FCON)
210                                         l->dpn.dval = l->fpn.fval;
211                                 if (r->in.op == ICON)
212                                         r->dpn.dval = r->tn.lval;
213                                 else if (r->in.op == FCON)
214                                         r->dpn.dval = r->fpn.fval;
215                                 switch (o) {
216
217                                 case PLUS:
218                                         l->dpn.dval += r->dpn.dval;
219                                         break;
220
221                                 case MINUS:
222                                         l->dpn.dval -= r->dpn.dval;
223                                         break;
224
225                                 case MUL:
226                                         l->dpn.dval *= r->dpn.dval;
227                                         break;
228
229                                 case DIV:
230                                         if (r->dpn.dval == 0)
231                                                 uerror("division by 0.");
232                                         else
233                                                 l->dpn.dval /= r->dpn.dval;
234                                         break;
235                                         }
236                         treatfpe:
237                                 if (fpe_count > 0) {
238                                         uerror("floating point exception in constant expression");
239                                         l->dpn.dval = 1.0/* Fairly harmless */
240                                         }
241                                 fpe_count = -1;
242                                 l->in.op = DCON;
243                                 l->in.type = l->fn.csiz = DOUBLE;
244                                 r->in.op = FREE;
245                                 return (l);
246                         }
247                 }
248
249         /* it's real; we must make a new node */
250
251         p = blockolrINT0INT );
252
253         actions = opact(p);
254 #ifndef BUG1
255         if (adebug)
256                 printact(pactions);
257 #endif
258
259         ifactions&LVAL ){ /* check left descendent */
260                 ifnotlval(p->in.left) ) {
261                         uerror"illegal lvalue operand of assignment operator" );
262                         }
263                 }
264
265         ifactions & NCVTR ){
266                 p->in.left = pconvertp->in.left );
267                 }
268         else if( !(actions & NCVT ) ){
269                 switchopty ){
270
271                 case BITYPE:
272                         p->in.right = pconvertp->in.right );
273                 case UTYPE:
274                         p->in.left = pconvertp->in.left );
275
276                         }
277                 }
278
279         if( (actions&PUN) && (o!=CAST||cflag) ){
280                 chkpun(p);
281                 }
282
283         ifactions & (TYPL|TYPR) ){
284
285                 q = (actions&TYPL) ? p->in.left : p->in.right;
286
287                 p->in.type = q->in.type;
288                 p->fn.cdim = q->fn.cdim;
289                 p->fn.csiz = q->fn.csiz;
290                 }
291
292         ifactions & CVTL ) p = convertpCVTL );
293         ifactions & CVTR ) p = convertpCVTR );
294         ifactions & TYMATCH ) p = tymatch(p);
295         ifactions & PTMATCH ) p = ptmatch(p);
296
297         ifactions & OTHER ){
298                 l = p->in.left;
299                 r = p->in.right;
300
301                 switch(o){
302
303                 case NAME:
304                         sp = &stab[idname];
305                         ifsp->stype == UNDEF ){
306 #ifndef FLEXNAMES
307                                 uerror"%.8s undefined"sp->sname );
308 #else
309                                 uerror"%s undefined"sp->sname );
310 #endif
311                                 /* make p look reasonable */
312                                 p->in.type = p->fn.csiz = INT;
313                                 p->fn.cdim = 0;
314                                 p->tn.rval = idname;
315                                 p->tn.lval = 0;
316                                 defidpSNULL );
317                                 break;
318                                 }
319                         p->in.type = sp->stype;
320                         p->fn.cdim = sp->dimoff;
321                         p->fn.csiz = sp->sizoff;
322                         p->tn.lval = 0;
323                         p->tn.rval = idname;
324                         /* special case: MOETY is really an ICON... */
325                         ifp->in.type == MOETY ){
326                                 p->tn.rval = NONAME;
327                                 p->tn.lval = sp->offset;
328                                 p->fn.cdim = 0;
329                                 p->in.type = ENUMTY;
330                                 p->in.op = ICON;
331                                 }
332                         break;
333
334                 case ICON:
335                         p->in.type = INT;
336                         p->fn.cdim = 0;
337                         p->fn.csiz = INT;
338                         break;
339
340                 case STRING:
341                         p->in.op = NAME;
342                         p->in.type = CHAR+ARY;
343                         p->tn.lval = 0;
344                         p->tn.rval = NOLAB;
345                         p->fn.cdim = curdim;
346                         p->fn.csiz = CHAR;
347                         break;
348
349                 case FCON:
350                         p->tn.lval = 0;
351                         p->tn.rval = 0;
352                         p->in.type = FLOAT;
353                         p->fn.cdim = 0;
354                         p->fn.csiz = FLOAT;
355                         break;
356
357                 case DCON:
358                         p->tn.lval = 0;
359                         p->tn.rval = 0;
360                         p->in.type = DOUBLE;
361                         p->fn.cdim = 0;
362                         p->fn.csiz = DOUBLE;
363                         break;
364
365                 case STREF:
366                         /* p->x turned into *(p+offset) */
367                         /* rhs must be a name; check correctness */
368
369                         i = r->tn.rval;
370                         ifi<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
371                                 uerror"member of structure or union required" );
372                                 }else
373                         /* if this name is non-unique, find right one */
374                         ifstab[i].sflags & SNONUNIQ &&
375                                 (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
376                                 (l->fn.csiz +1) >= 0 ){
377                                 /* nonunique name && structure defined */
378                                 char * memnam, * tabnam;
379                                 int j;
380                                 int memi;
381                                 j=dimtab[l->fn.csiz+1];
382                                 for( ; (memi=dimtab[j]) >= 0; ++j ){
383                                         tabnam = stab[memi].sname;
384                                         memnam = stab[i].sname;
385 # ifndef BUG1
386                                         ifddebug>1 ){
387 #ifndef FLEXNAMES
388                                                 printf("member %.8s==%.8s?\n",
389 #else
390                                                 printf("member %s==%s?\n",
391 #endif
392                                                         memnamtabnam);
393                                                 }
394 # endif
395                                         ifstab[memi].sflags & SNONUNIQ ){
396 #ifndef FLEXNAMES
397                                                 register k;
398                                                 fork=0k<NCHNAM; ++k ){
399                                                         if(*memnam++!=*tabnam)
400                                                                 goto next;
401                                                         if(!*tabnam++) break;
402                                                         }
403 #else
404                                                 if (memnam != tabnam)
405                                                         goto next;
406 #endif
407                                                 r->tn.rval = i = memi;
408                                                 break;
409                                                 }
410                                         nextcontinue;
411                                         }
412                                 ifmemi < 0 )
413 #ifndef FLEXNAMES
414                                         uerror("illegal member use: %.8s",
415 #else
416                                         uerror("illegal member use: %s",
417 #endif
418                                                 stab[i].sname);
419                                 }
420                         else {
421                                 register j;
422                                 ifl->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
423                                         ifstab[i].sflags & SNONUNIQ ){
424                                                 uerror"nonunique name demands struct/union or struct/union pointer" );
425                                                 }
426                                         else werror"struct/union or struct/union pointer required" );
427                                         }
428                                 else if( (j=l->fn.csiz+1)<0 ) cerror"undefined structure or union" );
429                                 else if( !chkstridimtab[j], DECREF(l->in.type) ) ){
430 #ifndef FLEXNAMES
431                                         werror"illegal member use: %.8s"stab[i].sname );
432 #else
433                                         werror"illegal member use: %s"stab[i].sname );
434 #endif
435                                         }
436                                 }
437
438                         p = strefp );
439                         break;
440
441                 case UNARY MUL:
442                         ifl->in.op == UNARY AND ){
443                                 p->in.op = l->in.op = FREE;
444                                 p = l->in.left;
445                                 }
446                         if( !ISPTR(l->in.type))uerror("illegal indirection");
447                         p->in.type = DECREF(l->in.type);
448                         p->fn.cdim = l->fn.cdim;
449                         p->fn.csiz = l->fn.csiz;
450                         break;
451
452                 case UNARY AND:
453                         switchl->in.op ){
454
455                         case UNARY MUL:
456                                 p->in.op = l->in.op = FREE;
457                                 p = l->in.left;
458                         case NAME:
459                                 p->in.type = INCREFl->in.type );
460                                 p->fn.cdim = l->fn.cdim;
461                                 p->fn.csiz = l->fn.csiz;
462                                 break;
463
464                         case COMOP:
465                                 lr = buildtreeUNARY ANDl->in.rightNIL );
466                                 p->in.op = l->in.op = FREE;
467                                 p = buildtreeCOMOPl->in.leftlr );
468                                 break;
469
470                         case QUEST:
471                                 lr = buildtreeUNARY ANDl->in.right->in.rightNIL );
472                                 ll = buildtreeUNARY ANDl->in.right->in.leftNIL );
473                                 p->in.op = l->in.op = l->in.right->in.op = FREE;
474                                 p = buildtreeQUESTl->in.leftbuildtreeCOLONlllr ) );
475                                 break;
476
477 # ifdef ADDROREG
478                         case OREG:
479                                 /* OREG was built in clocal()
480                                  * for an auto or formal parameter
481                                  * now its address is being taken
482                                  * local code must unwind it
483                                  * back to PLUS/MINUS REG ICON
484                                  * according to local conventions
485                                  */
486                                 {
487                                 extern NODE * addroreg();
488                                 p->in.op = FREE;
489                                 p = addroregl );
490                                 }
491                                 break;
492
493 # endif
494                         default:
495                                 uerror"unacceptable operand of &" );
496                                 break;
497                                 }
498                         break;
499
500                 case LS:
501                 case RS:
502                         ifl->in.type == CHAR || l->in.type == SHORT )
503                                 p->in.type = INT;
504                         else ifl->in.type == UCHAR || l->in.type == USHORT )
505                                 p->in.type = UNSIGNED;
506                         else
507                                 p->in.type = l->in.type;
508                 case ASG LS:
509                 case ASG RS:
510                         ifr->in.type != INT )
511                                 p->in.right = r = makety(rINT0INT );
512                         break;
513
514                 case RETURN:
515                 case ASSIGN:
516                 case CAST:
517                         /* structure assignment */
518                         /* take the addresses of the two sides; then make an
519                         /* operator using STASG and
520                         /* the addresses of left and right */
521
522                         {
523                                 register TWORD t;
524                                 register ds;
525
526                                 ifl->fn.csiz != r->fn.csiz ) uerror"assignment of different structures" );
527
528                                 r = buildtreeUNARY ANDrNIL );
529                                 t = r->in.type;
530                                 d = r->fn.cdim;
531                                 s = r->fn.csiz;
532
533                                 l = blockSTASGlrtds );
534
535                                 ifo == RETURN ){
536                                         p->in.op = FREE;
537                                         p = l;
538                                         break;
539                                         }
540
541                                 p->in.op = UNARY MUL;
542                                 p->in.left = l;
543                                 p->in.right = NIL;
544                                 break;
545                                 }
546                 case COLON:
547                         /* structure colon */
548
549                         ifl->fn.csiz != r->fn.csiz ) uerror"type clash in conditional" );
550                         break;
551
552                 case CALL:
553                         p->in.right = r = fixargsp->in.right );
554                 case UNARY CALL:
555                         if( !ISPTR(l->in.type)) uerror("illegal function");
556                         p->in.type = DECREF(l->in.type);
557                         if( !ISFTN(p->in.type)) uerror("illegal function");
558                         p->in.type = DECREFp->in.type );
559                         p->fn.cdim = l->fn.cdim;
560                         p->fn.csiz = l->fn.csiz;
561                         ifl->in.op == UNARY AND && l->in.left->in.op == NAME &&
562                                 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
563                                 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
564                                 p->in.op += (FORTCALL-CALL);
565                                 }
566                         ifp->in.type == STRTY || p->in.type == UNIONTY ){
567                                 /* function returning structure */
568                                 /*  make function really return ptr to str., with * */
569
570                                 p->in.op += STCALL-CALL;
571                                 p->in.type = INCREFp->in.type );
572                                 p = buildtreeUNARY MULpNIL );
573
574                                 }
575                         break;
576
577                 default:
578                         cerror"other code %d"o );
579                         }
580
581                 }
582
583         ifactions & CVTO ) p = oconvert(p);
584         p = clocal(p);
585
586 # ifndef BUG1
587         ifbdebug ) fwalkpeprint0 );
588 # endif
589
590         return(p);
591
592         }
593
594 int fpe_count = -1;
595 jmp_buf gotfpe;
596
597 void
598 fpe() {
599         if (fpe_count < 0)
600                 cerror("floating point exception");
601         ++fpe_count;
602         longjmp(gotfpe1);
603         }
604
605 /*
606  * Rewrite arguments in a function call.
607  * Structure arguments are massaged, single
608  * precision floating point constants are
609  * cast to double (to eliminate convert code).
610  */
611 NODE *
612 fixargsp ) register NODE *p;  {
613         int o = p->in.op;
614
615         ifo == CM ){
616                 p->in.left = fixargsp->in.left );
617                 p->in.right = fixargsp->in.right );
618                 returnp );
619                 }
620
621         ifp->in.type == STRTY || p->in.type == UNIONTY ){
622                 p = blockSTARGpNILp->in.typep->fn.cdimp->fn.csiz );
623                 p->in.left = buildtreeUNARY ANDp->in.leftNIL );
624                 p = clocal(p);
625                 }
626         else ifo == FCON )
627                 p = makety(pDOUBLE00);
628         returnp );
629         }
630
631 chkstrijtype ) TWORD type; {
632         /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
633         /* i has been checked to contain a MOS or MOU */
634         /* j is the index in dimtab of the members... */
635         int kkk;
636
637         extern int ddebug;
638
639 # ifndef BUG1
640 #ifndef FLEXNAMES
641         ifddebug > 1 ) printf"chkstr( %.8s(%d), %d )\n"stab[i].snameij );
642 #else
643         ifddebug > 1 ) printf"chkstr( %s(%d), %d )\n"stab[i].snameij );
644 #endif
645 # endif
646         if( (k = j) < 0 ) uerror"undefined structure or union" );
647         else {
648                 for( ; (kk = dimtab[k] ) >= 0; ++k ){
649                         ifkk >= SYMTSZ ){
650                                 cerror"gummy structure" );
651                                 return(1);
652                                 }
653                         ifkk == i ) return1 );
654                         switchstab[kk].stype ){
655
656                         case STRTY:
657                         case UNIONTY:
658                                 iftype == STRTY ) continue;  /* no recursive looking for strs */
659                                 ifhflag && chkstridimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
660                                         ifstab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
661                                         werror(
662 #ifndef FLEXNAMES
663                                         "illegal member use: perhaps %.8s.%.8s?",
664 #else
665                                         "illegal member use: perhaps %s.%s?",
666 #endif
667                                         stab[kk].snamestab[i].sname );
668                                         return(1);
669                                         }
670                                 }
671                         }
672                 }
673         return0 );
674         }
675
676 convalpoq ) register NODE *p, *q; {
677         /* apply the op o to the lval part of p; if binary, rhs is val */
678         /* works only on integer constants */
679         NODE *r;
680         int iu;
681         CONSZ val;
682         TWORD utype;
683
684         val = q->tn.lval;
685         u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
686         ifu && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
687
688         ifp->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
689         ifq->tn.rval != NONAME && o!=PLUS ) return(0);
690         ifp->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
691
692         /* usual type conversions -- handle casts of constants */
693 #define ISLONG(t)       ((t) == LONG || (t) == ULONG)
694         if (ISLONG(p->in.type) || ISLONG(q->in.type))
695                 utype = u ? ULONG : LONG;
696         else
697                 utype = u ? UNSIGNED : INT;
698         if( !ISPTR(p->in.type) && p->in.type != utype )
699                 p = makety(putype0, (int)utype);
700         ifq->in.type != utype )
701                 q = makety(qutype0, (int)utype);
702
703         switcho ){
704
705         case PLUS:
706                 p->tn.lval += val;
707                 ifp->tn.rval == NONAME ){
708                         p->tn.rval = q->tn.rval;
709                         p->in.type = q->in.type;
710                         }
711                 break;
712         case MINUS:
713                 p->tn.lval -= val;
714                 break;
715         case MUL:
716                 p->tn.lval *= val;
717                 break;
718         case DIV:
719                 ifval == 0 ) uerror"division by 0" );
720                 else if ( u ) p->tn.lval = (unsignedp->tn.lval / val;
721                 else p->tn.lval /= val;
722                 break;
723         case MOD:
724                 ifval == 0 ) uerror"division by 0" );
725                 else if ( u ) p->tn.lval = (unsignedp->tn.lval % val;
726                 else p->tn.lval %= val;
727                 break;
728         case AND:
729                 p->tn.lval &= val;
730                 break;
731         case OR:
732                 p->tn.lval |= val;
733                 break;
734         case ER:
735                 p->tn.lval ^= val;
736                 break;
737         case LS:
738                 i = val;
739                 p->tn.lval = p->tn.lval << i;
740                 break;
741         case RS:
742                 i = val;
743                 if ( u ) p->tn.lval = (unsignedp->tn.lval >> i;
744                 else p->tn.lval = p->tn.lval >> i;
745                 break;
746
747         case UNARY MINUS:
748                 p->tn.lval = - p->tn.lval;
749                 break;
750         case COMPL:
751                 p->tn.lval = ~p->tn.lval;
752                 break;
753         case NOT:
754                 p->tn.lval = !p->tn.lval;
755                 break;
756         case LT:
757                 p->tn.lval = p->tn.lval < val;
758                 break;
759         case LE:
760                 p->tn.lval = p->tn.lval <= val;
761                 break;
762         case GT:
763                 p->tn.lval = p->tn.lval > val;
764                 break;
765         case GE:
766                 p->tn.lval = p->tn.lval >= val;
767                 break;
768         case ULT:
769                 p->tn.lval = p->tn.lval < (unsignedval;
770                 break;
771         case ULE:
772                 p->tn.lval = p->tn.lval <= (unsignedval;
773                 break;
774         case UGT:
775                 p->tn.lval = p->tn.lval > (unsignedval;
776                 break;
777         case UGE:
778                 p->tn.lval = p->tn.lval >= (unsignedval;
779                 break;
780         case EQ:
781                 p->tn.lval = p->tn.lval == val;
782                 break;
783         case NE:
784                 p->tn.lval = p->tn.lval != val;
785                 break;
786         default:
787                 return(0);
788                 }
789         return(1);
790         }
791
792 chkpun(pregister NODE *p; {
793
794         /* checks p for the existance of a pun */
795
796         /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
797
798         /* one case is when enumerations are used: this applies only to lint */
799         /* in the other case, one operand is a pointer, the other integer type */
800         /* we check that this integer is in fact a constant zero... */
801
802         /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
803         /* this falls out, because the LHS is never 0 */
804
805         register NODE *q;
806         register t1t2;
807         register d1d2;
808         int ref1ref2;
809
810         t1 = p->in.left->in.type;
811         t2 = p->in.right->in.type;
812
813         ift1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
814                 /* rob pike says this is obnoxious...
815                 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
816                         werror( "comparison of enums" ); */
817                 ift1==ENUMTY && t2==ENUMTY ) {
818                         if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
819                                 werror"enumeration type clash, operator %s"opst[p->in.op] );
820                         return;
821                         }
822                 if ( t1 == ENUMTY ) t1 = INT;
823                 if ( t2 == ENUMTY ) t2 = INT;
824                 }
825
826         ref1 = ISPTR(t1) || ISARY(t1);
827         ref2 = ISPTR(t2) || ISARY(t2);
828
829         ifref1 ^ ref2 ){
830                 ifref1 ) q = p->in.right;
831                 else q = p->in.left;
832                 ifq->in.op != ICON || q->tn.lval != 0 ){
833                         werror"illegal combination of pointer and integer, op %s",
834                                 opst[p->in.op] );
835                         }
836                 }
837         else ifref1 ){
838                 ift1 == t2 ) {
839                         ifp->in.left->fn.csiz != p->in.right->fn.csiz ) {
840                                 werror"illegal structure pointer combination" );
841                                 return;
842                                 }
843                         d1 = p->in.left->fn.cdim;
844                         d2 = p->in.right->fn.cdim;
845                         for( ;; ){
846                                 ifISARY(t1) ){
847                                         ifdimtab[d1] != dimtab[d2] ){
848                                                 werror"illegal array size combination" );
849                                                 return;
850                                                 }
851                                         ++d1;
852                                         ++d2;
853                                         }
854                                 else if( !ISPTR(t1) ) break;
855                                 t1 = DECREF(t1);
856                                 }
857                         }
858                 else ift1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
859                         werror"illegal pointer combination" );
860                 }
861
862         }
863
864 NODE *
865 strefp ) register NODE *p; {
866
867         TWORD t;
868         int dsdscalign;
869         OFFSZ off;
870         register struct symtab *q;
871
872         /* make p->x */
873         /* this is also used to reference automatic variables */
874
875         q = &stab[p->in.right->tn.rval];
876         p->in.right->in.op = FREE;
877         p->in.op = FREE;
878         p = pconvertp->in.left );
879
880         /* make p look like ptr to x */
881
882         if( !ISPTR(p->in.type)){
883                 p->in.type = PTR+UNIONTY;
884                 }
885
886         t = INCREFq->stype );
887         d = q->dimoff;
888         s = q->sizoff;
889
890         p = maketyptds );
891
892         /* compute the offset to be added */
893
894         off = q->offset;
895         dsc = q->sclass;
896
897         ifdsc & FIELD ) {  /* normalize offset */
898                 align = ALINT;
899                 s = INT;
900                 off = (off/align)*align;
901                 }
902         ifoff != 0 ) p = clocalblockPLUSpoffconofftds ), tds ) );
903
904         p = buildtreeUNARY MULpNIL );
905
906         /* if field, build field info */
907
908         ifdsc & FIELD ){
909                 p = blockFLDpNILq->stype0q->sizoff );
910                 p->tn.rval = PKFIELDdsc&FLDSIZq->offset%align );
911                 }
912
913         returnclocal(p) );
914         }
915
916 notlval(pregister NODE *p; {
917
918         /* return 0 if p an lvalue, 1 otherwise */
919
920         again:
921
922         switchp->in.op ){
923
924         case FLD:
925                 p = p->in.left;
926                 goto again;
927
928         case UNARY MUL:
929                 /* fix the &(a=b) bug, given that a and b are structures */
930                 ifp->in.left->in.op == STASG ) return1 );
931                 /* and the f().a bug, given that f returns a structure */
932                 ifp->in.left->in.op == UNARY STCALL ||
933                     p->in.left->in.op == STCALL ) return1 );
934         case NAME:
935         case OREG:
936                 ifISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
937         case REG:
938                 return(0);
939
940         default:
941                 return(1);
942
943                 }
944
945         }
946
947 NODE *
948 bconi ){ /* make a constant node with value i */
949         register NODE *p;
950
951         p = blockICONNILNILINT0INT );
952         p->tn.lval = i;
953         p->tn.rval = NONAME;
954         returnclocal(p) );
955         }
956
957 NODE *
958 bpsize(pregister NODE *p; {
959         returnoffconpsize(p), p->in.typep->fn.cdimp->fn.csiz ) );
960         }
961
962 OFFSZ
963 psizep ) NODE *p; {
964         /* p is a node of type pointer; psize returns the
965            size of the thing pointed to */
966
967         if( !ISPTR(p->in.type) ){
968                 uerror"pointer required");
969                 returnSZINT );
970                 }
971         /* note: no pointers to fields */
972         returntsizeDECREF(p->in.type), p->fn.cdimp->fn.csiz ) );
973         }
974
975 NODE *
976 convertpf )  register NODE *p; {
977         /*  convert an operand of p
978             f is either CVTL or CVTR
979             operand has type int, and is converted by the size of the other side
980             */
981
982         register NODE *q, *r;
983
984         q = (f==CVTL)?p->in.left:p->in.right;
985
986         r = blockPMCONV,
987                 qbpsize(f==CVTL?p->in.right:p->in.left), INT0INT );
988         r = clocal(r);
989         iff == CVTL )
990                 p->in.left = r;
991         else
992                 p->in.right = r;
993         return(p);
994
995         }
996
997 #ifndef econvert
998 econvertp ) register NODE *p; {
999
1000         /* change enums to ints, or appropriate types */
1001
1002         register TWORD ty;
1003
1004         if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
1005                 ifdimtabp->fn.csiz ] == SZCHAR ) ty = CHAR;
1006                 else ifdimtabp->fn.csiz ] == SZINT ) ty = INT;
1007                 else ifdimtabp->fn.csiz ] == SZSHORT ) ty = SHORT;
1008                 else ty = LONG;
1009                 ty = ctypety );
1010                 p->fn.csiz = ty;
1011                 MODTYPE(p->in.type,ty);
1012                 ifp->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
1013                 }
1014         }
1015 #endif
1016
1017 NODE *
1018 pconvertp ) register NODE *p; {
1019
1020         /* if p should be changed into a pointer, do so */
1021
1022         ifISARYp->in.type) ){
1023                 p->in.type = DECREFp->in.type );
1024                 ++p->fn.cdim;
1025                 returnbuildtreeUNARY ANDpNIL ) );
1026                 }
1027         ifISFTNp->in.type) )
1028                 returnbuildtreeUNARY ANDpNIL ) );
1029
1030         returnp );
1031         }
1032
1033 NODE *
1034 oconvert(pregister NODE *p; {
1035         /* convert the result itself: used for pointer and unsigned */
1036
1037         switch(p->in.op) {
1038
1039         case LE:
1040         case LT:
1041         case GE:
1042         case GT:
1043                 ifISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
1044         case EQ:
1045         case NE:
1046                 returnp );
1047
1048         case MINUS:
1049                 return(  clocalblockPVCONV,
1050                         pbpsize(p->in.left), INT0INT ) ) );
1051                 }
1052
1053         cerror"illegal oconvert: %d"p->in.op );
1054
1055         return(p);
1056         }
1057
1058 NODE *
1059 ptmatch(p)  register NODE *p; {
1060
1061         /* makes the operands of p agree; they are
1062            either pointers or integers, by this time */
1063         /* with MINUS, the sizes must be the same */
1064         /* with COLON, the types must be the same */
1065
1066         TWORD t1t2t;
1067         int od2ds2s;
1068
1069         o = p->in.op;
1070         t = t1 = p->in.left->in.type;
1071         t2 = p->in.right->in.type;
1072         d = p->in.left->fn.cdim;
1073         d2 = p->in.right->fn.cdim;
1074         s = p->in.left->fn.csiz;
1075         s2 = p->in.right->fn.csiz;
1076
1077         switcho ){
1078
1079         case ASSIGN:
1080         case RETURN:
1081         case CAST:
1082                 {  break; }
1083
1084         case MINUS:
1085                 {  ifpsize(p->in.left) != psize(p->in.right) ){
1086                         uerror"illegal pointer subtraction");
1087                         }
1088                    break;
1089                    }
1090         case COLON:
1091                 {  ift1 != t2 ) uerror"illegal types in :");
1092                    break;
1093                    }
1094         default:  /* must work harder: relationals or comparisons */
1095
1096                 if( !ISPTR(t1) ){
1097                         t = t2;
1098                         d = d2;
1099                         s = s2;
1100                         break;
1101