// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/tiff.c
// Function: process_ifd
static void process_ifd(deark *c, lctx *d, int ifd_idx1, i64 ifdpos1, u8 ifdtype1,
	u8 is_in_main_ifd_list)
{
	struct page_ctx *pg = NULL;
	int num_tags;
	int i;
	i64 tmpoffset;
	de_ucstring *dbgline = NULL;
	struct taginfo tg;
	const char *name;
	static const struct tagnuminfo default_tni = { 0, 0x00, "?", NULL, NULL };

	pg = de_malloc(c, sizeof(struct page_ctx));
	pg->density_ImageWidth = 0.0;
	pg->density_ImageLength = 0.0;
	pg->ifd_idx = ifd_idx1;
	pg->ifdpos = ifdpos1;
	pg->ifdtype = ifdtype1;
	if(is_in_main_ifd_list) {
		pg->ifd_idx_in_main_list = d->num_main_ifds_processed++;
		// Calling the first IFD "#0" is consistent with Exif, though not
		// necessarily with all other TIFF literature.
		de_snprintf(pg->ifdnum_string, sizeof(pg->ifdnum_string), "%d",
			pg->ifd_idx_in_main_list);
	}
	else {
		pg->ifd_idx_in_main_list = -1;
		de_strlcpy(pg->ifdnum_string, "special", sizeof(pg->ifdnum_string));
	}
	de_snprintf(pg->errmsgtoken_ifd, sizeof(pg->errmsgtoken_ifd),
		"IFD#%s@%"I64_FMT, pg->ifdnum_string, pg->ifdpos);

	// NOTE: Some TIFF apps (e.g. Windows Photo Viewer) have been observed to encode
	// ASCII fields (e.g. ImageDescription) in UTF-8, in violation of the TIFF spec.
	// It might be better to give up trying to obey the various specifications, and
	// just try to autodetect the encoding, based on whether it is valid UTF-8, etc.

	if(d->fmt==DE_TIFFFMT_JPEGXR)
		d->current_textfield_encoding = DE_ENCODING_UTF8; // Might be overridden below
	else
		d->current_textfield_encoding = DE_ENCODING_ASCII;

	switch(pg->ifdtype) {
	case IFDTYPE_SUBIFD:
		name=" (SubIFD)";
		break;
	case IFDTYPE_GLOBALPARAMS:
		name=" (Global Parameters IFD)";
		break;
	case IFDTYPE_EXIF:
		name=" (Exif IFD)";
		d->current_textfield_encoding = DE_ENCODING_ASCII;
		break;
	case IFDTYPE_EXIFINTEROP:
		name=" (Exif Interoperability IFD)";
		d->current_textfield_encoding = DE_ENCODING_ASCII;
		break;
	case IFDTYPE_GPS:
		name=" (GPS IFD)";
		d->current_textfield_encoding = DE_ENCODING_ASCII;
		break;
	case IFDTYPE_NIKONPREVIEW:
		name=" (Nikon Preview)";
		break;
	case IFDTYPE_MASKSUBIFD:
		name=" (Mask SubIFD)";
		break;
	default:
		name="";
	}

	de_dbg(c, "IFD#%s at %"I64_FMT"%s", pg->ifdnum_string, pg->ifdpos, name);
	de_dbg_indent(c, 1);

	if(pg->ifdpos >= c->infile->len || pg->ifdpos<8) {
		detiff_warn(c, d, NULL, "Invalid IFD offset: %"I64_FMT, pg->ifdpos);
		goto done;
	}

	if(d->is_bigtiff) {
		num_tags = (int)dbuf_geti64x(c->infile, pg->ifdpos, d->is_le);
	}
	else {
		num_tags = (int)dbuf_getu16x(c->infile, pg->ifdpos, d->is_le);
	}

	de_dbg(c, "number of tags: %d", num_tags);
	if(num_tags>200) {
		detiff_warn(c, d, pg, "Invalid or excessive number of TIFF tags (%d)", num_tags);
		goto done;
	}

	// Record the next IFD in the main list.
	tmpoffset = getfpos(c, d, pg->ifdpos+d->ifdhdrsize+num_tags*d->ifditemsize);
	de_dbg(c, "offset of next IFD: %"I64_FMT"%s", tmpoffset, tmpoffset==0?" (none)":"");
	push_ifd(c, d, tmpoffset, IFDTYPE_NORMAL, 1);

	dbgline = ucstring_create(c);

	for(i=0; i<num_tags; i++) {
		const struct tagnuminfo *tni;

		de_zeromem(&tg, sizeof(struct taginfo));
		tg.pg = pg;

		tg.tagnum = (int)dbuf_getu16x(c->infile, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize, d->is_le);
		tg.datatype = (int)dbuf_getu16x(c->infile, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+2, d->is_le);
		tg.valcount = getvalcount(c, d, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+4);
		if(tg.valcount > DE_TIFF_MAX_VALCOUNT) {
			// Must ensure that valcount, even after multiplying by 8 and adding to
			// the file size, does not risk integer overflow.
			tg.valcount = DE_TIFF_MAX_VALCOUNT;
		}

		tg.unit_size = size_of_data_type(tg.datatype);
		tg.total_size = tg.unit_size * tg.valcount;
		if(tg.total_size <= d->offsetsize) {
			tg.val_offset = pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+d->offsetoffset;
		}
		else {
			tg.val_offset = getfpos(c, d, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+d->offsetoffset);
		}

		// Fixup potential bad sizes
		if(tg.val_offset + tg.total_size > c->infile->len + DE_TIFF_ALLOWED_VIRTUAL_BYTES) {
			if(tg.val_offset > c->infile->len) {
				tg.valcount = 0;
				tg.total_size = 0;
			}
			else {
				tg.valcount = (c->infile->len - tg.val_offset)/tg.unit_size;
				tg.total_size = tg.unit_size * tg.valcount;
			}
		}

		tni = find_tagnuminfo(tg.tagnum, d->fmt, pg->ifdtype);
		if(tni) {
			tg.tag_known = 1;
		}
		else {
			tni = &default_tni; // Make sure tni is not NULL.
		}

		ucstring_empty(dbgline);
		ucstring_printf(dbgline, DE_ENCODING_UTF8,
			"tag %d (%s) ty=%d #=%d offs=%" I64_FMT,
			tg.tagnum, tni->tagname,
			tg.datatype, (int)tg.valcount,
			tg.val_offset);

		do_dbg_print_values(c, d, &tg, tni, dbgline);

		// do_dbg_print_values() already tried to limit the line length.
		// The "500+" in the next line is an emergency brake.
		de_dbg(c, "%s", ucstring_getpsz_n(dbgline, 500+DE_DBG_MAX_STRLEN));

		de_dbg_indent(c, 1);

		if(tni->hfn) {
			tni->hfn(c, d, &tg, tni);
		}

		de_dbg_indent(c, -1);
	}

	postprocess_ifd_tags(c, d, pg);

	do_process_ifd_image(c, d, pg);

done:
	de_dbg_indent(c, -1);
	ucstring_destroy(dbgline);
	if(pg) {
		de_free(c, pg->strile_data);
		de_free(c, pg);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movl %r8d, -0xac(%rbp)
movq %rcx, %rax
movl -0xac(%rbp), %ecx
movq %rax, -0xa8(%rbp)
movl %edx, %eax
movq -0xa8(%rbp), %rdx
movl %eax, -0x9c(%rbp)
movq %rsi, %rax
movl -0x9c(%rbp), %esi
movq %rax, -0x98(%rbp)
movq %rdi, %r8
movq -0x98(%rbp), %rdi
movb %r9b, %al
movq %r8, -0x8(%rbp)
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movb %cl, -0x21(%rbp)
movb %al, -0x22(%rbp)
movq $0x0, -0x30(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x8(%rbp), %rdi
movl $0x510, %esi            # imm = 0x510
callq 0x15b780
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x50(%rax)
movq -0x30(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x58(%rax)
movl -0x14(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movb -0x21(%rbp), %cl
movq -0x30(%rbp), %rax
movb %cl, 0x10(%rax)
cmpb $0x0, -0x22(%rbp)
je 0x12e7cf
movq -0x10(%rbp), %rax
movl 0x4c(%rax), %ecx
movl %ecx, %edx
addl $0x1, %edx
movl %edx, 0x4c(%rax)
movq -0x30(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x30(%rbp), %rdi
addq $0x4d0, %rdi            # imm = 0x4D0
movq -0x30(%rbp), %rax
movl 0xc(%rax), %ecx
movl $0x14, %esi
leaq 0x93458(%rip), %rdx     # 0x1c1c1e
movb $0x0, %al
callq 0x15a980
jmp 0x12e7f6
movq -0x30(%rbp), %rax
movl $0xffffffff, 0xc(%rax)  # imm = 0xFFFFFFFF
movq -0x30(%rbp), %rdi
addq $0x4d0, %rdi            # imm = 0x4D0
leaq 0x85ca4(%rip), %rsi     # 0x1b4490
movl $0x14, %edx
callq 0x15aa30
movq -0x30(%rbp), %rdi
addq $0x4e4, %rdi            # imm = 0x4E4
movq -0x30(%rbp), %rcx
addq $0x4d0, %rcx            # imm = 0x4D0
movq -0x30(%rbp), %rax
movq (%rax), %r8
movl $0x28, %esi
leaq 0x99ffb(%rip), %rdx     # 0x1c881a
movb $0x0, %al
callq 0x15a980
movq -0x10(%rbp), %rax
cmpl $0x7, 0x4(%rax)
jne 0x12e83d
movq -0x10(%rbp), %rax
movl $0x2, 0x38(%rax)
jmp 0x12e848
movq -0x10(%rbp), %rax
movl $0x1, 0x38(%rax)
movq -0x30(%rbp), %rax
movzbl 0x10(%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0xb8(%rbp)
subl $0x8, %eax
ja 0x12e90f
movq -0xb8(%rbp), %rax
leaq 0x9965a(%rip), %rcx     # 0x1c7ecc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x99fa3(%rip), %rax     # 0x1c8825
movq %rax, -0x88(%rbp)
jmp 0x12e91d
leaq 0x99f9a(%rip), %rax     # 0x1c882f
movq %rax, -0x88(%rbp)
jmp 0x12e91d
leaq 0x99fa3(%rip), %rax     # 0x1c8848
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rax
movl $0x1, 0x38(%rax)
jmp 0x12e91d
leaq 0x99f94(%rip), %rax     # 0x1c8854
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rax
movl $0x1, 0x38(%rax)
jmp 0x12e91d
leaq 0x99f96(%rip), %rax     # 0x1c8871
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rax
movl $0x1, 0x38(%rax)
jmp 0x12e91d
leaq 0x99f86(%rip), %rax     # 0x1c887c
movq %rax, -0x88(%rbp)
jmp 0x12e91d
leaq 0x99f87(%rip), %rax     # 0x1c888d
movq %rax, -0x88(%rbp)
jmp 0x12e91d
leaq 0xa22ba(%rip), %rax     # 0x1d0bd0
movq %rax, -0x88(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rdx
addq $0x4d0, %rdx            # imm = 0x4D0
movq -0x30(%rbp), %rax
movq (%rax), %rcx
movq -0x88(%rbp), %r8
leaq 0x99f5b(%rip), %rsi     # 0x1c889c
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x30(%rbp), %rax
movq (%rax), %rax
movq -0x8(%rbp), %rcx
movq 0x18(%rcx), %rcx
cmpq 0x18(%rcx), %rax
jge 0x12e975
movq -0x30(%rbp), %rax
cmpq $0x8, (%rax)
jge 0x12e99b
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %r8
xorl %eax, %eax
movl %eax, %edx
leaq 0x99e4e(%rip), %rcx     # 0x1c87dd
movb $0x0, %al
callq 0x12dfd0
jmp 0x12edda
movq -0x10(%rbp), %rax
cmpb $0x0, 0x8(%rax)
je 0x12e9c4
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rax
movl (%rax), %edx
callq 0x165960
movl %eax, -0x34(%rbp)
jmp 0x12e9e1
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rax
movl (%rax), %edx
callq 0x165820
movl %eax, -0x34(%rbp)
movq -0x8(%rbp), %rdi
movl -0x34(%rbp), %edx
leaq 0x99180(%rip), %rsi     # 0x1c7b6f
movb $0x0, %al
callq 0x15b0d0
cmpl $0xc8, -0x34(%rbp)
jle 0x12ea22
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
movl -0x34(%rbp), %r8d
leaq 0x99e96(%rip), %rcx     # 0x1c88ac
movb $0x0, %al
callq 0x12dfd0
jmp 0x12edda
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rdx
movq -0x10(%rbp), %rax
addq 0x50(%rax), %rdx
movslq -0x34(%rbp), %rax
movq -0x10(%rbp), %rcx
imulq 0x58(%rcx), %rax
addq %rax, %rdx
callq 0x12e580
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rdx
movq -0x40(%rbp), %rsi
leaq 0xa216b(%rip), %rcx     # 0x1d0bd0
leaq 0x9eab5(%rip), %rax     # 0x1cd521
cmpq $0x0, %rsi
cmoveq %rax, %rcx
leaq 0x99e5f(%rip), %rsi     # 0x1c88da
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x40(%rbp), %rdx
xorl %ecx, %ecx
movl $0x1, %r8d
callq 0x12e3a0
movq -0x8(%rbp), %rdi
callq 0x1711d0
movq %rax, -0x48(%rbp)
movl $0x0, -0x38(%rbp)
movl -0x38(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x12edb8
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
movl $0x38, %edx
callq 0x19140
movq -0x30(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rax
addq 0x50(%rax), %rsi
movslq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
imulq 0x58(%rcx), %rax
addq %rax, %rsi
movq -0x10(%rbp), %rax
movl (%rax), %edx
callq 0x165820
movl %eax, -0x78(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x30(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rax
addq 0x50(%rax), %rsi
movslq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
imulq 0x58(%rcx), %rax
addq %rax, %rsi
addq $0x2, %rsi
movq -0x10(%rbp), %rax
movl (%rax), %edx
callq 0x165820
movl %eax, -0x74(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rdx
movq -0x10(%rbp), %rax
addq 0x50(%rax), %rdx
movslq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
imulq 0x58(%rcx), %rax
addq %rax, %rdx
addq $0x4, %rdx
callq 0x12e580
movq %rax, -0x68(%rbp)
movabsq $0x100000000000, %rax   # imm = 0x100000000000
cmpq %rax, -0x68(%rbp)
jle 0x12eb93
movabsq $0x100000000000, %rax   # imm = 0x100000000000
movq %rax, -0x68(%rbp)
movl -0x74(%rbp), %edi
callq 0x12efd0
cltq
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
imulq -0x68(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x68(%rcx), %rax
jg 0x12ebe9
movq -0x30(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
addq 0x50(%rcx), %rax
movslq -0x38(%rbp), %rcx
movq -0x10(%rbp), %rdx
imulq 0x58(%rdx), %rcx
addq %rcx, %rax
movq -0x10(%rbp), %rcx
addq 0x60(%rcx), %rax
movq %rax, -0x60(%rbp)
jmp 0x12ec21
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rdx
movq -0x10(%rbp), %rax
addq 0x50(%rax), %rdx
movslq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
imulq 0x58(%rcx), %rax
addq %rax, %rdx
movq -0x10(%rbp), %rax
addq 0x60(%rax), %rdx
callq 0x12e580
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
addq -0x50(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x18(%rcx), %rcx
movq 0x18(%rcx), %rcx
addq $0x400, %rcx            # imm = 0x400
cmpq %rcx, %rax
jle 0x12ec8e
movq -0x60(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x18(%rcx), %rcx
cmpq 0x18(%rcx), %rax
jle 0x12ec65
movq $0x0, -0x68(%rbp)
movq $0x0, -0x50(%rbp)
jmp 0x12ec8c
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x18(%rax), %rax
subq -0x60(%rbp), %rax
cqto
idivq -0x58(%rbp)
movq %rax, -0x68(%rbp)
movq -0x58(%rbp), %rax
imulq -0x68(%rbp), %rax
movq %rax, -0x50(%rbp)
jmp 0x12ec8e
movl -0x78(%rbp), %edi
movq -0x10(%rbp), %rax
movl 0x4(%rax), %esi
movq -0x30(%rbp), %rax
movzbl 0x10(%rax), %edx
callq 0x12f030
movq %rax, -0x90(%rbp)
cmpq $0x0, -0x90(%rbp)
je 0x12ecbf
movl $0x1, -0x70(%rbp)
jmp 0x12eccd
leaq 0xee77a(%rip), %rax     # 0x21d440
movq %rax, -0x90(%rbp)
movq -0x48(%rbp), %rdi
callq 0x171210
movq -0x48(%rbp), %rdi
movl -0x78(%rbp), %ecx
movq -0x90(%rbp), %rax
movq 0x8(%rax), %r8
movl -0x74(%rbp), %r9d
movq -0x68(%rbp), %rax
movl %eax, %r10d
movq -0x60(%rbp), %rax
movl $0x2, %esi
leaq 0x99bf1(%rip), %rdx     # 0x1c88f4
movl %r10d, (%rsp)
movq %rax, 0x8(%rsp)
movb $0x0, %al
callq 0x171660
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq -0x48(%rbp), %r8
leaq -0x80(%rbp), %rdx
callq 0x12f280
movq -0x8(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x48(%rbp), %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x172620
movq -0xc0(%rbp), %rdi
movq %rax, %rdx
leaq 0x71dd6(%rip), %rsi     # 0x1a0b2f
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x15b560
movq -0x90(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x12ed9c
movq -0x90(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x90(%rbp), %rcx
leaq -0x80(%rbp), %rdx
callq *%rax
movq -0x8(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x15b560
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x12eaaf
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x12f350
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x12f470
movq -0x8(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x15b560
movq -0x48(%rbp), %rdi
callq 0x171750
cmpq $0x0, -0x30(%rbp)
je 0x12ee19
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0xb8(%rax), %rsi
callq 0x15b820
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x15b820
addq $0xd0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)