// File: tomfunkhouser[P]gaps/pkgs/png/pngwutil.c
// Function: png_text_compress
static int /* PRIVATE */
png_text_compress(png_structp png_ptr,
        png_charp text, png_size_t text_len, int compression,
        compression_state *comp)
{
   int ret;

   comp->num_output_ptr = 0;
   comp->max_output_ptr = 0;
   comp->output_ptr = NULL;
   comp->input = NULL;
   comp->input_len = 0;

   /* We may just want to pass the text right through */
   if (compression == PNG_TEXT_COMPRESSION_NONE)
   {
       comp->input = text;
       comp->input_len = text_len;
       return((int)text_len);
   }

   if (compression >= PNG_TEXT_COMPRESSION_LAST)
   {
#ifdef PNG_STDIO_SUPPORTED
      char msg[50];
      png_snprintf(msg, 50, "Unknown compression type %d", compression);
      png_warning(png_ptr, msg);
#else
      png_warning(png_ptr, "Unknown compression type");
#endif
   }

   /* We can't write the chunk until we find out how much data we have,
    * which means we need to run the compressor first and save the
    * output.  This shouldn't be a problem, as the vast majority of
    * comments should be reasonable, but we will set up an array of
    * malloc'd pointers to be sure.
    *
    * If we knew the application was well behaved, we could simplify this
    * greatly by assuming we can always malloc an output buffer large
    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
    * and malloc this directly.  The only time this would be a bad idea is
    * if we can't malloc more than 64K and we have 64K of random input
    * data, or if the input string is incredibly large (although this
    * wouldn't cause a failure, just a slowdown due to swapping).
    */

   /* Set up the compression buffers */
   png_ptr->zstream.avail_in = (uInt)text_len;
   png_ptr->zstream.next_in = (Bytef *)text;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
   png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;

   /* This is the same compression loop as in png_write_row() */
   do
   {
      /* Compress the data */
      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
      if (ret != Z_OK)
      {
         /* Error */
         if (png_ptr->zstream.msg != NULL)
            png_error(png_ptr, png_ptr->zstream.msg);
         else
            png_error(png_ptr, "zlib error");
      }
      /* Check to see if we need more room */
      if (!(png_ptr->zstream.avail_out))
      {
         /* Make sure the output array has room */
         if (comp->num_output_ptr >= comp->max_output_ptr)
         {
            int old_max;

            old_max = comp->max_output_ptr;
            comp->max_output_ptr = comp->num_output_ptr + 4;
            if (comp->output_ptr != NULL)
            {
               png_charpp old_ptr;

               old_ptr = comp->output_ptr;
               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                  (png_alloc_size_t)
                  (comp->max_output_ptr * png_sizeof(png_charpp)));
               png_memcpy(comp->output_ptr, old_ptr, old_max
                  * png_sizeof(png_charp));
               png_free(png_ptr, old_ptr);
            }
            else
               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                  (png_alloc_size_t)
                  (comp->max_output_ptr * png_sizeof(png_charp)));
         }

         /* Save the data */
         comp->output_ptr[comp->num_output_ptr] =
            (png_charp)png_malloc(png_ptr,
            (png_alloc_size_t)png_ptr->zbuf_size);
         png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
            png_ptr->zbuf_size);
         comp->num_output_ptr++;

         /* and reset the buffer */
         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
         png_ptr->zstream.next_out = png_ptr->zbuf;
      }
   /* Continue until we don't have any more to compress */
   } while (png_ptr->zstream.avail_in);

   /* Finish the compression */
   do
   {
      /* Tell zlib we are finished */
      ret = deflate(&png_ptr->zstream, Z_FINISH);

      if (ret == Z_OK)
      {
         /* Check to see if we need more room */
         if (!(png_ptr->zstream.avail_out))
         {
            /* Check to make sure our output array has room */
            if (comp->num_output_ptr >= comp->max_output_ptr)
            {
               int old_max;

               old_max = comp->max_output_ptr;
               comp->max_output_ptr = comp->num_output_ptr + 4;
               if (comp->output_ptr != NULL)
               {
                  png_charpp old_ptr;

                  old_ptr = comp->output_ptr;
                  /* This could be optimized to realloc() */
                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                     (png_alloc_size_t)(comp->max_output_ptr *
                     png_sizeof(png_charp)));
                  png_memcpy(comp->output_ptr, old_ptr,
                     old_max * png_sizeof(png_charp));
                  png_free(png_ptr, old_ptr);
               }
               else
                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                     (png_alloc_size_t)(comp->max_output_ptr *
                     png_sizeof(png_charp)));
            }

            /* Save the data */
            comp->output_ptr[comp->num_output_ptr] =
               (png_charp)png_malloc(png_ptr,
               (png_alloc_size_t)png_ptr->zbuf_size);
            png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
               png_ptr->zbuf_size);
            comp->num_output_ptr++;

            /* and reset the buffer pointers */
            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
            png_ptr->zstream.next_out = png_ptr->zbuf;
         }
      }
      else if (ret != Z_STREAM_END)
      {
         /* We got an error */
         if (png_ptr->zstream.msg != NULL)
            png_error(png_ptr, png_ptr->zstream.msg);
         else
            png_error(png_ptr, "zlib error");
      }
   } while (ret != Z_STREAM_END);

   /* Text length is number of buffers plus last buffer */
   text_len = png_ptr->zbuf_size * comp->num_output_ptr;
   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;

   return((int)text_len);
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x78(%rsp)
movq %rsi, 0x70(%rsp)
movq %rdx, 0x68(%rsp)
movl %ecx, 0x64(%rsp)
movq %r8, 0x58(%rsp)
movq 0x58(%rsp), %rax
movl $0x0, 0xc(%rax)
movq 0x58(%rsp), %rax
movl $0x0, 0x10(%rax)
movq 0x58(%rsp), %rax
movq $0x0, 0x18(%rax)
movq 0x58(%rsp), %rax
movq $0x0, (%rax)
movq 0x58(%rsp), %rax
movl $0x0, 0x8(%rax)
cmpl $-0x1, 0x64(%rsp)
jne 0x12c350
movq 0x70(%rsp), %rcx
movq 0x58(%rsp), %rax
movq %rcx, (%rax)
movq 0x68(%rsp), %rax
movl %eax, %ecx
movq 0x58(%rsp), %rax
movl %ecx, 0x8(%rax)
movq 0x68(%rsp), %rax
movl %eax, 0x84(%rsp)
jmp 0x12c80d
cmpl $0x3, 0x64(%rsp)
jl 0x12c382
leaq 0x20(%rsp), %rdi
movl 0x64(%rsp), %ecx
movl $0x32, %esi
leaq 0x14876(%rip), %rdx     # 0x140be2
movb $0x0, %al
callq 0xf800
movq 0x78(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x113940
movq 0x68(%rsp), %rax
movl %eax, %ecx
movq 0x78(%rsp), %rax
movl %ecx, 0x130(%rax)
movq 0x70(%rsp), %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x128(%rax)
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rax
movl %eax, %ecx
movq 0x78(%rsp), %rax
movl %ecx, 0x148(%rax)
movq 0x78(%rsp), %rax
movq 0x198(%rax), %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x140(%rax)
movq 0x78(%rsp), %rdi
addq $0x128, %rdi            # imm = 0x128
xorl %esi, %esi
callq 0x115c80
movl %eax, 0x54(%rsp)
cmpl $0x0, 0x54(%rsp)
je 0x12c42e
movq 0x78(%rsp), %rax
cmpq $0x0, 0x158(%rax)
je 0x12c41b
movq 0x78(%rsp), %rdi
movq 0x78(%rsp), %rax
movq 0x158(%rax), %rsi
callq 0x113860
jmp 0x12c42c
movq 0x78(%rsp), %rdi
leaq 0xcd4b(%rip), %rsi      # 0x139172
callq 0x113860
jmp 0x12c42e
movq 0x78(%rsp), %rax
cmpl $0x0, 0x148(%rax)
jne 0x12c5a5
movq 0x58(%rsp), %rax
movl 0xc(%rax), %eax
movq 0x58(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jl 0x12c504
movq 0x58(%rsp), %rax
movl 0x10(%rax), %eax
movl %eax, 0x1c(%rsp)
movq 0x58(%rsp), %rax
movl 0xc(%rax), %ecx
addl $0x4, %ecx
movq 0x58(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x58(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x12c4df
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0x78(%rsp), %rdi
movq 0x58(%rsp), %rax
movslq 0x10(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq %rcx, 0x18(%rax)
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rdi
movq 0x10(%rsp), %rsi
movslq 0x1c(%rsp), %rdx
shlq $0x3, %rdx
callq 0xf3d0
movq 0x78(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x1136d0
jmp 0x12c502
movq 0x78(%rsp), %rdi
movq 0x58(%rsp), %rax
movslq 0x10(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq %rcx, 0x18(%rax)
jmp 0x12c504
movq 0x78(%rsp), %rdi
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rsi
callq 0x1135b0
movq %rax, %rdx
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x58(%rsp), %rcx
movslq 0xc(%rcx), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x58(%rsp), %rcx
movslq 0xc(%rcx), %rcx
movq (%rax,%rcx,8), %rdi
movq 0x78(%rsp), %rax
movq 0x198(%rax), %rsi
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rdx
callq 0xf3d0
movq 0x58(%rsp), %rax
movl 0xc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xc(%rax)
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rax
movl %eax, %ecx
movq 0x78(%rsp), %rax
movl %ecx, 0x148(%rax)
movq 0x78(%rsp), %rax
movq 0x198(%rax), %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x140(%rax)
jmp 0x12c5a7
movq 0x78(%rsp), %rax
cmpl $0x0, 0x130(%rax)
jne 0x12c3d6
jmp 0x12c5bb
movq 0x78(%rsp), %rdi
addq $0x128, %rdi            # imm = 0x128
movl $0x4, %esi
callq 0x115c80
movl %eax, 0x54(%rsp)
cmpl $0x0, 0x54(%rsp)
jne 0x12c756
movq 0x78(%rsp), %rax
cmpl $0x0, 0x148(%rax)
jne 0x12c754
movq 0x58(%rsp), %rax
movl 0xc(%rax), %eax
movq 0x58(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jl 0x12c6b3
movq 0x58(%rsp), %rax
movl 0x10(%rax), %eax
movl %eax, 0xc(%rsp)
movq 0x58(%rsp), %rax
movl 0xc(%rax), %ecx
addl $0x4, %ecx
movq 0x58(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x58(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x12c68e
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, (%rsp)
movq 0x78(%rsp), %rdi
movq 0x58(%rsp), %rax
movslq 0x10(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq %rcx, 0x18(%rax)
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rdi
movq (%rsp), %rsi
movslq 0xc(%rsp), %rdx
shlq $0x3, %rdx
callq 0xf3d0
movq 0x78(%rsp), %rdi
movq (%rsp), %rsi
callq 0x1136d0
jmp 0x12c6b1
movq 0x78(%rsp), %rdi
movq 0x58(%rsp), %rax
movslq 0x10(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq %rcx, 0x18(%rax)
jmp 0x12c6b3
movq 0x78(%rsp), %rdi
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rsi
callq 0x1135b0
movq %rax, %rdx
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x58(%rsp), %rcx
movslq 0xc(%rcx), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x58(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x58(%rsp), %rcx
movslq 0xc(%rcx), %rcx
movq (%rax,%rcx,8), %rdi
movq 0x78(%rsp), %rax
movq 0x198(%rax), %rsi
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rdx
callq 0xf3d0
movq 0x58(%rsp), %rax
movl 0xc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xc(%rax)
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rax
movl %eax, %ecx
movq 0x78(%rsp), %rax
movl %ecx, 0x148(%rax)
movq 0x78(%rsp), %rax
movq 0x198(%rax), %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x140(%rax)
jmp 0x12c799
cmpl $0x1, 0x54(%rsp)
je 0x12c797
movq 0x78(%rsp), %rax
cmpq $0x0, 0x158(%rax)
je 0x12c784
movq 0x78(%rsp), %rdi
movq 0x78(%rsp), %rax
movq 0x158(%rax), %rsi
callq 0x113860
jmp 0x12c795
movq 0x78(%rsp), %rdi
leaq 0xc9e2(%rip), %rsi      # 0x139172
callq 0x113860
jmp 0x12c797
jmp 0x12c799
jmp 0x12c79b
cmpl $0x1, 0x54(%rsp)
jne 0x12c5bb
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rax
movq 0x58(%rsp), %rcx
movslq 0xc(%rcx), %rcx
imulq %rcx, %rax
movq %rax, 0x68(%rsp)
movq 0x78(%rsp), %rax
movl 0x148(%rax), %eax
movq 0x78(%rsp), %rcx
cmpq 0x1a0(%rcx), %rax
jae 0x12c801
movq 0x78(%rsp), %rax
movq 0x1a0(%rax), %rax
movq 0x78(%rsp), %rcx
movl 0x148(%rcx), %ecx
subq %rcx, %rax
addq 0x68(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rax
movl %eax, 0x84(%rsp)
movl 0x84(%rsp), %eax
addq $0x88, %rsp
retq
nopl (%rax)