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