// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/ply.cpp
// Function: ply_read
PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
{
  int i,j;
  PlyFile *plyfile;
  const int max_line_size = 4096;
  char orig_line[max_line_size];
  const int max_words = 1024;
  char *words[max_words];
  char word_buffer[max_line_size];
  int nwords = 0;
  char **elist;
  PlyElement *elem;

  /* check for NULL file pointer */
  if (fp == NULL)
    return (NULL);

  if (native_binary_type == -1)
     get_native_binary_type();
  if (!types_checked)
     check_types();
  
  /* create record for this object */

  plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
  plyfile->nelems = 0;
  plyfile->comments = NULL;
  plyfile->num_comments = 0;
  plyfile->obj_info = NULL;
  plyfile->num_obj_info = 0;
  plyfile->fp = fp;
  plyfile->other_elems = NULL;

  /* read and parse the file's header */

  /* read in a line */
  if (!fgets (orig_line, max_line_size, plyfile->fp)) {
    fprintf(stderr, "Unable to read header from ply file\n");
    return (NULL);
  }

  /* break line into words */
  if (!get_words(orig_line, max_line_size, max_words, word_buffer, words, &nwords)) {
    fprintf(stderr, "Unable to parse first line from ply file\n");
    return (NULL);
  }

  // Check for ply keyword
  if (!equal_strings (words[0], "ply")) {
    fprintf(stderr, "No ply keyword at beginning of ply file\n");
    return (NULL);
  }

  // Parse rest of header
  while (true) {
    /* read in a line */
    if (!fgets (orig_line, max_line_size, plyfile->fp)) {
      fprintf(stderr, "Unable to read line from header of ply file\n");
      return (NULL);
    }

    /* break line into words */
    if (!get_words(orig_line, max_line_size, max_words, word_buffer, words, &nwords)) {
      fprintf(stderr, "Unable to parse words of line in header of ply file\n");
      return (NULL);
    }

    /* parse words */
    if (equal_strings (words[0], "format")) {
      if (nwords != 3) {
	return (NULL);
      }
      if (equal_strings (words[1], "ascii"))
        plyfile->file_type = PLY_ASCII;
      else if (equal_strings (words[1], "binary_big_endian"))
        plyfile->file_type = PLY_BINARY_BE;
      else if (equal_strings (words[1], "binary_little_endian"))
        plyfile->file_type = PLY_BINARY_LE;
      else {
        fprintf(stderr, "Unrecognized format (%s) in ply file\n", words[1]);
        return (NULL);
      }
      plyfile->version = atof (words[2]);
    }
    else if (equal_strings (words[0], "element"))
      add_element (plyfile, words);
    else if (equal_strings (words[0], "property"))
      add_property (plyfile, words);
    else if (equal_strings (words[0], "comment"))
      add_comment (plyfile, orig_line);
    else if (equal_strings (words[0], "obj_info"))
      add_obj_info (plyfile, orig_line);
    else if (equal_strings (words[0], "end_header")) {
      break;
    }
  }

  /* create tags for each property of each element, to be used */
  /* later to say whether or not to store each property for the user */

  for (i = 0; i < plyfile->nelems; i++) {
    elem = plyfile->elems[i];
    elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
    for (j = 0; j < elem->nprops; j++)
      elem->store_prop[j] = DONT_STORE_PROP;
    elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
  }

  /* set return values about the elements */

  elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
  for (i = 0; i < plyfile->nelems; i++)
    elist[i] = my_strdup (plyfile->elems[i]->name);

  *elem_names = elist;
  *nelems = plyfile->nelems;

  /* return a pointer to the file's information */

  return (plyfile);
}

// Assembly:
subq $0x4068, %rsp           # imm = 0x4068
movq %rdi, 0x4058(%rsp)
movq %rsi, 0x4050(%rsp)
movq %rdx, 0x4048(%rsp)
movl $0x1000, 0x4034(%rsp) # imm = 0x1000
movl $0x400, 0x302c(%rsp) # imm = 0x400
movl $0x0, 0x1c(%rsp)
cmpq $0x0, 0x4058(%rsp)
jne 0x72d19
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
cmpl $-0x1, 0x1055e4(%rip)   # 0x178304
jne 0x72d27
callq 0x71500
cmpl $0x0, 0x50694a(%rip)    # 0x579678
jne 0x72d35
callq 0x71580
movl $0x50, %edi
movl $0x2e6, %esi            # imm = 0x2E6
leaq 0xc25a9(%rip), %rdx     # 0x1352ef
callq 0x71630
movq %rax, 0x4038(%rsp)
movq 0x4038(%rsp), %rax
movl $0x0, 0x10(%rax)
movq 0x4038(%rsp), %rax
movq $0x0, 0x28(%rax)
movq 0x4038(%rsp), %rax
movl $0x0, 0x20(%rax)
movq 0x4038(%rsp), %rax
movq $0x0, 0x38(%rax)
movq 0x4038(%rsp), %rax
movl $0x0, 0x30(%rax)
movq 0x4058(%rsp), %rcx
movq 0x4038(%rsp), %rax
movq %rcx, (%rax)
movq 0x4038(%rsp), %rax
movq $0x0, 0x48(%rax)
leaq 0x3030(%rsp), %rdi
movq 0x4038(%rsp), %rax
movq (%rax), %rdx
movl $0x1000, %esi           # imm = 0x1000
callq 0xf7e0
cmpq $0x0, %rax
jne 0x72e0f
movq 0xfc1db(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
leaq 0xc26bc(%rip), %rsi     # 0x1354b3
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
leaq 0x3030(%rsp), %rdi
leaq 0x20(%rsp), %rcx
leaq 0x1020(%rsp), %r8
movl $0x1000, %esi           # imm = 0x1000
movl $0x400, %edx            # imm = 0x400
leaq 0x1c(%rsp), %r9
callq 0x732f0
cmpl $0x0, %eax
jne 0x72e66
movq 0xfc184(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
leaq 0xc268a(%rip), %rsi     # 0x1354d8
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
movq 0x1020(%rsp), %rdi
leaq 0xc051b(%rip), %rsi     # 0x133390
callq 0x734b0
cmpl $0x0, %eax
jne 0x72ea8
movq 0xfc142(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
leaq 0xc2672(%rip), %rsi     # 0x135502
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
jmp 0x72eaa
leaq 0x3030(%rsp), %rdi
movq 0x4038(%rsp), %rax
movq (%rax), %rdx
movl $0x1000, %esi           # imm = 0x1000
callq 0xf7e0
cmpq $0x0, %rax
jne 0x72ef6
movq 0xfc0f4(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
leaq 0xc264d(%rip), %rsi     # 0x13552b
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
leaq 0x3030(%rsp), %rdi
leaq 0x20(%rsp), %rcx
leaq 0x1020(%rsp), %r8
movl $0x1000, %esi           # imm = 0x1000
movl $0x400, %edx            # imm = 0x400
leaq 0x1c(%rsp), %r9
callq 0x732f0
cmpl $0x0, %eax
jne 0x72f4d
movq 0xfc09d(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
leaq 0xc2623(%rip), %rsi     # 0x135558
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
movq 0x1020(%rsp), %rdi
leaq 0xc2631(%rip), %rsi     # 0x13558d
callq 0x734b0
cmpl $0x0, %eax
je 0x7305b
cmpl $0x3, 0x1c(%rsp)
je 0x72f82
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
movq 0x1028(%rsp), %rdi
leaq 0xc2603(%rip), %rsi     # 0x135594
callq 0x734b0
cmpl $0x0, %eax
je 0x72faf
movq 0x4038(%rsp), %rax
movl $0x1, 0x8(%rax)
jmp 0x73038
movq 0x1028(%rsp), %rdi
leaq 0xc25dc(%rip), %rsi     # 0x13559a
callq 0x734b0
cmpl $0x0, %eax
je 0x72fd9
movq 0x4038(%rsp), %rax
movl $0x2, 0x8(%rax)
jmp 0x73036
movq 0x1028(%rsp), %rdi
leaq 0xc25c4(%rip), %rsi     # 0x1355ac
callq 0x734b0
cmpl $0x0, %eax
je 0x73003
movq 0x4038(%rsp), %rax
movl $0x3, 0x8(%rax)
jmp 0x73034
movq 0xfbfbe(%rip), %rax     # 0x16efc8
movq (%rax), %rdi
movq 0x1028(%rsp), %rdx
leaq 0xc25a5(%rip), %rsi     # 0x1355c1
movb $0x0, %al
callq 0xf730
movq $0x0, 0x4060(%rsp)
jmp 0x732e0
jmp 0x73036
jmp 0x73038
movq 0x1030(%rsp), %rdi
callq 0xf640
cvtsd2ss %xmm0, %xmm0
movq 0x4038(%rsp), %rax
movss %xmm0, 0xc(%rax)
jmp 0x73146
movq 0x1020(%rsp), %rdi
leaq 0xc257d(%rip), %rsi     # 0x1355e7
callq 0x734b0
cmpl $0x0, %eax
je 0x7308e
movq 0x4038(%rsp), %rdi
leaq 0x1020(%rsp), %rsi
callq 0x73550
jmp 0x73144
movq 0x1020(%rsp), %rdi
leaq 0xc2552(%rip), %rsi     # 0x1355ef
callq 0x734b0
cmpl $0x0, %eax
je 0x730c1
movq 0x4038(%rsp), %rdi
leaq 0x1020(%rsp), %rsi
callq 0x73640
jmp 0x73142
movq 0x1020(%rsp), %rdi
leaq 0xc2528(%rip), %rsi     # 0x1355f8
callq 0x734b0
cmpl $0x0, %eax
je 0x730f1
movq 0x4038(%rsp), %rdi
leaq 0x3030(%rsp), %rsi
callq 0x737c0
jmp 0x73140
movq 0x1020(%rsp), %rdi
leaq 0xc2500(%rip), %rsi     # 0x135600
callq 0x734b0
cmpl $0x0, %eax
je 0x73121
movq 0x4038(%rsp), %rdi
leaq 0x3030(%rsp), %rsi
callq 0x73840
jmp 0x7313e
movq 0x1020(%rsp), %rdi
leaq 0xc24d9(%rip), %rsi     # 0x135609
callq 0x734b0
cmpl $0x0, %eax
je 0x7313c
jmp 0x7314b
jmp 0x7313e
jmp 0x73140
jmp 0x73142
jmp 0x73144
jmp 0x73146
jmp 0x72eaa
movl $0x0, 0x4044(%rsp)
movl 0x4044(%rsp), %eax
movq 0x4038(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jge 0x7321d
movq 0x4038(%rsp), %rax
movq 0x18(%rax), %rax
movslq 0x4044(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rax
movslq 0x10(%rax), %rax
shlq $0x0, %rax
movl %eax, %edi
movl $0x334, %esi            # imm = 0x334
leaq 0xc2149(%rip), %rdx     # 0x1352ef
callq 0x71630
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x20(%rax)
movl $0x0, 0x4040(%rsp)
movl 0x4040(%rsp), %eax
movq 0x8(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jge 0x731fb
movq 0x8(%rsp), %rax
movq 0x20(%rax), %rax
movslq 0x4040(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movl 0x4040(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4040(%rsp)
jmp 0x731c2
movq 0x8(%rsp), %rax
movl $0xffffffff, 0x28(%rax) # imm = 0xFFFFFFFF
movl 0x4044(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4044(%rsp)
jmp 0x73156
movq 0x4038(%rsp), %rax
movslq 0x10(%rax), %rax
shlq $0x3, %rax
movl %eax, %edi
movl $0x33c, %esi            # imm = 0x33C
leaq 0xc20b4(%rip), %rdx     # 0x1352ef
callq 0x71630
movq %rax, 0x10(%rsp)
movl $0x0, 0x4044(%rsp)
movl 0x4044(%rsp), %eax
movq 0x4038(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jge 0x732ab
movq 0x4038(%rsp), %rax
movq 0x18(%rax), %rax
movslq 0x4044(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq (%rax), %rdi
callq 0x71680
movq %rax, %rdx
movq 0x10(%rsp), %rax
movslq 0x4044(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x4044(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4044(%rsp)
jmp 0x73250
movq 0x10(%rsp), %rcx
movq 0x4048(%rsp), %rax
movq %rcx, (%rax)
movq 0x4038(%rsp), %rax
movl 0x10(%rax), %ecx
movq 0x4050(%rsp), %rax
movl %ecx, (%rax)
movq 0x4038(%rsp), %rax
movq %rax, 0x4060(%rsp)
movq 0x4060(%rsp), %rax
addq $0x4068, %rsp           # imm = 0x4068
retq