// File: /workspace/github_c_makefile_star2_O0/janet-lang[P]janet/src/core/ev.c
// Function: ev_callback_write
void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
    JanetStream *stream = fiber->ev_stream;
    StateWrite *state = (StateWrite *) fiber->ev_state;
    switch (event) {
        default:
            break;
        case JANET_ASYNC_EVENT_MARK: {
            janet_mark(state->is_buffer
                       ? janet_wrap_buffer(state->src.buf)
                       : janet_wrap_string(state->src.str));
            if (state->mode == JANET_ASYNC_WRITEMODE_SENDTO) {
                janet_mark(janet_wrap_abstract(state->dest_abst));
            }
            break;
        }
        case JANET_ASYNC_EVENT_CLOSE:
            janet_cancel(fiber, janet_cstringv("stream closed"));
            janet_async_end(fiber);
            break;
#ifdef JANET_WINDOWS
        case JANET_ASYNC_EVENT_FAILED:
        case JANET_ASYNC_EVENT_COMPLETE: {
            /* Called when write finished */
            uint32_t ev_bytes = (uint32_t) state->overlapped.InternalHigh;
            if (ev_bytes == 0 && (state->mode != JANET_ASYNC_WRITEMODE_SENDTO)) {
                janet_cancel(fiber, janet_cstringv("disconnect"));
                janet_async_end(fiber);
                return;
            }

            janet_schedule(fiber, janet_wrap_nil());
            janet_async_end(fiber);
            return;
        }
        break;
        case JANET_ASYNC_EVENT_INIT: {
            /* Begin write */
            int32_t len;
            const uint8_t *bytes;
            if (state->is_buffer) {
                /* If buffer, convert to string. */
                /* TODO - be more efficient about this */
                JanetBuffer *buffer = state->src.buf;
                JanetString str = janet_string(buffer->data, buffer->count);
                bytes = str;
                len = buffer->count;
                state->is_buffer = 0;
                state->src.str = str;
            } else {
                bytes = state->src.str;
                len = janet_string_length(bytes);
            }
            memset(&(state->overlapped), 0, sizeof(WSAOVERLAPPED));

            int status;
#ifdef JANET_NET
            if (state->mode == JANET_ASYNC_WRITEMODE_SENDTO) {
                SOCKET sock = (SOCKET) stream->handle;
                state->wbuf.buf = (char *) bytes;
                state->wbuf.len = len;
                const struct sockaddr *to = state->dest_abst;
                int tolen = (int) janet_abstract_size((void *) to);
                status = WSASendTo(sock, &state->wbuf, 1, NULL, state->flags, to, tolen, &state->overlapped, NULL);
                if (status) {
                    if (WSA_IO_PENDING == WSAGetLastError()) {
                        janet_async_in_flight(fiber);
                    } else {
                        janet_cancel(fiber, janet_ev_lasterr());
                        janet_async_end(fiber);
                        return;
                    }
                }
            } else
#endif
            {
                /*
                 * File handles in IOCP need to specify this if they are writing to the
                 * ends of files, like how this is used here.
                 * If the underlying resource doesn't support seeking
                 * byte offsets, they will be ignored
                 * but this otherwise writes to the end of the file in question
                 * Right now, os/open streams aren't seekable, so this works.
                 * for more details see the lpOverlapped parameter in
                 * https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
                 */
                state->overlapped.Offset = (DWORD) 0xFFFFFFFF;
                state->overlapped.OffsetHigh = (DWORD) 0xFFFFFFFF;
                status = WriteFile(stream->handle, bytes, len, NULL, &state->overlapped);
                if (!status) {
                    if (ERROR_IO_PENDING == GetLastError()) {
                        janet_async_in_flight(fiber);
                    } else {
                        janet_cancel(fiber, janet_ev_lasterr());
                        janet_async_end(fiber);
                        return;
                    }
                }
            }
        }
        break;
#else
        case JANET_ASYNC_EVENT_ERR:
            janet_cancel(fiber, janet_cstringv("stream err"));
            janet_async_end(fiber);
            break;
        case JANET_ASYNC_EVENT_HUP:
            janet_cancel(fiber, janet_cstringv("stream hup"));
            janet_async_end(fiber);
            break;
        case JANET_ASYNC_EVENT_INIT:
        case JANET_ASYNC_EVENT_WRITE: {
            int32_t start, len;
            const uint8_t *bytes;
            start = state->start;
            if (state->is_buffer) {
                JanetBuffer *buffer = state->src.buf;
                bytes = buffer->data;
                len = buffer->count;
            } else {
                bytes = state->src.str;
                len = janet_string_length(bytes);
            }
            ssize_t nwrote = 0;
            if (start < len) {
                int32_t nbytes = len - start;
                void *dest_abst = state->dest_abst;
                do {
#ifdef JANET_NET
                    if (state->mode == JANET_ASYNC_WRITEMODE_SENDTO) {
                        nwrote = sendto(stream->handle, bytes + start, nbytes, state->flags,
                                        (struct sockaddr *) dest_abst, janet_abstract_size(dest_abst));
                    } else if (state->mode == JANET_ASYNC_WRITEMODE_SEND) {
                        nwrote = send(stream->handle, bytes + start, nbytes, state->flags);
                    } else
#endif
                    {
                        nwrote = write(stream->handle, bytes + start, nbytes);
                    }
                } while (nwrote == -1 && errno == EINTR);

                /* Handle write errors */
                if (nwrote == -1) {
                    if (errno == EAGAIN || errno == EWOULDBLOCK) break;
                    janet_cancel(fiber, janet_ev_lasterr());
                    janet_async_end(fiber);
                    break;
                }

                /* Unless using datagrams, empty message is a disconnect */
                if (nwrote == 0 && !dest_abst) {
                    janet_cancel(fiber, janet_cstringv("disconnect"));
                    janet_async_end(fiber);
                    break;
                }

                if (nwrote > 0) {
                    start += nwrote;
                } else {
                    start = len;
                }
            }
            state->start = start;
            if (start >= len) {
                janet_schedule(fiber, janet_wrap_nil());
                janet_async_end(fiber);
                break;
            }
            break;
        }
        break;
#endif
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0x20(%rbp)
movl -0xc(%rbp), %eax
movq %rax, -0xa0(%rbp)
subq $0x7, %rax
ja 0x2fe91
movq -0xa0(%rbp), %rax
leaq 0x56188(%rip), %rcx     # 0x86010
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x30259
movq -0x20(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x2febd
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rdi
movabsq $-0x2800000000000, %rsi # imm = 0xFFFD800000000000
callq 0x7b610
movq %rax, -0x28(%rbp)
jmp 0x2fed8
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x7b550
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x38b90
movq -0x20(%rbp), %rax
cmpl $0x2, 0x14(%rax)
jne 0x2ff0f
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rdi
movabsq $-0x1000000000000, %rsi # imm = 0xFFFF000000000000
callq 0x7b610
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x38b90
jmp 0x30259
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
leaq 0x57af3(%rip), %rdi     # 0x87a19
callq 0x64a70
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x7b550
movq -0xa8(%rbp), %rdi
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rsi
callq 0x2b130
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
movq -0x8(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq 0x57ab6(%rip), %rdi     # 0x87a27
callq 0x64a70
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x7b550
movq -0xb0(%rbp), %rdi
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rsi
callq 0x2b130
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
movq -0x8(%rbp), %rax
movq %rax, -0xb8(%rbp)
leaq 0x57a76(%rip), %rdi     # 0x87a32
callq 0x64a70
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x7b550
movq -0xb8(%rbp), %rdi
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rsi
callq 0x2b130
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x4c(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x3002d
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x60(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x50(%rbp)
jmp 0x30043
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl -0x8(%rax), %eax
movl %eax, -0x50(%rbp)
movq $0x0, -0x68(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x30206
movl -0x50(%rbp), %eax
subl -0x4c(%rbp), %eax
movl %eax, -0x6c(%rbp)
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x2, 0x14(%rax)
jne 0x300b3
movq -0x18(%rbp), %rax
movl (%rax), %edi
movq -0x58(%rbp), %rsi
movslq -0x4c(%rbp), %rax
addq %rax, %rsi
movslq -0x6c(%rbp), %rdx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x78(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x78(%rbp), %rax
movq -0x8(%rax), %rax
movl %eax, %r9d
movq -0x80(%rbp), %r8
callq 0x12450
movq %rax, -0x68(%rbp)
jmp 0x30103
movq -0x20(%rbp), %rax
cmpl $0x1, 0x14(%rax)
jne 0x300e3
movq -0x18(%rbp), %rax
movl (%rax), %edi
movq -0x58(%rbp), %rsi
movslq -0x4c(%rbp), %rax
addq %rax, %rsi
movslq -0x6c(%rbp), %rdx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
callq 0x12360
movq %rax, -0x68(%rbp)
jmp 0x30101
movq -0x18(%rbp), %rax
movl (%rax), %edi
movq -0x58(%rbp), %rsi
movslq -0x4c(%rbp), %rax
addq %rax, %rsi
movslq -0x6c(%rbp), %rdx
callq 0x12250
movq %rax, -0x68(%rbp)
jmp 0x30103
jmp 0x30105
xorl %eax, %eax
cmpq $-0x1, -0x68(%rbp)
movb %al, -0xb9(%rbp)
jne 0x30125
callq 0x12120
cmpl $0x4, (%rax)
sete %al
movb %al, -0xb9(%rbp)
movb -0xb9(%rbp), %al
testb $0x1, %al
jne 0x3006c
cmpq $-0x1, -0x68(%rbp)
jne 0x3018b
callq 0x12120
cmpl $0xb, (%rax)
je 0x3014e
callq 0x12120
cmpl $0xb, (%rax)
jne 0x30153
jmp 0x30259
movq -0x8(%rbp), %rax
movq %rax, -0xc8(%rbp)
callq 0x2f7c0
movq -0xc8(%rbp), %rdi
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rsi
callq 0x2b130
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
cmpq $0x0, -0x68(%rbp)
jne 0x301e7
cmpq $0x0, -0x78(%rbp)
jne 0x301e7
movq -0x8(%rbp), %rax
movq %rax, -0xd0(%rbp)
leaq 0x57892(%rip), %rdi     # 0x87a3d
callq 0x64a70
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x7b550
movq -0xd0(%rbp), %rdi
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
callq 0x2b130
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
cmpq $0x0, -0x68(%rbp)
jle 0x301fe
movq -0x68(%rbp), %rcx
movslq -0x4c(%rbp), %rax
addq %rcx, %rax
movl %eax, -0x4c(%rbp)
jmp 0x30204
movl -0x50(%rbp), %eax
movl %eax, -0x4c(%rbp)
jmp 0x30206
movl -0x4c(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x4(%rax)
movl -0x4c(%rbp), %eax
cmpl -0x50(%rbp), %eax
jl 0x30257
movq -0x8(%rbp), %rax
movq %rax, -0xd8(%rbp)
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x7b460
movq -0xd8(%rbp), %rdi
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rsi
callq 0x2b160
movq -0x8(%rbp), %rdi
callq 0x2a730
jmp 0x30259
jmp 0x30259
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)