Annotation of src/usr.bin/xlint/lint1/init.c, Revision 1.11
1.11 ! christos 1: /* $NetBSD: init.c,v 1.10 2002/01/31 19:36:54 tv Exp $ */
1.2 cgd 2:
1.1 cgd 3: /*
4: * Copyright (c) 1994, 1995 Jochen Pohl
5: * All Rights Reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Jochen Pohl for
18: * The NetBSD Project.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
1.5 christos 34: #include <sys/cdefs.h>
1.10 tv 35: #if defined(__RCSID) && !defined(lint)
1.11 ! christos 36: __RCSID("$NetBSD: init.c,v 1.10 2002/01/31 19:36:54 tv Exp $");
1.1 cgd 37: #endif
38:
39: #include <stdlib.h>
40:
41: #include "lint1.h"
42:
43: /*
1.8 wiz 44: * initerr is set as soon as a fatal error occurred in an initialisation.
1.1 cgd 45: * The effect is that the rest of the initialisation is ignored (parsed
46: * by yacc, expression trees built, but no initialisation takes place).
47: */
48: int initerr;
49:
50: /* Pointer to the symbol which is to be initialized. */
51: sym_t *initsym;
52:
53: /* Points to the top element of the initialisation stack. */
54: istk_t *initstk;
55:
56:
1.7 lukem 57: static void popi2(void);
58: static void popinit(int);
59: static void pushinit(void);
60: static void testinit(void);
61: static void nextinit(int);
62: static int strginit(tnode_t *);
1.1 cgd 63:
64:
65: /*
66: * Initialize the initialisation stack by putting an entry for the variable
67: * which is to be initialized on it.
68: */
69: void
1.7 lukem 70: prepinit(void)
1.1 cgd 71: {
72: istk_t *istk;
73:
74: if (initerr)
75: return;
76:
77: /* free memory used in last initialisation */
78: while ((istk = initstk) != NULL) {
79: initstk = istk->i_nxt;
80: free(istk);
81: }
82:
83: /*
84: * If the type which is to be initialized is an incomplete type,
85: * it must be duplicated.
86: */
87: if (initsym->s_type->t_tspec == ARRAY && incompl(initsym->s_type))
88: initsym->s_type = duptyp(initsym->s_type);
89:
90: istk = initstk = xcalloc(1, sizeof (istk_t));
91: istk->i_subt = initsym->s_type;
92: istk->i_cnt = 1;
93:
94: }
95:
96: static void
1.7 lukem 97: popi2(void)
1.1 cgd 98: {
99: istk_t *istk;
100: sym_t *m;
101:
102: initstk = (istk = initstk)->i_nxt;
103: if (initstk == NULL)
1.11 ! christos 104: LERROR("popi2()");
1.1 cgd 105: free(istk);
106:
107: istk = initstk;
108:
109: istk->i_cnt--;
110: if (istk->i_cnt < 0)
1.11 ! christos 111: LERROR("popi2()");
1.1 cgd 112:
113: /*
114: * If the removed element was a structure member, we must go
115: * to the next structure member.
116: */
117: if (istk->i_cnt > 0 && istk->i_type->t_tspec == STRUCT) {
118: do {
119: m = istk->i_mem = istk->i_mem->s_nxt;
120: if (m == NULL)
1.11 ! christos 121: LERROR("popi2()");
1.1 cgd 122: } while (m->s_field && m->s_name == unnamed);
123: istk->i_subt = m->s_type;
124: }
125: }
126:
127: static void
1.7 lukem 128: popinit(int brace)
1.1 cgd 129: {
1.7 lukem 130:
1.1 cgd 131: if (brace) {
132: /*
133: * Take all entries, including the first which requires
134: * a closing brace, from the stack.
135: */
136: do {
137: brace = initstk->i_brace;
138: popi2();
139: } while (!brace);
140: } else {
141: /*
142: * Take all entries which cannot be used for further
143: * initializers from the stack, but do this only if
144: * they do not require a closing brace.
145: */
146: while (!initstk->i_brace &&
147: initstk->i_cnt == 0 && !initstk->i_nolimit) {
148: popi2();
149: }
150: }
151: }
152:
153: static void
1.7 lukem 154: pushinit(void)
1.1 cgd 155: {
156: istk_t *istk;
157: int cnt;
158: sym_t *m;
159:
160: istk = initstk;
161:
162: /* Extend an incomplete array type by one element */
163: if (istk->i_cnt == 0) {
164: /*
165: * Inside of other aggregate types must not be an incomplete
166: * type.
167: */
168: if (istk->i_nxt->i_nxt != NULL)
1.11 ! christos 169: LERROR("pushinit()");
1.1 cgd 170: istk->i_cnt = 1;
171: if (istk->i_type->t_tspec != ARRAY)
1.11 ! christos 172: LERROR("pushinit()");
1.1 cgd 173: istk->i_type->t_dim++;
174: /* from now its an complete type */
175: setcompl(istk->i_type, 0);
176: }
177:
178: if (istk->i_cnt <= 0)
1.11 ! christos 179: LERROR("pushinit()");
1.1 cgd 180: if (istk->i_type != NULL && issclt(istk->i_type->t_tspec))
1.11 ! christos 181: LERROR("pushinit()");
1.1 cgd 182:
183: initstk = xcalloc(1, sizeof (istk_t));
184: initstk->i_nxt = istk;
185: initstk->i_type = istk->i_subt;
186: if (initstk->i_type->t_tspec == FUNC)
1.11 ! christos 187: LERROR("pushinit()");
1.1 cgd 188:
189: istk = initstk;
190:
191: switch (istk->i_type->t_tspec) {
192: case ARRAY:
193: if (incompl(istk->i_type) && istk->i_nxt->i_nxt != NULL) {
194: /* initialisation of an incomplete type */
195: error(175);
196: initerr = 1;
197: return;
198: }
199: istk->i_subt = istk->i_type->t_subt;
200: istk->i_nolimit = incompl(istk->i_type);
201: istk->i_cnt = istk->i_type->t_dim;
202: break;
203: case UNION:
204: if (tflag)
205: /* initialisation of union is illegal in trad. C */
206: warning(238);
207: /* FALLTHROUGH */
208: case STRUCT:
209: if (incompl(istk->i_type)) {
210: /* initialisation of an incomplete type */
211: error(175);
212: initerr = 1;
213: return;
214: }
215: cnt = 0;
216: for (m = istk->i_type->t_str->memb; m != NULL; m = m->s_nxt) {
217: if (m->s_field && m->s_name == unnamed)
218: continue;
219: if (++cnt == 1) {
220: istk->i_mem = m;
221: istk->i_subt = m->s_type;
222: }
223: }
224: if (cnt == 0) {
225: /* cannot init. struct/union with no named member */
226: error(179);
227: initerr = 1;
228: return;
229: }
230: istk->i_cnt = istk->i_type->t_tspec == STRUCT ? cnt : 1;
231: break;
232: default:
233: istk->i_cnt = 1;
234: break;
235: }
236: }
237:
238: static void
1.7 lukem 239: testinit(void)
1.1 cgd 240: {
241: istk_t *istk;
242:
243: istk = initstk;
244:
245: /*
246: * If a closing brace is expected we have at least one initializer
247: * too much.
248: */
249: if (istk->i_cnt == 0 && !istk->i_nolimit) {
250: switch (istk->i_type->t_tspec) {
251: case ARRAY:
252: /* too many array initializers */
253: error(173);
254: break;
255: case STRUCT:
256: case UNION:
257: /* too many struct/union initializers */
258: error(172);
259: break;
260: default:
261: /* too many initializers */
262: error(174);
263: break;
264: }
265: initerr = 1;
266: }
267: }
268:
269: static void
1.7 lukem 270: nextinit(int brace)
1.1 cgd 271: {
1.7 lukem 272:
1.1 cgd 273: if (!brace) {
274: if (initstk->i_type == NULL &&
275: !issclt(initstk->i_subt->t_tspec)) {
276: /* {}-enclosed initializer required */
277: error(181);
278: }
279: /*
280: * Make sure an entry with a scalar type is at the top
281: * of the stack.
282: */
283: if (!initerr)
284: testinit();
285: while (!initerr && (initstk->i_type == NULL ||
286: !issclt(initstk->i_type->t_tspec))) {
287: if (!initerr)
288: pushinit();
289: }
290: } else {
291: if (initstk->i_type != NULL &&
292: issclt(initstk->i_type->t_tspec)) {
293: /* invalid initializer */
294: error(176);
295: initerr = 1;
296: }
297: if (!initerr)
298: testinit();
299: if (!initerr)
300: pushinit();
301: if (!initerr)
302: initstk->i_brace = 1;
303: }
304: }
305:
306: void
1.7 lukem 307: initlbr(void)
1.1 cgd 308: {
1.7 lukem 309:
1.1 cgd 310: if (initerr)
311: return;
312:
313: if ((initsym->s_scl == AUTO || initsym->s_scl == REG) &&
314: initstk->i_nxt == NULL) {
315: if (tflag && !issclt(initstk->i_subt->t_tspec))
316: /* no automatic aggregate initialization in trad. C*/
317: warning(188);
318: }
319:
320: /*
321: * Remove all entries which cannot be used for further initializers
322: * and do not expect a closing brace.
323: */
324: popinit(0);
325:
326: nextinit(1);
327: }
328:
329: void
1.7 lukem 330: initrbr(void)
1.1 cgd 331: {
1.7 lukem 332:
1.1 cgd 333: if (initerr)
334: return;
335:
336: popinit(1);
337: }
338:
339: void
1.7 lukem 340: mkinit(tnode_t *tn)
1.1 cgd 341: {
342: ptrdiff_t offs;
343: sym_t *sym;
344: tspec_t lt, rt;
345: tnode_t *ln;
346: struct mbl *tmem;
347: scl_t sc;
348:
349: if (initerr || tn == NULL)
350: goto end;
351:
352: sc = initsym->s_scl;
353:
354: /*
355: * Do not test for automatic aggregat initialisation. If the
1.9 wiz 356: * initializer starts with a brace we have the warning already.
1.1 cgd 357: * If not, an error will be printed that the initializer must
358: * be enclosed by braces.
359: */
360:
361: /*
362: * Local initialisation of non-array-types with only one expression
363: * without braces is done by ASSIGN
364: */
365: if ((sc == AUTO || sc == REG) &&
366: initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) {
367: ln = getnnode(initsym, 0);
368: ln->tn_type = tduptyp(ln->tn_type);
369: ln->tn_type->t_const = 0;
370: tn = build(ASSIGN, ln, tn);
371: expr(tn, 0, 0);
372: goto end;
373: }
374:
375: /*
376: * Remove all entries which cannot be used for further initializers
377: * and do not require a closing brace.
378: */
379: popinit(0);
380:
381: /* Initialisations by strings are done in strginit(). */
382: if (strginit(tn))
383: goto end;
384:
385: nextinit(0);
386: if (initerr || tn == NULL)
387: goto end;
388:
389: initstk->i_cnt--;
390:
391: /* Create a temporary node for the left side. */
392: ln = tgetblk(sizeof (tnode_t));
393: ln->tn_op = NAME;
394: ln->tn_type = tduptyp(initstk->i_type);
395: ln->tn_type->t_const = 0;
396: ln->tn_lvalue = 1;
397: ln->tn_sym = initsym; /* better than nothing */
398:
399: tn = cconv(tn);
400:
401: lt = ln->tn_type->t_tspec;
402: rt = tn->tn_type->t_tspec;
403:
404: if (!issclt(lt))
1.11 ! christos 405: LERROR("mkinit()");
1.1 cgd 406:
407: if (!typeok(INIT, 0, ln, tn))
408: goto end;
409:
410: /*
411: * Store the tree memory. This is nessesary because otherwise
412: * expr() would free it.
413: */
414: tmem = tsave();
415: expr(tn, 1, 0);
416: trestor(tmem);
1.7 lukem 417:
1.1 cgd 418: if (isityp(lt) && ln->tn_type->t_isfield && !isityp(rt)) {
419: /*
420: * Bit-fields can be initialized in trad. C only by integer
421: * constants.
422: */
423: if (tflag)
424: /* bit-field initialisation is illegal in trad. C */
425: warning(186);
426: }
427:
428: if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON))
429: tn = convert(INIT, 0, initstk->i_type, tn);
430:
431: if (tn != NULL && tn->tn_op != CON) {
432: sym = NULL;
433: offs = 0;
434: if (conaddr(tn, &sym, &offs) == -1) {
1.3 jpo 435: if (sc == AUTO || sc == REG) {
1.1 cgd 436: /* non-constant initializer */
1.4 jpo 437: (void)gnuism(177);
1.1 cgd 438: } else {
439: /* non-constant initializer */
440: error(177);
441: }
442: }
443: }
444:
445: end:
446: tfreeblk();
447: }
448:
449:
450: static int
1.7 lukem 451: strginit(tnode_t *tn)
1.1 cgd 452: {
453: tspec_t t;
454: istk_t *istk;
455: int len;
456: strg_t *strg;
457:
458: if (tn->tn_op != STRING)
459: return (0);
460:
461: istk = initstk;
462: strg = tn->tn_strg;
463:
464: /*
465: * Check if we have an array type which can be initialized by
466: * the string.
467: */
468: if (istk->i_subt->t_tspec == ARRAY) {
469: t = istk->i_subt->t_subt->t_tspec;
470: if (!((strg->st_tspec == CHAR &&
471: (t == CHAR || t == UCHAR || t == SCHAR)) ||
472: (strg->st_tspec == WCHAR && t == WCHAR))) {
473: return (0);
474: }
475: /* Put the array at top of stack */
476: pushinit();
477: istk = initstk;
478: } else if (istk->i_type != NULL && istk->i_type->t_tspec == ARRAY) {
479: t = istk->i_type->t_subt->t_tspec;
480: if (!((strg->st_tspec == CHAR &&
481: (t == CHAR || t == UCHAR || t == SCHAR)) ||
482: (strg->st_tspec == WCHAR && t == WCHAR))) {
483: return (0);
484: }
485: /*
486: * If the array is already partly initialized, we are
487: * wrong here.
488: */
489: if (istk->i_cnt != istk->i_type->t_dim)
490: return (0);
491: } else {
492: return (0);
493: }
494:
495: /* Get length without trailing NUL character. */
496: len = strg->st_len;
497:
498: if (istk->i_nolimit) {
499: istk->i_nolimit = 0;
500: istk->i_type->t_dim = len + 1;
501: /* from now complete type */
502: setcompl(istk->i_type, 0);
503: } else {
504: if (istk->i_type->t_dim < len) {
505: /* non-null byte ignored in string initializer */
506: warning(187);
507: }
508: }
509:
510: /* In every case the array is initialized completely. */
511: istk->i_cnt = 0;
512:
513: return (1);
514: }
CVSweb <webmaster@jp.NetBSD.org>