// File: /workspace/github_c_makefile_star2_O1/janet-lang[P]janet/src/core/filewatch.c
// Function: watcher_callback_read
static void watcher_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
    JanetStream *stream = fiber->ev_stream;
    JanetWatcher *watcher = *((JanetWatcher **) fiber->ev_state);
    char buf[1024];
    switch (event) {
        default:
            break;
        case JANET_ASYNC_EVENT_MARK:
            janet_mark(janet_wrap_abstract(watcher));
            break;
        case JANET_ASYNC_EVENT_CLOSE:
            janet_schedule(fiber, janet_wrap_nil());
            janet_async_end(fiber);
            break;
        case JANET_ASYNC_EVENT_ERR: {
            janet_schedule(fiber, janet_wrap_nil());
            janet_async_end(fiber);
            break;
        }
    read_more:
        case JANET_ASYNC_EVENT_HUP:
        case JANET_ASYNC_EVENT_INIT:
        case JANET_ASYNC_EVENT_READ: {
            Janet name = janet_wrap_nil();

            /* Assumption - read will never return partial events *
             * From documentation:
             *
             * The behavior when the buffer given to read(2) is too small to
             * return information about the next event depends on the kernel
             * version: before Linux 2.6.21, read(2) returns 0; since Linux
             * 2.6.21, read(2) fails with the error EINVAL.  Specifying a buffer
             * of size
             *
             *     sizeof(struct inotify_event) + NAME_MAX + 1
             *
             * will be sufficient to read at least one event. */
            ssize_t nread;
            do {
                nread = read(stream->handle, buf, sizeof(buf));
            } while (nread == -1 && errno == EINTR);

            /* Check for errors - special case errors that can just be waited on to fix */
            if (nread == -1) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    break;
                }
                janet_cancel(fiber, janet_ev_lasterr());
                fiber->ev_state = NULL;
                janet_async_end(fiber);
                break;
            }
            if (nread < (ssize_t) sizeof(struct inotify_event)) break;

            /* Iterate through all events read from the buffer */
            char *cursor = buf;
            while (cursor < buf + nread) {
                struct inotify_event inevent;
                memcpy(&inevent, cursor, sizeof(inevent));
                cursor += sizeof(inevent);
                /* Read path of inevent */
                if (inevent.len) {
                    name = janet_cstringv(cursor);
                    cursor += inevent.len;
                }

                /* Got an event */
                Janet path = janet_table_get(watcher->watch_descriptors, janet_wrap_integer(inevent.wd));
                JanetKV *event = janet_struct_begin(6);
                janet_struct_put(event, janet_ckeywordv("wd"), janet_wrap_integer(inevent.wd));
                janet_struct_put(event, janet_ckeywordv("wd-path"), path);
                if (janet_checktype(name, JANET_NIL)) {
                    /* We were watching a file directly, so path is the full path. Split into dirname / basename */
                    JanetString spath = janet_unwrap_string(path);
                    const uint8_t *cursor = spath + janet_string_length(spath);
                    const uint8_t *cursor_end = cursor;
                    while (cursor > spath && cursor[0] != '/') {
                        cursor--;
                    }
                    if (cursor == spath) {
                        janet_struct_put(event, janet_ckeywordv("dir-name"), path);
                        janet_struct_put(event, janet_ckeywordv("file-name"), name);
                    } else {
                        janet_struct_put(event, janet_ckeywordv("dir-name"), janet_wrap_string(janet_string(spath, (cursor - spath))));
                        janet_struct_put(event, janet_ckeywordv("file-name"), janet_wrap_string(janet_string(cursor + 1, (cursor_end - cursor - 1))));
                    }
                } else {
                    janet_struct_put(event, janet_ckeywordv("dir-name"), path);
                    janet_struct_put(event, janet_ckeywordv("file-name"), name);
                }
                janet_struct_put(event, janet_ckeywordv("cookie"), janet_wrap_integer(inevent.cookie));
                Janet etype = janet_ckeywordv("type");
                const JanetWatchFlagName *wfn_end = watcher_flags_linux + sizeof(watcher_flags_linux) / sizeof(watcher_flags_linux[0]);
                for (const JanetWatchFlagName *wfn = watcher_flags_linux; wfn < wfn_end; wfn++) {
                    if ((inevent.mask & wfn->flag) == wfn->flag) janet_struct_put(event, etype, janet_ckeywordv(wfn->name));
                }
                Janet eventv = janet_wrap_struct(janet_struct_end(event));

                janet_channel_give(watcher->channel, eventv);
            }

            /* Read some more if possible */
            goto read_more;
        }
        break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x458, %rsp            # imm = 0x458
cmpl $0x6, %esi
ja 0x2b0c3
movq %rdi, %rbx
movq 0x60(%rdi), %rax
movq (%rax), %r13
movl %esi, %eax
leaq 0x33346(%rip), %rcx     # 0x5e010
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, -0x60(%rbp)
movq 0x58(%rbx), %rax
movq %rax, -0x58(%rbp)
movabsq $-0x77fffffffffff, %rax # imm = 0xFFF8800000000001
decq %rax
movq %rax, -0x78(%rbp)
leaq 0x57649(%rip), %r14     # 0x82340
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4f95a
movq %rax, -0x38(%rbp)
movq -0x60(%rbp), %rbx
movq -0x58(%rbp), %r15
leaq -0x480(%rbp), %r12
movl (%r15), %edi
movl $0x400, %edx            # imm = 0x400
movq %r12, %rsi
callq 0x12520
cmpq $-0x1, %rax
jne 0x2ad40
callq 0x12120
movl (%rax), %eax
cmpl $0x4, %eax
je 0x2ad19
jmp 0x2b09e
cmpq $0x10, %rax
jl 0x2b0c3
addq %rbp, %rax
addq $-0x480, %rax           # imm = 0xFB80
movq %rax, -0x68(%rbp)
movq %r12, %r15
movq %r13, -0x70(%rbp)
movl (%r15), %ecx
movl 0x4(%r15), %r12d
movl 0x8(%r15), %eax
movl %eax, -0x44(%rbp)
movl 0xc(%r15), %ebx
addq $0x10, %r15
testq %rbx, %rbx
je 0x2ada0
movq %r15, %rdi
movl %ecx, -0x30(%rbp)
callq 0x4516c
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4f9ad
movl -0x30(%rbp), %ecx
movq %rax, -0x38(%rbp)
addq %rbx, %r15
movq %r15, -0x50(%rbp)
movq 0x8(%r13), %rbx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, -0x40(%rbp)
callq 0x4fab8
movq %rbx, %rdi
movq %rax, %rsi
callq 0x47f51
movq %rax, -0x30(%rbp)
movl $0x6, %edi
callq 0x46f8c
movq %rax, %r15
leaq 0x3c461(%rip), %rdi     # 0x6723d
callq 0x47cd3
movq %rax, %rdi
movabsq $-0x5000000000000, %r13 # imm = 0xFFFB000000000000
movq %r13, %rsi
callq 0x4f9ad
movq %rax, %rbx
movsd -0x40(%rbp), %xmm0
callq 0x4fab8
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x472ba
leaq 0x33e55(%rip), %rdi     # 0x5ec6d
callq 0x47cd3
movq %rax, %rdi
movq %r13, %rsi
callq 0x4f9ad
movq %r15, %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rdx
callq 0x472ba
movq -0x38(%rbp), %rbx
movq %rbx, %rax
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
andq %rcx, %rax
cmpq -0x78(%rbp), %rax
jne 0x2af43
movq -0x30(%rbp), %rdi
callq 0x4f838
movq %rax, %rbx
movslq -0x8(%rax), %rax
leaq (%rbx,%rax), %rcx
movq %rcx, %r13
testq %rax, %rax
jle 0x2ae83
movq %rcx, %r13
cmpb $0x2f, (%r13)
je 0x2ae83
decq %r13
cmpq %rbx, %r13
ja 0x2ae74
movq %rcx, -0x40(%rbp)
leaq 0x33de7(%rip), %rdi     # 0x5ec75
callq 0x47cd3
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4f9ad
cmpq %rbx, %r13
je 0x2af8b
movl %r13d, %esi
subl %ebx, %esi
movq %rbx, %rdi
movq %rax, %rbx
callq 0x45094
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4f9ad
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x472ba
leaq 0x33d99(%rip), %rdi     # 0x5ec7e
callq 0x47cd3
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4f9ad
movq %rax, %rbx
movq %r13, %rdi
incq %rdi
notl %r13d
movq -0x40(%rbp), %rsi
addl %r13d, %esi
callq 0x45094
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4f9ad
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x472ba
movabsq $-0x5000000000000, %r13 # imm = 0xFFFB000000000000
jmp 0x2afca
leaq 0x33d2b(%rip), %rdi     # 0x5ec75
callq 0x47cd3
movq %rax, %rdi
movq %r13, %rsi
callq 0x4f9ad
movq %r15, %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rdx
callq 0x472ba
leaq 0x33d0e(%rip), %rdi     # 0x5ec7e
callq 0x47cd3
movq %rax, %rdi
movq %r13, %rsi
callq 0x4f9ad
movq %r15, %rdi
movq %rax, %rsi
movq %rbx, %rdx
jmp 0x2afc5
movq %r15, %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rdx
callq 0x472ba
leaq 0x33cdd(%rip), %rdi     # 0x5ec7e
callq 0x47cd3
movq %rax, %rdi
movabsq $-0x5000000000000, %r13 # imm = 0xFFFB000000000000
movq %r13, %rsi
callq 0x4f9ad
movq %r15, %rdi
movq %rax, %rsi
movq -0x38(%rbp), %rdx
callq 0x472ba
leaq 0x33cb7(%rip), %rdi     # 0x5ec88
callq 0x47cd3
movq %rax, %rdi
movq %r13, %rsi
callq 0x4f9ad
movq %rax, %rbx
xorps %xmm0, %xmm0
cvtsi2sdl -0x44(%rbp), %xmm0
callq 0x4fab8
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x472ba
leaq 0x3869b(%rip), %rdi     # 0x636a1
callq 0x47cd3
movq %rax, %rdi
movq %r13, %rsi
callq 0x4f9ad
movq %rax, %rbx
movq $-0x10, %r13
notl %r12d
testl %r12d, 0x18(%r13,%r14)
jne 0x2b054
movq 0x10(%r13,%r14), %rdi
callq 0x47cd3
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4f9ad
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x472ba
addq $0x10, %r13
cmpq $0xf0, %r13
jb 0x2b023
movq %r15, %rdi
callq 0x472c9
movq %rax, %rdi
movabsq $-0x3000000000000, %rsi # imm = 0xFFFD000000000000
callq 0x4f9ad
movq -0x70(%rbp), %r13
movq 0x10(%r13), %rdi
movq %rax, %rsi
callq 0x2351a
movq -0x50(%rbp), %r15
cmpq -0x68(%rbp), %r15
jb 0x2ad5e
jmp 0x2acf7
cmpl $0xb, %eax
je 0x2b0c3
callq 0x25958
movq %rbx, %rdi
movq %rax, %rsi
callq 0x22cdf
movq $0x0, 0x60(%rbx)
movq %rbx, %rdi
callq 0x226b4
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4f95a
movq %rbx, %rdi
movq %rax, %rsi
callq 0x22cf0
movq %rbx, %rdi
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x226b4
movabsq $-0x1000000000000, %rsi # imm = 0xFFFF000000000000
movq %r13, %rdi
callq 0x4f9f2
movq %rax, %rdi
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2b15b
nop