|
|
1.1 root 1: /*
2: * n0/init.c
3: * C compiler.
4: * Initializers.
5: * All storage classes.
6: */
7:
8: #ifdef vax
9: #include "INC$LIB:cc0.h"
10: #else
11: #include "cc0.h"
12: #endif
13:
14: init(sp, dp, bo, flex)
15: register SYM *sp;
16: register DIM *dp;
17: sizeof_t bo;
18: int flex;
19: {
20: register int t;
21: DIM *ndp;
22: TREE *tp;
23: sizeof_t width, nbe, nel, ninit;
24: int brace, c, adj;
25:
26: t = sp->s_type;
27: width = sdsize(sp, dp);
28: ndp = dp;
29: if (dp!=NULL && dp->d_type==D_ARRAY) {
30: if (dp->d_bound != 0)
31: flex = 0;
32: ndp = dp->d_dp;
33: if (width==0 && !flex)
34: cerror("array row has 0 length");
35: } else
36: flex = 0;
37: nel = 0;
38: nbe = sdsize(sp, ndp);
39: if (nbe != 0)
40: nel = width/nbe;
41: brace = 0;
42: if (s==LBRACE && (dp!=NULL || !istruct(t))) {
43: ++brace;
44: lex();
45: } else if (s!=LBRACE && (dp!=NULL || istruct(t)))
46: notbook();
47: ninit = 0;
48: while (s != RBRACE) {
49: if (ndp==NULL && istruct(t))
50: sinit(sp, bo);
51: else if (ndp!=NULL && ndp->d_type==D_ARRAY)
52: init(sp, ndp, bo, 0);
53: else {
54: adj = 0;
55: if (s==STRING && t<T_INT && ndp==NULL) {
56: again:
57: instring = '"';
58: while ((c = getmap('\"')) >= 0) {
59: newtree(sizeof(TREE));
60: icollect(bicon((ival_t)c), bo, sp, ndp);
61: ++ninit;
62: ++bo;
63: }
64: instring = 0;
65: if (lex() == STRING) {
66: ++adj;
67: goto again;
68: }
69: if (adj)
70: notbook();
71: if (!flex && ninit==nel) {
72: cwarn("string initializer not terminated by NUL");
73: break;
74: }
75: newtree(sizeof(TREE));
76: icollect(bicon((ival_t)0), bo, sp, ndp);
77: ++ninit;
78: break;
79: }
80: newtree(sizeof(TREE));
81: ++ininit;
82: tp = expr();
83: --ininit;
84: icollect(tp, bo, sp, ndp);
85: }
86: ++ninit;
87: bo += nbe;
88: if (s != COMMA)
89: break;
90: if (ninit>=nel && !flex) {
91: if (brace) {
92: lex();
93: if (s == RBRACE)
94: cwarn("trailing ',' in initialization list");
95: else {
96: cerror("too many initializers");
97: iskip();
98: }
99: }
100: break;
101: }
102: itrail();
103: }
104: if (brace)
105: mustbe(RBRACE);
106: if (ninit < nel) {
107: c = sp->s_class;
108: if (c==C_GDEF || c==C_SIN || c==C_SEX) {
109: bput(BLOCK);
110: zput(nbe*(nel-ninit));
111: }
112: }
113: if (ninit > nel) {
114: if (!flex)
115: cerror("too many initializers");
116: if (dp != NULL)
117: dp->d_bound = ninit;
118: }
119: }
120:
121: /*
122: * Initialize a structure.
123: * Create a fake variable for each member;
124: * this is necessary for the call to build() in iassign()
125: * to do the correct things.
126: */
127: sinit(sp, bo) SYM *sp; sizeof_t bo;
128: {
129: register SYM *mp;
130: register INFO *ip;
131: int n, brace, c, t, f, bfflag;
132: sizeof_t mo, lo;
133: SYM sym;
134:
135: c = sp->s_class;
136: t = sp->s_type;
137: if (t==T_UNION || t==T_FUNION)
138: cerror("cannot initialize unions");
139: if (t==T_FSTRUCT || t==T_FUNION)
140: return;
141: ip = sp->s_ip;
142: sym.s_class = c;
143: sym.s_value = sp->s_value;
144: brace = 0;
145: if (s == LBRACE) {
146: ++brace;
147: lex();
148: }
149: lo = n = f = 0;
150: while (s != RBRACE) {
151: bfflag = 0;
152: if (n >= ip->i_nsp) {
153: if (f == 0) {
154: cerror("too many structure initializers");
155: ++f;
156: }
157: sym.s_type = T_INT;
158: sym.s_dp = sym.s_ip = NULL;
159: mo = 0;
160: } else {
161: mp = ip->i_sp[n++];
162: sym.s_type = mp->s_type;
163: sym.s_dp = mp->s_dp;
164: sym.s_ip = mp->s_ip;
165: mo = mp->s_value;
166: if (!isauto(&sym) && lo!=mo) {
167: /* Output BLOCK item for padding. */
168: bput(BLOCK);
169: zput(mo-lo);
170: lo = mo;
171: }
172: if (mp->s_width != 0) /* bitfield initializer */
173: bfflag = bfinit(&sym, mp, ip, &n, bo+mo);
174: }
175: if (!bfflag)
176: init(&sym, sym.s_dp, bo+mo, 0);
177: lo += ssize(&sym);
178: if (bfflag != 2 && s != COMMA)
179: break;
180: if (n >= ip->i_nsp && !brace)
181: break;
182: if (bfflag != 2)
183: itrail(); /* skip COMMA, check for RBRACE */
184: }
185: if (brace)
186: mustbe(RBRACE);
187: if (t==T_STRUCT && (c==C_GDEF || c==C_SIN || c==C_SEX)) {
188: if ((mo = ip->i_size-lo) > 0) {
189: bput(BLOCK);
190: zput(mo);
191: }
192: }
193: }
194:
195: /*
196: * Fetch the next symbol.
197: * The current symbol is a COMMA.
198: * If the new symbol is '}', the program has said ", }"; this is legal.
199: * If you pull the comments here, it becomes not quite so legal.
200: */
201: static
202: itrail()
203: {
204: lex();
205: if (s == RBRACE)
206: cwarn("trailing ',' in initialization list");
207: }
208:
209: /*
210: * An initialization starting with '{' contains too many initializers.
211: * Skip initializers to the matching '}' or EOF.
212: */
213: static
214: iskip()
215: {
216: register int braces;
217:
218: braces = 0;
219: for(;;) {
220: if (s == LBRACE)
221: ++braces;
222: else if (s == RBRACE) {
223: if (braces == 0)
224: return;
225: else
226: --braces;
227: }
228: else if (s == EOF)
229: return;
230: lex();
231: }
232: }
233:
234: /*
235: * Return true if symbol "sp" is an automatic,
236: * in the sense that an assigment statement must be generated
237: * for the initialization item.
238: * Registers are considered auto.
239: */
240: int
241: isauto(sp) register SYM *sp;
242: {
243: register int c;
244:
245: c = sp->s_class;
246: return (c==C_AUTO || c==C_PAUTO || c==C_REG);
247: }
248:
249: /*
250: * This routine actually performs the initialization.
251: * Either an build an assignment node and evaluate it for effect,
252: * or output an initialization tree.
253: */
254: icollect(tp, bo, sp, dp)
255: register TREE *tp;
256: sizeof_t bo;
257: register SYM *sp;
258: DIM *dp;
259: {
260: register TREE *ip;
261:
262: if (isauto(sp)) {
263: iassign(sp, dp, bo, tp);
264: return;
265: }
266: ip = talloc();
267: ip->t_op = INIT;
268: ip->t_type = sp->s_type;
269: ip->t_dp = dp;
270: ip->t_ip = sp->s_ip;
271: ip->t_lp = tp;
272: tput(IEXPR, 0, ip);
273: }
274:
275: /*
276: * Actually do the assignment for an automatic initialization thing.
277: */
278: iassign(sp, dp, bo, tp)
279: register SYM *sp;
280: register TREE *tp;
281: sizeof_t bo;
282: DIM *dp;
283: {
284: register TREE *ip;
285: DIM *ssdp;
286:
287: ssdp = sp->s_dp;
288: sp->s_dp = dp;
289: ip = bid(sp);
290: sp->s_dp = ssdp;
291: if (sp->s_class != C_REG)
292: ip->t_offs += bo;
293: tp = build(ASSIGN, ip, tp);
294: tput(EEXPR, 0, tp);
295: }
296:
297: /*
298: * Collect one or more bitfield initializers.
299: * Each bitfield initializer must be an integer constant.
300: * Multiple bitfield initializers get output as a single initialization item:
301: * look for more initializers if the next
302: * structure member is another bitfield at the same offset (s_value).
303: * This may or may not need to look ahead to the next initializer,
304: * so it returns 1 if it has not read COMMA, 2 if it has read the COMMA.
305: */
306: int
307: bfinit(sp, mp, ip, np, off) SYM *sp; register SYM *mp; INFO *ip; register int *np; sizeof_t off;
308: {
309: register unsigned long val, mval, mask;
310: int status;
311:
312: for (val = (unsigned long)0; ; ) {
313:
314: status = 1; /* COMMA not read yet */
315:
316: /* Widen the initialized symbol base type if necessary. */
317: if (ssize(sp) < ssize(mp))
318: sp->s_type = mp->s_type;
319:
320: /* Grab the initializer value. */
321: ++ininit;
322: mval = iconexpr();
323: --ininit;
324:
325: /* Make sure the initializer is appropriate. */
326: mask = (((unsigned long)1) << mp->s_width) - 1;
327: if ((mval & ~mask) != (unsigned long)0 && (mval & ~mask) != ~mask)
328: cwarn("bitfield initializer out of range");
329: mval &= mask; /* mask value to bitfield width */
330:
331: /* Build up the initializer in val. */
332: val |= (mval << mp->s_offset); /* put value in the right place */
333:
334: /* Check whether more bitfield initializers follow. */
335: if (s != COMMA) /* no more initializers */
336: break;
337: itrail(); /* skip COMMA */
338: ++status; /* COMMA has been read */
339: if (s == LBRACE || s == RBRACE /* { or }, no more bitfield inits */
340: || *np >= ip->i_nsp /* no more members */
341: || ip->i_sp[*np]->s_width==0 /* next not a bitfield */
342: || ip->i_sp[*np]->s_value != mp->s_value) /* next at different value */
343: break;
344: mp = ip->i_sp[(*np)++]; /* repeat for next bitfield */
345: }
346:
347: /*
348: * Output the bitfield initializer built up in val.
349: * FIX_ME The initializer value collected in unsigned long 'val'
350: * is passed to icollect() as bicon((ival_t)val),
351: * this does not seem not quite right.
352: */
353: icollect(bicon((ival_t)val), off, sp, NULL);
354: return status;
355: }
356:
357: /* end of n0/init.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.