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