Synchronise with NetBSD: ANSIfy.
[dragonfly.git] / usr.bin / xlint / lint1 / init.c
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.
32  *
33  * $NetBSD: init.c,v 1.4 1995/10/02 17:21:37 jpo Exp $
34  * $DragonFly: src/usr.bin/xlint/lint1/init.c,v 1.5 2004/07/07 12:13:26 asmodai Exp $
35  */
36
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  */
46 int     initerr;
47
48 /* Pointer to the symbol which is to be initialized. */
49 sym_t   *initsym;
50
51 /* Points to the top element of the initialisation stack. */
52 istk_t  *initstk;
53
54
55 static  void    popi2(void);
56 static  void    popinit(int);
57 static  void    pushinit(void);
58 static  void    testinit(void);
59 static  void    nextinit(int);
60 static  int     strginit(tnode_t *);
61
62
63 /*
64  * Initialize the initialisation stack by putting an entry for the variable
65  * which is to be initialized on it.
66  */
67 void
68 prepinit(void)
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
94 static void
95 popi2(void)
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
125 static void
126 popinit(int brace)
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
150 static void
151 pushinit(void)
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
235 static void
236 testinit(void)
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
266 static void
267 nextinit(int brace)
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
302 void
303 initlbr(void)
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
324 void
325 initrbr(void)
326 {
327         if (initerr)
328                 return;
329
330         popinit(1);
331 }
332
333 void
334 mkinit(tnode_t *tn)
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
444 static int
445 strginit(tnode_t *tn)
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 }