// File: tomfunkhouser[P]gaps/pkgs/jpeg/jcmaster.c
// Function: validate_script
LOCAL(void)
validate_script (j_compress_ptr cinfo)
/* Verify that the scan script in cinfo->scan_info[] is valid; also
 * determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
 */
{
  const jpeg_scan_info * scanptr;
  int scanno, ncomps, ci, coefi, thisi;
  int Ss, Se, Ah, Al;
  jboolean component_sent[MAX_COMPONENTS];
#ifdef C_PROGRESSIVE_SUPPORTED
  int * last_bitpos_ptr;
  int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
  /* -1 until that coefficient has been seen; then last Al for it */
#endif

  if (cinfo->num_scans <= 0)
    ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);

  /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
   * for progressive JPEG, no scan can have this.
   */
  scanptr = cinfo->scan_info;
  if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
#ifdef C_PROGRESSIVE_SUPPORTED
    cinfo->progressive_mode = TRUE;
    last_bitpos_ptr = & last_bitpos[0][0];
    for (ci = 0; ci < cinfo->num_components; ci++) 
      for (coefi = 0; coefi < DCTSIZE2; coefi++)
	*last_bitpos_ptr++ = -1;
#else
    ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
  } else {
    cinfo->progressive_mode = FALSE;
    for (ci = 0; ci < cinfo->num_components; ci++) 
      component_sent[ci] = FALSE;
  }

  for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
    /* Validate component indexes */
    ncomps = scanptr->comps_in_scan;
    if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
    for (ci = 0; ci < ncomps; ci++) {
      thisi = scanptr->component_index[ci];
      if (thisi < 0 || thisi >= cinfo->num_components)
	ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
      /* Components must appear in SOF order within each scan */
      if (ci > 0 && thisi <= scanptr->component_index[ci-1])
	ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
    }
    /* Validate progression parameters */
    Ss = scanptr->Ss;
    Se = scanptr->Se;
    Ah = scanptr->Ah;
    Al = scanptr->Al;
    if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
      /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
       * seems wrong: the upper bound ought to depend on data precision.
       * Perhaps they really meant 0..N+1 for N-bit precision.
       * Here we allow 0..10 for 8-bit data; Al larger than 10 results in
       * out-of-range reconstructed DC values during the first DC scan,
       * which might cause problems for some decoders.
       */
#if BITS_IN_JSAMPLE == 8
#define MAX_AH_AL 10
#else
#define MAX_AH_AL 13
#endif
      if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
	  Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
	ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
      if (Ss == 0) {
	if (Se != 0)		/* DC and AC together not OK */
	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
      } else {
	if (ncomps != 1)	/* AC scans must be for only one component */
	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
      }
      for (ci = 0; ci < ncomps; ci++) {
	last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
	if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
	for (coefi = Ss; coefi <= Se; coefi++) {
	  if (last_bitpos_ptr[coefi] < 0) {
	    /* first scan of this coefficient */
	    if (Ah != 0)
	      ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
	  } else {
	    /* not first scan */
	    if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
	      ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
	  }
	  last_bitpos_ptr[coefi] = Al;
	}
      }
#endif
    } else {
      /* For sequential JPEG, all progression parameters must be these: */
      if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
	ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
      /* Make sure components are not sent twice */
      for (ci = 0; ci < ncomps; ci++) {
	thisi = scanptr->component_index[ci];
	if (component_sent[thisi])
	  ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
	component_sent[thisi] = TRUE;
      }
    }
  }

  /* Now verify that everything got sent. */
  if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
    /* For progressive mode, we only check that at least some DC data
     * got sent for each component; the spec does not require that all bits
     * of all coefficients be transmitted.  Would it be wiser to enforce
     * transmission of all coefficient bits??
     */
    for (ci = 0; ci < cinfo->num_components; ci++) {
      if (last_bitpos[ci][0] < 0)
	ERREXIT(cinfo, JERR_MISSING_DATA);
    }
#endif
  } else {
    for (ci = 0; ci < cinfo->num_components; ci++) {
      if (! component_sent[ci])
	ERREXIT(cinfo, JERR_MISSING_DATA);
    }
  }
}

// Assembly:
subq $0xa78, %rsp            # imm = 0xA78
movq %rdi, 0xa70(%rsp)
movq 0xa70(%rsp), %rax
cmpl $0x0, 0xf0(%rax)
jg 0xd7dbc
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x13, 0x28(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x0, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
movq 0xa70(%rsp), %rax
movq 0xf8(%rax), %rax
movq %rax, 0xa68(%rsp)
movq 0xa68(%rsp), %rax
cmpl $0x0, 0x14(%rax)
jne 0xd7df3
movq 0xa68(%rsp), %rax
cmpl $0x3f, 0x18(%rax)
je 0xd7e8b
movq 0xa70(%rsp), %rax
movl $0x1, 0x134(%rax)
movq %rsp, %rax
movq %rax, 0xa08(%rsp)
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0x4c(%rcx), %eax
jge 0xd7e89
movl $0x0, 0xa58(%rsp)
cmpl $0x40, 0xa58(%rsp)
jge 0xd7e74
movq 0xa08(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0xa08(%rsp)
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movl 0xa58(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa58(%rsp)
jmp 0xd7e3a
jmp 0xd7e76
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd7e1b
jmp 0xd7ee4
movq 0xa70(%rsp), %rax
movl $0x0, 0x134(%rax)
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0x4c(%rcx), %eax
jge 0xd7ee2
movslq 0xa5c(%rsp), %rax
movl $0x0, 0xa10(%rsp,%rax,4)
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd7ea8
jmp 0xd7ee4
movl $0x1, 0xa64(%rsp)
movl 0xa64(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0xf0(%rcx), %eax
jg 0xd8553
movq 0xa68(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xa60(%rsp)
cmpl $0x0, 0xa60(%rsp)
jle 0xd7f2f
cmpl $0x4, 0xa60(%rsp)
jle 0xd7f80
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x1a, 0x28(%rax)
movl 0xa60(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x4, 0x30(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
cmpl 0xa60(%rsp), %eax
jge 0xd809a
movq 0xa68(%rsp), %rax
movslq 0xa5c(%rsp), %rcx
movl 0x4(%rax,%rcx,4), %eax
movl %eax, 0xa54(%rsp)
cmpl $0x0, 0xa54(%rsp)
jl 0xd7fd8
movl 0xa54(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0x4c(%rcx), %eax
jl 0xd8017
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x13, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
cmpl $0x0, 0xa5c(%rsp)
jle 0xd8082
movl 0xa54(%rsp), %eax
movq 0xa68(%rsp), %rcx
movl 0xa5c(%rsp), %edx
subl $0x1, %edx
movslq %edx, %rdx
cmpl 0x4(%rcx,%rdx,4), %eax
jg 0xd8082
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x13, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd8084
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd7f8b
movq 0xa68(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, 0xa50(%rsp)
movq 0xa68(%rsp), %rax
movl 0x18(%rax), %eax
movl %eax, 0xa4c(%rsp)
movq 0xa68(%rsp), %rax
movl 0x1c(%rax), %eax
movl %eax, 0xa48(%rsp)
movq 0xa68(%rsp), %rax
movl 0x20(%rax), %eax
movl %eax, 0xa44(%rsp)
movq 0xa70(%rsp), %rax
cmpl $0x0, 0x134(%rax)
je 0xd840a
cmpl $0x0, 0xa50(%rsp)
jl 0xd814d
cmpl $0x40, 0xa50(%rsp)
jge 0xd814d
movl 0xa4c(%rsp), %eax
cmpl 0xa50(%rsp), %eax
jl 0xd814d
cmpl $0x40, 0xa4c(%rsp)
jge 0xd814d
cmpl $0x0, 0xa48(%rsp)
jl 0xd814d
cmpl $0xa, 0xa48(%rsp)
jg 0xd814d
cmpl $0x0, 0xa44(%rsp)
jl 0xd814d
cmpl $0xa, 0xa44(%rsp)
jle 0xd818c
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
cmpl $0x0, 0xa50(%rsp)
jne 0xd81e1
cmpl $0x0, 0xa4c(%rsp)
je 0xd81df
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd822c
cmpl $0x1, 0xa60(%rsp)
je 0xd822a
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd822c
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
cmpl 0xa60(%rsp), %eax
jge 0xd8405
movq 0xa68(%rsp), %rax
movslq 0xa5c(%rsp), %rcx
movslq 0x4(%rax,%rcx,4), %rcx
movq %rsp, %rax
shlq $0x8, %rcx
addq %rcx, %rax
movq %rax, 0xa08(%rsp)
cmpl $0x0, 0xa50(%rsp)
je 0xd82c8
movq 0xa08(%rsp), %rax
cmpl $0x0, (%rax)
jge 0xd82c8
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
movl 0xa50(%rsp), %eax
movl %eax, 0xa58(%rsp)
movl 0xa58(%rsp), %eax
cmpl 0xa4c(%rsp), %eax
jg 0xd83ed
movq 0xa08(%rsp), %rax
movslq 0xa58(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0xd834b
cmpl $0x0, 0xa48(%rsp)
je 0xd8349
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd83bd
movl 0xa48(%rsp), %eax
movq 0xa08(%rsp), %rcx
movslq 0xa58(%rsp), %rdx
cmpl (%rcx,%rdx,4), %eax
jne 0xd837c
movl 0xa44(%rsp), %eax
movl 0xa48(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0xd83bb
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd83bd
movl 0xa44(%rsp), %edx
movq 0xa08(%rsp), %rax
movslq 0xa58(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
movl 0xa58(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa58(%rsp)
jmp 0xd82d6
jmp 0xd83ef
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd8237
jmp 0xd8527
cmpl $0x0, 0xa50(%rsp)
jne 0xd8432
cmpl $0x3f, 0xa4c(%rsp)
jne 0xd8432
cmpl $0x0, 0xa48(%rsp)
jne 0xd8432
cmpl $0x0, 0xa44(%rsp)
je 0xd8471
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x11, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
cmpl 0xa60(%rsp), %eax
jge 0xd8525
movq 0xa68(%rsp), %rax
movslq 0xa5c(%rsp), %rcx
movl 0x4(%rax,%rcx,4), %eax
movl %eax, 0xa54(%rsp)
movslq 0xa54(%rsp), %rax
cmpl $0x0, 0xa10(%rsp,%rax,4)
je 0xd84fc
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x13, 0x28(%rax)
movl 0xa64(%rsp), %ecx
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
movslq 0xa54(%rsp), %rax
movl $0x1, 0xa10(%rsp,%rax,4)
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd847c
jmp 0xd8527
jmp 0xd8529
movq 0xa68(%rsp), %rax
addq $0x24, %rax
movq %rax, 0xa68(%rsp)
movl 0xa64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa64(%rsp)
jmp 0xd7eef
movq 0xa70(%rsp), %rax
cmpl $0x0, 0x134(%rax)
je 0xd85db
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0x4c(%rcx), %eax
jge 0xd85d9
movslq 0xa5c(%rsp), %rcx
movq %rsp, %rax
shlq $0x8, %rcx
addq %rcx, %rax
cmpl $0x0, (%rax)
jge 0xd85c4
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x2d, 0x28(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd85c6
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd856f
jmp 0xd864d
movl $0x0, 0xa5c(%rsp)
movl 0xa5c(%rsp), %eax
movq 0xa70(%rsp), %rcx
cmpl 0x4c(%rcx), %eax
jge 0xd864b
movslq 0xa5c(%rsp), %rax
cmpl $0x0, 0xa10(%rsp,%rax,4)
jne 0xd8636
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movl $0x2d, 0x28(%rax)
movq 0xa70(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0xa70(%rsp), %rdi
callq *%rax
jmp 0xd8638
movl 0xa5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa5c(%rsp)
jmp 0xd85e6
jmp 0xd864d
addq $0xa78, %rsp            # imm = 0xA78
retq
nopw %cs:(%rax,%rax)