// File: /workspace/github_c_makefile_star2_O0/deplinenoise[P]tundra/src/Scanner.cpp
// Function: t2::ScanImplicitDeps(t2::StatCache*, t2::ScanInput const*, t2::ScanOutput*)
bool ScanImplicitDeps(StatCache* stat_cache, const ScanInput* input, ScanOutput* output)
{
  MemAllocHeap      *scratch_heap   = input->m_ScratchHeap;
  MemAllocLinear    *scratch_alloc  = input->m_ScratchAlloc;
  const ScannerData *scanner_config = input->m_ScannerConfig;
  ScanCache         *scan_cache     = input->m_ScanCache;

  Buffer<const char*> found_includes;
  Buffer<const char*> filename_stack;
  BufferInitWithCapacity(&found_includes, scratch_heap, 128);
  BufferInitWithCapacity(&filename_stack, scratch_heap, 128);
  BufferAppendOne(&filename_stack, scratch_heap, input->m_FileName);

  IncludeSet incset;
  IncludeSetInit(&incset, scratch_heap, scratch_alloc);

  while (filename_stack.m_Size > 0)
  {
    const char* fn = BufferPopOne(&filename_stack);

    // Compute key for scan cache lookup/insert
    // Reuse scan key for initial file.
    HashDigest scan_key;

    FileInfo info = StatCacheStat(stat_cache, fn);

    if (!info.Exists())
      continue;

    ComputeScanCacheKey(&scan_key, fn, scanner_config->m_ScannerGuid);

    ScanCacheLookupResult cache_result;

    if (ScanCacheLookup(scan_cache, scan_key, info.m_Timestamp, &cache_result, scratch_alloc))
    {
      int                 file_count = cache_result.m_IncludedFileCount;
      const FileAndHash  *files      = cache_result.m_IncludedFiles;

      for (int i = 0; i < file_count; ++i)
      {
        if (IncludeSetAddNoDuplicateString(&incset, files[i].m_Filename, files[i].m_FilenameHash))
        {
          // This was a new file, schedule it for scanning as well. 
          BufferAppendOne(&filename_stack, scratch_heap, files[i].m_Filename);
        }
      }
    }
    else
    {
      // Reset buffer
      BufferClear(&found_includes);

      // Read file into RAM, and add a terminating newline character.
      FILE* f = fopen(fn, "rb");
      if (!f)
        continue;

      if (0 != fseek(f, 0, SEEK_END))
      {
        fclose(f);
        continue;
      }

      long file_size = ftell(f);
      if (-1 == file_size || 0 == file_size)
      {
        fclose(f);
        continue;
      }

      rewind(f);

      char* buffer = (char*) HeapAllocate(scratch_heap, file_size + 2);
      if (1 == (long) fread(buffer, file_size, 1, f))
      {
        // Add an extra newline to sort out trailing #includes on last line
        buffer[file_size + 0] = '\n';
        buffer[file_size + 1] = '\0';

        char* scan_start = buffer;

        // Skip UTF-8 marker if present as it freaks out ctype functions
        static const unsigned char utf8_mark[] = { 0xef, 0xbb, 0xbf };
        if (file_size >= 3 && 0 == memcmp(scan_start, utf8_mark, sizeof utf8_mark))
          scan_start += sizeof utf8_mark;

        ScanFile(stat_cache, fn, scan_start, input, &found_includes);
      }

      // Insert result into scan cache
      ScanCacheInsert(scan_cache, scan_key, info.m_Timestamp, found_includes.m_Storage, (int) found_includes.m_Size);

      for (const char* file : found_includes)
      {
        if (IncludeSetAddDuplicateString(&incset, file, Djb2HashPath(file)))
        {
          // This was a new file, schedule it for scanning as well. 
          BufferAppendOne(&filename_stack, scratch_heap, file);
        }
      }

      HeapFree(scratch_heap, buffer);
      fclose(f);
    }
  }

  // Allocate space for output array. String data is already in scratch allocator.
  int include_count = incset.m_HashTable.m_RecordCount;
  FileAndHash* result = LinearAllocateArray<FileAndHash>(scratch_alloc, include_count);
  HashSetWalk(&incset.m_HashTable, [=] (uint32_t index, uint32_t hash, const char* path) {
    result[index].m_Filename = path;
    result[index].m_FilenameHash = hash;
  });

  BufferDestroy(&filename_stack, scratch_heap);
  BufferDestroy(&found_includes, scratch_heap);

  output->m_IncludedFileCount = include_count;
  output->m_IncludedFiles     = result;

  IncludeSetDestroy(&incset);
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rsi
leaq -0x50(%rbp), %rdi
movl $0x80, %edx
callq 0x1d6e0
movq -0x20(%rbp), %rsi
leaq -0x68(%rbp), %rdi
movl $0x80, %edx
callq 0x1d6e0
movq -0x20(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdx
leaq -0x68(%rbp), %rdi
callq 0x1d730
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x98(%rbp), %rdi
callq 0x1d1d0
cmpq $0x0, -0x60(%rbp)
jbe 0x1d139
leaq -0x68(%rbp), %rdi
callq 0x1d770
movq %rax, -0xa0(%rbp)
movq -0x8(%rbp), %rsi
movq -0xa0(%rbp), %rdx
leaq -0xc8(%rbp), %rdi
callq 0x7420
leaq -0xc8(%rbp), %rdi
callq 0x71b0
testb $0x1, %al
jne 0x1cdc7
jmp 0x1cd83
movq -0xa0(%rbp), %rsi
movq -0x30(%rbp), %rdx
addq $0xc, %rdx
leaq -0xb0(%rbp), %rdi
callq 0x19f80
movq -0x38(%rbp), %rdi
movq -0xb8(%rbp), %rdx
movq -0x28(%rbp), %r8
leaq -0xb0(%rbp), %rsi
leaq -0xd8(%rbp), %rcx
callq 0x1a110
testb $0x1, %al
jne 0x1ce0d
jmp 0x1cec1
movl -0xd8(%rbp), %eax
movl %eax, -0xdc(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0xe8(%rbp)
movl $0x0, -0xec(%rbp)
movl -0xec(%rbp), %eax
cmpl -0xdc(%rbp), %eax
jge 0x1cebc
movq -0xe8(%rbp), %rax
movslq -0xec(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
movq -0xe8(%rbp), %rax
movslq -0xec(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %edx
leaq -0x98(%rbp), %rdi
callq 0x1d210
testb $0x1, %al
jne 0x1ce81
jmp 0x1cea6
movq -0x20(%rbp), %rsi
movq -0xe8(%rbp), %rax
movslq -0xec(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rdx
leaq -0x68(%rbp), %rdi
callq 0x1d730
jmp 0x1cea8
movl -0xec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xec(%rbp)
jmp 0x1ce31
jmp 0x1d134
leaq -0x50(%rbp), %rdi
callq 0x1d7b0
movq -0xa0(%rbp), %rdi
leaq 0x70b1(%rip), %rsi      # 0x23f89
callq 0x33c0
movq %rax, -0xf8(%rbp)
cmpq $0x0, -0xf8(%rbp)
jne 0x1cef3
jmp 0x1cd83
movq -0xf8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x2, %edx
callq 0x3390
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x1cf21
movq -0xf8(%rbp), %rdi
callq 0x3350
jmp 0x1cd83
movq -0xf8(%rbp), %rdi
callq 0x3030
movq %rax, -0x100(%rbp)
movq $-0x1, %rax
cmpq -0x100(%rbp), %rax
je 0x1cf4f
xorl %eax, %eax
cmpq -0x100(%rbp), %rax
jne 0x1cf60
movq -0xf8(%rbp), %rdi
callq 0x3350
jmp 0x1cd83
movq -0xf8(%rbp), %rdi
callq 0x3080
movq -0x20(%rbp), %rdi
movq -0x100(%rbp), %rsi
addq $0x2, %rsi
callq 0x18940
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rdi
movq -0x100(%rbp), %rsi
movq -0xf8(%rbp), %rcx
movl $0x1, %edx
callq 0x34d0
movq %rax, %rcx
movl $0x1, %eax
cmpq %rcx, %rax
jne 0x1d045
movq -0x108(%rbp), %rax
movq -0x100(%rbp), %rcx
movb $0xa, (%rax,%rcx)
movq -0x108(%rbp), %rax
movq -0x100(%rbp), %rcx
movb $0x0, 0x1(%rax,%rcx)
movq -0x108(%rbp), %rax
movq %rax, -0x110(%rbp)
cmpq $0x3, -0x100(%rbp)
jl 0x1d026
movq -0x110(%rbp), %rdi
leaq 0x84fa(%rip), %rsi      # 0x254fc
movl $0x3, %edx
callq 0x3160
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0x1d026
movq -0x110(%rbp), %rax
addq $0x3, %rax
movq %rax, -0x110(%rbp)
movq -0x8(%rbp), %rdi
movq -0xa0(%rbp), %rsi
movq -0x110(%rbp), %rdx
movq -0x10(%rbp), %rcx
leaq -0x50(%rbp), %r8
callq 0x1d270
movq -0x38(%rbp), %rdi
movq -0xb8(%rbp), %rdx
movq -0x50(%rbp), %rcx
movq -0x48(%rbp), %rax
movl %eax, %r8d
leaq -0xb0(%rbp), %rsi
callq 0x1a3f0
leaq -0x50(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rdi
callq 0x1d7d0
movq %rax, -0x120(%rbp)
movq -0x118(%rbp), %rdi
callq 0x1d7f0
movq %rax, -0x128(%rbp)
movq -0x120(%rbp), %rax
cmpq -0x128(%rbp), %rax
je 0x1d118
movq -0x120(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x130(%rbp), %rdi
callq 0x7470
movq -0x150(%rbp), %rsi
movl %eax, %edx
leaq -0x98(%rbp), %rdi
callq 0x1d3b0
testb $0x1, %al
jne 0x1d0ee
jmp 0x1d102
movq -0x20(%rbp), %rsi
movq -0x130(%rbp), %rdx
leaq -0x68(%rbp), %rdi
callq 0x1d730
jmp 0x1d104
movq -0x120(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x120(%rbp)
jmp 0x1d098
movq -0x20(%rbp), %rdi
movq -0x108(%rbp), %rsi
callq 0x18960
movq -0xf8(%rbp), %rdi
callq 0x3350
jmp 0x1cd83
movl -0x78(%rbp), %eax
movl %eax, -0x134(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x134(%rbp), %rsi
callq 0x1b7c0
movq %rax, -0x140(%rbp)
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
movq -0x140(%rbp), %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rsi
callq 0x1d430
movq -0x20(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x14db0
movq -0x20(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x14db0
movl -0x134(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, (%rax)
movq -0x140(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
leaq -0x98(%rbp), %rdi
callq 0x1d4d0
movb $0x1, %al
andb $0x1, %al
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
nopl (%rax)