// File: /workspace/github_c_makefile_star2_O2/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 0x287a9
movq %rdi, %rbx
movq 0x60(%rdi), %rax
movq (%rax), %r14
movl %esi, %eax
leaq 0x30c5e(%rip), %rcx     # 0x59010
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, -0x50(%rbp)
movq 0x58(%rbx), %rax
movq %rax, -0x78(%rbp)
movabsq $-0x77fffffffffff, %rax # imm = 0xFFF8800000000001
decq %rax
movq %rax, -0x68(%rbp)
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4b313
movq %rax, %rbx
movq -0x78(%rbp), %rax
movl (%rax), %edi
movl $0x400, %edx            # imm = 0x400
leaq -0x480(%rbp), %rsi
callq 0x12520
cmpq $-0x1, %rax
jne 0x28418
callq 0x12120
movl (%rax), %eax
cmpl $0x4, %eax
je 0x283ea
jmp 0x28783
cmpq $0x10, %rax
jl 0x287a9
addq %rbp, %rax
addq $-0x480, %rax           # imm = 0xFB80
movq %rax, -0x70(%rbp)
leaq -0x480(%rbp), %r15
movq %r14, -0x60(%rbp)
cmpq -0x70(%rbp), %r15
jae 0x283d8
movq %rbx, %r13
movl (%r15), %ecx
movl 0x4(%r15), %r12d
movl 0x8(%r15), %eax
movl %eax, -0x3c(%rbp)
movl 0xc(%r15), %ebx
addq $0x10, %r15
testq %rbx, %rbx
je 0x2848b
movq %r15, %rdi
movl %ecx, %r13d
callq 0x411ea
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4b366
movl %r13d, %ecx
movq %rax, -0x30(%rbp)
addq %rbx, %r15
movq %r15, -0x48(%rbp)
jmp 0x28493
movq %r15, -0x48(%rbp)
movq %r13, -0x30(%rbp)
movq 0x8(%r14), %rbx
cvtsi2sd %ecx, %xmm0
movsd %xmm0, -0x38(%rbp)
callq 0x4b471
movq %rbx, %rdi
movq %rax, %rsi
callq 0x43c35
movq %rax, %r13
pushq $0x6
popq %rdi
callq 0x42cb8
movq %rax, %r15
leaq 0x39d78(%rip), %rdi     # 0x6223d
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %r14 # imm = 0xFFFB000000000000
movq %r14, %rsi
callq 0x4b366
movq %rax, %rbx
movsd -0x38(%rbp), %xmm0
callq 0x4b471
movq %r15, %rdi
movq %rbx, %rsi
movq %r13, %rbx
movq %rax, %rdx
callq 0x4300f
leaq 0x31769(%rip), %rdi     # 0x59c6d
callq 0x439c6
movq %rax, %rdi
movq %r14, %rsi
callq 0x4b366
movq %r15, %rdi
movq %rax, %rsi
movq %r13, %rdx
callq 0x4300f
movq -0x30(%rbp), %r13
movq %r13, %rax
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
andq %rcx, %rax
cmpq -0x68(%rbp), %rax
jne 0x28568
movq %rbx, -0x58(%rbp)
movq %rbx, %rdi
callq 0x4b1f1
movq %rax, %r14
movslq -0x8(%rax), %rcx
leaq (%rax,%rcx), %r13
xorl %ebx, %ebx
leaq (%rbx,%r13), %rax
cmpq %r14, %rax
jbe 0x285b2
cmpb $0x2f, (%rax)
je 0x285b2
decq %rbx
jmp 0x28555
leaq 0x31706(%rip), %rdi     # 0x59c75
callq 0x439c6
movq %rax, %rdi
movq %r14, %rsi
callq 0x4b366
movq %r15, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x4300f
leaq 0x316ea(%rip), %rdi     # 0x59c7e
callq 0x439c6
movq %rax, %rdi
movq %r14, %rsi
callq 0x4b366
movq %r15, %rdi
movq %rax, %rsi
movq %r13, %rdx
jmp 0x286a8
leaq 0x316bc(%rip), %rdi     # 0x59c75
movq %rcx, -0x38(%rbp)
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4b366
movq -0x38(%rbp), %rsi
movq %rsi, %rcx
addq %rbx, %rcx
je 0x2866e
addl %ebx, %esi
movq %r14, %rdi
movq %rax, %r14
callq 0x41116
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4b366
movq %r15, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x4300f
leaq 0x31666(%rip), %rdi     # 0x59c7e
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4b366
movq %rax, %r14
leaq (%rbx,%r13), %rdi
incq %rdi
notl %ebx
movl %ebx, %esi
callq 0x41116
movq %rax, %rdi
movabsq $-0x6000000000000, %rsi # imm = 0xFFFA000000000000
callq 0x4b366
movq %r15, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x4300f
movabsq $-0x5000000000000, %r14 # imm = 0xFFFB000000000000
jmp 0x286ad
movq %r15, %rdi
movq %rax, %rsi
movq -0x58(%rbp), %rdx
callq 0x4300f
leaq 0x315fa(%rip), %rdi     # 0x59c7e
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %r14 # imm = 0xFFFB000000000000
movq %r14, %rsi
callq 0x4b366
movq %r15, %rdi
movq %rax, %rsi
movq -0x30(%rbp), %rdx
callq 0x4300f
leaq 0x315d4(%rip), %rdi     # 0x59c88
callq 0x439c6
movq %rax, %rdi
movq %r14, %rsi
callq 0x4b366
movq %rax, %rbx
cvtsi2sdl -0x3c(%rbp), %xmm0
callq 0x4b471
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4300f
leaq 0x35fbb(%rip), %rdi     # 0x5e6a1
callq 0x439c6
movq %rax, %rdi
movq %r14, %rsi
callq 0x4b366
movq %rax, %rbx
notl %r12d
xorl %r14d, %r14d
leaq 0x53c3a(%rip), %rax     # 0x7c340
cmpq $0x100, %r14            # imm = 0x100
jae 0x2874c
testl %r12d, 0x8(%r14,%rax)
jne 0x28746
movq (%r14,%rax), %rdi
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4b366
movq %r15, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4300f
leaq 0x53bfa(%rip), %rax     # 0x7c340
addq $0x10, %r14
jmp 0x28706
movq %r15, %rdi
callq 0x4301e
movq %rax, %rdi
movabsq $-0x3000000000000, %rsi # imm = 0xFFFD000000000000
callq 0x4b366
movq -0x60(%rbp), %r14
movq 0x10(%r14), %rdi
movq %rax, %rsi
callq 0x21168
movq -0x30(%rbp), %rbx
movq -0x48(%rbp), %r15
jmp 0x2843a
cmpl $0xb, %eax
movq -0x50(%rbp), %rbx
je 0x287a9
callq 0x233ac
movq %rbx, %rdi
movq %rax, %rsi
callq 0x209bb
andq $0x0, 0x60(%rbx)
movq %rbx, %rdi
callq 0x203ec
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4b313
movq %rbx, %rdi
movq %rax, %rsi
callq 0x209ca
movq %rbx, %rdi
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x203ec
movabsq $-0x1000000000000, %rsi # imm = 0xFFFF000000000000
movq %r14, %rdi
callq 0x4b3ab
movq %rax, %rdi
addq $0x458, %rsp            # imm = 0x458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x28843
nopl (%rax)