// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/stmt.c
// Function: switch_statement
static struct ASTnode *switch_statement(void) {
  struct ASTnode *left, *body, *n, *c;
  struct ASTnode *casetree = NULL, *casetail;
  int inloop = 1, casecount = 0;
  int seendefault = 0;
  int ASTop, casevalue;

  // 跳过'switch'和'('
  scan(&Token);
  lparen();

  // 获得switch表达式, ')' 和 '{'
  left = binexpr(0);
  rparen();
  lbrace();

  // 保证是个整型
  if (!inttype(left->type))
    fatal("Switch expression is not of integer type");

  // 创建一个A_SWITCH节点,用上面的表达式作为孩子
  n = mkastunary(A_SWITCH, P_NONE, NULL, left, NULL, 0);

  // 解析case
  Switchlevel++;
  while (inloop) {
    switch (Token.token) {
      // 当遇到'}'跳出循环
      case T_RBRACE:
        if (casecount == 0)
          fatal("No cases in switch");
        inloop = 0;
        break;
      case T_CASE:
      case T_DEFAULT:
        // 保证不是在'default'后面
        if (seendefault)
          fatal("case or default after existing default");

        // 设置语法树操作,如果需要,扫描case值
        if (Token.token == T_DEFAULT) {
          ASTop = A_DEFAULT;
          seendefault = 1;
          scan(&Token);
        } else {
          ASTop = A_CASE;
          scan(&Token);
          left = binexpr(0);

          // 保证case的值是整型字面量
          if (left->op != A_INTLIT)
            fatal("Expecting integer literal for case value");
          casevalue = left->atu.a_intvalue;

          // 检查有没有相同的case值
          for (c = casetree; c != NULL; c = c->right)
            if (casevalue == c->atu.a_intvalue)
              fatal("Duplicate case value");
        }

        // 匹配':' 和增加case数量
        match(T_COLON, ":");
        casecount++;

        // 如果下个token是个T_CASE,代表当前的case将没有body,直接进入下个case
        // 如果不是,解析body
        if (Token.token == T_CASE)
          body = NULL;
        else
          body = compound_statement(1);

        // 创建一个子树,body作为它的孩子,然后把这个子树链接到casetree的尾部
        if (casetree == NULL) {
          casetree = casetail =
            mkastunary(ASTop, P_NONE, NULL, body, NULL, casevalue);
        } else {
          casetail->right =
            mkastunary(ASTop, P_NONE, NULL, body, NULL, casevalue);
          casetail = casetail->right;
        }
        break;
      default:
        fatals("Unexpected token in switch", Token.tokstr);
    }
  }
  Switchlevel--;

  // 把casetree加入到A_SWITCH节点,同时也把case数设进去
  n->atu.a_intvalue = casecount;
  n->right = casetree;
  rbrace();

  return (n);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq $0x0, -0x28(%rbp)
movl $0x1, -0x34(%rbp)
movl $0x0, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
leaq 0x89b4(%rip), %rdi      # 0x12530
callq 0x84c0
callq 0x8090
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x8(%rbp)
callq 0x80b0
callq 0x8050
movq -0x8(%rbp), %rax
movl 0x8(%rax), %edi
callq 0xb6e0
cmpl $0x0, %eax
jne 0x9bb8
leaq 0x425a(%rip), %rdi      # 0xde0d
callq 0x8110
movq -0x8(%rbp), %rcx
movl $0x31, %edi
xorl %r9d, %r9d
xorl %eax, %eax
movl %eax, %r8d
movl %r9d, %esi
movq %r8, %rdx
callq 0xada0
movq %rax, -0x18(%rbp)
leaq 0x8b89(%rip), %rax      # 0x12768
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8b7d(%rip), %rax      # 0x12768
movl %ecx, (%rax)
cmpl $0x0, -0x34(%rbp)
je 0x9da0
leaq 0x8932(%rip), %rax      # 0x12530
movl (%rax), %eax
movl %eax, -0x48(%rbp)
addl $-0x2f, %eax
subl $0x2, %eax
jb 0x9c39
jmp 0x9c0d
movl -0x48(%rbp), %eax
subl $0x38, %eax
jne 0x9d84
jmp 0x9c1b
cmpl $0x0, -0x38(%rbp)
jne 0x9c2d
leaq 0x420e(%rip), %rdi      # 0xde36
callq 0x8110
movl $0x0, -0x34(%rbp)
jmp 0x9d9b
cmpl $0x0, -0x3c(%rbp)
je 0x9c4b
leaq 0x4203(%rip), %rdi      # 0xde49
callq 0x8110
leaq 0x88de(%rip), %rax      # 0x12530
cmpl $0x30, (%rax)
jne 0x9c73
movl $0x33, -0x40(%rbp)
movl $0x1, -0x3c(%rbp)
leaq 0x88c4(%rip), %rdi      # 0x12530
callq 0x84c0
jmp 0x9ce8
movl $0x32, -0x40(%rbp)
leaq 0x88af(%rip), %rdi      # 0x12530
callq 0x84c0
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x1a, 0x4(%rax)
je 0x9ca7
leaq 0x41ce(%rip), %rdi      # 0xde70
callq 0x8110
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x9ce6
movl -0x44(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x9cd6
leaq 0x41c8(%rip), %rdi      # 0xde99
callq 0x8110
jmp 0x9cd8
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x9cb8
jmp 0x9ce8
movl $0x40, %edi
leaq 0x2891(%rip), %rsi      # 0xc585
callq 0x7f70
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
leaq 0x8827(%rip), %rax      # 0x12530
cmpl $0x2f, (%rax)
jne 0x9d18
movq $0x0, -0x10(%rbp)
jmp 0x9d26
movl $0x1, %edi
callq 0x9420
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x9d51
movl -0x40(%rbp), %edi
movq -0x10(%rbp), %rcx
movl -0x44(%rbp), %r9d
xorl %esi, %esi
xorl %eax, %eax
movl %eax, %r8d
movq %r8, %rdx
callq 0xada0
movq %rax, -0x30(%rbp)
movq %rax, -0x28(%rbp)
jmp 0x9d82
movl -0x40(%rbp), %edi
movq -0x10(%rbp), %rcx
movl -0x44(%rbp), %r9d
xorl %esi, %esi
xorl %eax, %eax
movl %eax, %r8d
movq %r8, %rdx
callq 0xada0
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x30(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x9d9b
leaq 0x87a5(%rip), %rax      # 0x12530
movq 0x8(%rax), %rsi
leaq 0x4118(%rip), %rdi      # 0xdeae
callq 0x7fc0
jmp 0x9bed
leaq 0x89c1(%rip), %rax      # 0x12768
movl (%rax), %ecx
addl $-0x1, %ecx
leaq 0x89b5(%rip), %rax      # 0x12768
movl %ecx, (%rax)
movl -0x38(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, (%rax)
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x30(%rax)
callq 0x8070
movq -0x18(%rbp), %rax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)