// File: /workspace/github_cpp_makefile_star2_O2/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 %rsi, %r14
movq %rdi, %r15
movq %rdx, 0x30(%rsp)
testq %rdx, %rdx
jne 0x2b037
movq (%r15), %rax
movq %rax, 0x30(%rsp)
leaq 0xa0d65(%rip), %rsi     # 0xcbda3
movq %r14, %rdi
callq 0x21ab0
movq %rax, 0x38(%rsp)
testq %rax, %rax
je 0x2b4ac
leaq 0x140(%rsp), %rdi
movl $0x400, %edx            # imm = 0x400
xorl %esi, %esi
callq 0x21490
pushq $0x2f
popq %rsi
movq %r14, %rdi
callq 0x219c0
leaq 0x1(%rax), %rbx
testq %rax, %rax
cmoveq %r14, %rbx
pushq $0x2e
popq %rsi
movq %r14, 0x8(%rsp)
movq %r14, %rdi
callq 0x219c0
testq %rax, %rax
jne 0x2b09e
movq %rbx, %rdi
callq 0x21370
addq %rbx, %rax
subl %ebx, %eax
movl $0x3ff, %ecx            # imm = 0x3FF
cmpl %ecx, %eax
cmovgel %ecx, %eax
movslq %eax, %rdx
leaq 0x140(%rsp), %rdi
movq %rbx, %rsi
callq 0x21440
leaq 0x18(%rsp), %r13
movq %r13, %rdi
callq 0x7c1c6
pushq $0x1
popq %rax
leaq 0x40(%rsp), %r14
movq $0x0, 0x10(%rsp)
movl %eax, 0x4(%rsp)
xorl %ebp, %ebp
leaq 0x540(%rsp), %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq 0x38(%rsp), %rdx
callq 0x21f50
testq %rax, %rax
je 0x2b49d
movq %r15, %rbx
movq %r13, %r15
movq %r14, %r13
movl %ebp, %r14d
leaq 0x53f(%rsp), %r12
movsbl 0x1(%r12), %ebp
incq %r12
movl %ebp, %edi
callq 0x210b0
testl %eax, %eax
jne 0x2b115
movzbl %bpl, %eax
movl %r14d, %ebp
incl %ebp
testl %eax, %eax
movq %r13, %r14
movq %r15, %r13
movq %rbx, %r15
leaq 0xa08d6(%rip), %rbx     # 0xcba1a
je 0x2b0e1
cmpl $0x23, %eax
je 0x2b0e1
movq %r12, %rdi
leaq 0xb9b06(%rip), %rsi     # 0xe4c5b
movq %r14, %rdx
xorl %eax, %eax
callq 0x21890
cmpl $0x1, %eax
jne 0x2b4c1
movq %r14, %rdi
leaq 0x9ac74(%rip), %rsi     # 0xc5de6
pushq $0x9
popq %rdx
callq 0x21920
testl %eax, %eax
je 0x2b2a7
movq %r14, %rdi
leaq 0x9ad1f(%rip), %rsi     # 0xc5eab
pushq $0x5
popq %rdx
callq 0x21920
testl %eax, %eax
je 0x2b32d
movq %r14, %rdi
leaq 0x9ad0a(%rip), %rsi     # 0xc5eb0
pushq $0x7
popq %rdx
callq 0x21920
testl %eax, %eax
je 0x2b3b8
movq %r14, %rdi
leaq 0x9acfb(%rip), %rsi     # 0xc5ebb
pushq $0x9
popq %rdx
callq 0x21920
testl %eax, %eax
je 0x2b439
movq %r14, %rdi
leaq 0x9acee(%rip), %rsi     # 0xc5ec8
pushq $0xb
popq %rdx
callq 0x21920
testl %eax, %eax
jne 0x2b0e1
cmpq $0x0, 0x10(%rsp)
je 0x2b53b
cmpl $0x0, 0x4(%rsp)
je 0x2b490
movl %ebp, 0x2c(%rsp)
movq %r12, %rdi
leaq 0x9acb5(%rip), %rsi     # 0xc5ec4
callq 0x21f00
xorl %edi, %edi
leaq 0x9aca7(%rip), %rsi     # 0xc5ec4
callq 0x21f00
testq %rax, %rax
je 0x2b480
movq %rax, %rdi
callq 0x21ef0
leaq 0x940(%rsp), %rbx
movq %rbx, %rdi
leaq 0x9acc1(%rip), %rsi     # 0xc5f06
leaq 0x140(%rsp), %rdx
movl %eax, %ecx
xorl %eax, %eax
callq 0x21140
movq %rbx, %rdi
callq 0x3169b
movq %rax, %rbp
testq %rax, %rax
je 0x2b214
pushq $0x60
popq %rdi
callq 0x218d0
movq %rax, %r12
movq %rax, %rdi
xorl %esi, %esi
callq 0x394c0
movq %r12, %rdi
leaq 0x108f4b(%rip), %rsi    # 0x1341d0
callq 0x39714
movq %r12, %rdi
movq %rbp, %rsi
callq 0x3971a
movq 0x10(%rsp), %rdi
movq %r12, %rsi
callq 0x389c8
jmp 0x2b214
movq %r12, %rdi
leaq 0x9ab62(%rip), %rsi     # 0xc5e13
movq %r14, %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2b4d8
movl 0x24(%rsp), %edx
movslq (%rsp), %rax
cmpl %eax, %edx
jg 0x2b31a
leaq 0x940(%rsp), %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218d0
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
callq 0x37a1e
movq %r12, %rdi
leaq 0x940(%rsp), %rsi
callq 0x38b2e
movq %r13, %rdi
movq %r12, %rsi
callq 0x2737a
jmp 0x2b2c7
movq 0x18(%rsp), %rcx
movq (%rcx,%rax,8), %rax
movq %rax, 0x10(%rsp)
jmp 0x2b0e1
movq %r12, %rdi
leaq 0x9aadc(%rip), %rsi     # 0xc5e13
movq %r14, %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2b4ef
movl 0x24(%rsp), %edx
movslq (%rsp), %rax
cmpl %eax, %edx
jg 0x2b3a0
leaq 0x940(%rsp), %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218d0
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
callq 0x37a1e
movq %r12, %rdi
leaq 0x940(%rsp), %rsi
callq 0x38b2e
movq %r13, %rdi
movq %r12, %rsi
callq 0x2737a
jmp 0x2b34d
movq 0x18(%rsp), %rcx
movq (%rcx,%rax,8), %rsi
movq 0x30(%rsp), %rdi
callq 0x3898c
jmp 0x2b0e1
movq %r12, %rdi
leaq 0x9aa51(%rip), %rsi     # 0xc5e13
movq %r14, %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
cmpl $0x2, %eax
jne 0x2b506
movl (%rsp), %eax
testl %eax, %eax
js 0x2b0e1
movl 0x24(%rsp), %edx
cmpl %eax, %edx
jg 0x2b466
leaq 0x940(%rsp), %rdi
leaq 0x9aabd(%rip), %rsi     # 0xc5eb7
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218d0
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
callq 0x37a1e
movq %r12, %rdi
leaq 0x940(%rsp), %rsi
callq 0x38b2e
movq %r13, %rdi
movq %r12, %rsi
callq 0x2737a
movl (%rsp), %eax
jmp 0x2b3e3
movq %r12, %rdi
leaq 0x9aa81(%rip), %rbx     # 0xc5ec4
movq %rbx, %rsi
callq 0x21f00
xorl %edi, %edi
movq %rbx, %rsi
callq 0x21f00
xorl %ecx, %ecx
testq %rax, %rax
sete %cl
movl %ecx, 0x4(%rsp)
jmp 0x2b0e1
movq 0x18(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rdi
movq 0x10(%rsp), %rsi
callq 0x3898c
jmp 0x2b0e1
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
movl 0x2c(%rsp), %ebp
jmp 0x2b0e1
movl $0x0, 0x4(%rsp)
jmp 0x2b0e1
movq 0x38(%rsp), %rdi
callq 0x218c0
pushq $0x1
popq %rbx
jmp 0x2b51d
leaq 0x9a173(%rip), %rdi     # 0xc5626
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0x7e83e
jmp 0x2b527
leaq 0x9a8fb(%rip), %rdi     # 0xc5dc3
movl %ebp, %esi
movq 0x8(%rsp), %rdx
xorl %eax, %eax
callq 0x7e83e
jmp 0x2b51b
leaq 0x9a8e4(%rip), %rdi     # 0xc5dc3
movl %ebp, %esi
movq 0x8(%rsp), %rdx
xorl %eax, %eax
callq 0x7e83e
jmp 0x2b51b
leaq 0x9a8cd(%rip), %rdi     # 0xc5dc3
movl %ebp, %esi
movq 0x8(%rsp), %rdx
xorl %eax, %eax
callq 0x7e83e
jmp 0x2b51b
leaq 0x9a8b6(%rip), %rdi     # 0xc5dc3
movl %ebp, %esi
movq 0x8(%rsp), %rdx
xorl %eax, %eax
callq 0x7e83e
xorl %ebx, %ebx
leaq 0x18(%rsp), %rdi
callq 0x7c234
movl %ebx, %eax
addq $0x1948, %rsp           # imm = 0x1948
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9a991(%rip), %rdi     # 0xc5ed3
jmp 0x2b4c8
jmp 0x2b576
jmp 0x2b576
jmp 0x2b576
jmp 0x2b576
jmp 0x2b576
jmp 0x2b576
movq %rax, %rbx
pushq $0x60
popq %rsi
jmp 0x2b56a
jmp 0x2b576
jmp 0x2b576
jmp 0x2b562
jmp 0x2b562
jmp 0x2b576
movq %rax, %rbx
movl $0x1b0, %esi            # imm = 0x1B0
movq %r12, %rdi
callq 0x218f0
jmp 0x2b579
jmp 0x2b576
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x7c234
movq %rbx, %rdi
callq 0x220e0
nop