// File: rurban[P]dgnlib/dgnread.cpp
// Function: DGNParseTagSet(DGNInfo*)
static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )

{
    DGNElemCore *psElement;
    DGNElemTagSet *psTagSet;
    int          nDataOffset, iTag;
            
    psTagSet = (DGNElemTagSet *) CPLCalloc(sizeof(DGNElemTagSet),1);
    psElement = (DGNElemCore *) psTagSet;
    psElement->stype = DGNST_TAG_SET;

    DGNParseCore( psDGN, psElement );

/* -------------------------------------------------------------------- */
/*      Parse the overall information.                                  */
/* -------------------------------------------------------------------- */
    psTagSet->tagCount = 
        psDGN->abyElem[44] + psDGN->abyElem[45] * 256;
    psTagSet->flags = 
        psDGN->abyElem[46] + psDGN->abyElem[47] * 256;
    psTagSet->tagSetName = CPLStrdup( (const char *) (psDGN->abyElem + 48) );

/* -------------------------------------------------------------------- */
/*      Get the tag set number out of the attributes, if available.     */
/* -------------------------------------------------------------------- */
    psTagSet->tagSet = -1;

    if( psElement->attr_bytes >= 8 
        && psElement->attr_data[0] == 0x03
        && psElement->attr_data[1] == 0x10
        && psElement->attr_data[2] == 0x2f
        && psElement->attr_data[3] == 0x7d )
        psTagSet->tagSet = psElement->attr_data[4]
            + psElement->attr_data[5] * 256;

/* -------------------------------------------------------------------- */
/*      Parse each of the tag definitions.                              */
/* -------------------------------------------------------------------- */
    psTagSet->tagList = (DGNTagDef *) 
        CPLMalloc(sizeof(DGNTagDef) * psTagSet->tagCount);

    nDataOffset = 48 + strlen(psTagSet->tagSetName) + 1 + 1; 

    for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
    {
        DGNTagDef *tagDef = psTagSet->tagList + iTag;

        CPLAssert( nDataOffset < psDGN->nElemBytes );

        /* collect tag name. */
        tagDef->name = CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
        nDataOffset += strlen(tagDef->name)+1;

        /* Get tag id */
        tagDef->id = psDGN->abyElem[nDataOffset]
            + psDGN->abyElem[nDataOffset+1] * 256;
        nDataOffset += 2;

        /* Get User Prompt */
        tagDef->prompt = CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
        nDataOffset += strlen(tagDef->prompt)+1;


        /* Get type */
        tagDef->type = psDGN->abyElem[nDataOffset]
            + psDGN->abyElem[nDataOffset+1] * 256;
        nDataOffset += 2;

        /* skip five zeros */
        nDataOffset += 5;

        /* Get the default */
        if( tagDef->type == 1 )
        {
            tagDef->defaultValue.string = 
                CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
            nDataOffset += strlen(tagDef->defaultValue.string)+1;
        }
        else if( tagDef->type == 3 || tagDef->type == 5 )
        {
            memcpy( &(tagDef->defaultValue.integer), 
                    psDGN->abyElem + nDataOffset, 4 );
            tagDef->defaultValue.integer = 
                CPL_LSBWORD32( tagDef->defaultValue.integer );
            nDataOffset += 4;
        }
        else if( tagDef->type == 4 )
        {
            memcpy( &(tagDef->defaultValue.real), 
                    psDGN->abyElem + nDataOffset, 8 );
            DGN2IEEEDouble( &(tagDef->defaultValue.real) );
            nDataOffset += 8;
        }
        else
            nDataOffset += 4;
    }
    return psElement;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movl $0x70, %edi
movl $0x1, %esi
callq 0x2fc0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl $0xa, 0xc(%rax)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x109e0
movq -0x8(%rbp), %rax
movzbl 0x3c(%rax), %ecx
movq -0x8(%rbp), %rax
movzbl 0x3d(%rax), %eax
shll $0x8, %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x50(%rax)
movq -0x8(%rbp), %rax
movzbl 0x3e(%rax), %ecx
movq -0x8(%rbp), %rax
movzbl 0x3f(%rax), %eax
shll $0x8, %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x58(%rax)
movq -0x8(%rbp), %rdi
addq $0x10, %rdi
addq $0x30, %rdi
callq 0x31e0
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x60(%rax)
movq -0x18(%rbp), %rax
movl $0xffffffff, 0x54(%rax) # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rax
cmpl $0x8, 0x34(%rax)
jl 0x11c0f
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl (%rax), %eax
cmpl $0x3, %eax
jne 0x11c0f
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl 0x1(%rax), %eax
cmpl $0x10, %eax
jne 0x11c0f
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl 0x2(%rax), %eax
cmpl $0x2f, %eax
jne 0x11c0f
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl 0x3(%rax), %eax
cmpl $0x7d, %eax
jne 0x11c0f
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl 0x4(%rax), %ecx
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movzbl 0x5(%rax), %eax
shll $0x8, %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x54(%rax)
movq -0x18(%rbp), %rax
movslq 0x50(%rax), %rax
imulq $0x28, %rax, %rdi
callq 0x3040
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x68(%rax)
movq -0x18(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x2120
addq $0x30, %rax
addq $0x1, %rax
addq $0x1, %rax
movl %eax, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
movl -0x20(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x50(%rcx), %eax
jge 0x11e3e
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rax
movslq -0x20(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x1c(%rbp), %rax
addq %rax, %rdi
callq 0x31e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rdi
callq 0x2120
movq %rax, %rcx
addq $0x1, %rcx
movslq -0x1c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl 0x10(%rax,%rcx), %ecx
movq -0x8(%rbp), %rax
movl -0x1c(%rbp), %edx
addl $0x1, %edx
movslq %edx, %rdx
movzbl 0x10(%rax,%rdx), %eax
shll $0x8, %eax
addl %eax, %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x8(%rax)
movl -0x1c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x1c(%rbp), %rax
addq %rax, %rdi
callq 0x31e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2120
movq %rax, %rcx
addq $0x1, %rcx
movslq -0x1c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl 0x10(%rax,%rcx), %ecx
movq -0x8(%rbp), %rax
movl -0x1c(%rbp), %edx
addl $0x1, %edx
movslq %edx, %rdx
movzbl 0x10(%rax,%rdx), %eax
shll $0x8, %eax
addl %eax, %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x18(%rax)
movl -0x1c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
addl $0x5, %eax
movl %eax, -0x1c(%rbp)
movq -0x28(%rbp), %rax
cmpl $0x1, 0x18(%rax)
jne 0x11daa
movq -0x8(%rbp), %rdi
addq $0x10, %rdi
movslq -0x1c(%rbp), %rax
addq %rax, %rdi
callq 0x31e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x28(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x2120
movq %rax, %rcx
addq $0x1, %rcx
movslq -0x1c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x1c(%rbp)
jmp 0x11e2e
movq -0x28(%rbp), %rax
cmpl $0x3, 0x18(%rax)
je 0x11dbe
movq -0x28(%rbp), %rax
cmpl $0x5, 0x18(%rax)
jne 0x11dea
movq -0x28(%rbp), %rax
movq -0x8(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movl 0x10(%rcx,%rdx), %ecx
movl %ecx, 0x20(%rax)
movq -0x28(%rbp), %rax
movl 0x20(%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x20(%rax)
movl -0x1c(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x1c(%rbp)
jmp 0x11e2c
movq -0x28(%rbp), %rax
cmpl $0x4, 0x18(%rax)
jne 0x11e21
movq -0x28(%rbp), %rax
movq -0x8(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movq 0x10(%rcx,%rdx), %rcx
movq %rcx, 0x20(%rax)
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0xa190
movl -0x1c(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x1c(%rbp)
jmp 0x11e2a
movl -0x1c(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x1c(%rbp)
jmp 0x11e2c
jmp 0x11e2e
jmp 0x11e30
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x11c4e
movq -0x10(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax,%rax)