Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20020325225236

Diff

Diff from 1.2 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
283         if( (actions&PUN) && (o!=CAST||cflag) ){
284                 chkpun(p);
285                 }
286
287         ifactions & (TYPL|TYPR) ){
288
289                 q = (actions&TYPL) ? p->in.left : p->in.right;
290
291                 p->in.type = q->in.type;
292                 p->fn.cdim = q->fn.cdim;
293                 p->fn.csiz = q->fn.csiz;
294                 }
295
296         ifactions & CVTL ) p = convertpCVTL );
297         ifactions & CVTR ) p = convertpCVTR );
298         ifactions & TYMATCH ) p = tymatch(p);
299         ifactions & PTMATCH ) p = ptmatch(p);
300
301         ifactions & OTHER ){
302                 l = p->in.left;
303                 r = p->in.right;
304
305                 switch(o){
306
307                 case NAME:
308                         sp = &stab[idname];
309                         ifsp->stype == UNDEF ){
310 #ifndef FLEXNAMES
311                                 uerror"%.8s undefined"sp->sname );
312 #else
313                                 uerror"%s undefined"sp->sname );
314 #endif
315                                 /* make p look reasonable */
316                                 p->in.type = p->fn.csiz = INT;
317                                 p->fn.cdim = 0;
318                                 p->tn.rval = idname;
319                                 p->tn.lval = 0;
320                                 defidpSNULL );
321                                 break;
322                                 }
323                         p->in.type = sp->stype;
324                         p->fn.cdim = sp->dimoff;
325                         p->fn.csiz = sp->sizoff;
326                         p->tn.lval = 0;
327                         p->tn.rval = idname;
328                         /* special case: MOETY is really an ICON... */
329                         ifp->in.type == MOETY ){
330                                 p->tn.rval = NONAME;
331                                 p->tn.lval = sp->offset;
332                                 p->fn.cdim = 0;
333                                 p->in.type = ENUMTY;
334                                 p->in.op = ICON;
335                                 }
336                         break;
337
338                 case ICON:
339                         p->in.type = INT;
340                         p->fn.cdim = 0;
341                         p->fn.csiz = INT;
342                         break;
343
344                 case STRING:
345                         p->in.op = NAME;
346                         p->in.type = CHAR+ARY;
347                         p->tn.lval = 0;
348                         p->tn.rval = NOLAB;
349                         p->fn.cdim = curdim;
350                         p->fn.csiz = CHAR;
351                         break;
352
353                 case FCON:
354                         p->tn.lval = 0;
355                         p->tn.rval = 0;
356                         p->in.type = FLOAT;
357                         p->fn.cdim = 0;
358                         p->fn.csiz = FLOAT;
359                         break;
360
361                 case DCON:
362                         p->tn.lval = 0;
363                         p->tn.rval = 0;
364                         p->in.type = DOUBLE;
365                         p->fn.cdim = 0;
366                         p->fn.csiz = DOUBLE;
367                         break;
368
369                 case STREF:
370                         /* p->x turned into *(p+offset) */
371                         /* rhs must be a name; check correctness */
372
373                         i = r->tn.rval;
374                         ifi<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
375                                 uerror"member of structure or union required" );
376                                 }else
377                         /* if this name is non-unique, find right one */
378                         ifstab[i].sflags & SNONUNIQ &&
379                                 (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
380                                 (l->fn.csiz +1) >= 0 ){
381                                 /* nonunique name && structure defined */
382                                 char * memnam, * tabnam;
383                                 int j;
384                                 int memi;
385                                 j=dimtab[l->fn.csiz+1];
386                                 for( ; (memi=dimtab[j]) >= 0; ++j ){
387                                         tabnam = stab[memi].sname;
388                                         memnam = stab[i].sname;
389 # ifndef BUG1
390                                         ifddebug>1 ){
391 #ifndef FLEXNAMES
392                                                 printf("member %.8s==%.8s?\n",
393 #else
394                                                 printf("member %s==%s?\n",
395 #endif
396                                                         memnamtabnam);
397                                                 }
398 # endif
399                                         ifstab[memi].sflags & SNONUNIQ ){
400 #ifndef FLEXNAMES
401                                                 register k;
402                                                 fork=0k<NCHNAM; ++k ){
403                                                         if(*memnam++!=*tabnam)
404                                                                 goto next;
405                                                         if(!*tabnam++) break;
406                                                         }
407 #else
408                                                 if (memnam != tabnam)
409                                                         goto next;
410 #endif
411                                                 r->tn.rval = i = memi;
412                                                 break;
413                                                 }
414                                         nextcontinue;
415                                         }
416                                 ifmemi < 0 )
417 #ifndef FLEXNAMES
418                                         uerror("illegal member use: %.8s",
419 #else
420                                         uerror("illegal member use: %s",
421 #endif
422                                                 stab[i].sname);
423                                 }
424                         else {
ragge
1.2
425                                 int j;
ragge
1.1
426                                 ifl->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
427                                         ifstab[i].sflags & SNONUNIQ ){
428                                                 uerror"nonunique name demands struct/union or struct/union pointer" );
429                                                 }
430                                         else werror"struct/union or struct/union pointer required" );
431                                         }
432                                 else if( (j=l->fn.csiz+1)<0 ) cerror"undefined structure or union" );
433                                 else if( !chkstridimtab[j], DECREF(l->in.type) ) ){
434 #ifndef FLEXNAMES
435                                         werror"illegal member use: %.8s"stab[i].sname );
436 #else
437                                         werror"illegal member use: %s"stab[i].sname );
438 #endif
439                                         }
440                                 }
441
442                         p = strefp );
443                         break;
444
445                 case UNARY MUL:
446                         ifl->in.op == UNARY AND ){
447                                 p->in.op = l->in.op = FREE;
448                                 p = l->in.left;
449                                 }
450                         if( !ISPTR(l->in.type))uerror("illegal indirection");
451                         p->in.type = DECREF(l->in.type);
452                         p->fn.cdim = l->fn.cdim;
453                         p->fn.csiz = l->fn.csiz;
454                         break;
455
456                 case UNARY AND:
457                         switchl->in.op ){
458
459                         case UNARY MUL:
460                                 p->in.op = l->in.op = FREE;
461                                 p = l->in.left;
462                         case NAME:
463                                 p->in.type = INCREFl->in.type );
464                                 p->fn.cdim = l->fn.cdim;
465                                 p->fn.csiz = l->fn.csiz;
466                                 break;
467
468                         case COMOP:
469                                 lr = buildtreeUNARY ANDl->in.rightNIL );
470                                 p->in.op = l->in.op = FREE;
471                                 p = buildtreeCOMOPl->in.leftlr );
472                                 break;
473
474                         case QUEST:
475                                 lr = buildtreeUNARY ANDl->in.right->in.rightNIL );
476                                 ll = buildtreeUNARY ANDl->in.right->in.leftNIL );
477                                 p->in.op = l->in.op = l->in.right->in.op = FREE;
478                                 p = buildtreeQUESTl->in.leftbuildtreeCOLONlllr ) );
479                                 break;
480
481 # ifdef ADDROREG
482                         case OREG:
483                                 /* OREG was built in clocal()
484                                  * for an auto or formal parameter
485                                  * now its address is being taken
486                                  * local code must unwind it
487                                  * back to PLUS/MINUS REG ICON
488                                  * according to local conventions
489                                  */
490                                 p->in.op = FREE;
491                                 p = addroregl );
492                                 break;
493
494 # endif
495                         default:
496                                 uerror"unacceptable operand of &" );
497                                 break;
498                                 }
499                         break;
500
501                 case LS:
502                 case RS:
503                         ifl->in.type == CHAR || l->in.type == SHORT )
504                                 p->in.type = INT;
505                         else ifl->in.type == UCHAR || l->in.type == USHORT )
506                                 p->in.type = UNSIGNED;
507                         else
508                                 p->in.type = l->in.type;
509                 case ASG LS:
510                 case ASG RS:
511                         ifr->in.type != INT )
512                                 p->in.right = r = makety(rINT0INT );
513                         break;
514
515                 case RETURN:
516                 case ASSIGN:
517                 case CAST:
518                         /* structure assignment */
519                         /* take the addresses of the two sides; then make an
ragge
1.2
520                          * operator using STASG and
521                          * the addresses of left and right */
ragge
1.1
522
523                         {
ragge
1.2
524                                 TWORD t;
525                                 int ds;
ragge
1.1
526
527                                 ifl->fn.csiz != r->fn.csiz ) uerror"assignment of different structures" );
528
529                                 r = buildtreeUNARY ANDrNIL );
530                                 t = r->in.type;
531                                 d = r->fn.cdim;
532                                 s = r->fn.csiz;
533
534                                 l = blockSTASGlrtds );
535
536                                 ifo == RETURN ){
537                                         p->in.op = FREE;
538                                         p = l;
539                                         break;
540                                         }
541
542                                 p->in.op = UNARY MUL;
543                                 p->in.left = l;
544                                 p->in.right = NIL;
545                                 break;
546                                 }
547                 case COLON:
548                         /* structure colon */
549
550                         ifl->fn.csiz != r->fn.csiz ) uerror"type clash in conditional" );
551                         break;
552
553                 case CALL:
554                         p->in.right = r = fixargsp->in.right );
555                 case UNARY CALL:
556                         if( !ISPTR(l->in.type)) uerror("illegal function");
557                         p->in.type = DECREF(l->in.type);
558                         if( !ISFTN(p->in.type)) uerror("illegal function");
559                         p->in.type = DECREFp->in.type );
560                         p->fn.cdim = l->fn.cdim;
561                         p->fn.csiz = l->fn.csiz;
562                         ifl->in.op == UNARY AND && l->in.left->in.op == NAME &&
563                                 l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
564                                 ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
565                                 p->in.op += (FORTCALL-CALL);
566                                 }
567                         ifp->in.type == STRTY || p->in.type == UNIONTY ){
568                                 /* function returning structure */
569                                 /*  make function really return ptr to str., with * */
570
571                                 p->in.op += STCALL-CALL;
572                                 p->in.type = INCREFp->in.type );
573                                 p = buildtreeUNARY MULpNIL );
574
575                                 }
576                         break;
577
578                 default:
579                         cerror"other code %d"o );
580                         }
581
582                 }
583
584         ifactions & CVTO ) p = oconvert(p);
585         p = clocal(p);
586
587 # ifndef BUG1
588         ifbdebug ) fwalkpeprint0 );
589 # endif
590
591         return(p);
592
593         }
594
595 int fpe_count = -1;
596 jmp_buf gotfpe;
597
ragge
1.2
598 void fpe(int);
ragge
1.1
599 void
ragge
1.2
600 fpe(int a)
601 {
ragge
1.1
602         if (fpe_count < 0)
603                 cerror("floating point exception");
604         ++fpe_count;
605         longjmp(gotfpe1);
ragge
1.2
606 }
ragge
1.1
607
608 /*
609  * Rewrite arguments in a function call.
610  * Structure arguments are massaged, single
611  * precision floating point constants are
612  * cast to double (to eliminate convert code).
613  */
614 NODE *
615 fixargsp ) register NODE *p;  {
616         int o = p->in.op;
617
618         ifo == CM ){
619                 p->in.left = fixargsp->in.left );
620                 p->in.right = fixargsp->in.right );
621                 returnp );
622                 }
623
624         ifp->in.type == STRTY || p->in.type == UNIONTY ){
625                 p = blockSTARGpNILp->in.typep->fn.cdimp->fn.csiz );
626                 p->in.left = buildtreeUNARY ANDp->in.leftNIL );
627                 p = clocal(p);
628                 }
629         else ifo == FCON )
630                 p = makety(pDOUBLE00);
631         returnp );
ragge
1.2
632 }
ragge
1.1
633
ragge
1.2
634 /*
635  * is the MOS or MOU at stab[i] OK for strict reference by a ptr
636  * i has been checked to contain a MOS or MOU
637  * j is the index in dimtab of the members...
638  */
639 int
640 chkstr(int iint jTWORD type)
641 {
ragge
1.1
642         int kkk;
643
644         extern int ddebug;
645
646 # ifndef BUG1
647 #ifndef FLEXNAMES
648         ifddebug > 1 ) printf"chkstr( %.8s(%d), %d )\n"stab[i].snameij );
649 #else
650         ifddebug > 1 ) printf"chkstr( %s(%d), %d )\n"stab[i].snameij );
651 #endif
652 # endif
653         if( (k = j) < 0 ) uerror"undefined structure or union" );
654         else {
655                 for( ; (kk = dimtab[k] ) >= 0; ++k ){
656                         ifkk >= SYMTSZ ){
657                                 cerror"gummy structure" );
658                                 return(1);
659                                 }
660                         ifkk == i ) return1 );
661                         switchstab[kk].stype ){
662
663                         case STRTY:
664                         case UNIONTY:
665                                 iftype == STRTY ) continue;  /* no recursive looking for strs */
666                                 ifhflag && chkstridimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
667                                         ifstab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
668                                         werror(
669 #ifndef FLEXNAMES
670                                         "illegal member use: perhaps %.8s.%.8s?",
671 #else
672                                         "illegal member use: perhaps %s.%s?",
673 #endif
674                                         stab[kk].snamestab[i].sname );
675                                         return(1);
676                                         }
677                                 }
678                         }
679                 }
680         return0 );
ragge
1.2
681 }
ragge
1.1
682
ragge
1.2
683 /*
684  * apply the op o to the lval part of p; if binary, rhs is val
685  * works only on integer constants
686  */
687 int
688 conval(NODE *pint oNODE *q)
689 {
ragge
1.1
690         int iu;
691         CONSZ val;
692         TWORD utype;
693
694         val = q->tn.lval;
695         u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
696         ifu && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
697
698         ifp->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
699         ifq->tn.rval != NONAME && o!=PLUS ) return(0);
700         ifp->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
701
702         /* usual type conversions -- handle casts of constants */
703 #define ISLONG(t)       ((t) == LONG || (t) == ULONG)
704         if (ISLONG(p->in.type) || ISLONG(q->in.type))
705                 utype = u ? ULONG : LONG;
706         else
707                 utype = u ? UNSIGNED : INT;
708         if( !ISPTR(p->in.type) && p->in.type != utype )
709                 p = makety(putype0, (int)utype);
710         ifq->in.type != utype )
711                 q = makety(qutype0, (int)utype);
712
713         switcho ){
714
715         case PLUS:
716                 p->tn.lval += val;
717                 ifp->tn.rval == NONAME ){
718                         p->tn.rval = q->tn.rval;
719                         p->in.type = q->in.type;
720                         }
721                 break;
722         case MINUS:
723                 p->tn.lval -= val;
724                 break;
725         case MUL:
726                 p->tn.lval *= val;
727                 break;
728         case DIV:
729                 ifval == 0 ) uerror"division by 0" );
730                 else if ( u ) p->tn.lval = (unsignedp->tn.lval / val;
731                 else p->tn.lval /= val;
732                 break;
733         case MOD:
734                 ifval == 0 ) uerror"division by 0" );
735                 else if ( u ) p->tn.lval = (unsignedp->tn.lval % val;
736                 else p->tn.lval %= val;
737                 break;
738         case AND:
739                 p->tn.lval &= val;
740                 break;
741         case OR:
742                 p->tn.lval |= val;
743                 break;
744         case ER:
745                 p->tn.lval ^= val;
746                 break;
747         case LS:
748                 i = val;
749                 p->tn.lval = p->tn.lval << i;
750                 break;
751         case RS:
752                 i = val;
753                 if ( u ) p->tn.lval = (unsignedp->tn.lval >> i;
754                 else p->tn.lval = p->tn.lval >> i;
755                 break;
756
757         case UNARY MINUS:
758                 p->tn.lval = - p->tn.lval;
759                 break;
760         case COMPL:
761                 p->tn.lval = ~p->tn.lval;
762                 break;
763         case NOT:
764                 p->tn.lval = !p->tn.lval;
765                 break;
766         case LT:
767                 p->tn.lval = p->tn.lval < val;
768                 break;
769         case LE:
770                 p->tn.lval = p->tn.lval <= val;
771                 break;
772         case GT:
773                 p->tn.lval = p->tn.lval > val;
774                 break;
775         case GE:
776                 p->tn.lval = p->tn.lval >= val;
777                 break;
778         case ULT:
779                 p->tn.lval = p->tn.lval < (unsignedval;
780                 break;
781         case ULE:
782                 p->tn.lval = p->tn.lval <= (unsignedval;
783                 break;
784         case UGT:
785                 p->tn.lval = p->tn.lval > (unsignedval;
786                 break;
787         case UGE:
788                 p->tn.lval = p->tn.lval >= (unsignedval;
789                 break;
790         case EQ:
791                 p->tn.lval = p->tn.lval == val;
792                 break;
793         case NE:
794                 p->tn.lval = p->tn.lval != val;
795                 break;
796         default:
797                 return(0);
798                 }
799         return(1);
800         }
801
ragge
1.2
802 void
ragge
1.1
803 chkpun(pregister NODE *p; {
804
805         /* checks p for the existance of a pun */
806
807         /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
808
809         /* one case is when enumerations are used: this applies only to lint */
810         /* in the other case, one operand is a pointer, the other integer type */
811         /* we check that this integer is in fact a constant zero... */
812
813         /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
814         /* this falls out, because the LHS is never 0 */
815
ragge
1.2
816         NODE *q;
817         int t1t2d1d2ref1ref2;
ragge
1.1
818
819         t1 = p->in.left->in.type;
820         t2 = p->in.right->in.type;
821
822         ift1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
823                 /* rob pike says this is obnoxious...
824                 if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
825                         werror( "comparison of enums" ); */
826                 ift1==ENUMTY && t2==ENUMTY ) {
827                         if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
828                                 werror"enumeration type clash, operator %s"opst[p->in.op] );
829                         return;
830                         }
831                 if ( t1 == ENUMTY ) t1 = INT;
832                 if ( t2 == ENUMTY ) t2 = INT;
833                 }
834
835         ref1 = ISPTR(t1) || ISARY(t1);
836         ref2 = ISPTR(t2) || ISARY(t2);
837
838         ifref1 ^ ref2 ){
839                 ifref1 ) q = p->in.right;
840                 else q = p->in.left;
841                 ifq->in.op != ICON || q->tn.lval != 0 ){
842                         werror"illegal combination of pointer and integer, op %s",
843                                 opst[p->in.op] );
844                         }
845                 }
846         else ifref1 ){
847                 ift1 == t2 ) {
848                         ifp->in.left->fn.csiz != p->in.right->fn.csiz ) {
849                                 werror"illegal structure pointer combination" );
850                                 return;
851                                 }
852                         d1 = p->in.left->fn.cdim;
853                         d2 = p->in.right->fn.cdim;
854                         for( ;; ){
855                                 ifISARY(t1) ){
856                                         ifdimtab[d1] != dimtab[d2] ){
857                                                 werror"illegal array size combination" );
858                                                 return;
859                                                 }
860                                         ++d1;
861                                         ++d2;
862                                         }
863                                 else if( !ISPTR(t1) ) break;
864                                 t1 = DECREF(t1);
865                                 }
866                         }
867                 else ift1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
868                         werror"illegal pointer combination" );
869                 }
870
871         }
872
873 NODE *
874 strefp ) register NODE *p; {
875
876         TWORD t;
877         int dsdscalign;
878         OFFSZ off;
879         register struct symtab *q;
880
881         /* make p->x */
882         /* this is also used to reference automatic variables */
883
884         q = &stab[p->in.right->tn.rval];
885         p->in.right->in.op = FREE;
886         p->in.op = FREE;
887         p = pconvertp->in.left );
888
889         /* make p look like ptr to x */
890
891         if( !ISPTR(p->in.type)){
892                 p->in.type = PTR+UNIONTY;
893                 }
894
895         t = INCREFq->stype );
896         d = q->dimoff;
897         s = q->sizoff;
898
899         p = maketyptds );
900
901         /* compute the offset to be added */
902
903         off = q->offset;
904         dsc = q->sclass;
905
906         ifdsc & FIELD ) {  /* normalize offset */
907                 align = ALINT;
908                 s = INT;
909                 off = (off/align)*align;
910                 }
911         ifoff != 0 ) p = clocalblockPLUSpoffconofftds ), tds ) );
912
913         p = buildtreeUNARY MULpNIL );
914
915         /* if field, build field info */
916
917         ifdsc & FIELD ){
918                 p = blockFLDpNILq->stype0q->sizoff );
919                 p->tn.rval = PKFIELDdsc&FLDSIZq->offset%align );
920                 }
921
922         returnclocal(p) );
923         }
924
ragge
1.2
925 int
ragge
1.1
926 notlval(pregister NODE *p; {
927
928         /* return 0 if p an lvalue, 1 otherwise */
929
930         again:
931
932         switchp->in.op ){
933
934         case FLD:
935                 p = p->in.left;
936                 goto again;
937
938         case UNARY MUL:
939                 /* fix the &(a=b) bug, given that a and b are structures */
940                 ifp->in.left->in.op == STASG ) return1 );
941                 /* and the f().a bug, given that f returns a structure */
942                 ifp->in.left->in.op == UNARY STCALL ||
943                     p->in.left->in.op == STCALL ) return1 );
944         case NAME:
945         case OREG:
946                 ifISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
947         case REG:
948                 return(0);
949
950         default:
951                 return(1);
952
953                 }
954
955         }
956
957 NODE *
958 bconi ){ /* make a constant node with value i */
959         register NODE *p;
960
961         p = blockICONNILNILINT0INT );
962         p->tn.lval = i;
963         p->tn.rval = NONAME;
964         returnclocal(p) );
965         }
966
967 NODE *
968 bpsize(pregister NODE *p; {
969         returnoffconpsize(p), p->in.typep->fn.cdimp->fn.csiz ) );
970         }
971
972 OFFSZ
973 psizep ) NODE *p; {
974         /* p is a node of type pointer; psize returns the
975            size of the thing pointed to */
976
977         if( !ISPTR(p->in.type) ){
978                 uerror"pointer required");
979                 returnSZINT );
980                 }
981         /* note: no pointers to fields */
982         returntsizeDECREF(p->in.type), p->fn.cdimp->fn.csiz ) );
983         }
984
985 NODE *
986 convertpf )  register NODE *p; {
987         /*  convert an operand of p
988             f is either CVTL or CVTR
989             operand has type int, and is converted by the size of the other side
990             */
991
992         register NODE *q, *r;
993
994         q = (f==CVTL)?p->in.left:p->in.right;
995
996         r = blockPMCONV,
997                 qbpsize(f==CVTL?p->in.right:p->in.left), INT0INT );
998         r = clocal(r);
999         iff == CVTL )
1000                 p->in.left = r;
1001         else
1002                 p->in.right = r;
1003         return(p);
1004
1005         }
1006
1007 #ifndef econvert
ragge
1.2
1008 void
ragge
1.1
1009 econvertp ) register NODE *p; {
1010
1011         /* change enums to ints, or appropriate types */
1012
1013         register TWORD ty;
1014
1015         if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
1016                 ifdimtabp->fn.csiz ] == SZCHAR ) ty = CHAR;
1017                 else ifdimtabp->fn.csiz ] == SZINT ) ty = INT;
1018                 else ifdimtabp->fn.csiz ] == SZSHORT ) ty = SHORT;
1019                 else ty = LONG;
1020                 ty = ctypety );
1021                 p->fn.csiz = ty;
1022                 MODTYPE(p->in.type,ty);
1023                 ifp->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
1024                 }
1025         }
1026 #endif
1027
1028 NODE *
1029 pconvertp ) register NODE *p; {
1030
1031         /* if p should be changed into a pointer, do so */
1032
1033         ifISARYp->in.type) ){
1034                 p->in.type = DECREFp->in.type );
1035                 ++p->fn.cdim;
1036                 returnbuildtreeUNARY ANDpNIL ) );
1037                 }
1038         ifISFTNp->in.type) )
1039                 returnbuildtreeUNARY ANDpNIL ) );
1040
1041         returnp );
1042         }
1043
1044 NODE *
1045 oconvert(pregister NODE *p; {
1046         /* convert the result itself: used for pointer and unsigned */
1047
1048         switch(p->in.op) {
1049
1050         case LE:
1051         case LT:
1052         case GE:
1053         case GT:
1054                 ifISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
1055         case EQ:
1056         case NE:
1057                 returnp );
1058
1059         case MINUS:
1060                 return(  clocalblockPVCONV,
1061                         pbpsize(p->in.left), INT0INT ) ) );
1062                 }
1063
1064         cerror"illegal oconvert: %d"p->in.op );
1065
1066         return(p);
1067         }
1068
1069 NODE *
1070 ptmatch(p)  register NODE *p; {
1071
1072         /* makes the operands of p agree; they are
1073            either pointers or integers, by this time */
1074         /* with MINUS, the sizes must be the same */
1075         /* with COLON, the types must be the same */