// File: /workspace/github_c_makefile_star2_O2/ShinyaKato[P]skcc/preprocess.c
// Function: scan_macro
struct pp_list *scan_macro(struct preprocessor *pp, struct pp_list *list) {
  struct pp_list *result = allocate_pp_list();

  for(struct pp_node *node = list->head; node != NULL; node = node->next) {
    struct macro_entry *macro = search_macro_table(node->token->text->head);

    // object-like macro invocation
    if(check_object_macro_invocation(pp, node)) {
      struct macro_entry *macro = search_macro_table(node->token->text->head);
      struct pp_list *list = object_macro_invocation(pp, macro);
      concat_pp_list(result, list);
    }

    // function-like macro invocation
    else if(check_function_macro_invocation(pp, node)) {
      struct macro_entry *macro = search_macro_table(node->token->text->head);
      struct pp_list *args[MACRO_PARAMS_LIMIT];
      int args_count = 0;
      int level = 0;
      int valid = 0;

      node = node->next;
      if(node->token->type == PP_NEW_LINE || node->token->type == PP_SPACE) {
        node = node->next;
      }
      node = node->next;

      if(node != NULL && (node->token->type == PP_NEW_LINE || node->token->type == PP_SPACE)) {
        node = node->next;
      }

      // parse arguments
      if(node != NULL && node->token->type == PP_RPAREN) {
        valid = 1;
      } else if(node != NULL) {
        args[args_count] = allocate_pp_list();
        if(macro->parameter_size > 0) {
          for(; node != NULL; node = node->next) {
            struct pp_token *token = node->token;
            if(token->type == PP_LPAREN) {
              append_pp_list(args[args_count], token);
              level++;
            } else if(token->type == PP_RPAREN) {
              if(level == 0) {
                args_count++;
                valid = 1;
                break;
              }
              append_pp_list(args[args_count], token);
              level--;
            } else if(level == 0 && token->type == PP_COMMA) {
              args_count++;
              args[args_count] = allocate_pp_list();
              if(args_count == macro->parameter_size) {
                if(macro->parameter_ellipsis && !valid) {
                  node = node->next;
                  break;
                } else {
                  error("too many arguments.\n");
                }
                break;
              }
            } else {
              append_pp_list(args[args_count], node->token);
            }
          }
        }
        if(macro->parameter_ellipsis && !valid) {
          for(; node != NULL; node = node->next) {
            if(node->token->type == PP_RPAREN) {
              break;
            }
            append_pp_list(args[args_count], node->token);
          }
          args_count++;
          valid = 1;
        }
      }

      if(!valid) {
        error("macro arguments list is not terminated.\n");
      }

      for(int i = 0; i < args_count; i++) {
        if(args[i]->head == NULL) {
          continue;
        }
        if(args[i]->head->token->type == PP_NEW_LINE || args[i]->head->token->type == PP_SPACE) {
          args[i]->head = args[i]->head->next;
        }
        if(args[i]->head != NULL) {
          struct pp_node **arg_node = &(args[i]->head);
          for(; (*arg_node)->next != NULL; arg_node = &((*arg_node)->next));
          if((*arg_node)->token->type == PP_NEW_LINE || (*arg_node)->token->type == PP_SPACE) {
            *arg_node = NULL;
          }
        }
      }

      struct pp_list *list = function_macro_invocation(pp, macro, args, args_count);
      concat_pp_list(result, list);
    }

    // not replaced
    else {
      append_pp_list(result, node->token);
    }
  }

  return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x408, %rsp            # imm = 0x408
movq %rsi, %rbp
movq %rdi, %r13
callq 0x325c
movq %rax, %r14
leaq 0x385b(%rip), %rbx      # 0x6f10
movq %r13, 0x8(%rsp)
movq (%rbp), %rbp
testq %rbp, %rbp
je 0x392e
movq (%rbp), %r15
movq 0x10(%r15), %rax
movq (%rax), %rdi
callq 0x357e
movq %rax, %r12
movq %rbp, %rsi
callq 0x35e8
testl %eax, %eax
je 0x36f6
movq %r13, %rdi
movq %r12, %rsi
callq 0x3943
jmp 0x38d6
movq %rbp, %rsi
callq 0x3621
testl %eax, %eax
je 0x37f4
movq 0x8(%rbp), %rax
movq (%rax), %rcx
movl (%rcx), %ecx
addl $-0x3b, %ecx
cmpl $0x1, %ecx
ja 0x371b
movq 0x8(%rax), %rax
movq 0x8(%rax), %rbp
testq %rbp, %rbp
je 0x3804
movq (%rbp), %rax
movl (%rax), %eax
leal -0x3b(%rax), %ecx
cmpl $0x1, %ecx
ja 0x3749
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
je 0x3804
movq (%rbp), %rax
movl (%rax), %eax
xorl %r15d, %r15d
cmpl $0x8, %eax
je 0x3861
callq 0x325c
movq %rax, 0x10(%rsp)
cmpl $0x0, 0x10(%r12)
jle 0x3821
xorl %r15d, %r15d
xorl %r13d, %r13d
movq (%rbp), %rsi
movl (%rsi), %eax
movslq %r15d, %rbx
cmpl $0x8, %eax
je 0x3793
cmpl $0x7, %eax
jne 0x37ab
movq 0x10(%rsp,%rbx,8), %rdi
callq 0x32b4
incl %r13d
jmp 0x37db
testl %r13d, %r13d
je 0x3852
movq 0x10(%rsp,%rbx,8), %rdi
callq 0x32b4
decl %r13d
jmp 0x37db
testl %r13d, %r13d
jne 0x37d1
cmpl $0xd, %eax
jne 0x37d1
incl %r15d
callq 0x325c
movq %rax, 0x18(%rsp,%rbx,8)
xorl %r13d, %r13d
cmpl 0x10(%r12), %r15d
jne 0x37db
jmp 0x38f6
movq 0x10(%rsp,%rbx,8), %rdi
callq 0x32b4
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
jne 0x3771
xorl %ebp, %ebp
movq 0x8(%rsp), %r13
leaq 0x371e(%rip), %rbx      # 0x6f10
jmp 0x3824
movq %r14, %rdi
movq %r15, %rsi
callq 0x32b4
jmp 0x38ed
xorl %ebp, %ebp
xorl %r15d, %r15d
movq %rbx, %rdi
movl $0x108, %esi            # imm = 0x108
leaq 0x373b(%rip), %rdx      # 0x6f53
xorl %eax, %eax
callq 0x1252
jmp 0x3861
xorl %r15d, %r15d
cmpl $0x0, 0x14(%r12)
je 0x3809
movslq %r15d, %rbx
testq %rbp, %rbp
je 0x384d
movq (%rbp), %rsi
cmpl $0x8, (%rsi)
je 0x384d
movq 0x10(%rsp,%rbx,8), %rdi
callq 0x32b4
movq 0x8(%rbp), %rbp
jmp 0x382f
incl %r15d
jmp 0x385a
incl %r15d
movq 0x8(%rsp), %r13
leaq 0x36af(%rip), %rbx      # 0x6f10
testl %r15d, %r15d
movl $0x0, %eax
cmovgl %r15d, %eax
xorl %ecx, %ecx
cmpq %rax, %rcx
je 0x38c3
movq 0x10(%rsp,%rcx,8), %rdx
movq (%rdx), %rsi
testq %rsi, %rsi
je 0x38be
movq (%rsi), %rdi
movl (%rdi), %edi
addl $-0x3b, %edi
cmpl $0x1, %edi
ja 0x389a
movq 0x8(%rsi), %rsi
movq %rsi, (%rdx)
testq %rsi, %rsi
je 0x38be
movq %rdx, %rdi
movq %rsi, %r8
leaq 0x8(%rsi), %rdx
movq 0x8(%rsi), %rsi
testq %rsi, %rsi
jne 0x389a
movq (%r8), %rdx
movl (%rdx), %edx
addl $-0x3b, %edx
cmpl $0x1, %edx
ja 0x38be
andq $0x0, (%rdi)
incq %rcx
jmp 0x386f
movq %r13, %rdi
movq %r12, %rsi
leaq 0x10(%rsp), %rdx
movl %r15d, %ecx
callq 0x39ab
movq (%rax), %rcx
testq %rcx, %rcx
je 0x38ed
movq 0x8(%r14), %rdx
movq %rcx, (%rdx)
movq 0x8(%rax), %rax
movq %rax, 0x8(%r14)
addq $0x8, %rbp
jmp 0x36ba
cmpl $0x0, 0x14(%r12)
je 0x3907
movq 0x8(%rbp), %rbp
jmp 0x37e6
leaq 0x3602(%rip), %rbx      # 0x6f10
movq %rbx, %rdi
movl $0xf2, %esi
leaq 0x3621(%rip), %rdx      # 0x6f3e
xorl %eax, %eax
callq 0x1252
movq 0x8(%rsp), %r13
jmp 0x3824
movq %r14, %rax
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq