// File: /workspace/github_c_makefile_star2_O3/seojangho[P]clee/simclist.c
// Function: list_dump_filedescriptor
int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) {
    struct list_entry_s *x;
    void *ser_buf;
    uint32_t bufsize;
    struct timeval timeofday;
    struct list_dump_header_s header;

    if (l->attrs.meter == NULL && l->attrs.serializer == NULL) {
        errno = ENOTTY;
        return -1;
    }

    /****       DUMP FORMAT      ****

    [ ver   timestamp   |  totlen   numels  elemlen     hash    |   DATA ]
    
    where DATA can be:
    @ for constant-size list (element size is constant; elemlen > 0)
    [ elem    elem    ...    elem ]
    @ for other lists (element size dictated by element_meter each time; elemlen <= 0)
    [ size elem     size elem       ...     size elem ]
    
    all integers are encoded in NETWORK BYTE FORMAT
    *****/


    /* prepare HEADER */
    /* version */
    header.ver = htons( SIMCLIST_DUMPFORMAT_VERSION );

    /* timestamp */
    gettimeofday(&timeofday, NULL);
    header.timestamp = (int64_t)timeofday.tv_sec * 1000000 + (int64_t)timeofday.tv_usec;
    header.timestamp = hton64(header.timestamp);

    header.rndterm = htonl((int32_t)get_random());

    /* total list size is postprocessed afterwards */

    /* number of elements */
    header.numels = htonl(l->numels);

    /* include an hash, if possible */
    if (l->attrs.hasher != NULL) {
        if (htonl(list_hash(l, & header.listhash)) != 0) {
            /* could not compute list hash! */
            return -1;
        }
    } else {
        header.listhash = htonl(0);
    }

    header.totlistlen = header.elemlen = 0;

    /* leave room for the header at the beginning of the file */
    if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) {
        /* errno set by lseek() */
        return -1;
    }

    /* write CONTENT */
    if (l->numels > 0) {
        /* SPECULATE that the list has constant element size */
        
        if (l->attrs.serializer != NULL) {  /* user user-specified serializer */
            /* get preliminary length of serialized element in header.elemlen */
            ser_buf = l->attrs.serializer(l->head_sentinel->next->data, & header.elemlen);
            free(ser_buf);
            /* request custom serialization of each element */
            for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
                ser_buf = l->attrs.serializer(x->data, &bufsize);
                header.totlistlen += bufsize;
                if (header.elemlen != 0) {      /* continue on speculation */
                    if (header.elemlen != bufsize) {
                        free(ser_buf);
                        /* constant element length speculation broken! */
                        header.elemlen = 0;
                        header.totlistlen = 0;
                        x = l->head_sentinel;
                        if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) {
                            /* errno set by lseek() */
                            return -1;
                        }
                        /* restart from the beginning */
                        continue;
                    }
                    /* speculation confirmed */
                    WRITE_ERRCHECK(fd, ser_buf, bufsize);
                } else {                        /* speculation found broken */
                    WRITE_ERRCHECK(fd, & bufsize, sizeof(size_t));
                    WRITE_ERRCHECK(fd, ser_buf, bufsize);
                }
                free(ser_buf);
            }
        } else if (l->attrs.meter != NULL) {
            header.elemlen = (uint32_t)l->attrs.meter(l->head_sentinel->next->data);

            /* serialize the element straight from its data */
            for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) {
                bufsize = l->attrs.meter(x->data);
                header.totlistlen += bufsize;
                if (header.elemlen != 0) {
                    if (header.elemlen != bufsize) {
                        /* constant element length speculation broken! */
                        header.elemlen = 0;
                        header.totlistlen = 0;
                        x = l->head_sentinel;
                        /* restart from the beginning */
                        continue;
                    }
                    WRITE_ERRCHECK(fd, x->data, bufsize);
                } else {
                    WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t));
                    WRITE_ERRCHECK(fd, x->data, bufsize);
                }
            }
        }
        /* adjust endianness */
        header.elemlen = htonl(header.elemlen);
        header.totlistlen = htonl(header.totlistlen);
    }

    /* write random terminator */
    WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm));        /* list terminator */


    /* write header */
    lseek(fd, 0, SEEK_SET);

    WRITE_ERRCHECK(fd, & header.ver, sizeof(header.ver));                        /* version */
    WRITE_ERRCHECK(fd, & header.timestamp, sizeof(header.timestamp));            /* timestamp */
    WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm));                /* random terminator */

    WRITE_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen));          /* total length of elements */
    WRITE_ERRCHECK(fd, & header.numels, sizeof(header.numels));                  /* number of elements */
    WRITE_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen));                /* size of each element, or 0 for independent */
    WRITE_ERRCHECK(fd, & header.listhash, sizeof(header.listhash));             /* list hash, or 0 for "ignore" */


    /* possibly store total written length in "len" */
    if (len != NULL) {
        *len = sizeof(header) + ntohl(header.totlistlen);
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %r13
movl %esi, %r14d
movq %rdi, %r12
movq 0x50(%rdi), %rbx
testq %rbx, %rbx
jne 0x4dd2
cmpq $0x0, 0x68(%r12)
je 0x4f4a
movw $0x100, 0x8(%rsp)       # imm = 0x100
leaq 0x48(%rsp), %r15
movq %r15, %rdi
xorl %esi, %esi
callq 0x30b0
imulq $0xf4240, (%r15), %rax  # imm = 0xF4240
addq 0x8(%r15), %rax
bswapq %rax
movq %rax, 0x10(%rsp)
callq 0x31e0
bswapl %eax
movl %eax, 0x18(%rsp)
movl 0x18(%r12), %ebp
movl %ebp, %eax
bswapl %eax
movl %eax, 0x20(%rsp)
cmpq $0x0, 0x60(%r12)
je 0x4e38
leaq 0x28(%rsp), %rsi
movq %r12, %rdi
callq 0x4b86
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
testl %eax, %eax
jne 0x512d
jmp 0x4e40
movl $0x0, 0x28(%rsp)
xorl %eax, %eax
movl %eax, 0x24(%rsp)
movl %eax, 0x1c(%rsp)
movl $0x1e, %esi
movl %r14d, %edi
xorl %edx, %edx
callq 0x30a0
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
testq %rax, %rax
js 0x512d
testl %ebp, %ebp
je 0x5046
movq %r13, 0x40(%rsp)
movq 0x68(%r12), %r15
testq %r15, %r15
je 0x4f60
movq (%r12), %rbx
movq 0x8(%rbx), %rax
movq (%rax), %rdi
leaq 0x24(%rsp), %rsi
callq *%r15
movq %rax, %rdi
callq 0x3030
movq 0x8(%r12), %rbp
movq %rbx, 0x30(%rsp)
movq 0x8(%rbx), %rbx
cmpq %rbp, %rbx
je 0x5027
leaq 0x4(%rsp), %r12
movq (%rbx), %rdi
movq %r12, %rsi
callq *%r15
movl 0x4(%rsp), %edx
addl %edx, 0x1c(%rsp)
movq %rax, %r13
movl 0x24(%rsp), %eax
testl %eax, %eax
je 0x4f07
cmpl %edx, %eax
je 0x4f20
movq %r13, %rdi
callq 0x3030
xorl %eax, %eax
movl %eax, 0x24(%rsp)
movl %eax, 0x1c(%rsp)
movl $0x1e, %esi
movl %r14d, %edi
xorl %edx, %edx
callq 0x30a0
movq 0x30(%rsp), %rbx
testq %rax, %rax
jns 0x4f38
jmp 0x4f55
movl $0x8, %edx
movl %r14d, %edi
movq %r12, %rsi
callq 0x3070
testq %rax, %rax
js 0x4f55
movl 0x4(%rsp), %edx
movl %r14d, %edi
movq %r13, %rsi
callq 0x3070
testq %rax, %rax
js 0x4f55
movq %r13, %rdi
callq 0x3030
movq 0x8(%rbx), %rbx
cmpq %rbp, %rbx
jne 0x4eba
jmp 0x5027
callq 0x3040
movl $0x19, (%rax)
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
jmp 0x512d
testq %rbx, %rbx
je 0x5027
movq (%r12), %r15
movq 0x8(%r15), %rax
movq (%rax), %rdi
callq *%rbx
movq %rax, %r13
movl %r13d, 0x24(%rsp)
movq 0x8(%r12), %rax
movq %r15, 0x38(%rsp)
movq 0x8(%r15), %r12
movq %rax, 0x30(%rsp)
cmpq %rax, %r12
je 0x5027
xorl %ebp, %ebp
movq (%r12), %rdi
callq *%rbx
movq %rax, %r15
movl %r15d, 0x4(%rsp)
addl %r15d, %ebp
movl %ebp, 0x1c(%rsp)
testl %r13d, %r13d
je 0x4fcc
cmpl %r15d, %r13d
jne 0x5003
movq (%r12), %rsi
movl %r15d, %edx
movl %r14d, %edi
callq 0x3070
jmp 0x4ff9
movl $0x8, %edx
movl %r14d, %edi
leaq 0x4(%rsp), %rsi
callq 0x3070
testq %rax, %rax
js 0x4f55
movq (%r12), %rsi
movl %r15d, %edx
movl %r14d, %edi
callq 0x3070
xorl %r13d, %r13d
testq %rax, %rax
jns 0x5017
jmp 0x4f55
xorl %r13d, %r13d
movl %r13d, 0x24(%rsp)
movl %r13d, 0x1c(%rsp)
xorl %ebp, %ebp
movq 0x38(%rsp), %r12
movq 0x8(%r12), %r12
cmpq 0x30(%rsp), %r12
jne 0x4f9c
movl 0x1c(%rsp), %eax
movl 0x24(%rsp), %ecx
bswapl %ecx
movl %ecx, 0x24(%rsp)
bswapl %eax
movl %eax, 0x1c(%rsp)
movq 0x40(%rsp), %r13
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
leaq 0x18(%rsp), %r12
movl $0x4, %edx
movl %r14d, %edi
movq %r12, %rsi
callq 0x3070
testq %rax, %rax
js 0x512d
movl %r14d, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x30a0
leaq 0x8(%rsp), %rsi
movl $0x2, %edx
movl %r14d, %edi
callq 0x3070
testq %rax, %rax
js 0x512d
leaq 0x10(%rsp), %rsi
movl $0x8, %edx
movl %r14d, %edi
callq 0x3070
testq %rax, %rax
js 0x512d
movl $0x4, %edx
movl %r14d, %edi
movq %r12, %rsi
callq 0x3070
testq %rax, %rax
js 0x512d
leaq 0x1c(%rsp), %rsi
movl $0x4, %edx
movl %r14d, %edi
callq 0x3070
testq %rax, %rax
js 0x512d
leaq 0x20(%rsp), %rsi
movl $0x4, %edx
movl %r14d, %edi
callq 0x3070
testq %rax, %rax
js 0x512d
movl $0x4, %edx
movl %r14d, %edi
leaq 0x24(%rsp), %rsi
callq 0x3070
testq %rax, %rax
js 0x512d
leaq 0x28(%rsp), %rsi
movl $0x4, %edx
movl %r14d, %edi
callq 0x3070
testq %rax, %rax
js 0x512d
xorl %r15d, %r15d
testq %r13, %r13
je 0x512d
movl 0x1c(%rsp), %eax
bswapl %eax
addq $0x28, %rax
movq %rax, (%r13)
movl %r15d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq