// File: /workspace/github_cpp_makefile_star2_O1/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 $0x1938, %rsp           # imm = 0x1938
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
testq %rdx, %rdx
jne 0x2c5bc
movq (%r15), %rbx
leaq 0xb6a80(%rip), %rsi     # 0xe3043
movq %r14, %rdi
callq 0x21ac0
testq %rax, %rax
je 0x2cb09
movq %rax, %r12
movq %rbx, 0x28(%rsp)
leaq 0x530(%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 0x2c62a
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 0x530(%rsp), %rdi
movq %rbx, %rsi
callq 0x21430
leaq 0x8(%rsp), %rdi
callq 0x886bc
leaq 0x130(%rsp), %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq %r12, %rdx
callq 0x21f40
testq %rax, %rax
je 0x2cafa
movl $0x1, 0x4(%rsp)
leaq 0x930(%rsp), %r14
xorl %ebp, %ebp
movq $0x0, 0x18(%rsp)
leaq 0x12f(%rsp), %r13
movsbl 0x1(%r13), %ebx
incq %r13
movl %ebx, %edi
callq 0x210b0
testl %eax, %eax
jne 0x2c694
movzbl %bl, %eax
incl %ebp
movl $0x2, %ebx
testl %eax, %eax
je 0x2caa6
cmpl $0x23, %eax
je 0x2caa6
movq %r13, %rdi
leaq 0xcf88f(%rip), %rsi     # 0xfbf5b
leaq 0x30(%rsp), %rdx
xorl %eax, %eax
callq 0x21890
cmpl $0x1, %eax
jne 0x2c84c
movq 0x30(%rsp), %rax
movabsq $0x6c65646f4d77656e, %rcx # imm = 0x6C65646F4D77656E
xorq %rcx, %rax
movzbl 0x38(%rsp), %ecx
orq %rax, %rcx
je 0x2c86b
movl 0x30(%rsp), %eax
movl $0x746f6f72, %ecx       # imm = 0x746F6F72
xorl %ecx, %eax
movzbl 0x34(%rsp), %ecx
orl %eax, %ecx
je 0x2c8e6
movl 0x30(%rsp), %eax
movl $0x65726170, %ecx       # imm = 0x65726170
xorl %ecx, %eax
movl 0x33(%rsp), %ecx
movl $0x746e65, %edx         # imm = 0x746E65
xorl %edx, %ecx
orl %eax, %ecx
je 0x2c990
movq 0x30(%rsp), %rax
movabsq $0x6e6572646c696863, %rcx # imm = 0x6E6572646C696863
xorq %rcx, %rax
movzbl 0x38(%rsp), %ecx
orq %rax, %rcx
je 0x2ca43
movq 0x30(%rsp), %rax
movabsq $0x6f72675f6661656c, %rcx # imm = 0x6F72675F6661656C
xorq %rcx, %rax
movq 0x33(%rsp), %rcx
movabsq $0x70756f72675f66, %rdx # imm = 0x70756F72675F66
xorq %rdx, %rcx
orq %rax, %rcx
jne 0x2caa4
cmpq $0x0, 0x18(%rsp)
je 0x2cacb
cmpl $0x0, 0x4(%rsp)
je 0x2caf0
movq %r13, %rdi
leaq 0xb073f(%rip), %rbx     # 0xdcee4
movq %rbx, %rsi
callq 0x21f00
xorl %edi, %edi
movq %rbx, %rsi
callq 0x21f00
movl $0x1, 0x4(%rsp)
testq %rax, %rax
je 0x2caa4
movq %rax, %rdi
callq 0x21ef0
movq %r14, %rdi
leaq 0xb074c(%rip), %rsi     # 0xdcf26
leaq 0x530(%rsp), %rdx
movl %eax, %ecx
xorl %eax, %eax
callq 0x21140
movq %r14, %rdi
callq 0x33d50
movq %rax, %rbx
testq %rax, %rax
je 0x2c839
movl $0x60, %edi
callq 0x218c0
movq %rax, %r13
movq %rax, %rdi
xorl %esi, %esi
callq 0x3d9c4
movq %r13, %rdi
leaq 0x118994(%rip), %rsi    # 0x1451b0
callq 0x3dc66
movq %r13, %rdi
movq %rbx, %rsi
callq 0x3dc6c
movq 0x18(%rsp), %rdi
movq %r13, %rsi
callq 0x3ceca
xorl %edi, %edi
leaq 0xb06a2(%rip), %rsi     # 0xdcee4
callq 0x21f00
jmp 0x2c7bf
movl $0x1, %ebx
leaq 0xb058b(%rip), %rdi     # 0xdcde3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8b53a
jmp 0x2caa6
movq %r13, %rdi
leaq 0xb05be(%rip), %rsi     # 0xdce33
leaq 0x30(%rsp), %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
movl %eax, %r13d
cmpl $0x2, %eax
jne 0x2c961
movl 0x14(%rsp), %edx
movl (%rsp), %eax
cmpl %eax, %edx
jg 0x2c97b
movq %r14, %rdi
leaq 0xb6411(%rip), %rsi     # 0xe2cba
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %rbx
movq %rax, %rdi
movq %r15, %rsi
callq 0x3bab8
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3d0ca
movl 0x14(%rsp), %edx
leaq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x88752
jmp 0x2c890
movq %r13, %rdi
leaq 0xb0543(%rip), %rsi     # 0xdce33
leaq 0x30(%rsp), %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
movl %eax, %r13d
cmpl $0x2, %eax
jne 0x2ca15
movl 0x14(%rsp), %edx
movl (%rsp), %eax
cmpl %eax, %edx
jg 0x2ca2c
movq %r14, %rdi
leaq 0xb6396(%rip), %rsi     # 0xe2cba
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %rbx
movq %rax, %rdi
movq %r15, %rsi
callq 0x3bab8
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3d0ca
movl 0x14(%rsp), %edx
leaq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x88752
jmp 0x2c90b
leaq 0xb047b(%rip), %rdi     # 0xdcde3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8b53a
jmp 0x2ca99
movq 0x8(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rax
movq %rax, 0x18(%rsp)
jmp 0x2ca99
movq %r13, %rdi
leaq 0xb0499(%rip), %rsi     # 0xdce33
leaq 0x30(%rsp), %rdx
movq %rsp, %rcx
xorl %eax, %eax
callq 0x21890
movl %eax, %r13d
cmpl $0x2, %eax
jne 0x2ca6d
cmpl $0x0, (%rsp)
js 0x2ca99
movl 0x14(%rsp), %edx
movl (%rsp), %eax
cmpl %eax, %edx
jg 0x2ca84
movq %r14, %rdi
leaq 0xb04ff(%rip), %rsi     # 0xdced7
xorl %eax, %eax
callq 0x21140
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218c0
movq %rax, %rbx
movq %rax, %rdi
movq %r15, %rsi
callq 0x3bab8
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3d0ca
movl 0x14(%rsp), %edx
leaq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x88752
jmp 0x2c9bf
leaq 0xb03c7(%rip), %rdi     # 0xdcde3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8b53a
jmp 0x2ca99
movq 0x8(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rsi
movq 0x28(%rsp), %rdi
callq 0x3ce8e
jmp 0x2ca99
movq %r13, %rdi
leaq 0xb0497(%rip), %rbx     # 0xdcee4
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 0x2caa4
leaq 0xb036f(%rip), %rdi     # 0xdcde3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8b53a
jmp 0x2ca99
movq 0x8(%rsp), %rcx
cltq
movq (%rcx,%rax,8), %rdi
movq 0x18(%rsp), %rsi
callq 0x3ce8e
movl $0x1, %ebx
cmpl $0x2, %r13d
jne 0x2caa6
xorl %ebx, %ebx
testb $0x1, %bl
jne 0x2cb1e
leaq 0x130(%rsp), %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq %r12, %rdx
callq 0x21f40
testq %rax, %rax
jne 0x2c68c
jmp 0x2cafa
leaq 0xb0421(%rip), %rdi     # 0xdcef3
movl %ebp, %esi
movq 0x20(%rsp), %rdx
xorl %eax, %eax
callq 0x8b53a
movl $0x1, %ebx
movq $0x0, 0x18(%rsp)
jmp 0x2caa6
movl $0x0, 0x4(%rsp)
jmp 0x2caa4
movq %r12, %rdi
callq 0x218b0
movl $0x1, %ebx
jmp 0x2cb20
leaq 0xafb36(%rip), %rdi     # 0xdc646
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0x8b53a
jmp 0x2cb2a
xorl %ebx, %ebx
leaq 0x8(%rsp), %rdi
callq 0x88726
movl %ebx, %eax
addq $0x1938, %rsp           # imm = 0x1938
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2cb75
jmp 0x2cb75
jmp 0x2cb75
jmp 0x2cb75
jmp 0x2cb75
movq %rax, %r14
movl $0x60, %esi
movq %r13, %rdi
jmp 0x2cb6c
jmp 0x2cb75
jmp 0x2cb61
jmp 0x2cb75
jmp 0x2cb75
jmp 0x2cb61
jmp 0x2cb75
movq %rax, %r14
movl $0x1b0, %esi            # imm = 0x1B0
movq %rbx, %rdi
callq 0x218e0
jmp 0x2cb78
jmp 0x2cb75
movq %rax, %r14
leaq 0x8(%rsp), %rdi
callq 0x88726
movq %r14, %rdi
callq 0x220d0