ref: 1770b6f83b89855a47d3457c2a1c24127d033d43
dir: /stmt.c/
#include <stddef.h> #include <stdint.h> #include <stdio.h> #include "cc1.h" Symbol *curfun; extern Node *convert(Node *np, Type *tp1, char iscast); extern Node * iszero(Node *np); static void stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch); static Symbol * label(char *s) { if (!s) s = ""; else if (lookup(s, NS_LABEL)) error("label '%s' already defined", s); return install(s, NS_LABEL); } static void stmtexp(void) { if (accept(';')) return; emitexp(expr()); expect(';'); } static Node * condition(void) { Node *np; expect('('); np = iszero(expr()); expect(')'); return np; } static void While(Symbol *lswitch) { Symbol *begin= label(NULL), *cond = label(NULL), *end = label(NULL); Node *np; expect(WHILE); np = condition(); emitjump(cond, NULL); emitbloop(); emitlabel(begin); stmt(begin, end, lswitch); emitlabel(cond); emitjump(begin, np); emiteloop(); emitlabel(end); } static void For(Symbol *lswitch) { Symbol *begin= label(NULL), *cond = label(NULL), *end = label(NULL); Node *econd = NULL, *einc = NULL; expect(FOR); expect('('); stmtexp(); if (yytoken != ';') econd = expr(); expect(';'); if (yytoken != ')') einc = expr(); expect(')'); emitjump(cond, NULL); emitbloop(); emitlabel(begin); stmt(begin, end, lswitch); if (einc) emitexp(einc); emitlabel(cond); emitjump(begin, econd); emiteloop(); emitlabel(end); } static void Dowhile(Symbol *lswitch) { Symbol *begin= label(NULL), *end = label(NULL); expect(DO); emitbloop(); emitlabel(begin); stmt(begin, end, lswitch); expect(WHILE); emitjump(begin, condition()); emiteloop(); emitlabel(end); } static void Return(void) { Node *np; Type *tp = curfun->type->type; expect(RETURN); np = expr(); expect(';'); if (np->type != tp) { if (tp == voidtype) warn(1, "function returning void returns a value"); else if ((np = convert(np, tp, 0)) == NULL) error("incorrect type in return"); } emitret(tp); emitexp(np); } void compound(Symbol *lbreak, Symbol *lcont, Symbol *lswitch) { expect('{'); for (;;) { switch (yytoken) { case '}': next(); return; case TYPE: case SCLASS: case TQUALIFIER: decl(); break; default: stmt(lbreak, lcont, lswitch); } } } static void stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch) { switch (yytoken) { case '{': compound(lbreak, lcont, lswitch); break; case RETURN: Return(); break; case WHILE: While(lswitch); break; case FOR: For(lswitch); break; case DO: Dowhile(lswitch); break; default: stmtexp(); break; } }