From 538cf03964d804c5da66385acd725b9449dfae09 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 9 Dec 2011 15:46:41 +0000 Subject: Support nested case/default labels --- pp2cc.py | 50 +++++++++++++++++++++++++++++--------------------- tests/switch-case.c | 21 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 tests/switch-case.c diff --git a/pp2cc.py b/pp2cc.py index ac00ffd..6205e94 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -1139,29 +1139,37 @@ class Parse(object): switch_end = self.uniqLbl("switchEnd") linked_node.setBreak(switch_end) lbl_default = None + for cn in stmt.block_items: linked_cn = LinkedNode(cn, linked_node) - if linked_cn.type == "Case": - lbl_case = self.uniqLbl("case") - try: - case_val = self.determineConstValue(LinkedNode(cn.expr, - linked_cn)) - except RuntimeError: - e = sys.exc_info()[1] - print "case label does not reduce to an integer constant" - print e - raise - - lines_cases.append(self.asm.binary_op("CMP", switch_reg, case_val)) - lines_cases.append(self.asm.branch_op("BEQ", lbl_case)) - lines_stmts.append(self.asm.noop(lbl_case)) - lines_stmts += self.parseStatement(cn.stmt, linked_cn) - elif linked_cn.type == "Default": - lbl_default = self.uniqLbl("default") - lines_stmts.append(self.asm.noop(lbl_default)) - lines_stmts += self.parseStatement(cn.stmt, linked_cn) - else: - lines_stmts += self.parseStatement(cn, linked_cn) + while linked_cn is not None: + cn = linked_cn.node + if linked_cn.type == "Case": + lbl_case = self.uniqLbl("case") + try: + case_val = self.determineConstValue(LinkedNode(cn.expr, + linked_cn)) + except RuntimeError: + e = sys.exc_info()[1] + print "case label does not reduce to an integer constant" + print e + raise + + lines_cases.append(self.asm.binary_op("CMP", switch_reg, case_val)) + lines_cases.append(self.asm.branch_op("BEQ", lbl_case)) + lines_stmts.append(self.asm.noop(lbl_case)) + linked_cn = LinkedNode(cn.stmt, linked_cn.parent) + elif linked_cn.type == "Default": + lbl_default = self.uniqLbl("default") + lines_stmts.append(self.asm.noop(lbl_default)) + linked_cn = LinkedNode(cn.stmt, linked_cn.parent) + if linked_cn.type in ("Case", "Default"): + # nested case/default labels like case 1: case 2: stmt; + pass + else: + # regular body + lines_stmts += self.parseStatement(linked_cn.node, linked_cn.parent) + linked_cn = None lines += lines_cases if lbl_default: lines.append(self.asm.branch_op("BRA", lbl_default)) diff --git a/tests/switch-case.c b/tests/switch-case.c new file mode 100644 index 0000000..03d9bdc --- /dev/null +++ b/tests/switch-case.c @@ -0,0 +1,21 @@ +int f(int n) { + switch (n) { + case 1: + case 2: + return 1; + case 3: + return 3; + case 4: + break; + default: + return 5; + } + return 4; +} + +int main() { + int a; + // 1 + 1 + 3 + 4 + 5 = 14 + a = f(1) + f(2) + f(3) + f(4) + f(5); + return a;// 14, 0xe +} -- cgit v1.2.1