1/*	$NetBSD: init.c,v 1.10 2002/01/31 19:36:54 tv 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.10 2002/01/31 19:36:54 tv Exp $");
37#endif
38__FBSDID("$FreeBSD$");
39
40#include <ctype.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include "lint1.h"
45
46/*
47 * initerr is set as soon as a fatal error occurred in an initialisation.
48 * The effect is that the rest of the initialisation is ignored (parsed
49 * by yacc, expression trees built, but no initialisation takes place).
50 */
51int	initerr;
52
53/* Pointer to the symbol which is to be initialized. */
54sym_t	*initsym;
55
56/* Points to the top element of the initialisation stack. */
57istk_t	*initstk;
58
59typedef struct namlist {
60	const char *n_name;
61	struct namlist *n_prev;
62	struct namlist *n_next;
63} namlist_t;
64
65/* Points to a c9x named member; */
66namlist_t	*namedmem = NULL;
67
68
69static	void	popi2(void);
70static	void	popinit(int);
71static	void	pushinit(void);
72static	void	testinit(void);
73static	void	nextinit(int);
74static	int	strginit(tnode_t *);
75static	void	memberpop(void);
76
77#ifndef DEBUG
78#define DPRINTF(a)
79#else
80#define DPRINTF(a) printf a
81#endif
82
83void
84memberpush(sb)
85	sbuf_t *sb;
86{
87	namlist_t *nam = xcalloc(1, sizeof (namlist_t));
88	nam->n_name = sb->sb_name;
89	DPRINTF(("memberpush = %s\n", nam->n_name));
90	if (namedmem == NULL) {
91		nam->n_prev = nam->n_next = nam;
92		namedmem = nam;
93	} else {
94		namedmem->n_prev->n_next = nam;
95		nam->n_prev = namedmem->n_prev;
96		nam->n_next = namedmem;
97		namedmem->n_prev = nam;
98	}
99#if 0
100	nam->n_next = namedmem;
101	namedmem = nam;
102#endif
103}
104
105static void
106memberpop()
107{
108	DPRINTF(("memberpop = %s\n", namedmem->n_name));
109	if (namedmem->n_next == namedmem) {
110		free(namedmem);
111		namedmem = NULL;
112	} else {
113		namlist_t *nam = namedmem;
114		namedmem = namedmem->n_next;
115		free(nam);
116	}
117#if 0
118	namedmem = namedmem->n_next;
119	free(nam);
120#endif
121}
122
123
124/*
125 * Initialize the initialisation stack by putting an entry for the variable
126 * which is to be initialized on it.
127 */
128void
129prepinit(void)
130{
131	istk_t	*istk;
132
133	if (initerr)
134		return;
135
136	/* free memory used in last initialisation */
137	while ((istk = initstk) != NULL) {
138		initstk = istk->i_nxt;
139		free(istk);
140	}
141
142	/*
143	 * If the type which is to be initialized is an incomplete type,
144	 * it must be duplicated.
145	 */
146	if (initsym->s_type->t_tspec == ARRAY && incompl(initsym->s_type))
147		initsym->s_type = duptyp(initsym->s_type);
148
149	istk = initstk = xcalloc(1, sizeof (istk_t));
150	istk->i_subt = initsym->s_type;
151	istk->i_cnt = 1;
152
153}
154
155static void
156popi2(void)
157{
158#ifdef DEBUG
159	char	buf[64];
160#endif
161	istk_t	*istk;
162	sym_t	*m;
163
164	initstk = (istk = initstk)->i_nxt;
165	if (initstk == NULL)
166		LERROR("popi2()");
167	free(istk);
168
169	istk = initstk;
170
171	istk->i_cnt--;
172	if (istk->i_cnt < 0)
173		LERROR("popi2()");
174
175	DPRINTF(("popi2(): %d %s\n", istk->i_cnt,
176	    namedmem ? namedmem->n_name : "*null*"));
177	if (istk->i_cnt >= 0 && namedmem != NULL) {
178		DPRINTF(("popi2(): %d %s %s\n", istk->i_cnt,
179		    tyname(buf, sizeof(buf), istk->i_type), namedmem->n_name));
180		for (m = istk->i_type->t_str->memb; m != NULL; m = m->s_nxt) {
181			if (m->s_field && m->s_name == unnamed)
182				continue;
183			if (strcmp(m->s_name, namedmem->n_name) == 0) {
184				istk->i_subt = m->s_type;
185				istk->i_cnt++;
186				memberpop();
187				return;
188			}
189		}
190		error(101, namedmem->n_name);
191		memberpop();
192		istk->i_namedmem = 1;
193		return;
194	}
195	/*
196	 * If the removed element was a structure member, we must go
197	 * to the next structure member.
198	 */
199	if (istk->i_cnt > 0 && istk->i_type->t_tspec == STRUCT &&
200	    !istk->i_namedmem) {
201		do {
202			m = istk->i_mem = istk->i_mem->s_nxt;
203			if (m == NULL)
204				LERROR("popi2()");
205		} while (m->s_field && m->s_name == unnamed);
206		istk->i_subt = m->s_type;
207	}
208}
209
210static void
211popinit(int brace)
212{
213	DPRINTF(("popinit(%d)\n", brace));
214
215	if (brace) {
216		/*
217		 * Take all entries, including the first which requires
218		 * a closing brace, from the stack.
219		 */
220		do {
221			brace = initstk->i_brace;
222			popi2();
223		} while (!brace);
224	} else {
225		/*
226		 * Take all entries which cannot be used for further
227		 * initializers from the stack, but do this only if
228		 * they do not require a closing brace.
229		 */
230		while (!initstk->i_brace &&
231		       initstk->i_cnt == 0 && !initstk->i_nolimit) {
232			popi2();
233		}
234	}
235}
236
237static void
238pushinit(void)
239{
240#ifdef DEBUG
241	char	buf[64];
242#endif
243	istk_t	*istk;
244	int	cnt;
245	sym_t	*m;
246
247	istk = initstk;
248
249	/* Extend an incomplete array type by one element */
250	if (istk->i_cnt == 0) {
251		DPRINTF(("pushinit(extend) %s\n", tyname(buf, sizeof(buf),
252		    istk->i_type)));
253		/*
254		 * Inside of other aggregate types must not be an incomplete
255		 * type.
256		 */
257		if (istk->i_nxt->i_nxt != NULL)
258			LERROR("pushinit()");
259		istk->i_cnt = 1;
260		if (istk->i_type->t_tspec != ARRAY)
261			LERROR("pushinit()");
262		istk->i_type->t_dim++;
263		/* from now its a complete type */
264		setcompl(istk->i_type, 0);
265	}
266
267	if (istk->i_cnt <= 0)
268		LERROR("pushinit()");
269	if (istk->i_type != NULL && issclt(istk->i_type->t_tspec))
270		LERROR("pushinit() 4");
271
272	initstk = xcalloc(1, sizeof (istk_t));
273	initstk->i_nxt = istk;
274	initstk->i_type = istk->i_subt;
275	if (initstk->i_type->t_tspec == FUNC)
276		LERROR("pushinit()");
277
278again:
279	istk = initstk;
280
281	DPRINTF(("pushinit(%s)\n", tyname(buf, sizeof(buf), istk->i_type)));
282	switch (istk->i_type->t_tspec) {
283	case ARRAY:
284		if (namedmem) {
285			DPRINTF(("pushinit ARRAY %s\n", namedmem->n_name));
286			free(istk);
287			initstk = initstk->i_nxt;
288			goto again;
289		}
290		if (incompl(istk->i_type) && istk->i_nxt->i_nxt != NULL) {
291			/* initialisation of an incomplete type */
292			error(175);
293			initerr = 1;
294			return;
295		}
296		istk->i_subt = istk->i_type->t_subt;
297		istk->i_nolimit = incompl(istk->i_type);
298		istk->i_cnt = istk->i_type->t_dim;
299		DPRINTF(("elements array %s[%d] %s\n",
300		    tyname(buf, sizeof(buf), istk->i_subt), istk->i_cnt,
301		    namedmem ? namedmem->n_name : "*none*"));
302		break;
303	case UNION:
304		if (tflag)
305			/* initialisation of union is illegal in trad. C */
306			warning(238);
307		/* FALLTHROUGH */
308	case STRUCT:
309		if (incompl(istk->i_type)) {
310			/* initialisation of an incomplete type */
311			error(175);
312			initerr = 1;
313			return;
314		}
315		cnt = 0;
316		DPRINTF(("2. member lookup %s %s\n",
317		    tyname(buf, sizeof(buf), istk->i_type),
318		    namedmem ? namedmem->n_name : "*none*"));
319		for (m = istk->i_type->t_str->memb; m != NULL; m = m->s_nxt) {
320			if (m->s_field && m->s_name == unnamed)
321				continue;
322			if (namedmem != NULL) {
323				DPRINTF(("pushinit():[member:%s, looking:%s]\n",
324				    m->s_name, namedmem->n_name));
325				if (strcmp(m->s_name, namedmem->n_name) == 0) {
326					cnt++;
327					break;
328				} else
329					continue;
330			}
331			if (++cnt == 1) {
332				istk->i_mem = m;
333				istk->i_subt = m->s_type;
334			}
335		}
336		if (namedmem != NULL) {
337			istk->i_namedmem = 1;
338			if (m == NULL) {
339				error(101, namedmem->n_name);
340				initerr = 1;
341			} else {
342				istk->i_mem = m;
343				istk->i_subt = m->s_type;
344			}
345			memberpop();
346			cnt = istk->i_type->t_tspec == STRUCT ? 2 : 1;
347		}
348		if (cnt == 0) {
349			/* cannot init. struct/union with no named member */
350			error(179);
351			initerr = 1;
352			return;
353		}
354		istk->i_cnt = istk->i_type->t_tspec == STRUCT ? cnt : 1;
355		break;
356	default:
357		if (namedmem) {
358			DPRINTF(("pushinit(): pop\n"));
359			free(istk);
360			initstk = initstk->i_nxt;
361			goto again;
362		}
363		istk->i_cnt = 1;
364		break;
365	}
366}
367
368static void
369testinit(void)
370{
371	istk_t	*istk;
372
373	istk = initstk;
374
375	/*
376	 * If a closing brace is expected we have at least one initializer
377	 * too much.
378	 */
379	if (istk->i_cnt == 0 && !istk->i_nolimit && !istk->i_namedmem) {
380		switch (istk->i_type->t_tspec) {
381		case ARRAY:
382			/* too many array initializers */
383			error(173);
384			break;
385		case STRUCT:
386		case UNION:
387			/* too many struct/union initializers */
388			error(172);
389			break;
390		default:
391			/* too many initializers */
392			error(174);
393			break;
394		}
395		initerr = 1;
396	}
397}
398
399static void
400nextinit(int brace)
401{
402	char buf[64];
403
404	DPRINTF(("nextinit(%d)\n", brace));
405	if (!brace) {
406		if (initstk->i_type == NULL &&
407		    !issclt(initstk->i_subt->t_tspec)) {
408			/* {}-enclosed initializer required */
409			error(181);
410		}
411		/*
412		 * Make sure an entry with a scalar type is at the top
413		 * of the stack.
414		 */
415		if (!initerr)
416			testinit();
417		while (!initerr && (initstk->i_type == NULL ||
418				    !issclt(initstk->i_type->t_tspec))) {
419			if (!initerr)
420				pushinit();
421		}
422	} else {
423		if (initstk->i_type != NULL &&
424		    issclt(initstk->i_type->t_tspec)) {
425			/* invalid initializer */
426			error(176);
427			initerr = 1;
428		}
429		if (!initerr)
430			testinit();
431		if (!initerr)
432			pushinit();
433		if (!initerr)
434			initstk->i_brace = 1;
435	}
436}
437
438void
439initlbr(void)
440{
441
442	if (initerr)
443		return;
444
445	if ((initsym->s_scl == AUTO || initsym->s_scl == REG) &&
446	    initstk->i_nxt == NULL) {
447		if (tflag && !issclt(initstk->i_subt->t_tspec))
448			/* no automatic aggregate initialization in trad. C*/
449			warning(188);
450	}
451
452	/*
453	 * Remove all entries which cannot be used for further initializers
454	 * and do not expect a closing brace.
455	 */
456	popinit(0);
457
458	nextinit(1);
459}
460
461void
462initrbr(void)
463{
464
465	if (initerr)
466		return;
467
468	popinit(1);
469}
470
471void
472mkinit(tnode_t *tn)
473{
474	ptrdiff_t offs;
475	sym_t	*sym;
476	tspec_t	lt, rt;
477	tnode_t	*ln;
478	struct	mbl *tmem;
479	scl_t	sc;
480#ifdef DEBUG
481	char	buf[64];
482#endif
483
484	DPRINTF(("mkinit(%s)\n", tyname(buf, sizeof(buf), tn->tn_type)));
485	if (initerr || tn == NULL)
486		goto end;
487
488	sc = initsym->s_scl;
489
490	/*
491	 * Do not test for automatic aggregate initialisation. If the
492	 * initializer starts with a brace we have the warning already.
493	 * If not, an error will be printed that the initializer must
494	 * be enclosed by braces.
495	 */
496
497	/*
498	 * Local initialisation of non-array-types with only one expression
499	 * without braces is done by ASSIGN
500	 */
501	if ((sc == AUTO || sc == REG) &&
502	    initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) {
503		ln = getnnode(initsym, 0);
504		ln->tn_type = tduptyp(ln->tn_type);
505		ln->tn_type->t_const = 0;
506		tn = build(ASSIGN, ln, tn);
507		expr(tn, 0, 0, 1);
508		goto end;
509	}
510
511	/*
512	 * Remove all entries which cannot be used for further initializers
513	 * and do not require a closing brace.
514	 */
515	popinit(0);
516
517	/* Initialisations by strings are done in strginit(). */
518	if (strginit(tn))
519		goto end;
520
521	nextinit(0);
522	if (initerr || tn == NULL)
523		goto end;
524
525	initstk->i_cnt--;
526	DPRINTF(("mkinit() cnt=%d tn=%p\n", initstk->i_cnt, tn));
527	/* Create a temporary node for the left side. */
528	ln = tgetblk(sizeof (tnode_t));
529	ln->tn_op = NAME;
530	ln->tn_type = tduptyp(initstk->i_type);
531	ln->tn_type->t_const = 0;
532	ln->tn_lvalue = 1;
533	ln->tn_sym = initsym;		/* better than nothing */
534
535	tn = cconv(tn);
536
537	lt = ln->tn_type->t_tspec;
538	rt = tn->tn_type->t_tspec;
539
540	if (!issclt(lt))
541		LERROR("mkinit()");
542
543	if (!typeok(INIT, 0, ln, tn))
544		goto end;
545
546	/*
547	 * Store the tree memory. This is necessary because otherwise
548	 * expr() would free it.
549	 */
550	tmem = tsave();
551	expr(tn, 1, 0, 1);
552	trestor(tmem);
553
554	if (isityp(lt) && ln->tn_type->t_isfield && !isityp(rt)) {
555		/*
556		 * Bit-fields can be initialized in trad. C only by integer
557		 * constants.
558		 */
559		if (tflag)
560			/* bit-field initialisation is illegal in trad. C */
561			warning(186);
562	}
563
564	if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON))
565		tn = convert(INIT, 0, initstk->i_type, tn);
566
567	if (tn != NULL && tn->tn_op != CON) {
568		sym = NULL;
569		offs = 0;
570		if (conaddr(tn, &sym, &offs) == -1) {
571			if (sc == AUTO || sc == REG) {
572				/* non-constant initializer */
573				(void)gnuism(177);
574			} else {
575				/* non-constant initializer */
576				error(177);
577			}
578		}
579	}
580
581 end:
582	/*
583	 * We only free the block, if we are not a compound declaration
584	 * We know that the only symbols that start with a digit are the
585	 * ones we allocate with mktempsym() for compound declarations
586	 */
587	if (!isdigit((unsigned char)initsym->s_name[0]))
588		tfreeblk();
589}
590
591
592static int
593strginit(tnode_t *tn)
594{
595	tspec_t	t;
596	istk_t	*istk;
597	int	len;
598	strg_t	*strg;
599
600	if (tn->tn_op != STRING)
601		return (0);
602
603	istk = initstk;
604	strg = tn->tn_strg;
605
606	/*
607	 * Check if we have an array type which can be initialized by
608	 * the string.
609	 */
610	if (istk->i_subt != NULL && istk->i_subt->t_tspec == ARRAY) {
611		t = istk->i_subt->t_subt->t_tspec;
612		if (!((strg->st_tspec == CHAR &&
613		       (t == CHAR || t == UCHAR || t == SCHAR)) ||
614		      (strg->st_tspec == WCHAR && t == WCHAR))) {
615			return (0);
616		}
617		/* Put the array at top of stack */
618		pushinit();
619		istk = initstk;
620	} else if (istk->i_type != NULL && istk->i_type->t_tspec == ARRAY) {
621		t = istk->i_type->t_subt->t_tspec;
622		if (!((strg->st_tspec == CHAR &&
623		       (t == CHAR || t == UCHAR || t == SCHAR)) ||
624		      (strg->st_tspec == WCHAR && t == WCHAR))) {
625			return (0);
626		}
627		/*
628		 * If the array is already partly initialized, we are
629		 * wrong here.
630		 */
631		if (istk->i_cnt != istk->i_type->t_dim)
632			return (0);
633	} else {
634		return (0);
635	}
636
637	/* Get length without trailing NUL character. */
638	len = strg->st_len;
639
640	if (istk->i_nolimit) {
641		istk->i_nolimit = 0;
642		istk->i_type->t_dim = len + 1;
643		/* from now complete type */
644		setcompl(istk->i_type, 0);
645	} else {
646		if (istk->i_type->t_dim < len) {
647			/* non-null byte ignored in string initializer */
648			warning(187);
649		}
650	}
651
652	/* In every case the array is initialized completely. */
653	istk->i_cnt = 0;
654
655	return (1);
656}
657