// File: /workspace/github_c_makefile_star2_O1/GregorR[P]lstg/source/lst_socket_primitives.c
// Function: lstSocketPrimitive
struct object *
lstSocketPrimitive(int primitiveNumber, struct object *args, int *failed)
{
    struct object *returnedValue = nilObject;
    switch (integerValue(args->data[0])) {

        case 0:     /* constants */
            switch (integerValue(args->data[1])) {
            case 0:
                returnedValue = newInteger(AF_INET); break;
            case 1:
                returnedValue = newInteger(AF_INET6); break;
            case 2:
                returnedValue = newInteger(AF_LOCAL); break;
            case 10:
                returnedValue = newInteger(SOCK_STREAM); break;
            case 11:
                returnedValue = newInteger(SOCK_DGRAM); break;
            case 12:
                returnedValue = newInteger(SOCK_RAW); break;
            case 20:
                returnedValue = newInteger(IPPROTO_TCP); break;
            case 21:
                returnedValue = newInteger(IPPROTO_UDP); break;
#ifdef IPPROTO_SCTP
            case 22:
                returnedValue = newInteger(IPPROTO_SCTP); break;
#endif
            case 30:
                returnedValue = newInteger(SHUT_RD); break;
            case 31:
                returnedValue = newInteger(SHUT_WR); break;
            case 32:
                returnedValue = newInteger(SHUT_RDWR); break;
            }
            break;

        case 10: {   /* create socket */
            int family = integerValue(args->data[1]);
            int socketType = integerValue(args->data[2]);
            int protocol = integerValue(args->data[3]);
            int sockfd = socket(family, socketType, protocol);
            if (sockfd >= 0)
                returnedValue = newInteger(sockfd);
            break;
        }

        case 11: {   /* create TCP socket */
            int sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd >= 0)
                returnedValue = newInteger(sockfd);
            break;
        }

        case 12: {   /* create UDP socket */
            int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (sockfd >= 0)
                returnedValue = newInteger(sockfd);
            break;
        }

        case 20: {   /* close */
            int sockfd = integerValue(args->data[1]);
            int rc = close(sockfd);
            returnedValue = newInteger(rc);
            break;
        }

        case 21: {   /* shutdown */
            int sockfd = integerValue(args->data[1]);
            int how = integerValue(args->data[2]);
            int rc = shutdown(sockfd, how);
            returnedValue = newInteger(rc);
            break;
        }

        case 30: {   /* bind */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *addrObj = (struct byteObject *) args->data[2];
            int rc = bind(sockfd, (struct sockaddr *) addrObj->bytes, SIZE(addrObj));
            returnedValue = newInteger(rc);
            break;
        }

        case 40: {   /* listen */
            int sockfd = integerValue(args->data[1]);
            int backlog = integerValue(args->data[2]);
            int rc = listen(sockfd, backlog);
            returnedValue = newInteger(rc);
            break;
        }

        case 50: {   /* accept */
            int sockfd = integerValue(args->data[1]);
            int newsockfd = accept(sockfd, NULL, NULL);
            returnedValue = newInteger(newsockfd);
            break;
        }

        case 60: {   /* connect */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *addrObj = (struct byteObject *) args->data[2];
#if defined(DEBUG) && defined(TRACE)
            struct sockaddr_in *p = (struct sockaddr_in*) addrObj->bytes;
printf("before connect()\n");
printf("    sockfd=%d\n", sockfd);
printf("    family=%d\n", p->sin_family);
printf("    port=%d\n", ntohs(p->sin_port));
printf("    addr=%s\n", inet_ntoa(p->sin_addr));
#endif
            int rc = connect(sockfd, (struct sockaddr *) addrObj->bytes, SIZE(addrObj));
#if defined(DEBUG) && defined(TRACE)
printf("connect() returns %d\n", rc);
#endif
            returnedValue = newInteger(rc);
            break;
        }

        case 70: {   /* send */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *bufObj = (struct byteObject *) args->data[2];
            int n = integerValue(args->data[3]);
            if ((LstUInt) n > SIZE(bufObj)) {
                *failed = 1;
                break;
            }
            ssize_t sent = send(sockfd, bufObj->bytes, n, 0);
            returnedValue = newInteger(sent);
            break;
        }

        case 71: {   /* sendto */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *bufObj = (struct byteObject *) args->data[2];
            int n = integerValue(args->data[3]);
            if ((LstUInt) n > SIZE(bufObj)) {
                *failed = 1;
                break;
            }
            struct byteObject *addrObj = (struct byteObject *) args->data[4];
            ssize_t sent = sendto(sockfd, bufObj->bytes, n, 0,
                    (struct sockaddr *) addrObj->bytes, SIZE(addrObj));
            returnedValue = newInteger(sent);
            break;
        }

        case 80: {   /* recv */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *bufObj = (struct byteObject *) args->data[2];
            int n = integerValue(args->data[3]);
            if ((LstUInt) n > SIZE(bufObj)) {
                *failed = 1;
                break;
            }
            ssize_t got = recv(sockfd, bufObj->bytes, n, 0);
            returnedValue = newInteger(got);
            break;
        }

        case 81: {  /* recvfrom */
            int sockfd = integerValue(args->data[1]);
            struct byteObject *bufObj = (struct byteObject *) args->data[2];
            int n = integerValue(args->data[3]);
            if ((LstUInt) n > SIZE(bufObj)) {
                *failed = 1;
                break;
            }
            struct sockaddr_storage ss;
            socklen_t len = sizeof(ss);
            ssize_t got = recvfrom(sockfd, bufObj->bytes, n, 0,
                    (struct sockaddr *) &ss, &len);
            /* TODO , how to return both ssize_t and peer address? */
            returnedValue = newInteger(got);
            break;
        }

        case 90: {   /* getsockopt */
            /*
            int sockfd = integerValue(args->data[1]);
            int level = integerValue(args->data[2]);
            int optname = integerValue(args->data[3]);
            */
            // TODO
            break;
        }

        case 91: {   /* setsockopt */
            // TODO
            break;
        }

        case 92: {  /* select on a single fd */
#define LST_WAIT_R 1
#define LST_WAIT_W 2
            int fd = integerValue(args->data[1]);
            int waitfor = integerValue(args->data[2]);
            struct timeval timeout, *p = NULL;
            if (SIZE(args) > 3) {
                int timeout_in_milliseconds = integerValue(args->data[3]);
                timeout.tv_sec = (timeout_in_milliseconds) / 1000;
                timeout.tv_usec = (timeout_in_milliseconds) % 1000 * 1000;
                p = &timeout;
            }
            fd_set rfds, wfds, *rp = NULL, *wp = NULL;
            if (waitfor & LST_WAIT_R) { FD_ZERO(&rfds); FD_SET(fd, &rfds); rp = &rfds; }
            if (waitfor & LST_WAIT_W) { FD_ZERO(&wfds); FD_SET(fd, &wfds); wp = &wfds; }
            int rc = select(fd + 1, rp, wp, NULL, p);
            if (rc > 0) {
                rc = 0;
                if ((waitfor & LST_WAIT_R) && FD_ISSET(fd, &rfds)) rc |= LST_WAIT_R;
                if ((waitfor & LST_WAIT_W) && FD_ISSET(fd, &wfds)) rc |= LST_WAIT_W;
            }
#undef LST_WAIT_R
#undef LST_WAIT_W
            returnedValue = newInteger(rc);
            break;
        }

        case 93: {  /* getsockname */
            struct sockaddr_storage ss;
            socklen_t len = sizeof(ss);
            int sockfd = integerValue(args->data[1]);
            if (getsockname(sockfd, (struct sockaddr *) &ss, &len) >= 0)
                returnedValue = lstNewBinary(&ss, len);
            break;
        }

        case 94: {  /* getpeername */
            struct sockaddr_storage ss;
            socklen_t len = sizeof(ss);
            int sockfd = integerValue(args->data[1]);
            if (getpeername(sockfd, (struct sockaddr *) &ss, &len) >= 0)
                returnedValue = lstNewBinary(&ss, len);
            break;
        }

    }
    return returnedValue;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x110, %rsp            # imm = 0x110
leaq 0x3f963(%rip), %rax     # 0x45938
movq (%rax), %rbx
movq 0x10(%rsi), %rax
sarq %rax
cmpq $0x31, %rax
jle 0x6039
cmpq $0x4f, %rax
jle 0x6079
cmpq $0x5b, %rax
jle 0x6134
cmpq $0x5c, %rax
je 0x62a0
cmpq $0x5d, %rax
je 0x6263
cmpq $0x5e, %rax
jne 0x633b
movq %rsp, %rdx
movl $0x80, (%rdx)
movq 0x18(%rsi), %rdi
shrq %rdi
leaq 0x80(%rsp), %rsi
callq 0x20d0
jmp 0x6280
cmpq $0x1d, %rax
jg 0x60b1
leaq -0xa(%rax), %rcx
cmpq $0xb, %rcx
ja 0x618e
leaq 0x1568(%rip), %rax      # 0x75bc
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x18(%rsi), %rdi
movq 0x20(%rsi), %rax
shrq %rdi
shrq %rax
movq 0x28(%rsi), %rdx
shrq %rdx
movl %eax, %esi
jmp 0x6203
cmpq $0x45, %rax
jg 0x60dd
cmpq $0x32, %rax
je 0x621a
cmpq $0x3c, %rax
jne 0x633b
movq 0x18(%rsi), %rdi
movq 0x20(%rsi), %rsi
shrq %rdi
movl (%rsi), %edx
addq $0x10, %rsi
shrl $0x2, %edx
callq 0x2330
jmp 0x6331
cmpq $0x1e, %rax
je 0x6318
cmpq $0x28, %rax
jne 0x633b
movq 0x18(%rsi), %rdi
movq 0x20(%rsi), %rsi
shrq %rdi
shrq %rsi
callq 0x2230
jmp 0x6331
cmpq $0x46, %rax
je 0x622f
cmpq $0x47, %rax
jne 0x633b
movq 0x20(%rsi), %rax
movq 0x28(%rsi), %rcx
shrq %rcx
movl (%rax), %edi
shrl $0x2, %edi
cmpl %ecx, %edi
jb 0x6310
movq 0x18(%rsi), %rdi
movq 0x30(%rsi), %r8
shrq %rdi
addq $0x10, %rax
movl %ecx, %edx
movl (%r8), %r9d
addq $0x10, %r8
shrl $0x2, %r9d
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x2150
jmp 0x6333
cmpq $0x50, %rax
je 0x62f8
cmpq $0x51, %rax
jne 0x633b
movq 0x20(%rsi), %rax
movq 0x28(%rsi), %rcx
shrq %rcx
movl (%rax), %edi
shrl $0x2, %edi
cmpl %ecx, %edi
jb 0x6310
movq 0x18(%rsi), %rdi
shrq %rdi
movq %rsp, %r9
movl $0x80, (%r9)
addq $0x10, %rax
movl %ecx, %edx
leaq 0x80(%rsp), %r8
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x2240
jmp 0x6333
testq %rax, %rax
jne 0x633b
movq 0x18(%rsi), %rax
sarq %rax
cmpq $0xc, %rax
ja 0x6478
leaq 0x143d(%rip), %rcx      # 0x75ec
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x15, %ebx
jmp 0x633b
movq 0x18(%rsi), %rdi
shrq %rdi
callq 0x2170
jmp 0x6331
movl $0x2, %edi
movl $0x2, %esi
jmp 0x6201
movq 0x18(%rsi), %rdi
movq 0x20(%rsi), %rsi
shrq %rdi
shrq %rsi
callq 0x20f0
jmp 0x6331
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2380
leal 0x1(,%rax,2), %ecx
testl %eax, %eax
cmovnsq %rcx, %rbx
jmp 0x633b
movq 0x18(%rsi), %rdi
shrq %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x22d0
jmp 0x6331
movq 0x20(%rsi), %rax
movq 0x28(%rsi), %rcx
shrq %rcx
movl (%rax), %edi
shrl $0x2, %edi
cmpl %ecx, %edi
jb 0x6310
movq 0x18(%rsi), %rdi
shrq %rdi
addq $0x10, %rax
movl %ecx, %edx
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x2120
jmp 0x6333
movq %rsp, %rdx
movl $0x80, (%rdx)
movq 0x18(%rsi), %rdi
shrq %rdi
leaq 0x80(%rsp), %rsi
callq 0x22e0
testl %eax, %eax
js 0x633b
movl (%rsp), %esi
leaq 0x80(%rsp), %rdi
callq 0x56b5
movq %rax, %rbx
jmp 0x633b
movq 0x18(%rsi), %rbx
movq 0x20(%rsi), %r14
shrq %rbx
shrq %r14
cmpl $0x10, (%rsi)
jb 0x634b
movq 0x28(%rsi), %rax
shrq %rax
cltq
imulq $0x10624dd3, %rax, %rcx # imm = 0x10624DD3
movq %rcx, %rdx
shrq $0x3f, %rdx
sarq $0x26, %rcx
addl %edx, %ecx
movslq %ecx, %rcx
leaq 0x100(%rsp), %r8
movq %rcx, (%r8)
imull $0x3e8, %ecx, %ecx      # imm = 0x3E8
subl %ecx, %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
cltq
movq %rax, 0x8(%r8)
jmp 0x634e
movq 0x20(%rsi), %rax
movq 0x28(%rsi), %rcx
shrq %rcx
movl (%rax), %edi
shrl $0x2, %edi
cmpl %ecx, %edi
jae 0x645c
movl $0x1, (%rdx)
jmp 0x633b
movq 0x18(%rsi), %rdi
movq 0x20(%rsi), %rsi
shrq %rdi
movl (%rsi), %edx
addq $0x10, %rsi
shrl $0x2, %edx
callq 0x2280
cltq
leaq 0x1(,%rax,2), %rbx
movq %rbx, %rax
addq $0x110, %rsp            # imm = 0x110
popq %rbx
popq %r14
popq %r15
retq
xorl %r8d, %r8d
testb $0x1, %r14b
jne 0x6358
xorl %esi, %esi
jmp 0x63a8
xorps %xmm0, %xmm0
leaq 0x80(%rsp), %rsi
movaps %xmm0, 0x70(%rsi)
movaps %xmm0, 0x60(%rsi)
movaps %xmm0, 0x50(%rsi)
movaps %xmm0, 0x40(%rsi)
movaps %xmm0, 0x30(%rsi)
movaps %xmm0, 0x20(%rsi)
movaps %xmm0, 0x10(%rsi)
movaps %xmm0, (%rsi)
leal 0x3f(%rbx), %eax
testl %ebx, %ebx
cmovnsl %ebx, %eax
movl %eax, %edx
andl $-0x40, %edx
movl %ebx, %ecx
subl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
sarl $0x6, %eax
cltq
orq %rdx, 0x80(%rsp,%rax,8)
testb $0x2, %r14b
jne 0x63b2
xorl %edx, %edx
jmp 0x63f9
xorps %xmm0, %xmm0
movq %rsp, %rdx
movaps %xmm0, 0x70(%rdx)
movaps %xmm0, 0x60(%rdx)
movaps %xmm0, 0x50(%rdx)
movaps %xmm0, 0x40(%rdx)
movaps %xmm0, 0x30(%rdx)
movaps %xmm0, 0x20(%rdx)
movaps %xmm0, 0x10(%rdx)
movaps %xmm0, (%rdx)
leal 0x3f(%rbx), %eax
testl %ebx, %ebx
cmovnsl %ebx, %eax
movl %eax, %edi
andl $-0x40, %edi
movl %ebx, %ecx
subl %edi, %ecx
movl $0x1, %edi
shlq %cl, %rdi
sarl $0x6, %eax
cltq
orq %rdi, (%rsp,%rax,8)
leal 0x1(%rbx), %edi
xorl %r15d, %r15d
xorl %ecx, %ecx
callq 0x2200
testl %eax, %eax
jle 0x64a0
testb $0x1, %r14b
je 0x6434
leal 0x3f(%rbx), %eax
testl %ebx, %ebx
cmovnsl %ebx, %eax
sarl $0x6, %eax
cltq
movq 0x80(%rsp,%rax,8), %rax
xorl %r15d, %r15d
btq %rbx, %rax
setb %r15b
testb $0x2, %r14b
je 0x64a3
leal 0x3f(%rbx), %eax
testl %ebx, %ebx
cmovnsl %ebx, %eax
sarl $0x6, %eax
cltq
movq (%rsp,%rax,8), %rax
leal 0x2(%r15), %ecx
btq %rbx, %rax
cmovael %r15d, %ecx
movl %ecx, %r15d
jmp 0x64a3
movq 0x18(%rsi), %rdi
shrq %rdi
addq $0x10, %rax
movl %ecx, %edx
movq %rax, %rsi
xorl %ecx, %ecx
callq 0x2070
jmp 0x6333
addq $-0x14, %rax
cmpq $0xc, %rax
ja 0x633b
leaq 0x1193(%rip), %rcx      # 0x7620
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0xd, %ebx
jmp 0x633b
movl %eax, %r15d
movslq %r15d, %rax
jmp 0x6333
movl $0x5, %ebx
jmp 0x633b
movl $0x3, %ebx
jmp 0x633b
movl $0x7, %ebx
jmp 0x633b
movl $0x1, %ebx
jmp 0x633b
movl $0x23, %ebx
jmp 0x633b
movl $0x109, %ebx            # imm = 0x109
jmp 0x633b