Add tests, fixes for tests, reinstate and type-convert stuff marked "bitrot"
[ccom.git] / c01.c
1 /*
2  * C compiler
3  */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #ifdef __STDC__
9 #include <stdarg.h>
10 #define _va_start(argp, arg) va_start(argp, arg)
11 #else
12 #include <varargs.h>
13 #define _va_start(argp, arg) va_start(argp)
14 #endif
15 #include "c0.h"
16
17 /*
18  * Called from tree, this routine takes the top 1, 2, or 3
19  * operands on the expression stack, makes a new node with
20  * the operator op, and puts it on the stack.
21  * Essentially all the work is in inserting
22  * appropriate conversions.
23  */
24 void build(op) int op; {
25         register int t1;
26         int t2, t;
27         register struct node *p1, *p2, *p3;
28         int dope, leftc, cvn, pcvn;
29
30         /*
31          * a[i] => *(a+i)
32          */
33         if (op==LBRACK) {
34                 build(PLUS);
35                 op = STAR;
36         }
37         dope = opdope0[op];
38         t2 = INT;
39         if ((dope&BINARY)!=0) {
40                 p2 = chkfun(disarray(*--cp));
41                 if (p2)
42                         t2 = p2->n_type;
43         }
44         p1 = *--cp;
45         /*
46          * sizeof gets turned into a number here.
47          */
48         if (op==SIZEOF) {
49                 struct cnode *p = cblock(XXXlength(p1));
50                 p->cn_type = UNSIGN;
51                 *cp++ = (struct node *)p;
52                 return;
53         }
54         if (op!=AMPER) {
55                 p1 = disarray(p1);
56                 if (op!=CALL)
57                         p1 = chkfun(p1);
58         }
59         t1 = p1->n_type;
60         if (t1==CHAR)
61                 t1 = INT;
62         else if (t1==UNCHAR)
63                 t1 = UNSIGN;
64         if (t2==CHAR)
65                 t2 = INT;
66         else if (t2==UNCHAR)
67                 t2 = UNSIGN;
68         pcvn = 0;
69         t = INT;
70         switch (op) {
71
72         case CAST:
73                 if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY)
74                         error0("Disallowed conversion");
75                 if (p1->n_type==UNCHAR) {
76                         *cp++ = (struct node *)block(ETYPE, UNSIGN, (int *)NULL, (union str *)NULL,
77                            (struct node *)NULL, (struct node *)NULL);
78                         *cp++ = p2;
79                         build(CAST);
80                         *cp++ = (struct node *)cblock(0377);
81                         build(AND);
82                         return;
83                 }
84                 if (p2->n_type==CHAR || p2->n_type==UNCHAR)
85                         p2 = (struct node *)block(PLUS, t2, (int *)NULL, (union str *)NULL,
86                            p2, (struct node *)cblock(0));
87                 break;
88
89         /* end of expression */
90         case 0:
91                 *cp++ = p1;
92                 return;
93
94         /* no-conversion operators */
95         case QUEST:
96                 if (p2->n_op!=COLON)
97                         error0("Illegal conditional");
98                 else
99                         if (fold(QUEST, p1, p2))
100                                 return;
101
102         /*
103          * Bug fix, because copying type is not enough,
104          * i.e. t = (t, t) + 1;
105          * Original code was:
106          *      case SEQNC:
107          *              t = t2;
108          *      case COMMA:
109          */
110         case SEQNC:
111                 *cp++ = (struct node *)block(op, t2, p2->n_subsp, p2->n_strp, p1, p2);
112                 return;
113
114         case COMMA:
115         case LOGAND:
116         case LOGOR:
117                 *cp++ = (struct node *)block(op, t, p2->n_subsp, p2->n_strp, p1, p2);
118                 return;
119
120         case EXCLA:
121                 t1 = INT;
122                 break;
123
124         case CALL:
125                 if ((t1&XTYPE) == PTR && (decref0(t1)&XTYPE) == FUNC) {
126                         /*
127                          * Modification to allow calling a function via a
128                          * pointer to a function ("f") without explicitly
129                          * dereferencing the pointer.  That is: f(...) is now
130                          * legal as well as (*f)(...).  The insistence that
131                          * decref0(t1) be FUNC prevents pointers to pointers to
132                          * functions and so on from being automatically
133                          * dereferenced which would be incorrect and introduce
134                          * porting problems.  Note that for purity FUNC's
135                          * should really always be referenced (as in pcc) and
136                          * that the new notation is actually more consistent
137                          * with the rest of C ...
138                          */
139                         *cp++ = p1;
140                         build(STAR);
141                         *cp++ = p2;
142                         build(CALL);
143                         return;
144                 }
145                 if ((t1&XTYPE) != FUNC)
146                         error0("Call of non-function");
147                 *cp++ = (struct node *)block(CALL,decref0(t1),p1->n_subsp,p1->n_strp,p1,p2);
148                 return;
149
150         case STAR:
151                 if ((t1&XTYPE) == FUNC)
152                         error0("Illegal indirection");
153                 *cp++ = (struct node *)block(STAR, decref0(t1), p1->n_subsp, p1->n_strp, p1, (struct node *)NULL);
154                 return;
155
156         case AMPER:
157                 if (p1->n_op==NAME || p1->n_op==STAR) {
158                         *cp++ = (struct node *)block(op,incref0(p1->n_type),p1->n_subsp,p1->n_strp,p1,(struct node *)NULL);
159                         return;
160                 }
161                 error0("Illegal lvalue");
162                 break;
163
164         /*
165          * a.b goes to (&a)->b
166          */
167         case DOT:
168                 if (p1->n_op==CALL && t1==STRUCT) {
169                         t1 = incref0(t1);
170                         setype(p1, t1, p1);
171                 } else {
172                         *cp++ = p1;
173                         build(AMPER);
174                         p1 = *--cp;
175                 }
176
177         /*
178          * In a->b, a is given the type ptr-to-structure element;
179          * then the offset is added in without conversion;
180          * then * is tacked on to access the member.
181          */
182         case ARROW:
183                 if (p2->n_op!=NAME || ((struct nnode *)p2)->nn_nmlist->nl_class!=MOS) {
184                         error0("Illegal structure ref");
185                         *cp++ = p1;
186                         return;
187                 }
188 #define np2 ((struct nnode *)p2)
189                 structident(p1, np2);
190                 t2 = np2->nn_type;
191                 if (t2==INT && np2->nn_nmlist->/*nl_flag&FFIELD*/nl_dtype->t_id==BITFLD)
192                         t2 = UNSIGN;
193                 t = incref0(t2);
194                 chkw(p1, -1);
195                 setype(p1, t, (struct node *)np2);
196                 *cp++ = (struct node *)block(PLUS, t, np2->nn_subsp, np2->nn_strp,
197                    p1, (struct node *)cblock(np2->nn_nmlist->nl_offset));
198                 build(STAR);
199                 if (np2->nn_nmlist->/*nl_flag&FFIELD*/nl_dtype->t_id==BITFLD)
200 #if 1
201                         cp[-1] = (struct node *)block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL, 
202                             cp[-1], (struct node *)/*np2->nn_nmlist->nl_strp*/&((struct btype *)np2->nn_nmlist->nl_dtype)->bt_F);
203 #else
204                         *cp++ = (struct node *)block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL, 
205                             *--cp, (struct node *)/*np2->nn_nmlist->nl_strp*/&((struct btype *)np2->nn_nmlist->nl_dtype)->bt_F);
206 #endif
207                 return;
208 #undef np2
209         }
210         if ((dope&LVALUE)!=0)
211                 chklval(p1);
212         if ((dope&LWORD)!=0)
213                 chkw(p1, LONG);
214         if ((dope&RWORD)!=0)
215                 chkw(p2, LONG);
216         if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) {
217                 error0("Illegal use of void object");
218                 t = t1 = t2 = INT;
219         }
220         if ((dope&BINARY)==0) {
221                 if (op==ITOF)
222                         t1 = DOUBLE;
223                 else if (op==FTOI)
224                         t1 = INT;
225                 if (!fold(op, p1, (struct node *)NULL))
226                         *cp++ = (struct node *)block(op, t1, p1->n_subsp, p1->n_strp, p1,(struct node *)NULL);
227                 return;
228         }
229         cvn = 0;
230         if (t1==STRUCT || t2==STRUCT) {
231                 if (t1!=t2 || p1->n_strp != p2->n_strp)
232                         error0("Incompatible structures");
233                 cvn = 0;
234         } else
235                 cvn = cvtab[lintyp(t1)][lintyp(t2)];
236         leftc = (cvn>>4)&017;
237         cvn &= 017;
238         t = leftc? t2:t1;
239         if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
240                 t = UNSIGN;
241         if (dope&ASSGOP || op==CAST) {
242                 /*
243                  * Weird "lhs op= rhs" requiring a temporary to evaluate as
244                  * "lhs = lhs op rhs" so lhs can be converted up for the
245                  * operation and then the result converted back down for
246                  * the assignment.  As a special sub case, "(int) op= (long)"
247                  * doesn't require a temporary except for /= and %= ...
248                  */
249                 if (leftc && op>=ASPLUS && op<=ASXOR
250                     && (leftc!=LTI || op==ASDIV || op==ASMOD)) {
251                         assignop(op, p1, p2);
252                         return;
253                 }
254                 t = t1;
255                 if (op==ASSIGN) {
256                         if (cvn==PTI) {
257                                 if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->n_strp!=p2->n_strp))
258                                         werror0("mixed pointer assignment");
259                                 cvn = leftc = 0;
260                         } if ((cvn==ITP || cvn==LTP)
261                            && (p2->n_op!=CON || ((struct cnode *)p2)->cn_value!=0)
262                            && (p2->n_op!=LCON || ((struct lnode *)p2)->ln_lvalue!=0)) {
263                         /*
264                          * Allow "i = p" and "p = i" with a warning, where
265                          * i is some form of integer (not 0) and p is a
266                          * pointer.  Note that in both this patch and the
267                          * similar one for "?:" below, code from the CAST
268                          * immediately below and the illegal conversion
269                          * check farther below is simply stolen.  It would
270                          * require either a recursive call to build or a
271                          * fairly large rewrite to eliminate the
272                          * duplication.
273                          */
274                                 werror0("illegal combination of pointer and integer, op =");
275                                 if (cvn==ITP)
276                                         cvn = leftc = 0;
277                                 else
278                                         if (leftc==0)
279                                                 cvn = LTI;
280                                         else {
281                                                 cvn = ITL;
282                                                 leftc = 0;
283                                         }
284                         }
285                 } else if (op==CAST) {
286                         if (cvn==ITP||cvn==PTI)
287                                 cvn = leftc = 0;
288                         else if (cvn==LTP) {
289                                 if (leftc==0)
290                                         cvn = LTI;
291                                 else {
292                                         cvn = ITL;
293                                         leftc = 0;
294                                 }
295                         }
296                 }
297                 if (leftc)
298                         cvn = leftc;
299                 leftc = 0;
300         } else if (op==COLON || op==MAX || op==MIN) {
301                 if (t1>=PTR && t1==t2)
302                         cvn = 0;
303                 if (op!=COLON && (t1>=PTR || t2>=PTR))
304                         op += MAXP-MAX;
305                 /*
306                  * Allow "e ? i : p" and "e ? p : i" with warning.
307                  */
308                 if (op==COLON && (cvn==ITP || cvn==LTP)) {
309                         p3 = leftc? p1: p2;
310                         if ((p3->n_op!=CON || ((struct cnode *)p3)->cn_value!=0)
311                          && (p3->n_op!=LCON || ((struct lnode *)p3)->ln_lvalue!=0)) {
312                                 werror0("illegal combination of pointer and integer, op :");
313                                 if (cvn==ITP)
314                                         cvn = leftc = 0;
315                                 else
316                                         if (leftc==0)
317                                                 cvn = LTI;
318                                         else {
319                                                 cvn = ITL;
320                                                 leftc = 0;
321                                         }
322                         }
323                 }
324         } else if (dope&RELAT) {
325                 if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t1==UNLONG||t2==UNSIGN||t2==UNLONG)
326                  && (t==INT||t==CHAR||t==UNSIGN||t==UNLONG)))
327                         op += LESSEQP-LESSEQ;
328                 if (cvn==ITP || cvn==PTI)
329                         cvn = 0;
330         }
331         if (cvn==PTI) {
332                 cvn = 0;
333                 if (op==MINUS) {
334                         pcvn++;
335                         p1 = (struct node *)block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, (struct node *)NULL);
336                         p2 = (struct node *)block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, (struct node *)NULL);
337                         t = LONG;
338                 } else {
339                         if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR)))
340                                 cvn = XX;
341                 }
342         }
343         if (cvn) {
344                 if ((cvn==ITP || cvn==LTP) && (opdope0[op]&PCVOK)==0) {
345                         p3 = leftc? p1: p2;
346                         if ((p3->n_op!=CON || ((struct cnode *)p3)->cn_value!=0)
347                          && (p3->n_op!=LCON || ((struct lnode *)p3)->ln_lvalue!=0))
348                                 cvn = XX;
349                         else
350                                 cvn = 0;
351                 }
352                 t1 = plength(p1);
353                 t2 = plength(p2);
354                 if (cvn==XX || (cvn==PTI&&t1!=t2))
355                         error0("Illegal conversion");
356                 else if (leftc)
357                         p1 = convert(p1, t, cvn, t2);
358                 else
359                         p2 = convert(p2, t, cvn, t1);
360         }
361         if (dope&RELAT)
362                 t = INT;
363         if (t==FLOAT)
364                 t = DOUBLE;
365         if (t==CHAR)
366                 t = INT;
367         if (op==CAST) {
368                 /* could the below be an oversight? gcc notes rhs always true */
369                 if (t!=DOUBLE /*&& (t!=INT || p2->n_type!=CHAR || p2->n_type!=UNCHAR)*/) {
370                         p2->n_type = t;
371                         p2->n_subsp = p1->n_subsp;
372                         p2->n_strp = p1->n_strp;
373                 }
374                 if (t==INT && p1->n_type==CHAR)
375                         p2 = (struct node *)block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, (struct node *)NULL);
376                 *cp++ = p2;
377                 return;
378         }
379         if (pcvn) /* says op == MINUS */
380                 t2 = plength(((struct tnode *)p1)->tn_tr1);
381         if (fold(op, p1, p2)==0) {
382                 p3 = leftc?p2:p1;
383                 *cp++ = (struct node *)block(op, t, p3->n_subsp, p3->n_strp, p1, p2);
384         }
385         if (pcvn) {
386                 p1 = *--cp;
387                 *cp++ = convert(p1, 0, PTI, t2);
388         }
389 }
390
391 int XXXeqtype(struct type *t0, struct type *t1) {
392  while (t0->t_id == t1->t_id) {
393   if ((t0->t_id & TYPE) != REF)
394    return 1;
395   t0 = ((struct rtype *)t0)->rt_reftype;
396   t1 = ((struct rtype *)t1)->rt_reftype;
397  }
398  return 0;
399 }
400 void structident(p1, p2) register struct node *p1; register struct nnode *p2; {
401         register struct nmlist *np, *nporig;
402         int vartypes = 0, namesame = 1;
403  struct tdim dim;
404  int a;
405
406  /*fprintf(stderr, "structident %p op %d type %x strp %p field %s\n", p1, p1->n_op, p1->n_type, p1->n_strp, p2->nn_nmlist->nl_name);*/
407         np = nporig = p2->nn_nmlist;
408         for (;;) {
409                 if (namesame && p1->n_type==STRUCT+PTR && p1->n_strp == np->nl_sparent) {
410  /*fprintf(stderr, "found %p type %x strp %p\n", np, np->nl_type, np->nl_strp);*/
411  /*                     p2->nn_type = np->nl_type;
412                         p2->nn_strp = np->nl_strp;
413                         p2->nn_subsp = np->nl_subsp;*/
414  dim.rank = 0;
415  p2->nn_type = XXXoldtype(np->nl_dtype, &dim, (struct SS **)&p2->nn_strp);
416  p2->nn_subsp = dim.rank ? (int *)Tblock(dim.rank*sizeof(dim.rank)) : NULL;
417  for (a=0; a<dim.rank; a++)
418   p2->nn_subsp[a] = dim.dimens[a];
419                         p2->nn_nmlist = np;
420                         return;
421                 }
422                 np = np->nl_nextnm;
423                 if (np==NULL)
424                         break;
425                 namesame = 0;
426                 if (strcmp(nporig->nl_name, np->nl_name) != 0)
427                         continue;
428                 if ((nporig->nl_flag&FKIND) != (np->nl_flag&FMOS))
429                         continue;
430                 namesame = 1;
431                 if (/*nporig->nl_type==np->nl_type*/XXXeqtype(nporig->nl_dtype, np->nl_dtype) && nporig->nl_offset==np->nl_offset)
432                         continue;
433                 vartypes++;
434         }
435         if (vartypes)
436                 error0("Ambiguous structure reference for %s",nporig->nl_name);
437         else
438                 werror0("%s not member of cited struct/union",nporig->nl_name);
439 }
440
441 /*
442  * Generate the appropriate conversion operator.
443  */
444 struct node *convert(p, t, cvn, len) struct node *p; int t; int cvn; int len; {
445         register int op;
446
447         if (cvn==0)
448                 return(p);
449         op = cvntab[cvn];
450         if (opdope0[op]&BINARY) {
451                 if (len==0)
452                         error0("Illegal conversion");
453                 return((struct node *)block(op, t, (int *)NULL, (union str *)NULL, p, (struct node *)cblock(len)));
454         }
455         return((struct node *)block(op, t, (int *)NULL, (union str *)NULL, p, (struct node *)NULL));
456 }
457
458 /*
459  * Traverse an expression tree, adjust things
460  * so the types of things in it are consistent
461  * with the view that its top node has
462  * type at.
463  * Used with structure references.
464  */
465 void setype(p, t, newp) register struct node *p; register int t; register struct node *newp; {
466         for (;; p = ((struct tnode *)p)->tn_tr1) {
467                 p->n_subsp = newp->n_subsp;
468                 p->n_strp = newp->n_strp;
469                 p->n_type = t;
470                 if (p->n_op==AMPER)
471                         t = decref0(t);
472                 else if (p->n_op==STAR)
473                         t = incref0(t);
474                 else if (p->n_op!=PLUS)
475                         break;
476         }
477 }
478
479 /*
480  * A mention of a function name is turned into
481  * a pointer to that function.
482  */
483 struct node *chkfun(p) register struct node *p; {
484         register int t;
485
486         if (((t = p->n_type)&XTYPE)==FUNC && p->n_op!=ETYPE)
487                 return((struct node *)block(AMPER,incref0(t),p->n_subsp,p->n_strp,p,(struct node *)NULL));
488         return(p);
489 }
490
491 /*
492  * A mention of an array is turned into
493  * a pointer to the base of the array.
494  */
495 struct node *disarray(p) register struct node *p; {
496         register int t;
497
498         if (p==NULL)
499                 return(p);
500         /* check array & not MOS and not typer */
501         if (((t = p->n_type)&XTYPE)!=ARRAY
502          || p->n_op==NAME && ((struct nnode *)p)->nn_nmlist->nl_class==MOS
503          || p->n_op==ETYPE)
504                 return(p);
505         p->n_subsp++;
506         *cp++ = p;
507         setype(p, decref0(t), p);
508         build(AMPER);
509         return(*--cp);
510 }
511
512 /*
513  * make sure that p is a ptr to a node
514  * with type int or char or 'okt.'
515  * okt might be nonexistent or 'long'
516  * (e.g. for <<).
517  */
518 void chkw(p, okt) struct node *p; int okt; {
519         register int t = p->n_type;
520
521         if (t == UNLONG)
522                 t = LONG;
523         if (t!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt)
524                 error0("Illegal type of operand");
525         return;
526 }
527
528 /*
529  *'linearize' a type for looking up in the
530  * conversion table
531  */
532 int lintyp(t) int t; {
533         switch(t) {
534
535         case INT:
536         case CHAR:
537         case UNSIGN:
538         case UNCHAR:
539                 return(0);
540
541         case FLOAT:
542         case DOUBLE:
543                 return(1);
544
545         case UNLONG:
546         case LONG:
547                 return(2);
548
549         default:
550                 return(3);
551         }
552 }
553
554 /*
555  * Report an error.
556  */
557
558 #ifdef __STDC__
559 void werror0(char *s, ...)
560 #else
561 void werror0(s, va_alist) char *s; va_dcl
562 #endif
563 {
564         va_list argp;
565
566         if (Wflag)
567                 return;
568         if (filename[0])
569                 fprintf(stderr, "%s:", filename);
570         fprintf(stderr, "%d: warning: ", line);
571         _va_start(argp, s);
572         vfprintf(stderr, s, argp);
573         va_end(argp);
574         fprintf(stderr, "\n");
575  /*abort();*/
576 }
577
578 #ifdef __STDC__
579 void error0(char *s, ...)
580 #else
581 void error0(s, va_alist) char *s; va_dcl
582 #endif
583 {
584         va_list argp;
585
586         nerror++;
587         if (filename[0])
588                 fprintf(stderr, "%s:", filename);
589         fprintf(stderr, "%d: ", line);
590         _va_start(argp, s);
591         vfprintf(stderr, s, argp);
592         va_end(argp);
593         fprintf(stderr, "\n");
594  /*abort();*/
595 }
596
597 /*
598  * Generate a node in an expression tree,
599  * setting the operator, type, dimen/struct table ptrs,
600  * and the operands.
601  */
602 /*static struct type *newtype(type, dimp, strp) int type; int **dimp; union str *strp; {
603  struct type *t;
604  static struct type basic_types[] = {
605   {INT},
606   {CHAR},
607   {FLOAT},
608   {DOUBLE},
609   {STRUCT},
610   {RSTRUCT},
611   {LONG},
612   {UNSIGN},
613   {UNCHAR},
614   {UNLONG},
615   {VOID}
616  };
617
618  switch (type & XTYPE) {
619  case PTR:
620   fprintf(stderr, "ptr(");
621 #define rt (*(struct rtype **)&t)
622   rt = (struct rtype *)Tblock(sizeof(struct rtype));
623   rt->rt_id = REF | PTR;
624 reft:
625
626   goto reft;
627 #undef pt
628  case FUNC:
629   fprintf(stderr, "func(");
630 #define ft (*(struct ftype **)&t)
631   ft = (struct ftype *)Tblock(sizeof(struct ftype));
632   ft->ft_id = REF | FUNC;
633   ft->ft_arglist = NULL;
634   goto reft;
635 #undef ft
636  case ARRAY:
637   if (*dimp)
638    fprintf(stderr, "array(%d, ", *dimp);
639   else
640    fprintf(stderr, "array(?, ");
641 #define at (*(struct atype **)&t)
642   at = (struct atype *)Tblock(sizeof(struct atype));
643   at->at_id = REF | PTR;
644   at->at_nelt = *dimp ? *(*dimp)++ : 0;
645 #undef at
646  reft:
647 #define rt ((struct rtype *)t)
648   rt->rt_reftype = newtype((type >> TYLEN & ~TYPE) | (type & TYPE), dimp, strp);
649   break;
650 #undef rt
651  default:
652   fprintf(stderr, "basic(%d", type);
653   if (type == STRUCT) {
654 #define st (*(struct stype **)&t)
655    st = (struct stype *)Tblock(sizeof(struct stype));
656    st->st_id = STRUCT;
657    st->st_S = *(struct SS *)strp;
658 #undef st
659   }
660   else
661    t = basic_types + type;
662   break;
663  }
664  fprintf(stderr, ")");
665  return t;
666 }*/
667 struct tnode *block(op, t, subs, str, p1, p2) int op; int t; int *subs; union str *str; struct node *p1; struct node *p2; {
668         register struct tnode *p;
669
670         p = (struct tnode *)Tblock(sizeof(struct tnode));
671         p->tn_op = op;
672         p->tn_type = t;
673         p->tn_subsp = subs;
674         p->tn_strp = str;
675  /*fprintf(stderr, "newtype ");
676  p->tn_dtype = newtype(t, &subs, str);
677  fprintf(stderr, "\n");*/
678         p->tn_tr1 = p1;
679         if (opdope0[op]&BINARY)
680                 p->tn_tr2 = p2;
681         else
682                 p->tn_tr2 = NULL;
683         return(p);
684 }
685
686 struct nnode *nblock(ds) register struct nmlist *ds; {
687  /*     return(block(NAME, ds->nl_type, ds->nl_subsp, ds->nl_strp, (struct node *)ds, (struct node *)NULL));*/
688         struct nnode *p;
689  struct tdim dim;
690  int a;
691
692         if (ds->nl_class == EXTERN) {
693 #define extp (*(struct extnnode **)&p)
694                 extp = (struct extnnode *)Tblock(sizeof(struct extnnode));
695                 extp->extnn_name = Tblock((strlen(ds->nl_name)+2+LNCPW-1) & ~(LNCPW-1));
696                 extp->extnn_name[0] = '_';
697                 strcpy(extp->extnn_name + 1, ds->nl_name);
698 #undef extp
699         }
700         else {
701 #define locp (*(struct locnnode **)&p)
702                 locp = (struct locnnode *)Tblock(sizeof(struct locnnode));
703                 locp->locnn_nloc = ds->nl_offset;
704 #undef locp
705         }
706  /*fprintf(stderr, "nblock %p name %s type %x strp %p\n", p, ds->nl_name, ds->nl_type, ds->nl_strp);*/
707         p->nn_op = NAME;
708  /*     p->nn_type = ds->nl_type;
709         p->nn_subsp = ds->nl_subsp;
710         p->nn_strp = ds->nl_strp;*/
711  dim.rank = 0;
712  p->nn_type = XXXoldtype(ds->nl_dtype, &dim, (struct SS **)&p->nn_strp);
713  p->nn_subsp = dim.rank ? (int *)Tblock(dim.rank*sizeof(dim.rank)) : NULL;
714  for (a=0; a<dim.rank; a++)
715   p->nn_subsp[a] = dim.dimens[a];
716         p->nn_nmlist = ds;
717         p->nn_class = ds->nl_class==0?STATIC:ds->nl_class;
718         p->nn_regno = 0;
719         p->nn_offset = 0;
720         return p;
721 }
722
723 /*
724  * Generate a block for a constant
725  */
726 struct cnode *cblock(value) _INT value; {
727         register struct cnode *p;
728  /*static struct type t_int = {INT};*/
729
730         p = (struct cnode *)Tblock(sizeof(struct cnode));
731         p->cn_op = CON;
732         p->cn_type = INT;
733         p->cn_subsp = NULL;
734         p->cn_strp = NULL;
735  /*p->cn_dtype = &t_int;*/
736         p->cn_value = value;
737         return(p);
738 }
739
740 /*
741  * A block for a float constant
742  */
743 struct lnode *lblock(lvalue) _LONG lvalue; {
744         register struct lnode *p;
745  /*static struct type t_long = {LONG};*/
746
747         p = (struct lnode *)Tblock(sizeof(struct lnode));
748         p->ln_op = LCON;
749         p->ln_type = LONG;
750         p->ln_subsp = NULL;
751         p->ln_strp = NULL;
752  /*p->ln_dtype = &t_long;*/
753         p->ln_lvalue = lvalue;
754         return(p);
755 }
756
757 /*
758  * A block for a float constant
759  */
760 struct fnode *fblock(value, fvalue) int value; _DOUBLE fvalue; {
761         register struct fnode *p;
762  /*static struct type t_double = {DOUBLE};*/
763
764         p = (struct fnode *)Tblock(sizeof(struct fnode));
765         p->fn_op = FCON;
766         p->fn_type = DOUBLE;
767         p->fn_subsp = NULL;
768         p->fn_strp = NULL;
769  /*p->fn_dtype = &t_double;*/
770         p->fn_value = value;
771         p->fn_fvalue = fvalue;
772         return(p);
773 }
774
775 /*
776  * Assign a block for use in the
777  * expression tree.
778  */
779 char *Tblock(n) int n; {
780         register char *p;
781
782  /*fprintf(stderr, "treebase=%p n=%p coremax=%p\n", treebase, n, coremax);*/
783         p = treebase;
784         if (p==NULL) {
785                 error0("c0 internal error: Tblock");
786                 exit(1);
787         }
788         if ((treebase += n) >= coremax) {
789 #ifdef pdp11
790                 if (sbrk(1024) == (char *)-1) {
791 #else
792  /*fprintf(stderr, "sbrk\n");*/
793                 if (sbrk(1024) != coremax) {
794 #endif
795                         error0("Out of space");
796                         exit(1);
797                 }
798                 coremax += 1024;
799         }
800         return(p);
801 }
802
803 char *starttree() {
804         register char *st;
805
806  /*fprintf(stderr, "starttree() locbase=%p coremax=%p\n", locbase, coremax);*/
807         st = treebase;
808         if (st==NULL)
809                 treebot = treebase = locbase+DCLSLOP;
810  /*fprintf(stderr, "starttree() treebase=%p treebot=%p\n", treebase, treebot);*/
811         return(st);
812 }
813
814 void endtree(tp) char *tp; {
815         treebase = tp;
816         if (tp==NULL)
817                 treebot = NULL;
818  /*fprintf(stderr, "endtree() treebase=%p treebot=%p\n", treebase, treebot);*/
819 }
820
821 /*
822  * Assign a block for use in a declaration
823  */
824 char *Dblock(n) int n; {
825         register char *p;
826
827  /*fprintf(stderr, "locbase=%p n=%d treebot=%p coremax=%p\n", locbase, n, treebot, coremax);*/
828         p = locbase;
829         locbase += n;
830         if (treebot && locbase > treebot) {
831                 error0("Too much declaring in an expression");
832                 exit(1);
833         }
834         if (locbase > coremax) {
835 #ifdef pdp11
836                 if (sbrk(1024) == (char *)-1) {
837 #else
838  /*fprintf(stderr, "sbrk\n");*/
839                 if (sbrk(1024) != coremax) {
840 #endif
841                         error0("out of space");
842                         exit(1);
843                 }
844                 coremax += 1024;
845         }
846         return(p);
847 }
848
849 /*
850  * Check that a tree can be used as an lvalue.
851  */
852 void chklval(p) register struct node *p; {
853         if (p->n_op==FSEL)
854                 p = ((struct tnode *)p)->tn_tr1;
855         if (p->n_op!=NAME && p->n_op!=STAR)
856                 error0("Lvalue required");
857 }
858
859 /*
860  * reduce some forms of `constant op constant'
861  * to a constant.  More of this is done in the next pass
862  * but this is used to allow constant expressions
863  * to be used in switches and array bounds.
864  */
865 int fold(op, p1, p2) int op; register struct node *p1; struct node *p2; {
866         register int v1, v2;
867         int unsignf;
868
869         if (p1->n_op!=CON)
870                 return(0);
871 #define cp1 ((struct cnode *)p1)
872         unsignf = cp1->cn_type==UNSIGN;
873         unsignf |= cp1->cn_type==UNLONG;
874         if (op==QUEST) {
875 #define tp2 ((struct tnode *)p2)
876                 if (tp2->tn_tr1->n_op==CON && tp2->tn_tr2->n_op==CON) {
877                         cp1->cn_value = cp1->cn_value? ((struct cnode *)tp2->tn_tr1)->cn_value: ((struct cnode *)tp2->tn_tr2)->cn_value;
878                         *cp++ = (struct node *)cp1;
879                         cp1->cn_type = tp2->tn_type;
880                         return(1);
881                 }
882                 return(0);
883 #undef tp2
884         }
885         if (p2) {
886                 if (p2->n_op!=CON)
887                         return(0);
888 #define cp2 ((struct cnode *)p2)
889                 v2 = cp2->cn_value;
890                 unsignf |= cp2->cn_type==UNSIGN;
891                 unsignf |= cp2->cn_type==UNLONG;
892 #undef cp2
893         }
894         v1 = cp1->cn_value;
895         switch (op) {
896
897         case PLUS:
898                 v1 += v2;
899                 break;
900
901         case MINUS:
902                 v1 -= v2;
903                 break;
904
905         case TIMES:
906                 v1 *= v2;
907                 break;
908
909         case DIVIDE:
910                 if (v2==0)
911                         goto divchk;
912                 if (unsignf) {
913                         if (v2==1)
914                                 break;
915                         if (v2<0) {
916                                 v1 = (_UNSIGNED_INT)v1 >= (_UNSIGNED_INT)v2;
917                                 break;
918                         }
919                         v1 = (_UNSIGNED_INT)v1 / v2;
920                         break;
921                 }
922                 v1 /= v2;
923                 break;
924
925         case MOD:
926                 if (v2==0)
927                         goto divchk;
928                 if (unsignf) {
929                         if (v2==1) {
930                                 v1 = 0;
931                                 break;
932                         }
933                         if (v2<0) {
934                                 if ((_UNSIGNED_INT)v1 >= (_UNSIGNED_INT)v2)
935                                         v1 -= v2;
936                                 break;
937                         }
938                         v1 = (_UNSIGNED_INT)v1 % v2;
939                         break;
940                 }
941                 v1 %= v2;
942                 break;
943
944         case AND:
945                 v1 &= v2;
946                 break;
947
948         case OR:
949                 v1 |= v2;
950                 break;
951
952         case EXOR:
953                 v1 ^= v2;
954                 break;
955
956         case NEG:
957                 v1 = - v1;
958                 break;
959
960         case COMPL:
961                 v1 = ~ v1;
962                 break;
963
964         case LSHIFT:
965                 v1 <<= v2;
966                 break;
967
968         case RSHIFT:
969                 if (unsignf) {
970                         v1 = (_UNSIGNED_INT)v1 >> v2;
971                         break;
972                 }
973                 v1 >>= v2;
974                 break;
975
976         case EQUAL:
977                 v1 = v1==v2;
978                 break;
979
980         case NEQUAL:
981                 v1 = v1!=v2;
982                 break;
983
984         case LESS:
985                 v1 = v1<v2;
986                 break;
987
988         case GREAT:
989                 v1 = v1>v2;
990                 break;
991
992         case LESSEQ:
993                 v1 = v1<=v2;
994                 break;
995
996         case GREATEQ:
997                 v1 = v1>=v2;
998                 break;
999
1000         case LESSP:
1001                 v1 = (_UNSIGNED_INT)v1<v2;
1002                 break;
1003
1004         case GREATP:
1005                 v1 = (_UNSIGNED_INT)v1>v2;
1006                 break;
1007
1008         case LESSEQP:
1009                 v1 = (_UNSIGNED_INT)v1<=v2;
1010                 break;
1011
1012         case GREATQP:
1013                 v1 = (_UNSIGNED_INT)v1>=v2;
1014                 break;
1015
1016         divchk:
1017                 error0("Divide check");
1018                 nerror--;
1019         default:
1020                 return(0);
1021         }
1022         cp1->cn_value = v1;
1023         *cp++ = (struct node *)cp1;
1024         if (unsignf)
1025                 cp1->cn_type = UNSIGN;
1026         return(1);
1027 #undef cp1
1028 }
1029
1030 /*
1031  * Compile an expression expected to have constant value,
1032  * for example an array bound or a case value.
1033  */
1034 int conexp() {
1035         register struct node *t;
1036  char *st = starttree();
1037         initflg++;
1038         if (t = tree(/*1*/))
1039                 if (t->n_op != CON)
1040                         error0("Constant required");
1041  if (!t) abort(); /* don't think this can ever happen */
1042         initflg--;
1043  endtree(st);
1044         return(((struct cnode *)t)->cn_value);
1045 }
1046
1047 /*
1048  * Handle peculiar assignment ops that need a temporary.
1049  */
1050 void assignop(op, p1, p2) int op; register struct node *p1; register struct node *p2; {
1051         register struct nmlist *np;
1052
1053         op += PLUS - ASPLUS;
1054         if (p1->n_op==NAME) {
1055                 *cp++ = p1;
1056                 *cp++ = p1;
1057                 *cp++ = p2;
1058                 build(op);
1059                 build(ASSIGN);
1060                 return;
1061         }
1062         np = gentemp(incref0(p1->n_type));
1063         *cp++ = (struct node *)nblock(np);
1064         *cp++ = p1;
1065         build(AMPER);
1066         build(ASSIGN);
1067         *cp++ = (struct node *)nblock(np);
1068         build(STAR);
1069         *cp++ = (struct node *)nblock(np);
1070         build(STAR);
1071         *cp++ = p2;
1072         build(op);
1073         build(ASSIGN);
1074         build(SEQNC);
1075 }
1076
1077 /*
1078  * Generate an automatic temporary for
1079  * use in certain assignment ops
1080  */
1081 struct nmlist *gentemp(type) int type; {
1082         register struct nmlist *tp;
1083  static struct type basic_types[] = {
1084   {INT},
1085   {CHAR},
1086   {FLOAT},
1087   {DOUBLE},
1088   {STRUCT},
1089   {RSTRUCT},
1090   {LONG},
1091   {UNSIGN},
1092   {UNCHAR},
1093   {UNLONG},
1094   {VOID}
1095  };
1096
1097         tp = (struct nmlist *)Tblock(sizeof(struct nmlist));
1098         tp->nl_class = AUTO;
1099  /*     tp->nl_type = type;*/
1100         tp->nl_flag = 0;
1101  /*     tp->nl_subsp = NULL;
1102         tp->nl_strp = NULL;*/
1103  tp->nl_dtype = basic_types + type;
1104         tp->nl_blklev = blklev;
1105         autolen -= rlength(/*(struct node *)tp*/tp->nl_dtype);
1106         tp->nl_offset = autolen;
1107         if (autolen < maxauto)
1108                 maxauto = autolen;
1109         return(tp);
1110 }