|
|
1.1 root 1: /*
2: * C compiler.
3: * Expressions et al.
4: */
5: #ifdef vax
6: #include "INC$LIB:cc0.h"
7: #else
8: #include "cc0.h"
9: #endif
10:
11: #define LOW 0
12: #define HIGH 0177
13: #define INARGS 0200
14:
15: #define bcvint(p) bconvert((p), T_INT, NULL, NULL, NULL)
16:
17: static char csmsg1[] = "structure \"%s\" does not contain member \"%s\"";
18: static char csmsg2[] = "union \"%s\" does not contain member \"%s\"";
19: static char tclash[] = "type clash";
20:
21: /*
22: * Read a tree.
23: * This is the top level routine that is called by the user.
24: * The mysterious call to "build" with opcode "NOP" is to get any function or
25: * array name conversions applied, even if the top of the tree is a term.
26: * Ditto for getting types converted to computables.
27: */
28: TREE *
29: expr()
30: {
31: if (notvariant(VCPP)) {
32: bput(LINE);
33: iput((ival_t) line);
34: }
35: return (build(NOP, tree(LOW), NULL));
36: }
37:
38: /*
39: * Read in a tree.
40: * The "n" argument is a firewall precedence.
41: * You continue reading until the precedence of the operator
42: * in the input is less than the priority "n".
43: * The "INARGS" flag is or'ed into the priority to indicate
44: * that the expression is an argument list, and that "," is special.
45: * Passing it in this unconventional way lets you pass a single
46: * parameter to "tree".
47: */
48: TREE *
49: tree(n)
50: {
51: register TREE *lp, *rp;
52: register SYM *sp;
53: DIM *dp;
54: TREE *tp, *fp;
55: int c, d, op, p, isarray, isinargs;
56:
57: isinargs = 0;
58: if ((n&INARGS) != 0) {
59: ++isinargs;
60: n &= ~INARGS;
61: }
62: lp = term();
63: for (;;) {
64: switch (s) {
65:
66: case LPAREN:
67: lex();
68: rp = NULL;
69: if (s != RPAREN)
70: rp = tree(LOW|INARGS);
71: mustbe(RPAREN);
72: lp = build(CALL, lp, rp);
73: break;
74:
75: case LBRACK:
76: lex();
77: lp = build(ADD, lp, tree(LOW));
78: adjust(lp, lp->t_type, lp->t_dp, lp->t_ip);
79: lp = build(STAR, lp, NULL);
80: mustbe(RBRACK);
81: break;
82:
83: case DOT:
84: case ARROW:
85: lp = build((s==DOT?ADDR:NOP), lp, NULL);
86: if (lex() != ID) {
87: cerror("missing member");
88: break;
89: }
90: sp = moslookup(lp);
91: if (bitcompat(T_PTR, tltype(lp)) == 0)
92: cerror("left side of \"%s\" not usable",
93: s==DOT?".":"->");
94: if (sp==NULL || ((c=sp->s_class)!=C_MOS && c!=C_MOU)) {
95: cerror("member \"%s\" is not defined", id);
96: sp = fakedef(SL_MOS);
97: } else if (isvariant(VSMEMB))
98: csmemb(lp, sp);
99: lex();
100: tp = talloc();
101: tp->t_op = ADD;
102: tp->t_lp = lp;
103: tp->t_rp = bicon(sp->s_value);
104: lp = tp;
105: isarray = 0;
106: dp = sp->s_dp;
107: if (dp!=NULL && dp->d_type==D_ARRAY) {
108: ++isarray;
109: dp = tdalloc(dp->d_dp, D_MOSAR, dp->d_bound);
110: } else
111: dp = tdalloc(dp, D_PTR, (sizeof_t)0);
112: adjust(lp, sp->s_type, dp, sp->s_ip);
113: if (!isarray)
114: lp = build(STAR, lp, NULL);
115: if (sp->s_width != 0) {
116: fp = talloc();
117: fp->t_op = FIELD;
118: fp->t_type = lp->t_type;
119: fp->t_lp = lp;
120: fp->t_width = sp->s_width;
121: fp->t_base = sp->s_offset;
122: lp = fp;
123: }
124: break;
125:
126: case INCBEF:
127: case DECBEF:
128: op = s+INCAFT-INCBEF;
129: lex();
130: lp = build(op, lp, bicon(1));
131: break;
132:
133: default:
134: if ((s==COMMA && ininit!=0 && isinargs==0)
135: || (s==COLON))
136: goto out;
137: if (s<MIOBASE || s>=MDOBASE)
138: goto out;
139: d = opdope[s-MIOBASE];
140: if ((p=(d&PRIO)) == 0)
141: goto out;
142: if (p<n || ((d&RAS)==0 && p==n))
143: goto out;
144: if ((op = s) == QUEST) {
145: lex();
146: rp = tree(LOW);
147: mustbe(COLON);
148: rp = build(COLON, rp, tree(--p));
149: lp = build(QUEST, lp, rp);
150: break;
151: }
152: if (op==COMMA && isinargs!=0)
153: op = ARGLST;
154: lex();
155: lp = build(op, lp, tree(p));
156: }
157: }
158: out:
159: return (lp);
160: }
161:
162: /*
163: * Check that a structure member is
164: * indeed a member of the left hand structure.
165: * If the member is untagged, don't object to any clash.
166: * The structure declaration reader sets the S_TAG bit
167: * in the flags word of all tagged structures.
168: */
169: csmemb(lp, sp)
170: TREE *lp;
171: SYM *sp;
172: {
173: register INFO *ip;
174: register SYM *tsp;
175: register int type;
176: char *msg;
177: int i;
178:
179: type = lp->t_type;
180: if (lp->t_dp==NULL || lp->t_dp->d_type!=D_PTR
181: || type<T_STRUCT || type>T_FUNION) {
182: cstrict("potentially nonportable structure access");
183: return;
184: }
185: if ((type==T_STRUCT || type==T_UNION) && (sp->s_flag&S_TAG)!=0) {
186: ip = lp->t_ip;
187: if (ip != NULL) {
188: for (i=0; i<ip->i_nsp && ip->i_sp[i]!=sp; ++i)
189: ;
190: if (i >= ip->i_nsp) {
191: tsp = taglookup(ip);
192: if (tsp != NULL) {
193: msg = csmsg1;
194: if (tsp->s_class == C_UTAG)
195: msg = csmsg2;
196: cstrict(msg, tsp->s_id, sp->s_id);
197: }
198: }
199: }
200: }
201: }
202:
203: /*
204: * Read a term.
205: * Handle all of the leaf nodes and the unary operations here.
206: */
207: TREE *
208: term()
209: {
210: register TREE *tp;
211: register SYM *sp;
212: register int op;
213: TREE *cp;
214: DIM *dp;
215: int tt, lt, n;
216:
217: switch (op = s) {
218:
219: case ICON:
220: tp = bicon(ival);
221: tp->t_type = tval;
222: lex();
223: break;
224:
225: case LCON:
226: tp = talloc();
227: tp->t_op = LCON;
228: tp->t_type = tval;
229: tp->t_lval = lval;
230: lex();
231: break;
232:
233: case DCON:
234: tp = talloc();
235: tp->t_op = DCON;
236: tp->t_type = tval;
237: copy((char *)tp->t_dval, (char *)dval, sizeof(dval_t));
238: lex();
239: break;
240:
241: case STRING:
242: tp = bstring();
243: break;
244:
245: case ID:
246: if ((sp=reflookup(SL_VAR)) == NULL) {
247: /*
248: * An undefined name followed by a "(" is declared
249: * to be a function that returns an integer.
250: * So says the manual.
251: */
252: TOK *tp;
253: tp = idp;
254: if (spnextis('(')) {
255: setid(tp->t_id);
256: sp = deflookup(SL_VAR, 0);
257: dp = tackdim(NULL, D_FUNC, 0);
258: sp = declare(sp, C_CXT, T_INT, dp, NULL, 0);
259: } else
260: setid(tp->t_id);
261: if (sp == NULL) {
262: cerror("identifier \"%s\" is not defined", id);
263: sp = fakedef(SL_VAR);
264: }
265: }
266: tp = bid(sp);
267: lex();
268: break;
269:
270: case LPAREN:
271: lex();
272: if ((cp=cast()) != NULL) {
273: if (cp->t_type==T_FLOAT && cp->t_dp==NULL)
274: cp->t_type = T_DOUBLE;
275: cp->t_lp = build(NOP, tree(HIGH), NULL);
276: tt = tltype(cp);
277: lt = tltype(cp->t_lp);
278: if (tt == T_STRUCT)
279: cerror("cannot cast to structure or union");
280: if (lt == T_STRUCT)
281: cerror("cannot cast structure or union");
282: if (tt == T_PTR && isfloat(lt))
283: cerror("cannot cast double to pointer");
284: if (isfloat(tt) && lt == T_PTR)
285: cerror("cannot cast pointer to double");
286: if (bitcompat(tt, lt)) {
287: tp = cp->t_lp;
288: adjust(tp, cp->t_type, cp->t_dp, cp->t_ip);
289: if (tp->t_op == CONVERT && tp->t_rp == NULL)
290: tp->t_op = CAST;
291: } else
292: tp = cp;
293: break;
294: }
295: n = ininit;
296: ininit = 0;
297: tp = tree(LOW);
298: ininit = n;
299: mustbe(RPAREN);
300: break;
301:
302: case SIZEOF:
303: lex();
304: if (s == LPAREN) {
305: lex();
306: if ((tp=cast()) == NULL) {
307: tp = tree(LOW);
308: mustbe(RPAREN);
309: }
310: } else
311: tp = tree(HIGH);
312: tp = build(SIZEOF, tp, NULL);
313: break;
314:
315: case NOT:
316: lex();
317: tp = build(EQ, tree(HIGH), bicon(0));
318: break;
319:
320: case SUB:
321: op = NEG;
322: goto unary;
323: case ADD: /* Unary plus == no rearrangement FIX.ME */
324: lex();
325: tp = tree(HIGH); /* ignored for present */
326: break;
327: op = POS;
328: goto unary;
329: case MUL:
330: op = STAR;
331: goto unary;
332: case AND:
333: op = ADDR;
334: goto unary;
335: case COM:
336: unary:
337: lex();
338: tp = build(op, tree(HIGH), NULL);
339: break;
340:
341: case INCBEF:
342: case DECBEF:
343: lex();
344: tp = build(op, tree(HIGH), bicon(1));
345: break;
346:
347: default:
348: cerror("error in expression syntax");
349: while (s!=EOF && s!=SEMI && s!=LBRACE && s!=RBRACE)
350: skip();
351: return (bicon(0));
352: }
353: return (tp);
354: }
355:
356: /*
357: * Given an operator "op" and left and right subtrees "lp" and "rp",
358: * build a tree node, folding any constant expressions
359: * that can be folded, supplying any required type conversions.
360: * All of the conversions that are possible are added;
361: * the routine "transform" may remove some of them.
362: */
363: TREE *
364: build(op, lp, rp)
365: TREE *lp;
366: TREE *rp;
367: {
368: TREE *tp, *gtp, gt;
369: DIM *dp;
370: int rt, lt, d, cv;
371: sizeof_t ll, lr;
372:
373: if (op == SIZEOF)
374: return (bzcon(tsize(lp)));
375: rt = T_NONE;
376: if (rp != NULL) {
377: chmos(rp);
378: rp = chfun(charray(rp));
379: rt = tltype(rp);
380: }
381: chmos(lp);
382: lp = charray(lp);
383: if (op!=ADDR && op!=CALL)
384: lp = chfun(lp);
385: lt = tltype(lp);
386: if (op == NOP)
387: goto conversion;
388: /*
389: * Make sure that the operands are
390: * suitable as operands of the specified operation.
391: * Look mainly at the type, although some consideration
392: * is made of storage class.
393: */
394: if ((op!=COMMA && rt==T_VOID) ||
395: (op!=COMMA && op!=COLON && lt==T_VOID)) {
396: cerror("illegal operation on \"void\" type");
397: lt = T_INT;
398: rt = T_INT;
399: }
400: if (op==ADDR && lp->t_op==REG)
401: cerror("cannot apply unary '&' to a register variable");
402: if (op==ADDR && lp->t_op==FIELD)
403: cerror("cannot apply unary '&' to a bit field");
404: if (op==ADDR && lp->t_op==GID && lp->t_seg==SALIEN)
405: cerror("cannot apply unary '&' to an alien function");
406: d = opdope[op-MIOBASE];
407: if ((d&RLVL) != 0
408: && (lp->t_op<=DCON
409: || (lp->t_op>=MIOBASE && lp->t_op!=STAR && lp->t_op!=FIELD
410: && (lp->t_op!=CALL || lp->t_type!=T_STRUCT || lp->t_dp!=NULL)
411: )))
412: cerror("lvalue required");
413: if ((d&NFLT)!=0 && (isfloat(lt) || isfloat(rt)))
414: cerror("illegal use of floating point");
415: if (((d&NPTL)!=0 && lt==T_PTR) || ((d&NPTR)!=0 && rt==T_PTR))
416: cerror("illegal use of a pointer");
417: if (((d&NSTL)!=0 && lt==T_STRUCT) || ((d&NSTR)!=0 && rt==T_STRUCT))
418: cerror("illegal use of a structure or union");
419: if ((d&RTOL) != 0)
420: truth(lp);
421: if ((d&RTOR) != 0)
422: truth(rp);
423: /*
424: * The operation may just fold away to nothing.
425: * If so, return a pointer to the new, constant tree node.
426: */
427: if ((tp=fold0(op, lp, rp)) != NULL)
428: return (tp);
429: /*
430: * Insert conversion nodes.
431: */
432: conversion:
433: gt.t_op = CONVERT;
434: gt.t_dp = NULL;
435: gt.t_ip = NULL;
436: switch (op) {
437:
438: case QUEST:
439: if (rp->t_op != COLON)
440: cerror("mismatched conditional");
441:
442: case COMMA:
443: case ARGLST:
444: gt.t_type = rp->t_type;
445: gt.t_dp = rp->t_dp;
446: gt.t_ip = rp->t_ip;
447: break;
448:
449: case ANDAND:
450: case OROR:
451: case NOT:
452: gt.t_type = T_INT;
453: break;
454:
455: case CALL:
456: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_FUNC)
457: gt.t_dp = dp->d_dp;
458: else
459: cerror("call of non function");
460: if (rp != NULL && rp->t_op != ARGLST) {
461: rp = build(NOP, rp, NULL);
462: rt = tltype(rp);
463: }
464: gt.t_type = lp->t_type;
465: gt.t_ip = lp->t_ip;
466: break;
467:
468: case STAR:
469: if ((dp = lp->t_dp)!=NULL && dp->d_type==D_PTR)
470: gt.t_dp = dp->d_dp;
471: else
472: cerror("indirection through non pointer");
473: gt.t_type = lp->t_type;
474: gt.t_ip = lp->t_ip;
475: break;
476:
477: case ADDR:
478: gt.t_type = lp->t_type;
479: gt.t_dp = tdalloc(lp->t_dp, D_PTR, (sizeof_t)0);
480: gt.t_ip = lp->t_ip;
481: break;
482:
483: default:
484: if (rt == T_NONE)
485: rt = lt;
486: cv = cvdope[13*(lt-T_CHAR) + rt - T_CHAR];
487: if (noconvert(op, lt, rt))
488: cv &= ~(CVL|CVR|CVRA|CARA);
489: gt.t_type = cv&GOAL;
490: gt.t_rp = NULL;
491: if ((cv&(GTL|GTR)) != 0) {
492: gtp = ((cv>L)!=0) ? lp : rp;
493: gt.t_type = gtp->t_type;
494: gt.t_dp = gtp->t_dp;
495: gt.t_ip = gtp->t_ip;
496: if ((cv&(CVL|CVR|CVRA)) != 0)
497: gt.t_rp = bzcon(psize(gtp));
498: }
499: if (gt.t_type == T_NONE && op!=NOP && lt!=T_VOID)
500: cerror(tclash);
501: if ((d&ASGN) != 0) {
502: gt.t_type = lp->t_type;
503: gt.t_dp = lp->t_dp;
504: gt.t_ip = lp->t_ip;
505: if (gt.t_dp == NULL) {
506: if (gt.t_type==T_CHAR
507: || gt.t_type==T_UCHAR
508: || gt.t_type==T_SHORT
509: || gt.t_type==T_ENUM
510: || gt.t_type==T_FENUM)
511: gt.t_type = T_INT;
512: if (gt.t_type == T_USHORT)
513: gt.t_type = T_UINT;
514: if (gt.t_type == T_FLOAT)
515: gt.t_type = T_DOUBLE;
516: }
517: if (op==ASHL || op==ASHR) {
518: if (bitcompat(T_INT, rt) == 0)
519: rp = bcvint(rp);
520: } else if ((cv&CVRA) != 0) {
521: rp = bcvt(rp, >);
522: } else if ((cv&CARA) != 0) {
523: gt.t_op = CAST;
524: gt.t_rp = NULL;
525: rp = bcvt(rp, >);
526: }
527: } else {
528: if (op>=INCBEF && op<=DECAFT)
529: cv &= ~CVL;
530: if (op == COLON && lt != rt) {
531: if (lt == T_PTR)
532: if (iszero(rp)) {
533: gt.t_op = CAST;
534: gt.t_rp = NULL;
535: } else
536: cerror(tclash);
537: else if (rt == T_PTR)
538: if (iszero(lp)) {
539: gt.t_op = CAST;
540: gt.t_rp = NULL;
541: } else
542: cerror(tclash);
543: }
544: if ((cv&CVL) != 0)
545: lp = bcvt(lp, >);
546: if (op==SHL || op==SHR) {
547: if (bitcompat(T_INT, rt) == 0)
548: rp = bcvint(rp);
549: gt.t_type = lp->t_type;
550: gt.t_dp = lp->t_dp;
551: gt.t_ip = lp->t_ip;
552: } else if (rp!=NULL && (cv&CVR)!=0)
553: rp = bcvt(rp, >);
554: if ((cv&UREL)!=0 && (op>=GT && op<=LT))
555: op += UGT-GT;
556: if (op>=EQ && op<=ULT) {
557: gt.t_type = T_INT;
558: gt.t_dp = gt.t_ip = NULL;
559: }
560: }
561: }
562: if (op==NOP)
563: return (lp);
564: tp = talloc();
565: tp->t_op = op;
566: tp->t_type = gt.t_type;
567: tp->t_dp = gt.t_dp;
568: tp->t_ip = gt.t_ip;
569: tp->t_lp = lp;
570: tp->t_rp = rp;
571: if (lt==T_PTR && rt==T_PTR) {
572: if (op == ADD)
573: cerror("cannot add pointers");
574: if (op == SUB) {
575: if ((ll=psize(lp)) != (lr=psize(rp)))
576: cerror("illegal subtraction of pointers");
577: tp = bconvert(tp, T_INT, NULL, NULL, bzcon(ll));
578: }
579: }
580: if (op==ASSIGN && lt==T_STRUCT && rt==T_STRUCT) {
581: notbook();
582: if ((ll=tsize(lp)) != (lr=tsize(rp)))
583: cerror("illegal structure assignment");
584: }
585: if (isvariant(VSPVAL) && lt != rt
586: && ((lt==T_PTR && !iszero(rp)) || (rt==T_PTR && !iszero(lp)))) {
587: if (op == ASSIGN)
588: cstrict("integer pointer pun");
589: else if (op >= EQ && op <= ULT)
590: cstrict("integer pointer comparison");
591: }
592: return (tp);
593: }
594:
595: /*
596: * If the first entry in the dimensions of tree "tp" is a
597: * MOS array, stomp it into the pointer it truly is.
598: */
599: chmos(tp)
600: TREE *tp;
601: {
602: register struct dim *dp;
603:
604: if ((dp = tp->t_dp)!=NULL && dp->d_type==D_MOSAR) {
605: dp->d_type = D_PTR;
606: dp->d_bound = 0;
607: }
608: }
609:
610: /*
611: * Read constant expression.
612: * Call the standard expression reader, and make sure that
613: * the folder has squashed it down to nothing.
614: * Return the value.
615: */
616: iconexpr()
617: {
618: register TREE *tp;
619:
620: tp = expr();
621: while (tp->t_op == CAST || tp->t_op == CONVERT)
622: tp = tp->t_lp;
623: if (tp->t_op == ICON)
624: return tp->t_ival;
625: if (tp->t_op == LCON && (ival_t)tp->t_lval == tp->t_lval)
626: return tp->t_lval;
627: if (tp->t_op == ZCON && (ival_t)tp->t_zval == tp->t_zval)
628: return tp->t_zval;
629: cerror("int constant expression required");
630: return (0);
631: }
632:
633: /*
634: * Check for floating point.
635: */
636: isfloat(t)
637: register int t;
638: {
639: if (t==T_FLOAT || t==T_DOUBLE)
640: return (1);
641: return (0);
642: }
643:
644: /*
645: * Look for a constant zero of integral type.
646: */
647: iszero(tp)
648: register TREE *tp;
649: {
650: register int op;
651:
652: if (tp != NULL) {
653: while ((op = tp->t_op) == CONVERT || op == CAST)
654: tp = tp->t_lp;
655: if (op == ICON && tp->t_ival == 0)
656: return (1);
657: if (op == LCON && tp->t_lval == 0L)
658: return (1);
659: }
660: return (0);
661: }
662:
663: /*
664: * Build a conversion node.
665: * Used by build and stat when bcvt is unsuitable.
666: */
667: TREE *
668: bconvert(lp, gt, gdp, gip, rp)
669: TREE *lp, *rp;
670: DIM *gdp;
671: INFO *gip;
672: {
673: TREE t;
674:
675: t.t_op = CONVERT;
676: t.t_type = gt;
677: t.t_dp = gdp;
678: t.t_ip = gip;
679: t.t_rp = rp;
680: return (bcvt(lp, &t));
681: }
682:
683: /*
684: * Build a conversion or cast node.
685: */
686: TREE *
687: bcvt(lp, gtp)
688: TREE *lp, *gtp;
689: {
690: register TREE *tp;
691:
692: tp = lp;
693: tp = talloc();
694: tp->t_op = gtp->t_op;
695: tp->t_type = gtp->t_type;
696: tp->t_dp = gtp->t_dp;
697: tp->t_ip = gtp->t_ip;
698: tp->t_lp = lp;
699: tp->t_rp = gtp->t_rp;
700: return (tp);
701: }
702:
703: /*
704: * Given a pointer to its symbol table node,
705: * return a pointer to the tree node for an identifier.
706: * Enumeration tags get changed into integer constants here.
707: */
708: TREE *
709: bid(sp)
710: register SYM *sp;
711: {
712: register TREE *tp;
713:
714: sp->s_flag |= S_USED;
715: if (sp->s_class == C_MOE)
716: return (bicon(sp->s_value));
717: tp = talloc();
718: switch (sp->s_class) {
719:
720: case C_AUTO:
721: tp->t_op = AID;
722: tp->t_offs = sp->s_value;
723: break;
724:
725: case C_PAUTO:
726: tp->t_op = PID;
727: tp->t_offs = sp->s_value;
728: break;
729:
730: case C_SIN:
731: tp->t_op = LID;
732: tp->t_seg = sp->s_seg;
733: tp->t_label = sp->s_value;
734: break;
735:
736: case C_REG:
737: tp->t_op = REG;
738: tp->t_reg = sp->s_value;
739: break;
740:
741: case C_GDEF:
742: case C_GREF:
743: case C_CXT:
744: case C_SEX:
745: tp->t_op = GID;
746: tp->t_seg = sp->s_seg;
747: tp->t_sp = sp;
748: break;
749:
750: default:
751: cerror("identifier \"%s\" not usable", sp->s_id);
752: tp->t_op = ICON;
753: tp->t_type = T_INT;
754: return (tp);
755: }
756: tp->t_type = sp->s_type;
757: tp->t_dp = sp->s_dp;
758: tp->t_ip = sp->s_ip;
759: return (tp);
760: }
761:
762: /*
763: * Build ICON tree node.
764: */
765: TREE *
766: bicon(n)
767: {
768: register TREE *tp;
769:
770: tp = talloc();
771: tp->t_op = ICON;
772: tp->t_type = T_INT;
773: tp->t_ival = n;
774: return (tp);
775: }
776:
777: TREE *
778: bzcon(n)
779: sizeof_t n;
780: {
781: register TREE *tp;
782:
783: tp = talloc();
784: tp->t_op = ZCON;
785: tp->t_type = T_UINT;
786: tp->t_zval = n;
787: return (tp);
788: }
789:
790: /*
791: * Read in a string and hide it in the string section.
792: * Return a pointer to a local identifier node;
793: * the local identifier is planted at the start of the string.
794: * The type of the node is set to array of char.
795: */
796: static
797: TREE *
798: bstring()
799: {
800: register TREE *tp;
801: register int c, nbb, nbs;
802: int old, lab, adj;
803: char bb[11];
804:
805: old = newseg(SSTRN);
806: lab = here();
807: nbb = nbs = adj = 0;
808: again:
809: instring = '"';
810: while ((c=getmap('\"')) >= 0) {
811: ++nbs;
812: if (nbb >= 10) { /* Leave space for NUL */
813: bsflush(bb, nbb);
814: nbb = 0;
815: }
816: bb[nbb++] = c;
817: }
818: instring = 0;
819: if (lex() == STRING) { /* e.g. "Hello " "world" */
820: ++adj;
821: goto again;
822: }
823: bb[nbb++] = 0;
824: bsflush(bb, nbb);
825: if (adj)
826: notbook();
827: newseg(old);
828: tp = talloc();
829: tp->t_op = LID;
830: tp->t_type = T_CHAR;
831: tp->t_dp = tdalloc(NULL, D_ARRAY, (sizeof_t)nbs+1);
832: tp->t_label = lab;
833: tp->t_seg = SSTRN;
834: return (tp);
835: }
836:
837: /*
838: * Dump out the string buffer.
839: */
840: bsflush(bb, nbb)
841: register unsigned char *bb;
842: register int nbb;
843: {
844: bput(IBLOCK);
845: bput(nbb);
846: while (nbb--)
847: bput(*bb++);
848: }
849:
850: /*
851: * Make all the types and dims in a tree agree with the viewpoint at the top.
852: * This is used by casts and the code that builds up structure access trees.
853: */
854: adjust(tp, t, dp, ip)
855: register TREE *tp;
856: register DIM *dp;
857: INFO *ip;
858: {
859: register int op;
860:
861: again:
862: tp->t_type = t;
863: tp->t_dp = dp;
864: tp->t_ip = ip;
865: if ((op = tp->t_op) == ADDR) {
866: if (dp==NULL || (dp->d_type!=D_PTR && dp->d_type!=D_MOSAR))
867: return;
868: dp = dp->d_dp;
869: tp = tp->t_lp;
870: goto again;
871: }
872: if (op == STAR) {
873: dp = tdalloc(dp, D_PTR, (sizeof_t)0);
874: tp = tp->t_lp;
875: goto again;
876: }
877: if (dp!=NULL && dp->d_type==D_MOSAR)
878: dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0);
879: if (op==CAST && bitcompat(tltype(tp), tltype(tp->t_lp))) {
880: tp = tp->t_lp;
881: goto again;
882: }
883: }
884:
885: /*
886: * If the tree "tp" is a pointer,
887: * return the size of the item to which the pointer points;
888: * if it is not a pointer, return 1.
889: */
890: sizeof_t psize(tp)
891: register TREE *tp;
892: {
893: register DIM *dp;
894: register sizeof_t n;
895:
896: dp = tp->t_dp;
897: if (dp==NULL || dp->d_type!=D_PTR)
898: return (1);
899: tp->t_dp = dp->d_dp;
900: n = tsize(tp);
901: tp->t_dp = dp;
902: return (n);
903: }
904:
905: /*
906: * Check if a tree has type "function returning ...".
907: * If it does, modify the tree to add the free "address of".
908: */
909: TREE *
910: chfun(tp)
911: register TREE *tp;
912: {
913: register DIM *dp;
914:
915: dp = tp->t_dp;
916: if (dp!=NULL && dp->d_type==D_FUNC) {
917: tp = build(ADDR, tp, NULL);
918: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip);
919: }
920: return (tp);
921: }
922:
923: /*
924: * Check for arrays.
925: * Add the free '&' operation.
926: * We build the node ourselves (rather than calling build)
927: * to avoid a recursive call to this routine on
928: * a multidimensional structure.
929: */
930: TREE *
931: charray(tp)
932: register TREE *tp;
933: {
934: register TREE *ap;
935: register DIM *dp;
936:
937: dp = tp->t_dp;
938: if (dp!=NULL && dp->d_type==D_ARRAY) {
939: ap = talloc();
940: ap->t_op = ADDR;
941: ap->t_type = tp->t_type;
942: ap->t_dp = tdalloc(dp->d_dp, D_PTR, (sizeof_t)0);
943: ap->t_ip = tp->t_ip;
944: ap->t_lp = tp;
945: tp = ap;
946: adjust(tp, tp->t_type, tp->t_dp, tp->t_ip);
947: }
948: return (tp);
949: }
950:
951: /*
952: * Given a tree node, get a type for the tree that is
953: * usable for indexing into the type conversion tables.
954: * All non-scalars are pointers.
955: * All structures and unions are structures.
956: * All enumerations are set right.
957: */
958: tltype(tp)
959: register TREE *tp;
960: {
961: register int type;
962:
963: if (tp->t_dp != NULL)
964: return (T_PTR);
965: if ((type=tp->t_type) == T_FENUM)
966: return (T_INT);
967: if (type == T_ENUM)
968: return (tp->t_ip->i_type);
969: if (type > T_VOID)
970: return (T_STRUCT);
971: return (type);
972: }
973:
974: /*
975: * Check if two linear types are "bit compatable".
976: */
977: bitcompat(t1, t2)
978: {
979: return (noconvert(CAST, t1, t2));
980: }
981:
982: /*
983: * Allocate a new dim structure in the tree area.
984: * Used to create pointers in the tree.
985: */
986: DIM *
987: tdalloc(p, t, b)
988: DIM *p;
989: int t;
990: sizeof_t b;
991: {
992: register DIM *dp;
993:
994: dp = (struct dim *) talloc();
995: dp->d_dp = p;
996: dp->d_type = t;
997: dp->d_bound = b;
998: return (dp);
999: }
1000:
1001: /*
1002: * Output a tree.
1003: */
1004: tput(why, lab, tp)
1005: register why;
1006: register TREE *tp;
1007: {
1008: tp = transform(tp, why, -1);
1009: bput(why);
1010: if (why==TEXPR || why==FEXPR)
1011: iput((ival_t) lab);
1012: tput1(tp);
1013: }
1014:
1015: /*
1016: * Output a tree, part II.
1017: */
1018: tput1(tp)
1019: register TREE *tp;
1020: {
1021: register int op;
1022:
1023: if (tp == NULL) {
1024: iput((ival_t) NIL);
1025: return;
1026: }
1027: op = tp->t_op;
1028: iput((ival_t) op);
1029: bput(tp->t_type);
1030: if (tp->t_type == BLK)
1031: iput((ival_t)tp->t_ip->i_size);
1032: switch (op) {
1033:
1034: case ICON:
1035: iput((ival_t) tp->t_ival);
1036: break;
1037:
1038: case LCON:
1039: lput(tp->t_lval);
1040: break;
1041:
1042: case ZCON:
1043: zput(tp->t_zval);
1044: break;
1045:
1046: case DCON:
1047: dput(tp->t_dval); /* An array */
1048: break;
1049:
1050: case AID:
1051: case PID:
1052: case LID:
1053: case GID:
1054: zput(tp->t_offs);
1055: if (op==LID || op==GID) {
1056: bput(tp->t_seg);
1057: if (op == LID)
1058: iput((ival_t) tp->t_label);
1059: else
1060: nput(tp->t_sp->s_id);
1061: }
1062: break;
1063:
1064: case REG:
1065: iput((ival_t) tp->t_reg);
1066: break;
1067:
1068: case FIELD:
1069: bput(tp->t_width);
1070: bput(tp->t_base);
1071: tput1(tp->t_lp);
1072: break;
1073:
1074: default:
1075: tput1(tp->t_lp);
1076: tput1(tp->t_rp);
1077: }
1078: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.