Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020817125448

Diff

Diff from 1.8 to:

Annotations

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

Annotated File View

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