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