Add tests, fixes for tests, reinstate and type-convert stuff marked "bitrot"
[ccom.git] / c00.c
1 /* C compiler
2  *
3  *      2.1     (2.11BSD)       1996/01/04
4  *
5  * Called from cc:
6  *   c0 source temp1 temp2 [ profileflag ]
7  * temp1 gets most of the intermediate code;
8  * strings are put on temp2, which c1 reads after temp1.
9  */
10
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include "c0.h"
16 #include "c1.h" /* for isn1 since want to keep float labels the same */
17
18 int     isn0    = 1;
19 int     peeksym = -1;
20 int     line    = 1;
21 struct  locnnode funcblk = { { { NAME, 0, (int *)NULL, (union str *)NULL }, (struct nmlist *)NULL, 0/*nn_class*/, 0/*nn_regno*/, 0/*nn_offset*/}, 0/*locnn_nloc*/ };
22
23 struct kwtab kwtab[] = {
24         {"int",         INT},
25         {"char",        CHAR},
26         {"float",       FLOAT},
27         {"double",      DOUBLE},
28         {"struct",      STRUCT},
29         {"long",        LONG},
30         {"unsigned",    UNSIGN},
31         {"union",       UNION},
32         {"short",       INT},
33         {"void",        VOID},
34         {"auto",        AUTO},
35         {"extern",      EXTERN},
36         {"static",      STATIC},
37         {"register",    REG},
38         {"goto",        GOTO},
39         {"return",      RETURN},
40         {"if",          IF},
41         {"while",       WHILE},
42         {"else",        ELSE},
43         {"switch",      SWITCH},
44         {"case",        CASE},
45         {"break",       BREAK},
46         {"continue",    CONTIN},
47         {"do",          DO},
48         {"default",     DEFAULT},
49         {"for",         FOR},
50         {"sizeof",      SIZEOF},
51         {"typedef",     TYPEDEF},
52         {"enum",        ENUM},
53         {"asm",         ASM},
54         {0,             0}
55 };
56
57 struct  node *cmst[CMSIZ];
58 struct  node **cp = cmst;
59
60 #if 0
61 int main(argc, argv) int argc; char *argv[]; {
62         register unsigned i;
63         register struct kwtab *ip;
64         char    buf1[BUFSIZ],
65                 buf2[BUFSIZ];
66
67         if (argc>1 && strcmp(argv[1], "-u")==0) {
68                 argc--;
69                 argv++;
70                 unscflg++;
71         }
72         if(argc<4) {
73                 error0("Arg count");
74                 exit(1);
75         }
76         if (freopen(argv[1], "r", stdin)==NULL) {
77                 error0("Can't find %s", argv[1]);
78                 exit(1);
79         }
80         setbuf(stdin,buf1);     /* stdio sbrk problems */
81         if (freopen(argv[2], "w", stdout)==NULL || (sbufp=fopen(argv[3],"w"))==NULL) {
82                 error0("Can't create temp");
83                 exit(1);
84         }
85         setbuf(stdout,buf2);    /* stdio sbrk problems */
86         setbuf(sbufp, sbuf);
87         /*
88          * Overlays: allow an extra word on the stack for
89          * each stack from to store the overlay number.
90          */
91         STAUTO = -8;
92         while (argc>4) {
93                 switch (argv[4][1]) {
94                 case 'P':
95                         proflg++;
96                         break;
97                 case 'V':               /* overlays; default, now */
98                         break;
99                 case 'w':
100                 case 'W':               /* don't print warning messages */
101                         Wflag++;
102                         break;
103                 }
104                 argc--; argv++;
105         }
106         /*
107          * The hash table locations of the keywords
108          * are marked; if an identifier hashes to one of
109          * these locations, it is looked up in in the keyword
110          * table first.
111          */
112         for (ip=kwtab; ip->kwname; ip++) {
113                 i = hash(ip->kwname);
114                 kwhash[i/LNBPW] |= 1 << (i%LNBPW);
115         }
116         coremax = locbase = sbrk(0);
117         while(!eof)
118                 extdef();
119         outcode("B", EOFC);
120         strflg++;
121         outcode("B", EOFC);
122         blkend();
123         exit(nerror!=0);
124 }
125 #endif
126
127 /*
128  * Look up the identifier in symbuf in the symbol table.
129  * If it hashes to the same spot as a keyword, try the keyword table
130  * first.
131  * Return is a ptr to the symbol table entry.
132  */
133 int lookup() {
134         unsigned ihash;
135         register struct nmlist *rp;
136
137         ihash = hash(symbuf);
138         if (kwhash[ihash/LNBPW] & (1 << (ihash%LNBPW)))
139                 if (findkw())
140                         return(KEYW);
141         rp = hshtab[ihash];
142         while (rp) {
143                 if (strcmp(symbuf, rp->nl_name) != 0)
144                         goto no;
145                 if (mossym != (rp->nl_flag&FKIND))
146                         goto no;
147                 csym = rp;
148                 return(NAME);
149         no:
150                 rp = rp->nl_nextnm;
151         }
152         rp = (struct nmlist *)Dblock(sizeof(struct nmlist));
153         rp->nl_nextnm = hshtab[ihash];
154         hshtab[ihash] = rp;
155         rp->nl_class = 0;
156  /*     rp->nl_type = 0;*/
157         rp->nl_offset = 0;
158  /*     rp->nl_subsp = NULL;
159         rp->nl_strp = NULL;*/
160  rp->nl_dtype = NULL;
161         rp->nl_sparent = NULL;
162         rp->nl_blklev = blklev;
163         rp->nl_flag = mossym;
164         rp->nl_name = Dblock((strlen(symbuf) + 1 + LNCPW - 1) & ~(LNCPW - 1));
165         strcpy(rp->nl_name, symbuf);
166         csym = rp;
167         return(NAME);
168 }
169
170 /*
171  * Search the keyword table.
172  */
173 int findkw() {
174         register struct kwtab *kp;
175
176         for (kp=kwtab; kp->kwname; kp++) {
177                 if (strcmp(symbuf, kp->kwname) == 0) {
178                         cval = kp->kwval;
179                         return(1);
180                 }
181         }
182         return(0);
183 }
184
185
186 /*
187  * Return the next symbol from the input.
188  * peeksym is a pushed-back symbol, peekc is a pushed-back
189  * character (after peeksym).
190  * mosflg means that the next symbol, if an identifier,
191  * is a member of structure or a structure tag or an enum tag
192  */
193 int symbol() {
194         register int c;
195         register char *sp;
196         register int tline;
197
198         if (peeksym>=0) {
199                 c = peeksym;
200                 peeksym = -1;
201                 if (c==NAME)
202                         mosflg = 0;
203                 return(c);
204         }
205         if (peekc) {
206                 c = peekc;
207                 peekc = 0;
208         } else
209                 if (eof)
210                         return(EOFC);
211                 else
212                         c = getchar();
213 loop:
214         if (c==EOF) {
215                 eof++;
216                 return(EOFC);
217         }
218         switch(ctab[c]) {
219
220         case SHARP:
221                 if ((c=symbol())!=CON) {
222                         error0("Illegal #");
223                         return(c);
224                 }
225                 tline = cval;
226                 while (ctab[peekc]==SPACE)
227                         peekc = getchar();
228                 if (peekc=='"') {
229                         sp = filename;
230                         while (sp < filename + MAXPATHLEN - 1 && (c = mapch('"')) >= 0) /* Nick */
231                                 *sp++ = c;
232                         *sp++ = 0;
233                         peekc = getchar();
234                 }
235                 if (peekc != '\n') {
236                         error0("Illegal #");
237                         while (getchar()!='\n' && eof==0)
238                                 ;
239                 }
240                 peekc = 0;
241                 line = tline;
242                 return(symbol());
243
244         case NEWLN:
245                 line++;
246
247         case SPACE:
248                 c = getchar();
249                 goto loop;
250
251         case PLUS:
252                 return(subseq(c,PLUS,INCBEF));
253
254         case MINUS:
255                 if (subseq(c, 0, 1))
256                         return(DECBEF);
257                 return(subseq('>', MINUS, ARROW));
258
259         case ASSIGN:
260                 return(subseq(c, ASSIGN, EQUAL));
261
262         case LESS:
263                 if (subseq(c,0,1))
264                         return(LSHIFT);
265                 return(subseq('=',LESS,LESSEQ));
266
267         case GREAT:
268                 if (subseq(c,0,1))
269                         return(RSHIFT);
270                 return(subseq('=',GREAT,GREATEQ));
271
272         case EXCLA:
273                 return(subseq('=',EXCLA,NEQUAL));
274
275         case BSLASH:
276                 if (subseq('/', 0, 1))
277                         return(MAX);
278                 goto unkn;
279
280         case DIVIDE:
281                 if (subseq('\\', 0, 1))
282                         return(MIN);
283                 if (subseq('*',1,0))
284                         return(DIVIDE);
285                 while ((c = spnextchar()) != EOFC) {
286                         peekc = 0;
287                         if (c=='*') {
288                                 if (spnextchar() == '/') {
289                                         peekc = 0;
290                                         c = getchar();
291                                         goto loop;
292                                 }
293                         }
294                 }
295                 eof++;
296                 error0("Nonterminated comment");
297                 return(0);
298
299         case PERIOD:
300         case DIGIT:
301                 peekc = c;
302                 return(getnum());
303
304         case DQUOTE:
305                 cval = isn0++;
306                 return(STRING);
307
308         case SQUOTE:
309                 return(getcc());
310
311         case LETTER:
312                 sp = symbuf;
313                 while (ctab[c]==LETTER || ctab[c]==DIGIT) {
314                         if (sp < symbuf + MAXCPS)
315                                 *sp++ = c;
316                         c = getchar();
317                 }
318                 *sp++ = '\0';
319                 mossym = mosflg;
320                 mosflg = 0;
321                 peekc = c;
322                 if ((c=lookup())==KEYW && cval==SIZEOF)
323                         c = SIZEOF;
324                 return(c);
325
326         case AND:
327                 return(subseq('&', AND, LOGAND));
328
329         case OR:
330                 return(subseq('|', OR, LOGOR));
331
332         case UNKN:
333         unkn:
334                 error0("Unknown character");
335                 c = getchar();
336                 goto loop;
337
338         }
339         return(ctab[c]);
340 }
341
342 /*
343  * Read a number.  Return kind.
344  */
345 int getnum() {
346         register char *np;
347         register int c, base;
348         int expseen, sym, ndigit;
349         char *nsyn;
350         int maxdigit;
351
352         nsyn = "Number syntax";
353         lcval = 0;
354         base = 10;
355         maxdigit = 0;
356         np = numbuf;
357         ndigit = 0;
358         sym = CON;
359         expseen = 0;
360         if ((c=spnextchar()) == '0')
361                 base = 8;
362         for (;; c = getchar()) {
363                 *np++ = c;
364                 if (ctab[c]==DIGIT || (base==16) && ('a'<=c&&c<='f'||'A'<=c&&c<='F')) {
365                         if (base==8)
366                                 lcval <<= 3;
367                         else if (base==10)
368                                 lcval = ((lcval<<2) + lcval)<<1;
369                         else
370                                 lcval <<= 4;
371                         if (ctab[c]==DIGIT)
372                                 c -= '0';
373                         else if (c>='a')
374                                 c -= 'a'-10;
375                         else
376                                 c -= 'A'-10;
377                         lcval += c;
378                         ndigit++;
379                         if (c>maxdigit)
380                                 maxdigit = c;
381                         continue;
382                 }
383                 if (c=='.') {
384                         if (base==16 || sym==FCON)
385                                 error0(nsyn);
386                         sym = FCON;
387                         base = 10;
388                         continue;
389                 }
390                 if (ndigit==0) {
391                         sym = DOT;
392                         break;
393                 }
394                 if ((c=='e'||c=='E') && expseen==0) {
395                         expseen++;
396                         sym = FCON;
397                         if (base==16 || maxdigit>=10)
398                                 error0(nsyn);
399                         base = 10;
400                         *np++ = c = getchar();
401                         if (c!='+' && c!='-' && ctab[c]!=DIGIT)
402                                 break;
403                 } else if (c=='x' || c=='X') {
404                         if (base!=8 || lcval!=0 || sym!=CON)
405                                 error0(nsyn);
406                         base = 16;
407                 } else if ((c=='l' || c=='L') && sym==CON) {
408                         c = getchar();
409                         sym = LCON;
410                         break;
411                 } else
412                         break;
413         }
414         peekc = c;
415         if (maxdigit >= base)
416                 error0(nsyn);
417         if (sym==FCON) {
418                 np[-1] = 0;
419  /*             cval = np-numbuf;*/
420 #ifdef pdp11
421  fcval = atof(numbuf);
422 #else
423  fcval = fp_atof(numbuf);
424 #endif
425                 return(FCON);
426         }
427         if (sym==CON && (lcval<0 || lcval>MAXINT&&base==10 || (lcval>>1)>MAXINT)) {
428                 sym = LCON;
429         }
430         cval = lcval;
431         return(sym);
432 }
433
434 /*
435  * If the next input character is c, return b and advance.
436  * Otherwise push back the character and return a.
437  */
438 int subseq(c, a, b) int c; int a; int b; {
439         if (spnextchar() != c)
440                 return(a);
441         peekc = 0;
442         return(b);
443 }
444
445 /*
446  * Write out a string, either in-line
447  * or in the string temp file labelled by
448  * lab.
449  */
450 void putstr(lab, max) int lab; register int max; {
451  static char def_prefix[] = "\n.byte ";
452  static char com_prefix[] = ",";
453  char *prefix = def_prefix + 1;
454         register int c;
455
456         nchstr = 0;
457         if (lab) {
458 #if 1
459                 temp_fi = 1;
460 #else
461                 strflg++;
462 #endif
463                 outcode("BN", LABEL, lab);
464                 max = 10000;
465         }
466  /*     outcode("B", BDATA);*/
467         while ((c = mapch('"')) >= 0) {
468                 if (nchstr < max) {
469                         nchstr++;
470                         if (nchstr%15 == 0)
471  /*                             outcode("0B", BDATA);*/
472  prefix = def_prefix;
473
474  /*                     outcode("1N", c & 0377);*/
475  fprintf(temp_fp[temp_fi], "%s%o", prefix, c & 0377);
476  prefix = com_prefix;
477                 }
478         }
479         if (nchstr < max) {
480                 nchstr++;
481  /*             outcode("10");*/
482  fprintf(temp_fp[temp_fi], "%s0", prefix);
483  prefix = com_prefix;
484         }
485  /*     outcode("0");*/
486  if (prefix == com_prefix)
487   fputc('\n', temp_fp[temp_fi]);
488 #if 1
489         temp_fi = 0;
490 #else
491         strflg = 0;
492 #endif
493 }
494
495 void cntstr() {
496         register int c;
497
498         nchstr = 1;
499         while ((c = mapch('"')) >= 0) {
500                 nchstr++;
501         }
502 }
503
504 /*
505  * read a single-quoted character constant.
506  * The routine is sensitive to the layout of
507  * characters in a word.
508  */
509 int getcc() {
510         register int c, cc;
511 #ifdef pdp11
512         register char *ccp;
513         char realc;
514 #else
515         register int shift;
516 #endif
517
518         cval = 0;
519 #ifdef pdp11
520         ccp = (char *)&cval;
521 #else
522         shift = 0;
523 #endif
524         cc = 0;
525         while((c=mapch('\'')) >= 0)
526                 if(cc++ < LNCPW) {
527 #ifdef pdp11
528                         *ccp++ = c;
529 #else
530                         cval |= (c & 0377) << shift;
531                         shift += 8;
532 #endif
533                 }
534         if (cc>LNCPW)
535                 error0("Long character constant");
536         if (cc==1) {
537 #ifdef pdp11
538                 realc = cval;
539                 cval = realc;
540 #else
541                 /* we default to signed char */
542                 if (cval & 0200)
543                         cval |= ~0377;
544 #endif
545         }
546         return(CON);
547 }
548
549 /*
550  * Read a character in a string or character constant,
551  * detecting the end of the string.
552  * It implements the escape sequences.
553  */
554 int mapch(ac) int ac; {
555         register int a, c, n;
556         static int mpeek;
557
558         c = ac;
559         if (a = mpeek)
560                 mpeek = 0;
561         else
562                 a = getchar();
563 loop:
564         if (a==c)
565                 return(-1);
566         switch(a) {
567
568         case '\n':
569         case '\0':
570                 error0("Nonterminated string");
571                 peekc = a;
572                 return(-1);
573
574         case '\\':
575                 switch (a=getchar()) {
576
577                 case 't':
578                         return('\t');
579
580                 case 'n':
581                         return('\n');
582
583                 case 'b':
584                         return('\b');
585
586                 case 'f':
587                         return('\014');
588
589                 case 'v':
590                         return('\013');
591
592                 case '0': case '1': case '2': case '3':
593                 case '4': case '5': case '6': case '7':
594                         n = 0;
595                         c = 0;
596                         while (++c<=3 && '0'<=a && a<='7') {
597                                 n <<= 3;
598                                 n += a-'0';
599                                 a = getchar();
600                         }
601                         mpeek = a;
602                         return(n);
603
604                 case 'r':
605                         return('\r');
606
607                 case '\n':
608                         line++;
609                         a = getchar();
610                         goto loop;
611                 }
612         }
613         return(a);
614 }
615
616 /*
617  * Read an expression and return a pointer to its tree.
618  * It's the classical bottom-up, priority-driven scheme.
619  * The initflg prevents the parse from going past
620  * "," or ":" because those delimiters are special
621  * in initializer (and some other) expressions.
622  */
623 struct node *tree(/*eflag*/) /*int eflag;*/ {
624         int *op, opst[SSIZE], *pp, prst[SSIZE];
625         register int andflg, o;
626         register struct nmlist *cs;
627         int p, ps, os, xo = 0, *xop;
628         /*char *svtree;*/
629         static struct cnode garbage = { { CON, INT, (int *)NULL, (union str *)NULL}, 0 };
630  static struct type t_int = {INT};
631  static struct ftype t_func_int = {{{FUNC}, &t_int}, (struct nmlist **)NULL};
632  static struct type t_char = {CHAR};
633  static struct type t_unchar = {UNCHAR};
634
635         /*svtree = starttree();*/
636         op = opst;
637         pp = prst;
638         *op = SEOF;
639         *pp = 06;
640         andflg = 0;
641
642 advanc:
643         switch (o=symbol()) {
644
645         case NAME:
646                 cs = csym;
647                 if (cs->nl_class==TYPEDEF)
648                         goto atype;
649                 if (cs->nl_class==ENUMCON) {
650                         *cp++ = (struct node *)cblock(cs->nl_offset);
651                         goto tand;
652                 }
653                 if (cs->nl_class==0 && /*cs->nl_type==0*/cs->nl_dtype==NULL)
654                         if(nextchar()=='(') {
655                                 /* set function */
656                                 cs->nl_class = EXTERN;
657  /*                             cs->nl_type = FUNC;*/
658  cs->nl_dtype = (struct type *)&t_func_int;
659                         } else {
660                                 cs->nl_class = STATIC;
661                                 error0("%s undefined; func. %s", cs->nl_name,
662                                         funcsym ? funcsym->nl_name : "(none)");
663                         }
664                 *cp++ = (struct node *)nblock(cs);
665                 goto tand;
666
667         case FCON:
668  /*             *cp++ = fblock(DOUBLE, copnum(cval));*/
669                 *cp++ = (struct node *)fblock(isn1++, fcval);
670                 goto tand;
671
672         case LCON:
673 #if 1 /* one-pass version */
674  if (lcval >= -0x8000L && lcval < 0x8000L) {
675   *cp++ = (struct node *)cblock((_INT)lcval);
676   cp[-1] = (struct node *)block(ITOL, LONG, (int *)NULL, (union str *)NULL, cp[-1], (struct node *)NULL);
677  }
678  else
679 #endif
680                 *cp++ = (struct node *)lblock(lcval);
681                 goto tand;
682
683         case CON:
684                 *cp++ = (struct node *)cblock(cval);
685                 goto tand;
686
687         /* fake a static char array */
688         case STRING:
689 /*
690  * This hack is to compensate for a bit of simplemindedness I'm not sure how
691  * else to fix.  
692  *
693  *      i = sizeof ("foobar");
694  *
695  * or
696  *      i = sizeof "foobar";
697  *
698  * would generate ".byte 'f,'o','o,'b,'a,'r,0" into the data segment!
699  *
700  * What I did here was to scan to "operator" stack looking for left parens
701  * "(" preceeded by a "sizeof".  If both are seen and in that order or only
702  * a SIZEOF is sedn then the string is inside a 'sizeof' and should not 
703  * generate any data to the object file.
704 */
705                 xop = op;
706                 while   (xop > opst)
707                         {
708                         xo = *xop--;
709                         if      (xo != LPARN)
710                                 break;
711                         }
712                 if      (xo == SIZEOF)
713                         cntstr();
714                 else
715                         putstr(cval, 0);
716                 cs = (struct nmlist *)Tblock(sizeof(struct nmlist));
717                 cs->nl_class = STATIC;
718  /*             cs->nl_offset = cval;
719                 *cp++ = block(NAME, unscflg? ARRAY+UNCHAR:ARRAY+CHAR, &nchstr,
720                   (union str *)NULL, (struct node *)cs, (struct node *)NULL);*/
721                 cs->nl_flag = 0;
722  /*             cs->nl_type = unscflg? ARRAY+UNCHAR:ARRAY+CHAR;
723                 cs->nl_subsp = &nchstr;
724                 cs->nl_strp = (union str *)NULL;*/
725  cs->nl_dtype = (struct type *)Tblock(sizeof(struct atype));
726  ((struct atype *)cs->nl_dtype)->at_id = REF | ARRAY;
727  ((struct atype *)cs->nl_dtype)->at_reftype = unscflg ? &t_unchar : &t_char;
728  ((struct atype *)cs->nl_dtype)->at_nelt = nchstr;
729                 cs->nl_offset = cval;
730                 cs->nl_nextnm = 0;
731                 cs->nl_sparent = 0;
732                 cs->nl_blklev = 0;
733                 cs->nl_name = /*0*/"<string>";
734                 *cp++ = (struct node *)nblock(cs);
735
736         tand:
737                 if(cp>=cmst+CMSIZ) {
738                         error0("Expression overflow");
739                         exit(1);
740                 }
741                 if (andflg)
742                         goto syntax;
743                 andflg = 1;
744                 goto advanc;
745
746         case KEYW:
747         atype:
748                 if (*op != LPARN || andflg)
749                         goto syntax;
750                 peeksym = o;
751                 *cp++ = (struct node *)xprtype();
752                 if ((o=symbol()) != RPARN)
753                         goto syntax;
754                 o = CAST;
755                 --op;
756                 --pp;
757                 if (*op == SIZEOF) {
758                         andflg = 1;
759                         *pp = 100;
760                         goto advanc;
761                 }
762                 goto oponst;
763
764         case INCBEF:
765         case DECBEF:
766                 if (andflg)
767                         o += 2;
768                 goto oponst;
769
770         case COMPL:
771         case EXCLA:
772         case SIZEOF:
773                 if (andflg)
774                         goto syntax;
775                 goto oponst;
776
777         case MINUS:
778                 if (!andflg)
779                         o = NEG;
780                 andflg = 0;
781                 goto oponst;
782
783         case AND:
784         case TIMES:
785                 if (andflg)
786                         andflg = 0;
787                 else if (o==AND)
788                         o = AMPER;
789                 else
790                         o = STAR;
791                 goto oponst;
792
793         case LPARN:
794                 if (andflg) {
795                         o = symbol();
796                         if (o==RPARN)
797                                 o = MCALL;
798                         else {
799                                 peeksym = o;
800                                 o = CALL;
801                                 andflg = 0;
802                         }
803                 }
804                 goto oponst;
805
806         case RBRACK:
807         case RPARN:
808                 if (!andflg)
809                         goto syntax;
810                 goto oponst;
811
812         case DOT:
813         case ARROW:
814                 mosflg = FMOS;
815                 break;
816
817         case ASSIGN:
818                 if (andflg==0 && PLUS<=*op && *op<=EXOR) {
819                         o = *op-- + ASPLUS - PLUS;
820                         pp--;
821                         goto oponst;
822                 }
823                 break;
824
825         }
826         /* binaries */
827         if (andflg==0)
828                 goto syntax;
829         andflg = 0;
830
831 oponst:
832         p = (opdope0[o]>>9) & 037;
833 opon1:
834         if (o==COLON && op[0]==COLON && op[-1]==QUEST) {
835                 build(*op--);
836                 build(*op--);
837                 pp -= 2;
838         }
839         ps = *pp;
840         if (p>ps || p==ps && (opdope0[o]&RASSOC)!=0) {
841                 switch (o) {
842
843                 case INCAFT:
844                 case DECAFT:
845                         p = 37;
846                         break;
847                 case LPARN:
848                 case LBRACK:
849                 case CALL:
850                         p = 04;
851                 }
852                 if (initflg) {
853                         if ((o==COMMA && *op!=LPARN && *op!=CALL)
854                          || (o==COLON && *op!=QUEST)) {
855                                 p = 00;
856                                 goto opon1;
857                         }
858                 }
859                 if (op >= &opst[SSIZE-1]) {
860                         error0("expression overflow");
861                         exit(1);
862                 }
863                 *++op = o;
864                 *++pp = p;
865                 goto advanc;
866         }
867         --pp;
868         os = *op--;
869         if (andflg==0 && p>5 && ((opdope0[o]&BINARY)==0 || o>=INCBEF&&o<=DECAFT) && opdope0[os]&BINARY)
870                 goto syntax;
871         switch (os) {
872
873         case SEOF:
874                 peeksym = o;
875                 build(0);               /* flush conversions */
876                 /*if (eflag)
877                         endtree(svtree);*/
878                 return(*--cp);
879
880         case COMMA:
881                 if (*op != CALL)
882                         os = SEQNC;
883                 break;
884
885         case CALL:
886                 if (o!=RPARN)
887                         goto syntax;
888                 build(os);
889                 goto advanc;
890
891         case MCALL:
892                 *cp++ = (struct node *)block(NULLOP0, INT, (int *)NULL,
893                   (union str *)NULL, (struct node *)NULL, (struct node *)NULL);
894                 os = CALL;
895                 break;
896
897         case INCBEF:
898         case INCAFT:
899         case DECBEF:
900         case DECAFT:
901                 *cp++ = (struct node *)cblock(1);
902                 break;
903
904         case LPARN:
905                 if (o!=RPARN)
906                         goto syntax;
907                 goto advanc;
908
909         case LBRACK:
910                 if (o!=RBRACK)
911                         goto syntax;
912                 build(LBRACK);
913                 goto advanc;
914         }
915         build(os);
916         goto opon1;
917
918 syntax:
919         error0("Expression syntax");
920         errflush(o);
921         /*if (eflag)
922                 endtree(svtree);*/
923         return((struct node *) &garbage);
924 }
925
926 struct tnode *xprtype() {
927         struct nmlist /*typer,*/ absname;
928         int sc;
929         register struct node **scp;
930  struct type *dtype;
931  static struct type t_int = {INT};
932  struct tdim dim;
933  int type;
934  union str *strp;
935  int *subsp, a;
936
937         scp = cp;
938         sc = DEFXTRN;           /* will cause error if class mentioned */
939  /*     getkeywords(&sc, &typer);*/
940  dtype = getkeywords(&sc);
941  if (dtype == NULL)
942   dtype = &t_int;
943         absname.nl_class = 0;
944         absname.nl_blklev = blklev;
945  /*     absname.nl_subsp = NULL;
946         absname.nl_strp = NULL;
947         absname.nl_type = 0;*/
948  absname.nl_dtype = NULL;
949  absname.nl_name = "<anon>";
950         decl1(sc, /*&typer*/dtype, 0, &absname);
951         cp = scp;
952  dim.rank = 0;
953  type = XXXoldtype(absname.nl_dtype, &dim, (struct SS **)&strp);
954  subsp = dim.rank ? (int *)Tblock(dim.rank*sizeof(dim.rank)) : NULL;
955  for (a=0; a<dim.rank; a++)
956   subsp[a] = dim.dimens[a];
957         return(block(ETYPE, /*absname.nl_*/type, /*absname.nl_*/subsp,
958            /*absname.nl_*/strp, (struct node *)NULL, (struct node *)NULL));
959 }
960
961 /*char *copnum(len) int len; {
962         register char *s1;
963
964         s1 = Tblock((len+LNCPW-1) & ~(LNCPW-1));
965         strcpy(s1, numbuf);
966         return(s1);
967 }*/