// File: /workspace/github_c_makefile_star2_O3/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, %r15
movq %rdi, %r14
callq 0x33b4
movq %rax, %r13
movq (%r15), %rbp
testq %rbp, %rbp
je 0x3c7f
movq %r14, 0x8(%rsp)
movq %r13, (%rsp)
movq (%rbp), %rbx
movq 0x10(%rbx), %rax
movq (%rax), %rdi
callq 0x378b
movq %rax, %r12
movq %rbp, %rsi
callq 0x3833
testl %eax, %eax
je 0x393d
movq %r14, %rdi
movq %r12, %rsi
callq 0x3c94
jmp 0x3b8f
movq %rbp, %rsi
callq 0x386c
testl %eax, %eax
je 0x3ace
movq 0x8(%rbp), %rax
movq (%rax), %rcx
movl (%rcx), %ecx
addl $-0x3b, %ecx
cmpl $0x1, %ecx
ja 0x3962
movq 0x8(%rax), %rax
movq 0x8(%rax), %rbp
testq %rbp, %rbp
je 0x3afe
movq (%rbp), %rax
movl (%rax), %eax
leal -0x3b(%rax), %ecx
cmpl $0x1, %ecx
ja 0x3990
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
je 0x3afe
movq (%rbp), %rax
movl (%rax), %eax
xorl %r15d, %r15d
cmpl $0x8, %eax
je 0x3b7c
callq 0x33b4
movq %rax, 0x10(%rsp)
cmpl $0x0, 0x10(%r12)
jle 0x3bb8
xorl %r15d, %r15d
xorl %r13d, %r13d
movq (%rbp), %rbx
movl (%rbx), %eax
cmpl $0x8, %eax
je 0x3a03
cmpl $0x7, %eax
jne 0x3a44
movslq %r15d, %rax
movq 0x10(%rsp,%rax,8), %r14
movl $0x18, %edi
callq 0x10b0
movq %rbx, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r14), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r14)
incl %r13d
jmp 0x3aa5
testl %r13d, %r13d
je 0x3c1d
movslq %r15d, %rax
movq 0x10(%rsp,%rax,8), %r14
movl $0x18, %edi
callq 0x10b0
movq %rbx, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r14), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r14)
decl %r13d
jmp 0x3aa5
testl %r13d, %r13d
jne 0x3a72
cmpl $0xd, %eax
jne 0x3a72
leal 0x1(%r15), %ebx
callq 0x33b4
movslq %r15d, %rcx
movq %rax, 0x18(%rsp,%rcx,8)
xorl %r13d, %r13d
cmpl 0x10(%r12), %ebx
je 0x3c49
movl %ebx, %r15d
jmp 0x3aa5
movslq %r15d, %rax
movq 0x10(%rsp,%rax,8), %r14
movl $0x18, %edi
callq 0x10b0
movq %rbx, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r14), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r14)
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
jne 0x39b8
cmpl $0x0, 0x14(%r12)
movl $0x0, %ebp
movq 0x8(%rsp), %r14
movq (%rsp), %r13
jne 0x3c41
jmp 0x3b03
movl $0x18, %edi
callq 0x10b0
movq %rbx, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r13), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r13)
jmp 0x3ba6
xorl %ebp, %ebp
xorl %r15d, %r15d
leaq 0x4406(%rip), %rdi      # 0x7f10
movl $0x108, %esi            # imm = 0x108
leaq 0x443d(%rip), %rdx      # 0x7f53
xorl %eax, %eax
callq 0x142c
testl %r15d, %r15d
jle 0x3b7c
movl %r15d, %eax
xorl %ecx, %ecx
movq 0x10(%rsp,%rcx,8), %rdx
movq (%rdx), %rsi
testq %rsi, %rsi
je 0x3b74
movq (%rsi), %rdi
movl (%rdi), %edi
addl $-0x3b, %edi
cmpl $0x1, %edi
ja 0x3b4d
movq 0x8(%rsi), %rsi
movq %rsi, (%rdx)
testq %rsi, %rsi
je 0x3b74
movq %rdx, %rdi
movq %rsi, %r8
leaq 0x8(%rsi), %rdx
movq 0x8(%rsi), %rsi
testq %rsi, %rsi
jne 0x3b4d
movq (%r8), %rdx
movl (%rdx), %edx
addl $-0x3b, %edx
cmpl $0x1, %edx
ja 0x3b74
movq $0x0, (%rdi)
incq %rcx
cmpq %rax, %rcx
jne 0x3b27
movq %r14, %rdi
movq %r12, %rsi
leaq 0x10(%rsp), %rdx
movl %r15d, %ecx
callq 0x3d2c
movq (%rax), %rcx
testq %rcx, %rcx
je 0x3ba6
movq 0x8(%r13), %rdx
movq %rcx, (%rdx)
movq 0x8(%rax), %rax
movq %rax, 0x8(%r13)
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
jne 0x390e
jmp 0x3c7f
xorl %ebx, %ebx
cmpl $0x0, 0x14(%r12)
je 0x3c15
testq %rbp, %rbp
je 0x3c2e
movslq %ebx, %r15
movq (%rbp), %r13
cmpl $0x8, (%r13)
je 0x3c35
movq 0x10(%rsp,%r15,8), %r14
movl $0x18, %edi
callq 0x10b0
movq %r13, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r14), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r14)
movq 0x8(%rbp), %rbp
testq %rbp, %rbp
jne 0x3bca
movl %ebx, %r15d
xorl %ebp, %ebp
jmp 0x3c38
movl %ebx, %r15d
jmp 0x3b03
incl %r15d
movq 0x8(%rsp), %r14
movq (%rsp), %r13
jmp 0x3b1d
movl %ebx, %r15d
xorl %ebp, %ebp
jmp 0x3c41
movl %ebx, %r15d
movq 0x8(%rsp), %r14
movq (%rsp), %r13
incl %r15d
jmp 0x3b1d
cmpl $0x0, 0x14(%r12)
je 0x3c57
movq 0x8(%rbp), %rbp
jmp 0x3c71
leaq 0x42b2(%rip), %rdi      # 0x7f10
movl $0xf2, %esi
leaq 0x42d4(%rip), %rdx      # 0x7f3e
xorl %eax, %eax
callq 0x142c
movq 0x8(%rsp), %r14
movq (%rsp), %r13
jmp 0x3bba
movq %r13, %rax
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq