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