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