summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xpp2cc.py50
-rw-r--r--tests/switch-case.c21
2 files changed, 50 insertions, 21 deletions
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
+}