// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Scene.cpp
// Function: gaps::R3Scene::ReadGrammarHierarchyFile(char const*, gaps::R3SceneNode*)
int R3Scene::
ReadGrammarHierarchyFile(const char *filename, R3SceneNode *parent_node)
{
  // Get/set parent node
  if (!parent_node) parent_node = root;

  // Open file
  FILE *fp;
  if (!(fp = fopen(filename, "r"))) {
    RNFail("Unable to open file %s", filename);
    return 0;
  }

  // Extract base name
  char basename[1024] = { '\0' };
  const char *startp = strrchr(filename, '/');
  if (!startp) startp = filename;
  else startp++;
  const char *endp = strrchr(filename, '.');
  if (!endp) endp = startp + strlen(startp);
  int basename_length = endp - startp;
  if (basename_length > 1023) basename_length = 1023;
  strncpy(basename, startp, basename_length);

  // Read scene
  char buffer[1024];
  int line_count = 0;
  RNBoolean leaf = TRUE;
  RNArray<R3SceneNode *> parsed_nodes;
  R3SceneNode *current_node = NULL;
  while (fgets(buffer, 1023, fp)) {
    // Increment line counter
    line_count++;

    // Skip white space
    char *bufferp = buffer;
    while (isspace(*bufferp)) bufferp++;

    // Skip blank lines and comments
    if (*bufferp == '#') continue;
    if (*bufferp == '\0') continue;

    // Get keyword
    char keyword[256];
    if (sscanf(bufferp, "%s", keyword) != 1) {
      RNFail("Syntax error on line %d in file %s", line_count, filename);
      return 0;
    }

    // Check keyword
    if (!strcmp(keyword, "newModel")) {
      // Read fields
      int model_index;
      if (sscanf(bufferp, "%s%d", keyword, &model_index) != (unsigned int) 2) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Create node
      while (parsed_nodes.NEntries() <= model_index) {
        char node_name[4096];
        sprintf(node_name, "%d", parsed_nodes.NEntries());
        R3SceneNode *node = new R3SceneNode(this);
        node->SetName(node_name);
        parsed_nodes.Insert(node);
      }

      // Remember current node
      current_node = parsed_nodes.Kth(model_index);
    }
    else if (!strcmp(keyword, "root")) {
      // Read fields
      int root_index;
      if (sscanf(bufferp, "%s%d", keyword, &root_index) != (unsigned int) 2) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Create node
      while (parsed_nodes.NEntries() <= root_index) {
        char node_name[4096];
        sprintf(node_name, "%d", parsed_nodes.NEntries());
        R3SceneNode *node = new R3SceneNode(this);
        node->SetName(node_name);
        parsed_nodes.Insert(node);
      }

      // Insert root of this parse as child of root
      R3SceneNode *node = parsed_nodes.Kth(root_index);
      parent_node->InsertChild(node);
    }
    else if (!strcmp(keyword, "parent")) {
      // Read fields
      int parent_index;
      if (sscanf(bufferp, "%s%d", keyword, &parent_index) != (unsigned int) 2) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Check parent index
      if (parent_index >= 0) {
        // Create parent node
        while (parsed_nodes.NEntries() <= parent_index) {
          char node_name[4096];
          sprintf(node_name, "I%d", parsed_nodes.NEntries());
          R3SceneNode *node = new R3SceneNode(this);
          node->SetName(node_name);
          parsed_nodes.Insert(node);
        }
      
        // Set last node's parent
        R3SceneNode *parent = parsed_nodes.Kth(parent_index);
        parent->InsertChild(current_node);
      }
    }
    else if (!strcmp(keyword, "children")) {
      const char *token = strtok(bufferp, " \n\t");
      assert(token && (!strcmp(token, "children")));
      token = strtok(NULL, " \n\t");
      leaf = (token) ? FALSE : TRUE;
    }
    else if (!strcmp(keyword, "leaf_group")) {
      // Check current node
      if (!current_node) {
        RNFail("leaf_group before first newModel at line %d in %s\n", line_count, filename);
        return 0;
      }

      // Read models
      if (leaf) {
        const char *token = strtok(bufferp, " \n\t");
        assert(token && (!strcmp(token, "leaf_group")));
        while (TRUE) {
          token = strtok(NULL, " \n\t");
          if (!token) break;
          int model_index = atoi(token);
          // char node_name[4096];
          // sprintf(node_name, "L%d", model_index);
          // R3SceneNode *node = new R3SceneNode(this);
          // node->SetName(node_name);
          // current_node->InsertChild(node);
          char model_filename[2048];
          sprintf(model_filename, "models/%s/%d.off", basename, model_index);
          R3TriangleArray *shape = ReadMesh(model_filename);
          if (shape) {
            R3SceneElement *element = new R3SceneElement();
            element->SetMaterial(&R3default_material);
            element->InsertShape(shape);
            current_node->InsertElement(element);
          }
        }    
      }    
    }
  }

  // Close file
  fclose(fp);

  // Return success
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1948, %rsp           # imm = 0x1948
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
testq %rdx, %rdx
jne 0x2c43a
movq (%r15), %rbx
leaq 0xb4c42(%rip), %rsi     # 0xe1083
movq %r14, %rdi
callq 0x21ab0
movq %rax, 0x30(%rsp)
testq %rax, %rax
je 0x2c8fe
movq %rbx, 0x38(%rsp)
leaq 0x540(%rsp), %rdi
movl $0x400, %edx            # imm = 0x400
xorl %esi, %esi
callq 0x21490
movq %r14, %rdi
movl $0x2f, %esi
callq 0x219b0
leaq 0x1(%rax), %rbx
testq %rax, %rax
cmoveq %r14, %rbx
movq %r14, 0x20(%rsp)
movq %r14, %rdi
movl $0x2e, %esi
callq 0x219b0
testq %rax, %rax
jne 0x2c4aa
movq %rbx, %rdi
callq 0x21380
addq %rbx, %rax
subl %ebx, %eax
movl $0x3ff, %ecx            # imm = 0x3FF
cmpl %ecx, %eax
cmovgel %ecx, %eax
movslq %eax, %rdx
leaq 0x540(%rsp), %rdi
movq %rbx, %rsi
callq 0x21430
leaq 0x10(%rsp), %rdi
callq 0x8758c
leaq 0x140(%rsp), %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq 0x30(%rsp), %rdx
callq 0x21f30
testq %rax, %rax
je 0x2c8ed
movl $0x1, 0xc(%rsp)
leaq 0x940(%rsp), %rbx
leaq 0x10(%rsp), %r13
xorl %ebp, %ebp
movq $0x0, 0x28(%rsp)
leaq 0x13f(%rsp), %r12
movsbl 0x1(%r12), %r14d
incq %r12
movl %r14d, %edi
callq 0x210b0
testl %eax, %eax
jne 0x2c51b
movzbl %r14b, %eax
incl %ebp
testl %eax, %eax
je 0x2c8b7
cmpl $0x23, %eax
je 0x2c8b7
movq %r12, %rdi
leaq 0xcda5a(%rip), %rsi     # 0xf9fab
leaq 0x40(%rsp), %rdx
xorl %eax, %eax
callq 0x21890
cmpl $0x1, %eax
jne 0x2c913
movq 0x40(%rsp), %rax
movabsq $0x6c65646f4d77656e, %rcx # imm = 0x6C65646F4D77656E
xorq %rcx, %rax
movzbl 0x48(%rsp), %ecx
orq %rax, %rcx
je 0x2c6da
movl 0x40(%rsp), %eax
movl $0x746f6f72, %ecx       # imm = 0x746F6F72
xorl %ecx, %eax
movzbl 0x44(%rsp), %ecx
orl %eax, %ecx
je 0x2c764
movl 0x40(%rsp), %eax
movl $0x65726170, %ecx       # imm = 0x65726170
xorl %ecx, %eax
movl 0x43(%rsp), %ecx
movl $0x746e65, %edx         # imm = 0x746E65
xorl %edx, %ecx
orl %eax, %ecx
je 0x2c7f3
movq 0x40(%rsp), %rax
movabsq $0x6e6572646c696863, %rcx # imm = 0x6E6572646C696863
xorq %rcx, %rax
movzbl 0x48(%rsp), %ecx
orq %rax, %rcx
je 0x2c878
movq 0x40(%rsp), %rax
movabsq $0x6f72675f6661656c, %rcx # imm = 0x6F72675F6661656C
xorq %rcx, %rax
movq 0x43(%rsp), %rcx
movabsq $0x70756f72675f66, %rdx # imm = 0x70756F72675F66
xorq %rdx, %rcx
orq %rax, %rcx
jne 0x2c8b7
cmpq $0x0, 0x28(%rsp)
je 0x2c98d
cmpl $0x0, 0xc(%rsp)
je 0x2c8d9
movq %r12, %rdi
leaq 0xae8ca(%rip), %r14     # 0xdaef4
movq %r14, %rsi
callq 0x21ef0
xorl %edi, %edi
movq %r14, %rsi
callq 0x21ef0
testq %rax, %rax
je 0x2c8e3
movl $0x1, 0xc(%rsp)
movq %rax, %rdi
callq 0x21ee0
movq %rbx, %rdi
leaq 0xae8d7(%rip), %rsi     # 0xdaf36
leaq 0x540(%rsp), %rdx
movl %eax, %ecx
xorl %eax, %eax
callq 0x21140
movq %rbx, %rdi
callq 0x339e1
movq %rax, %r14
testq %rax, %rax
je 0x2c6be
movl $0x60, %edi
callq 0x218c0
movq %rax, %r12
movq %rax, %rdi
xorl %esi, %esi
callq 0x3d514
movq %r12, %rdi
leaq 0x116b0f(%rip), %rsi    # 0x1431b0
callq 0x3d7b6
movq %r12, %rdi
movq %r14, %rsi
callq 0x3d7bc
movq 0x28(%rsp), %rdi
movq %r12, %rsi
callq 0x3c9ce
xorl %edi, %edi
leaq 0xae82d(%rip), %rsi     # 0xdaef4
callq 0x21ef0
testq %rax, %rax
jne 0x2c64d
jmp 0x2c8b7
movq %r12, %rdi
leaq 0xae75f(%rip), %rsi     # 0xdae43
leaq 0x40(%rsp), %rdx
leaq 0x8(%rsp), %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2c92a
movl 0x1c(%rsp), %edx
movl 0x8(%rsp), %eax
cmpl %eax, %edx
jg 0x2c74f
movq %rbx, %rdi
leaq 0xb45e6(%rip), %rsi     # 0xe0cfa
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x3b560
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3cc1a
movl 0x1c(%rsp), %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x87622
jmp 0x2c6fe
movq 0x10(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rax
movq %rax, 0x28(%rsp)
jmp 0x2c8b7
movq %r12, %rdi
leaq 0xae6d5(%rip), %rsi     # 0xdae43
leaq 0x40(%rsp), %rdx
leaq 0x8(%rsp), %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2c941
movl 0x1c(%rsp), %edx
movl 0x8(%rsp), %eax
cmpl %eax, %edx
jg 0x2c7d9
movq %rbx, %rdi
leaq 0xb455c(%rip), %rsi     # 0xe0cfa
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x3b560
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3cc1a
movl 0x1c(%rsp), %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x87622
jmp 0x2c788
movq 0x10(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rsi
movq 0x38(%rsp), %rdi
callq 0x3c97e
jmp 0x2c8b7
movq %r12, %rdi
leaq 0xae646(%rip), %rsi     # 0xdae43
leaq 0x40(%rsp), %rdx
leaq 0x8(%rsp), %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2c958
movl 0x8(%rsp), %eax
testl %eax, %eax
js 0x2c8b7
movl 0x1c(%rsp), %edx
cmpl %eax, %edx
jg 0x2c8a2
movq %rbx, %rdi
leaq 0xae6b2(%rip), %rsi     # 0xdaee7
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x3b560
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3cc1a
movl 0x1c(%rsp), %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x87622
movl 0x1c(%rsp), %edx
movl 0x8(%rsp), %eax
jmp 0x2c827
movq %r12, %rdi
leaq 0xae672(%rip), %r14     # 0xdaef4
movq %r14, %rsi
callq 0x21ef0
xorl %edi, %edi
movq %r14, %rsi
callq 0x21ef0
xorl %ecx, %ecx
testq %rax, %rax
sete %cl
movl %ecx, 0xc(%rsp)
jmp 0x2c8b7
movq 0x10(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rdi
movq 0x28(%rsp), %rsi
callq 0x3c97e
leaq 0x140(%rsp), %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq 0x30(%rsp), %rdx
callq 0x21f30
testq %rax, %rax
jne 0x2c513
jmp 0x2c8ed
movl $0x0, 0xc(%rsp)
jmp 0x2c8b7
movl $0x1, 0xc(%rsp)
jmp 0x2c8b7
movq 0x30(%rsp), %rdi
callq 0x218b0
movl $0x1, %ebx
jmp 0x2c96f
leaq 0xadd51(%rip), %rdi     # 0xda656
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0x8a0fe
jmp 0x2c979
leaq 0xae4d9(%rip), %rdi     # 0xdadf3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8a0fe
jmp 0x2c96d
leaq 0xae4c2(%rip), %rdi     # 0xdadf3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8a0fe
jmp 0x2c96d
leaq 0xae4ab(%rip), %rdi     # 0xdadf3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8a0fe
jmp 0x2c96d
leaq 0xae494(%rip), %rdi     # 0xdadf3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8a0fe
xorl %ebx, %ebx
leaq 0x10(%rsp), %rdi
callq 0x875f6
movl %ebx, %eax
addq $0x1948, %rsp           # imm = 0x1948
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xae56f(%rip), %rdi     # 0xdaf03
jmp 0x2c91a
jmp 0x2c9cd
jmp 0x2c9cd
jmp 0x2c9cd
jmp 0x2c9cd
jmp 0x2c9cd
jmp 0x2c9cd
movq %rax, %rbx
movl $0x60, %esi
movq %r12, %rdi
jmp 0x2c9c4
jmp 0x2c9cd
jmp 0x2c9b9
jmp 0x2c9cd
jmp 0x2c9b9
jmp 0x2c9cd
movq %rax, %rbx
movl $0x1b0, %esi            # imm = 0x1B0
movq %r14, %rdi
callq 0x218e0
jmp 0x2c9d0
jmp 0x2c9cd
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x875f6
movq %rbx, %rdi
callq 0x220c0