// File: /workspace/github_c_makefile_star2_O0/ttoobne[P]bohttpd/src/http/http_parse.c
// Function: http_parse_request_headers
int http_parse_request_headers(void* http_request) {
    http_request_t* rq;
    http_header_t* cur_header;
    unsigned char ch;
    unsigned char* p;

    rq = (http_request_t*)http_request;

    /* 维护一个状态机来解析 http 首部字段 */
    /* 格式：<name>: <value> CRLF */
    enum {
        start = 0,
        name,
        spaces_after_name,
        spaces_after_colon,
        value,
        spaces_after_value,
        cur_header_almost_done,
        almost_done
    } state;

    state = rq->state;

    //DBG("in parse headers: start for.\n");
    for (p = rq->bufst; p != rq->bufed; ++ p) {
        //DBG("state: %d\n", state);
        ch = *p;

        //DBG("ch = %c\n", ch);

        switch (state) {
        /* 开始 or 开始解析一行新的字段 */
        case start:
            //DBG("start.\n");
            switch (ch) {
            case CR:
                state = almost_done;    /* 如果连续两个 <CR><LF> ，表示首部字段结束 */
                break;

            case LF:
                goto done;

            default:
                rq->cur_header_name_start = p;
                state = name;
                break;
            }

            break;  /* case start */
        
        /* 首部字段名 */
        case name:
            //DBG("name.\n");
            switch (ch) {
            case ' ':
                rq->cur_header_name_end = p - 1;
                state = spaces_after_name;
                break;

            case ':':
                rq->cur_header_name_end = p - 1;
                state = spaces_after_colon;
                break;
            
            default:
                break;
            }

            break;  /* case name */

        case spaces_after_name:
            //DBG("spaces after name.\n");
            switch (ch) {
            case ' ':
                break;
            
            case ':':
                state = spaces_after_colon;
                break;

            default:
                return HTTP_PARSE_INVALID_HEADER;
            }

            break;  /* case spaces_after_name */

        case spaces_after_colon:
            //DBG("spaces after colon.\n");
            switch (ch) {
            case ' ':
                break;
            
            default:
                rq->cur_header_value_start = p;
                state = value;
                break;
            }

            break;  /* case spaces_after_colon */

        /* 首部字段值 */
        case value:
            //DBG("value.\n");
            switch (ch) {
            case ' ':
                rq->cur_header_value_end = p - 1;
                state = spaces_after_value;
                break;

            case CR:
                rq->cur_header_value_end = p - 1;
                state = cur_header_almost_done;
                break;
            
            case LF:
                rq->cur_header_value_end = p - 1;

                cur_header = (http_header_t*)malloc(sizeof(http_header_t));
                cur_header->header_name_start = rq->cur_header_name_start;
                cur_header->header_name_end = rq->cur_header_name_end;
                cur_header->header_value_start = rq->cur_header_value_start;
                cur_header->header_value_end = rq->cur_header_value_end;
                list_add(&(cur_header->list_node), &(rq->headers_list_head));

                state = start;  /* 继续解析下一行的首部字段 */
                break;
            
            default:
                break;
            }

            break;  /* case value */

        case spaces_after_value:
            switch (ch) {
            case ' ':
                break;
            
            case CR:
                state = cur_header_almost_done;
                break;

            case LF:
                cur_header = (http_header_t*)malloc(sizeof(http_header_t));
                cur_header->header_name_start = rq->cur_header_name_start;
                cur_header->header_name_end = rq->cur_header_name_end;
                cur_header->header_value_start = rq->cur_header_value_start;
                cur_header->header_value_end = rq->cur_header_value_end;
                list_add(&(cur_header->list_node), &(rq->headers_list_head));

                state = start;  /* 继续解析下一行的首部字段 */
                break;

            default:
                state = value;  /* 首部字段值可能会有空格 */
                break;
            }

            break;  /* case spaces_after_value */
            
        case cur_header_almost_done:
            switch (ch) {
            case LF:
                cur_header = (http_header_t*)malloc(sizeof(http_header_t));
                cur_header->header_name_start = rq->cur_header_name_start;
                cur_header->header_name_end = rq->cur_header_name_end;
                cur_header->header_value_start = rq->cur_header_value_start;
                cur_header->header_value_end = rq->cur_header_value_end;
                list_add(&(cur_header->list_node), &(rq->headers_list_head));

                state = start;  /* 继续解析下一行的首部字段 */
                break;
            
            case CR:
                break;

            default:
                return HTTP_PARSE_INVALID_HEADER;
            }

            break;  /* case cur_header_almost_done */

        case almost_done:
            switch (ch) {
            case LF:
                goto done;

            case CR:
                break;
            
            default:
                return HTTP_PARSE_INVALID_HEADER;
            }

            break;  /* case almost_done */

        default:
            break;
        }
    }

    //DBG("for done.\n");

    rq->bufst = p;
    rq->state = state;

    return REQUEST_AGAIN;

done:

    rq->bufst = p + 1;
    rq->state = start;

    return REQUEST_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x48(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x18(%rbp), %rax
movq 0x2098(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x20a0(%rcx), %rax
je 0x5622
movq -0x30(%rbp), %rax
movb (%rax), %al
movb %al, -0x21(%rbp)
movl -0x34(%rbp), %eax
movq %rax, -0x40(%rbp)
subq $0x7, %rax
ja 0x560d
movq -0x40(%rbp), %rax
leaq 0x4845(%rip), %rcx      # 0x9b1c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movzbl -0x21(%rbp), %eax
movl %eax, -0x44(%rbp)
subl $0xa, %eax
je 0x5301
jmp 0x52ee
movl -0x44(%rbp), %eax
subl $0xd, %eax
jne 0x5306
jmp 0x52f8
movl $0x7, -0x34(%rbp)
jmp 0x5319
jmp 0x5644
movq -0x30(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x68(%rax)
movl $0x1, -0x34(%rbp)
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x48(%rbp)
subl $0x20, %eax
je 0x5336
jmp 0x532c
movl -0x48(%rbp), %eax
subl $0x3a, %eax
je 0x534f
jmp 0x5368
movq -0x30(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x70(%rax)
movl $0x2, -0x34(%rbp)
jmp 0x536a
movq -0x30(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x70(%rax)
movl $0x3, -0x34(%rbp)
jmp 0x536a
jmp 0x536a
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x4c(%rbp)
subl $0x20, %eax
je 0x5387
jmp 0x537d
movl -0x4c(%rbp), %eax
subl $0x3a, %eax
je 0x5389
jmp 0x5392
jmp 0x539e
movl $0x3, -0x34(%rbp)
jmp 0x539e
movl $0xc, -0x4(%rbp)
jmp 0x5669
jmp 0x560f
movb -0x21(%rbp), %al
subb $0x20, %al
jne 0x53ae
jmp 0x53ac
jmp 0x53c1
movq -0x30(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x78(%rax)
movl $0x4, -0x34(%rbp)
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x50(%rbp)
subl $0xa, %eax
je 0x542a
jmp 0x53d4
movl -0x50(%rbp), %eax
subl $0xd, %eax
je 0x540b
jmp 0x53de
movl -0x50(%rbp), %eax
subl $0x20, %eax
jne 0x54a8
jmp 0x53ec
movq -0x30(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x80(%rax)
movl $0x5, -0x34(%rbp)
jmp 0x54aa
movq -0x30(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x80(%rax)
movl $0x6, -0x34(%rbp)
jmp 0x54aa
movq -0x30(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x80(%rax)
movl $0x30, %edi
callq 0x22f0
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
movq 0x78(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x18(%rbp), %rax
movq 0x80(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x58, %rsi
callq 0x6370
movl $0x0, -0x34(%rbp)
jmp 0x54aa
jmp 0x54aa
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x54(%rbp)
subl $0xa, %eax
je 0x54dc
jmp 0x54bd
movl -0x54(%rbp), %eax
subl $0xd, %eax
je 0x54d3
jmp 0x54c7
movl -0x54(%rbp), %eax
subl $0x20, %eax
jne 0x5547
jmp 0x54d1
jmp 0x554e
movl $0x6, -0x34(%rbp)
jmp 0x554e
movl $0x30, %edi
callq 0x22f0
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
movq 0x78(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x18(%rbp), %rax
movq 0x80(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x58, %rsi
callq 0x6370
movl $0x0, -0x34(%rbp)
jmp 0x554e
movl $0x4, -0x34(%rbp)
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x58(%rbp)
subl $0xa, %eax
je 0x556b
jmp 0x5561
movl -0x58(%rbp), %eax
subl $0xd, %eax
je 0x55d6
jmp 0x55d8
movl $0x30, %edi
callq 0x22f0
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
movq 0x78(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x18(%rbp), %rax
movq 0x80(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x58, %rsi
callq 0x6370
movl $0x0, -0x34(%rbp)
jmp 0x55e4
jmp 0x55e4
movl $0xc, -0x4(%rbp)
jmp 0x5669
jmp 0x560f
movzbl -0x21(%rbp), %eax
movl %eax, -0x5c(%rbp)
subl $0xa, %eax
je 0x55fe
jmp 0x55f4
movl -0x5c(%rbp), %eax
subl $0xd, %eax
je 0x5600
jmp 0x5602
jmp 0x5644
jmp 0x560b
movl $0xc, -0x4(%rbp)
jmp 0x5669
jmp 0x560f
jmp 0x560f
jmp 0x5611
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x529d
movq -0x30(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x2098(%rax)
movl -0x34(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x48(%rax)
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x5669
movq -0x30(%rbp), %rcx
addq $0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x2098(%rax)
movq -0x18(%rbp), %rax
movl $0x0, 0x48(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)