// File: tomfunkhouser[P]gaps/pkgs/png/pngrutil.c
// Function: png_handle_sCAL
void /* PRIVATE */
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_charp ep;
#ifdef PNG_FLOATING_POINT_SUPPORTED
   double width, height;
   png_charp vp;
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_charp swidth, sheight;
#endif
#endif
   png_size_t slength;

   png_debug(1, "in png_handle_sCAL");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sCAL");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sCAL after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
   {
      png_warning(png_ptr, "Duplicate sCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
      length + 1);
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (png_ptr->chunkdata == NULL)
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
   slength = (png_size_t)length;
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);

   if (png_crc_finish(png_ptr, 0))
   {
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
   }

   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */

   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */

#ifdef PNG_FLOATING_POINT_SUPPORTED
   width = png_strtod(png_ptr, ep, &vp);
   if (*vp)
   {
      png_warning(png_ptr, "malformed width string in sCAL chunk");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
   }
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   if (swidth == NULL)
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
   }
   png_memcpy(swidth, ep, png_strlen(ep));
#endif
#endif

   for (ep = png_ptr->chunkdata; *ep; ep++)
      /* Empty loop */ ;
   ep++;

   if (png_ptr->chunkdata + slength < ep)
   {
      png_warning(png_ptr, "Truncated sCAL chunk");
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
      png_free(png_ptr, swidth);
#endif
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
   }

#ifdef PNG_FLOATING_POINT_SUPPORTED
   height = png_strtod(png_ptr, ep, &vp);
   if (*vp)
   {
      png_warning(png_ptr, "malformed height string in sCAL chunk");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      return;
   }
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   if (sheight == NULL)
   {
      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
      png_free(png_ptr, swidth);
      return;
   }
   png_memcpy(sheight, ep, png_strlen(ep));
#endif
#endif

   if (png_ptr->chunkdata + slength < ep
#ifdef PNG_FLOATING_POINT_SUPPORTED
      || width <= 0. || height <= 0.
#endif
      )
   {
      png_warning(png_ptr, "Invalid sCAL data");
      png_free(png_ptr, png_ptr->chunkdata);
      png_ptr->chunkdata = NULL;
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
      png_free(png_ptr, swidth);
      png_free(png_ptr, sheight);
#endif
      return;
   }


#ifdef PNG_FLOATING_POINT_SUPPORTED
   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
#endif
#endif

   png_free(png_ptr, png_ptr->chunkdata);
   png_ptr->chunkdata = NULL;
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
   png_free(png_ptr, swidth);
   png_free(png_ptr, sheight);
#endif
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movl %edx, 0x34(%rsp)
movq 0x40(%rsp), %rax
movl 0x11c(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x1264a8
movq 0x40(%rsp), %rdi
leaq 0x196f2(%rip), %rsi     # 0x13fb93
callq 0x113860
jmp 0x126521
movq 0x40(%rsp), %rax
movl 0x11c(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x1264df
movq 0x40(%rsp), %rdi
leaq 0x196e5(%rip), %rsi     # 0x13fbac
callq 0x113940
movq 0x40(%rsp), %rdi
movl 0x34(%rsp), %esi
callq 0x122b90
jmp 0x1267fe
cmpq $0x0, 0x38(%rsp)
je 0x12651d
movq 0x38(%rsp), %rax
movl 0x8(%rax), %eax
andl $0x4000, %eax           # imm = 0x4000
cmpl $0x0, %eax
je 0x12651d
movq 0x40(%rsp), %rdi
leaq 0x196bf(%rip), %rsi     # 0x13fbc4
callq 0x113940
movq 0x40(%rsp), %rdi
movl 0x34(%rsp), %esi
callq 0x122b90
jmp 0x1267fe
jmp 0x12651f
jmp 0x126521
movq 0x40(%rsp), %rdi
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
callq 0x113760
movq %rax, %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x488(%rax)
movq 0x40(%rsp), %rax
cmpq $0x0, 0x488(%rax)
jne 0x126578
movq 0x40(%rsp), %rdi
leaq 0x19679(%rip), %rsi     # 0x13fbd9
callq 0x113940
movq 0x40(%rsp), %rdi
movl 0x34(%rsp), %esi
callq 0x122b90
jmp 0x1267fe
movl 0x34(%rsp), %eax
movq %rax, 0x8(%rsp)
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
movq 0x8(%rsp), %rdx
callq 0x122b40
movq 0x40(%rsp), %rdi
xorl %esi, %esi
callq 0x122b90
cmpl $0x0, %eax
je 0x1265d8
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
jmp 0x1267fe
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
movq 0x8(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
addq $0x1, %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0xf370
movsd %xmm0, 0x20(%rsp)
movq 0x10(%rsp), %rax
cmpb $0x0, (%rax)
je 0x12665d
movq 0x40(%rsp), %rdi
leaq 0x195d6(%rip), %rsi     # 0x13fc03
callq 0x113940
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
jmp 0x1267fe
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
cmpb $0x0, (%rax)
je 0x12668a
jmp 0x12667a
movq 0x28(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x28(%rsp)
jmp 0x12666e
movq 0x28(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
addq 0x8(%rsp), %rax
cmpq 0x28(%rsp), %rax
jae 0x1266ec
movq 0x40(%rsp), %rdi
leaq 0x1956c(%rip), %rsi     # 0x13fc28
callq 0x113940
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
jmp 0x1267fe
movq 0x28(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0xf370
movsd %xmm0, 0x18(%rsp)
movq 0x10(%rsp), %rax
cmpb $0x0, (%rax)
je 0x126747
movq 0x40(%rsp), %rdi
leaq 0x19526(%rip), %rsi     # 0x13fc3d
callq 0x113940
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
jmp 0x1267fe
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
addq 0x8(%rsp), %rax
cmpq 0x28(%rsp), %rax
jb 0x126775
xorps %xmm0, %xmm0
ucomisd 0x20(%rsp), %xmm0
jae 0x126775
xorps %xmm0, %xmm0
ucomisd 0x18(%rsp), %xmm0
jb 0x1267ae
movq 0x40(%rsp), %rdi
leaq 0x194e2(%rip), %rsi     # 0x13fc63
callq 0x113940
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
jmp 0x1267fe
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rax
movsbl (%rax), %edx
movsd 0x20(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
callq 0xfd8a0
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rax
movq 0x488(%rax), %rsi
callq 0x1136d0
movq 0x40(%rsp), %rax
movq $0x0, 0x488(%rax)
addq $0x48, %rsp
retq
nopw %cs:(%rax,%rax)