|
|
1.1 ! root 1: /* ! 2: * n0/stat.c ! 3: * C compiler. ! 4: * Statement compilation. ! 5: * The routines in this file compile C statements. ! 6: * This file also contains a number of small routines that are ! 7: * only used by the statement compilation code. ! 8: * This is the new VAX/VMS base version. ! 9: */ ! 10: ! 11: #ifdef vax ! 12: #include "INC$LIB:cc0.h" ! 13: #else ! 14: #include "cc0.h" ! 15: #endif ! 16: ! 17: /* ! 18: * Compile one statement. ! 19: * On entry, 's' contains the first symbol of the new statement. ! 20: * On exit, 's' contains the first token beyond the end of the statement. ! 21: */ ! 22: statement() ! 23: { ! 24: register TREE *tp; ! 25: register int lab1, lab2; ! 26: TREE *lp, *rp; ! 27: TREE *itree, *ctree, *stree; ! 28: SBLOCK *ssbp; ! 29: int i, sclab, sblab, tt; ! 30: ival_t v; ! 31: ! 32: loop: ! 33: dbstat(s, line); ! 34: switch (s) { ! 35: ! 36: case EOF: ! 37: cerror("unexpected end of file"); ! 38: break; ! 39: ! 40: case SEMI: ! 41: lex(); ! 42: break; ! 43: ! 44: case LBRACE: ! 45: lex(); ! 46: savelocals(); ! 47: ++llex; ! 48: locals(); ! 49: putautos(); ! 50: while (s!=EOF && s!=RBRACE) ! 51: statement(); ! 52: mustbe(RBRACE); ! 53: --llex; ! 54: downlex(); ! 55: dbstat(RBRACE, line); ! 56: restlocals(); ! 57: break; ! 58: ! 59: case BREAK: ! 60: lex(); ! 61: if (cblab == 0) ! 62: cerror("break not in a loop"); ! 63: jump(cblab); ! 64: mustbe(SEMI); ! 65: break; ! 66: ! 67: case CONTINUE: ! 68: lex(); ! 69: if (cclab == 0) ! 70: cerror("continue not in a loop"); ! 71: jump(cclab); ! 72: mustbe(SEMI); ! 73: break; ! 74: ! 75: case CASE: ! 76: lex(); ! 77: newtree(sizeof(TREE)); ! 78: ++incase; ! 79: v = iconexpr(); ! 80: --incase; ! 81: mustbe(COLON); ! 82: if (sbp == NULL) ! 83: cerror("case not in a switch"); ! 84: else ! 85: newcase(v); ! 86: goto loop; ! 87: ! 88: case DEFAULT: ! 89: lex(); ! 90: mustbe(COLON); ! 91: if (sbp == NULL) ! 92: cerror("default label not in a switch"); ! 93: else { ! 94: if (sbp->sb_dlab != 0) ! 95: cerror("only one default label allowed"); ! 96: sbp->sb_dlab = here(); ! 97: } ! 98: goto loop; ! 99: ! 100: case GOTO: ! 101: lex(); ! 102: if (s != ID) { ! 103: cerror("missing label name in goto"); ! 104: skip(); ! 105: } else { ! 106: dogoto(); ! 107: lex(); ! 108: mustbe(SEMI); ! 109: } ! 110: break; ! 111: ! 112: case IF: ! 113: lex(); ! 114: tp = pexpr(); ! 115: truth(tp); ! 116: tput(FEXPR, lab1=newlab(), tp); ! 117: statement(); ! 118: if (s == ELSE) { ! 119: lab2 = newlab(); ! 120: jump(lab2); ! 121: label(lab1); ! 122: lex(); ! 123: statement(); ! 124: label(lab2); ! 125: break; ! 126: } ! 127: label(lab1); ! 128: break; ! 129: ! 130: case DO: ! 131: sblab = cblab; ! 132: sclab = cclab; ! 133: cblab = newlab(); ! 134: cclab = newlab(); ! 135: lab1 = here(); ! 136: lex(); ! 137: statement(); ! 138: label(cclab); ! 139: dbstat(s, line); ! 140: mustbe(WHILE); ! 141: tp = pexpr(); ! 142: truth(tp); ! 143: tput(TEXPR, lab1, tp); ! 144: label(cblab); ! 145: mustbe(SEMI); ! 146: cclab = sclab; ! 147: cblab = sblab; ! 148: break; ! 149: ! 150: case WHILE: ! 151: sblab = cblab; ! 152: sclab = cclab; ! 153: cblab = newlab(); ! 154: cclab = here(); ! 155: lex(); ! 156: tp = pexpr(); ! 157: truth(tp); ! 158: tput(FEXPR, cblab, tp); ! 159: statement(); ! 160: jump(cclab); ! 161: label(cblab); ! 162: cclab = sclab; ! 163: cblab = sblab; ! 164: break; ! 165: ! 166: case SWITCH: ! 167: lex(); ! 168: tp = pexpr(); ! 169: tt = tltype(tp); ! 170: if ((tt == T_LONG && mytypes[T_INT] == mytypes[T_LONG]) ! 171: || (tt == T_ULONG && mytypes[T_UINT] == mytypes[T_ULONG])) { ! 172: if (isvariant(VSBOOK)) ! 173: cstrict("switch expression is long"); ! 174: } else if (tt > T_UINT) ! 175: cerror("switch of non integer"); ! 176: if (tt != T_INT) { ! 177: rp = NULL; ! 178: if (tt == T_PTR) ! 179: rp = bzcon(psize(tp)); ! 180: tp = bconvert(tp, T_INT, NULL, NULL, rp); ! 181: } ! 182: tput(SEXPR, 0, tp); ! 183: ssbp = sbp; ! 184: sbp = (SBLOCK *) new(sizeof(SBLOCK)); ! 185: sbp->sb_dlab = 0; ! 186: sbp->sb_ncase = 0; ! 187: sblab = cblab; ! 188: cblab = newlab(); ! 189: statement(); ! 190: jump(cblab); ! 191: if (sbp->sb_dlab==0 && sbp->sb_ncase==0) ! 192: cwarn("empty switch"); ! 193: if (sbp->sb_dlab == 0) ! 194: sbp->sb_dlab = cblab; ! 195: bput(SBODY); ! 196: iput((ival_t) sbp->sb_dlab); ! 197: iput((ival_t) sbp->sb_ncase); ! 198: for (i=0; i<sbp->sb_ncase; ++i) { ! 199: iput((ival_t) sbp->sb_case[i].sc_val); ! 200: iput((ival_t) sbp->sb_case[i].sc_lab); ! 201: } ! 202: label(cblab); ! 203: cblab = sblab; ! 204: free((char *) sbp); ! 205: sbp = ssbp; ! 206: break; ! 207: ! 208: case FOR: ! 209: lex(); ! 210: mustbe(LPAREN); ! 211: newtree(sizeof(TREE)); ! 212: itree = NULL; ! 213: if (s != SEMI) ! 214: itree = expr(); ! 215: mustbe(SEMI); ! 216: ctree = NULL; ! 217: if (s != SEMI) { ! 218: ctree = expr(); ! 219: truth(ctree); ! 220: } ! 221: mustbe(SEMI); ! 222: stree = NULL; ! 223: if (s != RPAREN) ! 224: stree = expr(); ! 225: mustbe(RPAREN); ! 226: sblab = cblab; ! 227: sclab = cclab; ! 228: cblab = newlab(); ! 229: cclab = newlab(); ! 230: if (itree != NULL) { ! 231: tput(EEXPR, 0, itree); ! 232: } ! 233: if (stree != NULL) ! 234: jump(lab1 = newlab()); ! 235: label(cclab); ! 236: if (stree != NULL) { ! 237: tput(EEXPR, 0, stree); ! 238: label(lab1); ! 239: } ! 240: if (ctree != NULL) { ! 241: tput(FEXPR, cblab, ctree); ! 242: } ! 243: statement(); ! 244: jump(cclab); ! 245: label(cblab); ! 246: cclab = sclab; ! 247: cblab = sblab; ! 248: break; ! 249: ! 250: case RETURN: ! 251: lex(); ! 252: if (s != SEMI) { ! 253: newtree(sizeof(TREE)); ! 254: tp = expr(); ! 255: if (cfsym==NULL) { ! 256: cerror("return(e) not inside valid function"); ! 257: mustbe(SEMI); ! 258: break; ! 259: } ! 260: lp = talloc(); ! 261: lp->t_op = CONVERT; ! 262: lp->t_type = cfsym->s_type; ! 263: lp->t_dp = cfsym->s_dp->d_dp; /* Skip D_FUNC */ ! 264: lp->t_ip = cfsym->s_ip; ! 265: if (lp->t_dp==NULL && lp->t_type==T_VOID) { ! 266: cerror("return(e) illegal in void function"); ! 267: mustbe(SEMI); ! 268: break; ! 269: } ! 270: if ((tltype(lp)==T_STRUCT || tltype(tp)==T_STRUCT) ! 271: && (lp->t_type!=tp->t_type||lp->t_dp!=tp->t_dp||lp->t_ip!=tp->t_ip)) { ! 272: cerror("return type/function type mismatch"); ! 273: mustbe(SEMI); ! 274: break; ! 275: } ! 276: if (bitcompat(tltype(lp), tltype(tp))) ! 277: adjust(tp, lp->t_type, lp->t_dp, lp->t_ip); ! 278: else { ! 279: lp->t_lp = tp; ! 280: tp = lp; ! 281: } ! 282: tput(REXPR, 0, tp); ! 283: } ! 284: jump(cflab); ! 285: mustbe(SEMI); ! 286: break; ! 287: ! 288: case ID: ! 289: if (spnextis(':')) { ! 290: dolabel(); ! 291: lex(); ! 292: lex(); ! 293: goto loop; ! 294: } ! 295: ! 296: default: ! 297: newtree(sizeof(TREE)); ! 298: tp = expr(); ! 299: tput(EEXPR, 0, tp); ! 300: mustbe(SEMI); ! 301: } ! 302: } ! 303: ! 304: /* ! 305: * Check if the given tree can be used in a truth value context. ! 306: * Put out the appropriate diagnostics. ! 307: * What does this have to do with stat()? ! 308: */ ! 309: truth(tp) ! 310: TREE *tp; ! 311: { ! 312: register int tt, op; ! 313: ! 314: tt = tltype(tp); ! 315: op = tp->t_op; ! 316: if (tt>=T_STRUCT && tt<=T_FUNION) ! 317: cerror("structure or union used in truth context"); ! 318: if (incpp) ! 319: return; ! 320: if (isvariant(VSRTVC)) { ! 321: if ((tt>=T_PTR && tt<=T_DOUBLE) ! 322: || (op==EQ && tp->t_lp->t_type==T_DOUBLE)) ! 323: cstrict("risky type in truth context"); ! 324: } ! 325: if (isvariant(VSCCON)) { ! 326: /* Catch typing error "if (i = 1) ..." for "if (i == 1)...". */ ! 327: while (op == ASSIGN) { ! 328: tp = tp->t_rp; ! 329: op = tp->t_op; ! 330: } ! 331: if (op==ICON || op==LCON || op==DCON) ! 332: cstrict("constant used in truth context"); ! 333: } ! 334: } ! 335: ! 336: /* ! 337: * Read an expression enclosed in parentheses. ! 338: * Used to read the control expressions in 'if', 'do', 'while' and 'switch'. ! 339: */ ! 340: TREE * ! 341: pexpr() ! 342: { ! 343: register TREE *tp; ! 344: ! 345: mustbe(LPAREN); ! 346: newtree(sizeof(TREE)); ! 347: tp = expr(); ! 348: mustbe(RPAREN); ! 349: return (tp); ! 350: } ! 351: ! 352: /* ! 353: * Labels. ! 354: */ ! 355: dolabel() ! 356: { ! 357: register SYM *sp; ! 358: register int c; ! 359: ! 360: sp = deflookup(SL_LAB, 2); ! 361: c = sp->s_class; ! 362: if (c==C_NONE || c==C_FREF) { ! 363: if (c == C_NONE) ! 364: sp->s_value = newlab(); ! 365: sp->s_class = C_LAB; ! 366: sp->s_dline = line; ! 367: label(sp->s_value); ! 368: dblabel(sp); ! 369: } else ! 370: cerror("illegal label \"%s\"", sp->s_id); ! 371: } ! 372: ! 373: /* ! 374: * The dreaded 'goto' statement. ! 375: */ ! 376: dogoto() ! 377: { ! 378: register SYM *sp; ! 379: register int c; ! 380: ! 381: sp = deflookup(SL_LAB, 2); ! 382: c = sp->s_class; ! 383: if (c == C_NONE) { ! 384: sp->s_class = C_FREF; ! 385: sp->s_value = newlab(); ! 386: } else if (c!=C_LAB && c!=C_FREF) ! 387: cerror("identifier \"%s\" is not a label", sp->s_id); ! 388: jump(sp->s_value); ! 389: sp->s_flag |= S_USED; ! 390: } ! 391: ! 392: /* ! 393: * Append a new case to the current switch, ! 394: * adjusting the size of the switch block if necessary and possible. ! 395: */ ! 396: newcase(v) ! 397: ival_t v; ! 398: { ! 399: SBLOCK *ssbp; ! 400: register SCASE *scp, *ocp; ! 401: register int i; ! 402: ! 403: i = sbp->sb_ncase; ! 404: scp = sbp->sb_case; ! 405: while (--i >= 0) { ! 406: if (scp->sc_val == v) { ! 407: cerror("duplicated case constant"); ! 408: return; ! 409: } else ! 410: scp += 1; ! 411: } ! 412: i = sbp->sb_ncase; ! 413: scp = &sbp->sb_case[i]; ! 414: if ((i % 32) == 0) { ! 415: ssbp = sbp; ! 416: sbp = new(sizeof(SBLOCK) + (i+32) * sizeof(SCASE)); ! 417: sbp->sb_ncase = ssbp->sb_ncase; ! 418: sbp->sb_dlab = ssbp->sb_dlab; ! 419: scp = sbp->sb_case; ! 420: ocp = ssbp->sb_case; ! 421: while (--i >= 0) { ! 422: scp->sc_val = ocp->sc_val; ! 423: scp->sc_lab = ocp->sc_lab; ! 424: scp += 1; ! 425: ocp += 1; ! 426: } ! 427: free((char *) ssbp); ! 428: scp = &sbp->sb_case[sbp->sb_ncase]; ! 429: } ! 430: scp->sc_val = v; ! 431: scp->sc_lab = here(); ! 432: sbp->sb_ncase += 1; ! 433: } ! 434: ! 435: /* end of n0/stat.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.