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