|
|
1.1 ! root 1: /* ! 2: * n0/init.c ! 3: * C compiler. ! 4: * Initializers. ! 5: * All storage classes. ! 6: */ ! 7: ! 8: #ifdef vax ! 9: #include "INC$LIB:cc0.h" ! 10: #else ! 11: #include "cc0.h" ! 12: #endif ! 13: ! 14: init(sp, dp, bo, flex) ! 15: register SYM *sp; ! 16: register DIM *dp; ! 17: sizeof_t bo; ! 18: int flex; ! 19: { ! 20: register int t; ! 21: DIM *ndp; ! 22: TREE *tp; ! 23: sizeof_t width, nbe, nel, ninit; ! 24: int brace, c, adj; ! 25: ! 26: t = sp->s_type; ! 27: width = sdsize(sp, dp); ! 28: ndp = dp; ! 29: if (dp!=NULL && dp->d_type==D_ARRAY) { ! 30: if (dp->d_bound != 0) ! 31: flex = 0; ! 32: ndp = dp->d_dp; ! 33: if (width==0 && !flex) ! 34: cerror("array row has 0 length"); ! 35: } else ! 36: flex = 0; ! 37: nel = 0; ! 38: nbe = sdsize(sp, ndp); ! 39: if (nbe != 0) ! 40: nel = width/nbe; ! 41: brace = 0; ! 42: if (s==LBRACE && (dp!=NULL || !istruct(t))) { ! 43: ++brace; ! 44: lex(); ! 45: } else if (s!=LBRACE && (dp!=NULL || istruct(t))) ! 46: notbook(); ! 47: ninit = 0; ! 48: while (s != RBRACE) { ! 49: if (ndp==NULL && istruct(t)) ! 50: sinit(sp, bo); ! 51: else if (ndp!=NULL && ndp->d_type==D_ARRAY) ! 52: init(sp, ndp, bo, 0); ! 53: else { ! 54: adj = 0; ! 55: if (s==STRING && t<T_INT && ndp==NULL) { ! 56: again: ! 57: instring = '"'; ! 58: while ((c = getmap('\"')) >= 0) { ! 59: newtree(sizeof(TREE)); ! 60: icollect(bicon((ival_t)c), bo, sp, ndp); ! 61: ++ninit; ! 62: ++bo; ! 63: } ! 64: instring = 0; ! 65: if (lex() == STRING) { ! 66: ++adj; ! 67: goto again; ! 68: } ! 69: if (adj) ! 70: notbook(); ! 71: if (!flex && ninit==nel) { ! 72: cwarn("string initializer not terminated by NUL"); ! 73: break; ! 74: } ! 75: newtree(sizeof(TREE)); ! 76: icollect(bicon((ival_t)0), bo, sp, ndp); ! 77: ++ninit; ! 78: break; ! 79: } ! 80: newtree(sizeof(TREE)); ! 81: ++ininit; ! 82: tp = expr(); ! 83: --ininit; ! 84: icollect(tp, bo, sp, ndp); ! 85: } ! 86: ++ninit; ! 87: bo += nbe; ! 88: if (s != COMMA) ! 89: break; ! 90: if (ninit>=nel && !flex) { ! 91: if (brace) { ! 92: lex(); ! 93: if (s == RBRACE) ! 94: cwarn("trailing ',' in initialization list"); ! 95: else { ! 96: cerror("too many initializers"); ! 97: iskip(); ! 98: } ! 99: } ! 100: break; ! 101: } ! 102: itrail(); ! 103: } ! 104: if (brace) ! 105: mustbe(RBRACE); ! 106: if (ninit < nel) { ! 107: c = sp->s_class; ! 108: if (c==C_GDEF || c==C_SIN || c==C_SEX) { ! 109: bput(BLOCK); ! 110: zput(nbe*(nel-ninit)); ! 111: } ! 112: } ! 113: if (ninit > nel) { ! 114: if (!flex) ! 115: cerror("too many initializers"); ! 116: if (dp != NULL) ! 117: dp->d_bound = ninit; ! 118: } ! 119: } ! 120: ! 121: /* ! 122: * Initialize a structure. ! 123: * Create a fake variable for each member; ! 124: * this is necessary for the call to build() in iassign() ! 125: * to do the correct things. ! 126: */ ! 127: sinit(sp, bo) SYM *sp; sizeof_t bo; ! 128: { ! 129: register SYM *mp; ! 130: register INFO *ip; ! 131: int n, brace, c, t, f, bfflag; ! 132: sizeof_t mo, lo; ! 133: SYM sym; ! 134: ! 135: c = sp->s_class; ! 136: t = sp->s_type; ! 137: if (t==T_UNION || t==T_FUNION) ! 138: cerror("cannot initialize unions"); ! 139: if (t==T_FSTRUCT || t==T_FUNION) ! 140: return; ! 141: ip = sp->s_ip; ! 142: sym.s_class = c; ! 143: sym.s_value = sp->s_value; ! 144: brace = 0; ! 145: if (s == LBRACE) { ! 146: ++brace; ! 147: lex(); ! 148: } ! 149: lo = n = f = 0; ! 150: while (s != RBRACE) { ! 151: bfflag = 0; ! 152: if (n >= ip->i_nsp) { ! 153: if (f == 0) { ! 154: cerror("too many structure initializers"); ! 155: ++f; ! 156: } ! 157: sym.s_type = T_INT; ! 158: sym.s_dp = sym.s_ip = NULL; ! 159: mo = 0; ! 160: } else { ! 161: mp = ip->i_sp[n++]; ! 162: sym.s_type = mp->s_type; ! 163: sym.s_dp = mp->s_dp; ! 164: sym.s_ip = mp->s_ip; ! 165: mo = mp->s_value; ! 166: if (!isauto(&sym) && lo!=mo) { ! 167: /* Output BLOCK item for padding. */ ! 168: bput(BLOCK); ! 169: zput(mo-lo); ! 170: lo = mo; ! 171: } ! 172: if (mp->s_width != 0) /* bitfield initializer */ ! 173: bfflag = bfinit(&sym, mp, ip, &n, bo+mo); ! 174: } ! 175: if (!bfflag) ! 176: init(&sym, sym.s_dp, bo+mo, 0); ! 177: lo += ssize(&sym); ! 178: if (bfflag != 2 && s != COMMA) ! 179: break; ! 180: if (n >= ip->i_nsp && !brace) ! 181: break; ! 182: if (bfflag != 2) ! 183: itrail(); /* skip COMMA, check for RBRACE */ ! 184: } ! 185: if (brace) ! 186: mustbe(RBRACE); ! 187: if (t==T_STRUCT && (c==C_GDEF || c==C_SIN || c==C_SEX)) { ! 188: if ((mo = ip->i_size-lo) > 0) { ! 189: bput(BLOCK); ! 190: zput(mo); ! 191: } ! 192: } ! 193: } ! 194: ! 195: /* ! 196: * Fetch the next symbol. ! 197: * The current symbol is a COMMA. ! 198: * If the new symbol is '}', the program has said ", }"; this is legal. ! 199: * If you pull the comments here, it becomes not quite so legal. ! 200: */ ! 201: static ! 202: itrail() ! 203: { ! 204: lex(); ! 205: if (s == RBRACE) ! 206: cwarn("trailing ',' in initialization list"); ! 207: } ! 208: ! 209: /* ! 210: * An initialization starting with '{' contains too many initializers. ! 211: * Skip initializers to the matching '}' or EOF. ! 212: */ ! 213: static ! 214: iskip() ! 215: { ! 216: register int braces; ! 217: ! 218: braces = 0; ! 219: for(;;) { ! 220: if (s == LBRACE) ! 221: ++braces; ! 222: else if (s == RBRACE) { ! 223: if (braces == 0) ! 224: return; ! 225: else ! 226: --braces; ! 227: } ! 228: else if (s == EOF) ! 229: return; ! 230: lex(); ! 231: } ! 232: } ! 233: ! 234: /* ! 235: * Return true if symbol "sp" is an automatic, ! 236: * in the sense that an assigment statement must be generated ! 237: * for the initialization item. ! 238: * Registers are considered auto. ! 239: */ ! 240: int ! 241: isauto(sp) register SYM *sp; ! 242: { ! 243: register int c; ! 244: ! 245: c = sp->s_class; ! 246: return (c==C_AUTO || c==C_PAUTO || c==C_REG); ! 247: } ! 248: ! 249: /* ! 250: * This routine actually performs the initialization. ! 251: * Either an build an assignment node and evaluate it for effect, ! 252: * or output an initialization tree. ! 253: */ ! 254: icollect(tp, bo, sp, dp) ! 255: register TREE *tp; ! 256: sizeof_t bo; ! 257: register SYM *sp; ! 258: DIM *dp; ! 259: { ! 260: register TREE *ip; ! 261: ! 262: if (isauto(sp)) { ! 263: iassign(sp, dp, bo, tp); ! 264: return; ! 265: } ! 266: ip = talloc(); ! 267: ip->t_op = INIT; ! 268: ip->t_type = sp->s_type; ! 269: ip->t_dp = dp; ! 270: ip->t_ip = sp->s_ip; ! 271: ip->t_lp = tp; ! 272: tput(IEXPR, 0, ip); ! 273: } ! 274: ! 275: /* ! 276: * Actually do the assignment for an automatic initialization thing. ! 277: */ ! 278: iassign(sp, dp, bo, tp) ! 279: register SYM *sp; ! 280: register TREE *tp; ! 281: sizeof_t bo; ! 282: DIM *dp; ! 283: { ! 284: register TREE *ip; ! 285: DIM *ssdp; ! 286: ! 287: ssdp = sp->s_dp; ! 288: sp->s_dp = dp; ! 289: ip = bid(sp); ! 290: sp->s_dp = ssdp; ! 291: if (sp->s_class != C_REG) ! 292: ip->t_offs += bo; ! 293: tp = build(ASSIGN, ip, tp); ! 294: tput(EEXPR, 0, tp); ! 295: } ! 296: ! 297: /* ! 298: * Collect one or more bitfield initializers. ! 299: * Each bitfield initializer must be an integer constant. ! 300: * Multiple bitfield initializers get output as a single initialization item: ! 301: * look for more initializers if the next ! 302: * structure member is another bitfield at the same offset (s_value). ! 303: * This may or may not need to look ahead to the next initializer, ! 304: * so it returns 1 if it has not read COMMA, 2 if it has read the COMMA. ! 305: */ ! 306: int ! 307: bfinit(sp, mp, ip, np, off) SYM *sp; register SYM *mp; INFO *ip; register int *np; sizeof_t off; ! 308: { ! 309: register unsigned long val, mval, mask; ! 310: int status; ! 311: ! 312: for (val = (unsigned long)0; ; ) { ! 313: ! 314: status = 1; /* COMMA not read yet */ ! 315: ! 316: /* Widen the initialized symbol base type if necessary. */ ! 317: if (ssize(sp) < ssize(mp)) ! 318: sp->s_type = mp->s_type; ! 319: ! 320: /* Grab the initializer value. */ ! 321: ++ininit; ! 322: mval = iconexpr(); ! 323: --ininit; ! 324: ! 325: /* Make sure the initializer is appropriate. */ ! 326: mask = (((unsigned long)1) << mp->s_width) - 1; ! 327: if ((mval & ~mask) != (unsigned long)0 && (mval & ~mask) != ~mask) ! 328: cwarn("bitfield initializer out of range"); ! 329: mval &= mask; /* mask value to bitfield width */ ! 330: ! 331: /* Build up the initializer in val. */ ! 332: val |= (mval << mp->s_offset); /* put value in the right place */ ! 333: ! 334: /* Check whether more bitfield initializers follow. */ ! 335: if (s != COMMA) /* no more initializers */ ! 336: break; ! 337: itrail(); /* skip COMMA */ ! 338: ++status; /* COMMA has been read */ ! 339: if (s == LBRACE || s == RBRACE /* { or }, no more bitfield inits */ ! 340: || *np >= ip->i_nsp /* no more members */ ! 341: || ip->i_sp[*np]->s_width==0 /* next not a bitfield */ ! 342: || ip->i_sp[*np]->s_value != mp->s_value) /* next at different value */ ! 343: break; ! 344: mp = ip->i_sp[(*np)++]; /* repeat for next bitfield */ ! 345: } ! 346: ! 347: /* ! 348: * Output the bitfield initializer built up in val. ! 349: * FIX_ME The initializer value collected in unsigned long 'val' ! 350: * is passed to icollect() as bicon((ival_t)val), ! 351: * this does not seem not quite right. ! 352: */ ! 353: icollect(bicon((ival_t)val), off, sp, NULL); ! 354: return status; ! 355: } ! 356: ! 357: /* end of n0/init.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.