// File: /workspace/github_c_makefile_star2_O2/takoeight0821[P]hoc_nyan/src/parse.c
// Function: funcdef
static Function *funcdef(bool is_static) {
  Token *back = peek(0);
  Type *ret_type = type_specifier();

  while (match("*")) {
    ret_type = ptr_to(ret_type);
  }

  char *name = peek(0)->ident;

  if (peek_tag(0) != TIDENT) {
    if (match(";")) {
      // type definition
      return NULL;
    }
    parse_error("function name or ;", peek(0));
  } else {
    consume(); // TIDENT
  }

  if (!match("(")) {
    tokens = back;
    global_var();
    return NULL;
  }

  Vector *params = new_vec();
  LVar *tmp = local_env; // start scope
  bool has_va_arg = false;
  local_size = 0;

  if (eq_reserved(peek(0), "void") && eq_reserved(peek(1), ")")) {
    consume();
    consume();
  } else {
    for (;;) {
      if (is_typename(peek(0))) {
        Node *param_decl = declarator(type_specifier()); // NDEFVAR
        add_lvar(param_decl->token, param_decl->name, param_decl->type);
        Node *param = find_var(param_decl->token, param_decl->name);

        vec_push(params, param);
        if (match(")"))
          break;
        if (!match(",")) {
          parse_error(", or )", peek(0));
        }
      } else if (match("...") && match(")")) {
        has_va_arg = true;
        break;
      } else if (match(")")) {
        break;
      } else {
        parse_error(")", peek(0));
      }
    }
  }

  if (match(";")) {
    local_env = tmp; // end scope

    Function *func = calloc(1, sizeof(Function));
    func->name = name;
    func->ret_type = ret_type;
    func->body = NULL;
    func->params = params;
    func->local_size = local_size;
    func->is_static = is_static;
    func->has_va_arg = has_va_arg;
    return func;
  }

  Node *body = statement();

  local_env = tmp; // end scope

  Function *func = calloc(1, sizeof(Function));
  func->name = name;
  func->ret_type = ret_type;
  func->body = body;
  func->params = params;
  func->local_size = local_size;
  func->is_static = is_static;
  func->has_va_arg = has_va_arg;

  return func;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %edi, %ebx
movq 0xa694(%rip), %r12      # 0x12158
callq 0x7db4
movq %rax, %r14
leaq 0x59fc(%rip), %r15      # 0xd4cf
movq %r15, %rdi
callq 0x7967
testq %rax, %rax
je 0x7aed
movq %r14, %rdi
callq 0x76a2
movq %rax, %r14
jmp 0x7ad3
movq 0xa664(%rip), %rax      # 0x12158
cmpl $0x2, 0x8(%rax)
jne 0x7c19
movq 0x10(%rax), %r13
movq (%rax), %rax
movq %rax, 0xa64c(%rip)      # 0x12158
leaq 0x5d3f(%rip), %rdi      # 0xd852
callq 0x7967
testq %rax, %rax
je 0x7c3d
xorl %eax, %eax
callq 0x229c
movq %rax, %r15
movq 0xa64e(%rip), %rbp      # 0x12180
andq $0x0, 0xa656(%rip)      # 0x12190
movq 0xa617(%rip), %rdi      # 0x12158
leaq 0x56b6(%rip), %rsi      # 0xd1fe
callq 0xab1d
testb %al, %al
movl %ebx, 0x4(%rsp)
je 0x7b95
movq 0xa5fc(%rip), %rax      # 0x12158
movq (%rax), %rdi
leaq 0x578c(%rip), %rsi      # 0xd2f2
callq 0xab1d
testb %al, %al
je 0x7b95
movq %r13, %rbx
movq %rbp, %r13
movq 0xa5dc(%rip), %rax      # 0x12158
movq (%rax), %rax
movq %rax, 0xa5d2(%rip)      # 0x12158
movq (%rax), %rax
movq %rax, 0xa5c8(%rip)      # 0x12158
jmp 0x7ca5
movq 0xa5bc(%rip), %rdi      # 0x12158
callq 0x876f
testl %eax, %eax
je 0x7c50
callq 0x7db4
movq %rax, %rdi
callq 0x80e4
movq %rax, %r12
movq 0x10(%rax), %rsi
movq 0x40(%rax), %rdi
callq 0x8ec8
movq 0x8(%r12), %rdi
movq 0x40(%r12), %rsi
callq 0x8d93
movq %r15, %rdi
movq %rax, %rsi
callq 0x22c6
leaq 0x570b(%rip), %rdi      # 0xd2f2
callq 0x7967
testq %rax, %rax
jne 0x7c9f
leaq 0x4452(%rip), %rdi      # 0xc04e
callq 0x7967
testq %rax, %rax
jne 0x7b95
movq 0xa54b(%rip), %rsi      # 0x12158
leaq 0x56d9(%rip), %rdi      # 0xd2ed
callq 0x7d21
leaq 0x5729(%rip), %rdi      # 0xd349
callq 0x7967
testq %rax, %rax
jne 0x7c49
movq 0xa527(%rip), %rsi      # 0x12158
leaq 0x56a2(%rip), %rdi      # 0xd2da
callq 0x7d21
movq %r12, 0xa514(%rip)      # 0x12158
callq 0x799c
xorl %eax, %eax
jmp 0x7d12
movq %r13, %rbx
movq %rbp, %r13
leaq 0x5697(%rip), %rdi      # 0xd2f4
callq 0x7967
testq %rax, %rax
je 0x7c7b
leaq 0x5684(%rip), %rdi      # 0xd2f2
callq 0x7967
movb $0x1, %bpl
testq %rax, %rax
jne 0x7ca7
leaq 0x5670(%rip), %rdi      # 0xd2f2
callq 0x7967
testq %rax, %rax
jne 0x7ca5
movq 0xa4c5(%rip), %rsi      # 0x12158
leaq 0x5658(%rip), %rdi      # 0xd2f2
callq 0x7d21
movq %r13, %rbx
movq %rbp, %r13
xorl %ebp, %ebp
leaq 0x569b(%rip), %rdi      # 0xd349
callq 0x7967
testq %rax, %rax
je 0x7cd3
movq %r13, 0xa4c1(%rip)      # 0x12180
pushq $0x1
popq %rdi
pushq $0x30
popq %rsi
callq 0x20f0
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
jmp 0x7cf8
callq 0x8f1a
movq %rax, %r12
movq %r13, 0xa49e(%rip)      # 0x12180
pushq $0x1
popq %rdi
pushq $0x30
popq %rsi
callq 0x20f0
movq %rbx, (%rax)
movq %r14, 0x8(%rax)
movq %r12, 0x10(%rax)
movq %r15, 0x18(%rax)
movq 0xa48d(%rip), %rcx      # 0x12190
movq %rcx, 0x20(%rax)
movl 0x4(%rsp), %ecx
movb %cl, 0x28(%rax)
movb %bpl, 0x29(%rax)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq