10 #define _va_start(argp, arg) va_start(argp, arg)
13 #define _va_start(argp, arg) va_start(argp)
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.
24 void build(op) int op; {
27 register struct node *p1, *p2, *p3;
28 int dope, leftc, cvn, pcvn;
39 if ((dope&BINARY)!=0) {
40 p2 = chkfun(disarray(*--cp));
46 * sizeof gets turned into a number here.
49 struct cnode *p = cblock(XXXlength(p1));
51 *cp++ = (struct node *)p;
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);
80 *cp++ = (struct node *)cblock(0377);
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));
89 /* end of expression */
94 /* no-conversion operators */
97 error0("Illegal conditional");
99 if (fold(QUEST, p1, p2))
103 * Bug fix, because copying type is not enough,
104 * i.e. t = (t, t) + 1;
111 *cp++ = (struct node *)block(op, t2, p2->n_subsp, p2->n_strp, p1, p2);
117 *cp++ = (struct node *)block(op, t, p2->n_subsp, p2->n_strp, p1, p2);
125 if ((t1&XTYPE) == PTR && (decref0(t1)&XTYPE) == FUNC) {
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 ...
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);
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);
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);
161 error0("Illegal lvalue");
165 * a.b goes to (&a)->b
168 if (p1->n_op==CALL && t1==STRUCT) {
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.
183 if (p2->n_op!=NAME || ((struct nnode *)p2)->nn_nmlist->nl_class!=MOS) {
184 error0("Illegal structure ref");
188 #define np2 ((struct nnode *)p2)
189 structident(p1, np2);
191 if (t2==INT && np2->nn_nmlist->/*nl_flag&FFIELD*/nl_dtype->t_id==BITFLD)
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));
199 if (np2->nn_nmlist->/*nl_flag&FFIELD*/nl_dtype->t_id==BITFLD)
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);
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);
210 if ((dope&LVALUE)!=0)
216 if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) {
217 error0("Illegal use of void object");
220 if ((dope&BINARY)==0) {
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);
230 if (t1==STRUCT || t2==STRUCT) {
231 if (t1!=t2 || p1->n_strp != p2->n_strp)
232 error0("Incompatible structures");
235 cvn = cvtab[lintyp(t1)][lintyp(t2)];
236 leftc = (cvn>>4)&017;
239 if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
241 if (dope&ASSGOP || op==CAST) {
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 %= ...
249 if (leftc && op>=ASPLUS && op<=ASXOR
250 && (leftc!=LTI || op==ASDIV || op==ASMOD)) {
251 assignop(op, p1, p2);
257 if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->n_strp!=p2->n_strp))
258 werror0("mixed pointer assignment");
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)) {
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
274 werror0("illegal combination of pointer and integer, op =");
285 } else if (op==CAST) {
286 if (cvn==ITP||cvn==PTI)
300 } else if (op==COLON || op==MAX || op==MIN) {
301 if (t1>=PTR && t1==t2)
303 if (op!=COLON && (t1>=PTR || t2>=PTR))
306 * Allow "e ? i : p" and "e ? p : i" with warning.
308 if (op==COLON && (cvn==ITP || cvn==LTP)) {
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 :");
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)
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);
339 if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR)))
344 if ((cvn==ITP || cvn==LTP) && (opdope0[op]&PCVOK)==0) {
346 if ((p3->n_op!=CON || ((struct cnode *)p3)->cn_value!=0)
347 && (p3->n_op!=LCON || ((struct lnode *)p3)->ln_lvalue!=0))
354 if (cvn==XX || (cvn==PTI&&t1!=t2))
355 error0("Illegal conversion");
357 p1 = convert(p1, t, cvn, t2);
359 p2 = convert(p2, t, cvn, t1);
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)*/) {
371 p2->n_subsp = p1->n_subsp;
372 p2->n_strp = p1->n_strp;
374 if (t==INT && p1->n_type==CHAR)
375 p2 = (struct node *)block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, (struct node *)NULL);
379 if (pcvn) /* says op == MINUS */
380 t2 = plength(((struct tnode *)p1)->tn_tr1);
381 if (fold(op, p1, p2)==0) {
383 *cp++ = (struct node *)block(op, t, p3->n_subsp, p3->n_strp, p1, p2);
387 *cp++ = convert(p1, 0, PTI, t2);
391 int XXXeqtype(struct type *t0, struct type *t1) {
392 while (t0->t_id == t1->t_id) {
393 if ((t0->t_id & TYPE) != REF)
395 t0 = ((struct rtype *)t0)->rt_reftype;
396 t1 = ((struct rtype *)t1)->rt_reftype;
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;
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;
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;*/
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];
426 if (strcmp(nporig->nl_name, np->nl_name) != 0)
428 if ((nporig->nl_flag&FKIND) != (np->nl_flag&FMOS))
431 if (/*nporig->nl_type==np->nl_type*/XXXeqtype(nporig->nl_dtype, np->nl_dtype) && nporig->nl_offset==np->nl_offset)
436 error0("Ambiguous structure reference for %s",nporig->nl_name);
438 werror0("%s not member of cited struct/union",nporig->nl_name);
442 * Generate the appropriate conversion operator.
444 struct node *convert(p, t, cvn, len) struct node *p; int t; int cvn; int len; {
450 if (opdope0[op]&BINARY) {
452 error0("Illegal conversion");
453 return((struct node *)block(op, t, (int *)NULL, (union str *)NULL, p, (struct node *)cblock(len)));
455 return((struct node *)block(op, t, (int *)NULL, (union str *)NULL, p, (struct node *)NULL));
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
463 * Used with structure references.
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;
472 else if (p->n_op==STAR)
474 else if (p->n_op!=PLUS)
480 * A mention of a function name is turned into
481 * a pointer to that function.
483 struct node *chkfun(p) register struct node *p; {
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));
492 * A mention of an array is turned into
493 * a pointer to the base of the array.
495 struct node *disarray(p) register struct node *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
507 setype(p, decref0(t), p);
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'
518 void chkw(p, okt) struct node *p; int okt; {
519 register int t = p->n_type;
523 if (t!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt)
524 error0("Illegal type of operand");
529 *'linearize' a type for looking up in the
532 int lintyp(t) int t; {
559 void werror0(char *s, ...)
561 void werror0(s, va_alist) char *s; va_dcl
569 fprintf(stderr, "%s:", filename);
570 fprintf(stderr, "%d: warning: ", line);
572 vfprintf(stderr, s, argp);
574 fprintf(stderr, "\n");
579 void error0(char *s, ...)
581 void error0(s, va_alist) char *s; va_dcl
588 fprintf(stderr, "%s:", filename);
589 fprintf(stderr, "%d: ", line);
591 vfprintf(stderr, s, argp);
593 fprintf(stderr, "\n");
598 * Generate a node in an expression tree,
599 * setting the operator, type, dimen/struct table ptrs,
602 /*static struct type *newtype(type, dimp, strp) int type; int **dimp; union str *strp; {
604 static struct type basic_types[] = {
618 switch (type & XTYPE) {
620 fprintf(stderr, "ptr(");
621 #define rt (*(struct rtype **)&t)
622 rt = (struct rtype *)Tblock(sizeof(struct rtype));
623 rt->rt_id = REF | PTR;
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;
638 fprintf(stderr, "array(%d, ", *dimp);
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;
647 #define rt ((struct rtype *)t)
648 rt->rt_reftype = newtype((type >> TYLEN & ~TYPE) | (type & TYPE), dimp, strp);
652 fprintf(stderr, "basic(%d", type);
653 if (type == STRUCT) {
654 #define st (*(struct stype **)&t)
655 st = (struct stype *)Tblock(sizeof(struct stype));
657 st->st_S = *(struct SS *)strp;
661 t = basic_types + type;
664 fprintf(stderr, ")");
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;
670 p = (struct tnode *)Tblock(sizeof(struct tnode));
675 /*fprintf(stderr, "newtype ");
676 p->tn_dtype = newtype(t, &subs, str);
677 fprintf(stderr, "\n");*/
679 if (opdope0[op]&BINARY)
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));*/
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);
701 #define locp (*(struct locnnode **)&p)
702 locp = (struct locnnode *)Tblock(sizeof(struct locnnode));
703 locp->locnn_nloc = ds->nl_offset;
706 /*fprintf(stderr, "nblock %p name %s type %x strp %p\n", p, ds->nl_name, ds->nl_type, ds->nl_strp);*/
708 /* p->nn_type = ds->nl_type;
709 p->nn_subsp = ds->nl_subsp;
710 p->nn_strp = ds->nl_strp;*/
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];
717 p->nn_class = ds->nl_class==0?STATIC:ds->nl_class;
724 * Generate a block for a constant
726 struct cnode *cblock(value) _INT value; {
727 register struct cnode *p;
728 /*static struct type t_int = {INT};*/
730 p = (struct cnode *)Tblock(sizeof(struct cnode));
735 /*p->cn_dtype = &t_int;*/
741 * A block for a float constant
743 struct lnode *lblock(lvalue) _LONG lvalue; {
744 register struct lnode *p;
745 /*static struct type t_long = {LONG};*/
747 p = (struct lnode *)Tblock(sizeof(struct lnode));
752 /*p->ln_dtype = &t_long;*/
753 p->ln_lvalue = lvalue;
758 * A block for a float constant
760 struct fnode *fblock(value, fvalue) int value; _DOUBLE fvalue; {
761 register struct fnode *p;
762 /*static struct type t_double = {DOUBLE};*/
764 p = (struct fnode *)Tblock(sizeof(struct fnode));
769 /*p->fn_dtype = &t_double;*/
771 p->fn_fvalue = fvalue;
776 * Assign a block for use in the
779 char *Tblock(n) int n; {
782 /*fprintf(stderr, "treebase=%p n=%p coremax=%p\n", treebase, n, coremax);*/
785 error0("c0 internal error: Tblock");
788 if ((treebase += n) >= coremax) {
790 if (sbrk(1024) == (char *)-1) {
792 /*fprintf(stderr, "sbrk\n");*/
793 if (sbrk(1024) != coremax) {
795 error0("Out of space");
806 /*fprintf(stderr, "starttree() locbase=%p coremax=%p\n", locbase, coremax);*/
809 treebot = treebase = locbase+DCLSLOP;
810 /*fprintf(stderr, "starttree() treebase=%p treebot=%p\n", treebase, treebot);*/
814 void endtree(tp) char *tp; {
818 /*fprintf(stderr, "endtree() treebase=%p treebot=%p\n", treebase, treebot);*/
822 * Assign a block for use in a declaration
824 char *Dblock(n) int n; {
827 /*fprintf(stderr, "locbase=%p n=%d treebot=%p coremax=%p\n", locbase, n, treebot, coremax);*/
830 if (treebot && locbase > treebot) {
831 error0("Too much declaring in an expression");
834 if (locbase > coremax) {
836 if (sbrk(1024) == (char *)-1) {
838 /*fprintf(stderr, "sbrk\n");*/
839 if (sbrk(1024) != coremax) {
841 error0("out of space");
850 * Check that a tree can be used as an lvalue.
852 void chklval(p) register struct node *p; {
854 p = ((struct tnode *)p)->tn_tr1;
855 if (p->n_op!=NAME && p->n_op!=STAR)
856 error0("Lvalue required");
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.
865 int fold(op, p1, p2) int op; register struct node *p1; struct node *p2; {
871 #define cp1 ((struct cnode *)p1)
872 unsignf = cp1->cn_type==UNSIGN;
873 unsignf |= cp1->cn_type==UNLONG;
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;
888 #define cp2 ((struct cnode *)p2)
890 unsignf |= cp2->cn_type==UNSIGN;
891 unsignf |= cp2->cn_type==UNLONG;
916 v1 = (_UNSIGNED_INT)v1 >= (_UNSIGNED_INT)v2;
919 v1 = (_UNSIGNED_INT)v1 / v2;
934 if ((_UNSIGNED_INT)v1 >= (_UNSIGNED_INT)v2)
938 v1 = (_UNSIGNED_INT)v1 % v2;
970 v1 = (_UNSIGNED_INT)v1 >> v2;
1001 v1 = (_UNSIGNED_INT)v1<v2;
1005 v1 = (_UNSIGNED_INT)v1>v2;
1009 v1 = (_UNSIGNED_INT)v1<=v2;
1013 v1 = (_UNSIGNED_INT)v1>=v2;
1017 error0("Divide check");
1023 *cp++ = (struct node *)cp1;
1025 cp1->cn_type = UNSIGN;
1031 * Compile an expression expected to have constant value,
1032 * for example an array bound or a case value.
1035 register struct node *t;
1036 char *st = starttree();
1038 if (t = tree(/*1*/))
1040 error0("Constant required");
1041 if (!t) abort(); /* don't think this can ever happen */
1044 return(((struct cnode *)t)->cn_value);
1048 * Handle peculiar assignment ops that need a temporary.
1050 void assignop(op, p1, p2) int op; register struct node *p1; register struct node *p2; {
1051 register struct nmlist *np;
1053 op += PLUS - ASPLUS;
1054 if (p1->n_op==NAME) {
1062 np = gentemp(incref0(p1->n_type));
1063 *cp++ = (struct node *)nblock(np);
1067 *cp++ = (struct node *)nblock(np);
1069 *cp++ = (struct node *)nblock(np);
1078 * Generate an automatic temporary for
1079 * use in certain assignment ops
1081 struct nmlist *gentemp(type) int type; {
1082 register struct nmlist *tp;
1083 static struct type basic_types[] = {
1097 tp = (struct nmlist *)Tblock(sizeof(struct nmlist));
1098 tp->nl_class = AUTO;
1099 /* tp->nl_type = type;*/
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)