// File: /workspace/github_c_makefile_star2_O1/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 $0x418, %rsp            # imm = 0x418
movq %rsi, %r15
movq %rdi, %r14
callq 0x3ad0
movq %rax, %r13
movq (%r15), %r15
testq %r15, %r15
je 0x43ee
movq %r14, 0x18(%rsp)
movq %r13, 0x10(%rsp)
movq (%r15), %rbx
movq 0x10(%rbx), %rax
movq (%rax), %rdi
callq 0x3ede
movq %rax, %rbp
movq %r15, %rsi
callq 0x3f86
testl %eax, %eax
je 0x408e
movq %r14, %rdi
movq %rbp, %rsi
callq 0x4403
jmp 0x43ca
movq %r15, %rsi
callq 0x3fbf
testl %eax, %eax
je 0x40cc
movq 0x8(%r15), %rax
movq (%rax), %rcx
movl (%rcx), %ecx
addl $-0x3b, %ecx
cmpl $0x1, %ecx
ja 0x40af
movq 0x8(%rax), %rax
movq 0x8(%rax), %r13
testq %r13, %r13
je 0x40fc
movq (%r13), %rax
movl (%rax), %eax
addl $-0x3b, %eax
cmpl $0x1, %eax
ja 0x40ff
movq 0x8(%r13), %r13
jmp 0x40ff
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 0x43e1
xorl %r13d, %r13d
testq %r13, %r13
je 0x4128
movq (%r13), %rax
xorl %r12d, %r12d
xorl %ecx, %ecx
cmpl $0x8, (%rax)
sete %al
movl $0x0, %r15d
cmoveq %r13, %r15
jne 0x4135
movb %al, %cl
movl %ecx, %eax
jmp 0x4331
xorl %r12d, %r12d
xorl %eax, %eax
xorl %r15d, %r15d
jmp 0x4331
callq 0x3ad0
movq %rax, 0x20(%rsp)
cmpl $0x0, 0x10(%rbp)
jle 0x42bd
xorl %r12d, %r12d
xorl %r15d, %r15d
movl $0x0, 0xc(%rsp)
movq (%r13), %r14
movl (%r14), %eax
cmpl $0x8, %eax
je 0x41a3
cmpl $0x7, %eax
jne 0x41e7
movslq %r12d, %rax
movq 0x20(%rsp,%rax,8), %rbx
movl $0x18, %edi
callq 0x10b0
movq %r14, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%rbx), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%rbx)
incl %r15d
jmp 0x4271
testl %r15d, %r15d
je 0x4275
movslq %r12d, %rax
movq 0x20(%rsp,%rax,8), %rbx
movl $0x18, %edi
callq 0x10b0
movq %r14, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%rbx), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%rbx)
decl %r15d
jmp 0x4271
testl %r15d, %r15d
jne 0x423e
cmpl $0xd, %eax
jne 0x423e
leal 0x1(%r12), %r14d
callq 0x3ad0
movslq %r12d, %rcx
movq %rax, 0x28(%rsp,%rcx,8)
cmpl 0x10(%rbp), %r14d
jne 0x4285
cmpl $0x0, 0x14(%rbp)
sete %al
cmpl $0x0, 0xc(%rsp)
setne %cl
orb %al, %cl
je 0x428f
xorl %r15d, %r15d
leaq 0x3c0a(%rip), %rdi      # 0x7e30
movl $0xf2, %esi
leaq 0x3c2c(%rip), %rdx      # 0x7e5e
xorl %eax, %eax
callq 0x140c
movl %r14d, %r12d
jmp 0x42a1
movslq %r12d, %rax
movq 0x20(%rsp,%rax,8), %rbx
movl $0x18, %edi
callq 0x10b0
movq %r14, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%rbx), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%rbx)
movb $0x1, %al
jmp 0x42a3
incl %r12d
movl $0x1, 0xc(%rsp)
xorl %r15d, %r15d
jmp 0x42a1
movb $0x1, %al
xorl %r15d, %r15d
movl %r14d, %r12d
jmp 0x42a3
movq 0x8(%r13), %r13
xorl %r15d, %r15d
movl %r14d, %r12d
movl $0x0, 0xc(%rsp)
xorl %eax, %eax
testb %al, %al
je 0x42b7
movq 0x8(%r13), %r13
testq %r13, %r13
jne 0x4157
xorl %r13d, %r13d
movl 0xc(%rsp), %ecx
jmp 0x42c2
xorl %r12d, %r12d
xorl %ecx, %ecx
cmpl $0x0, 0x14(%rbp)
sete %al
movl %ecx, %edx
testl %ecx, %ecx
setne %cl
orb %al, %cl
je 0x42db
movq %r13, %r15
movl %edx, %eax
jmp 0x4331
testq %r13, %r13
je 0x4326
movslq %r12d, %rbx
movq (%r13), %r14
cmpl $0x8, (%r14)
je 0x4326
movq 0x20(%rsp,%rbx,8), %r15
movl $0x18, %edi
callq 0x10b0
movq %r14, (%rax)
leaq 0x8(%rax), %rcx
movq $0x0, 0x8(%rax)
movl $0x0, 0x10(%rax)
movq 0x8(%r15), %rdx
movq %rax, (%rdx)
movq %rcx, 0x8(%r15)
movq 0x8(%r13), %r13
testq %r13, %r13
jne 0x42e3
incl %r12d
movl $0x1, %eax
movq %r13, %r15
testl %eax, %eax
movq 0x18(%rsp), %r14
movq 0x10(%rsp), %r13
jne 0x4359
leaq 0x3aea(%rip), %rdi      # 0x7e30
movl $0x108, %esi            # imm = 0x108
leaq 0x3b21(%rip), %rdx      # 0x7e73
xorl %eax, %eax
callq 0x140c
testl %r12d, %r12d
jle 0x43b7
movl %r12d, %eax
xorl %ecx, %ecx
movq 0x20(%rsp,%rcx,8), %rdx
movq (%rdx), %rsi
testq %rsi, %rsi
je 0x43af
movq (%rsi), %rdi
movl (%rdi), %edi
addl $-0x3b, %edi
cmpl $0x1, %edi
ja 0x4384
movq 0x8(%rsi), %rsi
movq %rsi, (%rdx)
cmpq $0x0, (%rdx)
je 0x43af
movq %rdx, %rsi
movq (%rdx), %rdi
leaq 0x8(%rdi), %rdx
cmpq $0x0, 0x8(%rdi)
jne 0x438a
movq (%rdi), %rdx
movl (%rdx), %edx
addl $-0x3b, %edx
cmpl $0x1, %edx
ja 0x43af
movq $0x0, (%rsi)
incq %rcx
cmpq %rax, %rcx
jne 0x4363
movq %r14, %rdi
movq %rbp, %rsi
leaq 0x20(%rsp), %rdx
movl %r12d, %ecx
callq 0x4490
movq (%rax), %rcx
testq %rcx, %rcx
je 0x43e1
movq 0x8(%r13), %rdx
movq %rcx, (%rdx)
movq 0x8(%rax), %rax
movq %rax, 0x8(%r13)
movq 0x8(%r15), %r15
testq %r15, %r15
jne 0x4060
movq %r13, %rax
addq $0x418, %rsp            # imm = 0x418
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq