// File: /workspace/github_c_makefile_star2_O0/ttoobne[P]bohttpd/src/http/http_parse.c
// Function: http_parse_request_line
int http_parse_request_line(void* http_request) {
    http_request_t* rq;
    unsigned char   ch;
    unsigned char*  p;
    unsigned char*  m;

    rq = (http_request_t*)http_request;

    /* 维护一个状态机来解析 http 请求行 */
    /* 格式：<method> <uri> <version> CRLF */
    enum {
        start = 0,
        method,
        spaces_before_uri,
        after_slash_in_uri,
        spaces_after_uri,
        http_version_H,
        http_version_HT,
        http_version_HTT,
        http_version_HTTP,
        http_version_first_major_digit,
        http_version_major_digit,
        http_version_first_minor_digit,
        http_version_minor_digit,
        spaces_after_digit,
        almost_done
    } state;

    state = rq->state;

    //DBG("ready to parse.\n");

    for (p = rq->bufst; p != rq->bufed; ++ p) {
        ch = *p;

        switch (state) {
        
        /* 开始解析 */
        case start:

            //DBG("start.\n");

            if (ch == CR || ch == LF) {
                break;
            }

            rq->request_start = p;
            rq->method_start = p;

            if (ch < 'A' || ch > 'Z') {
                return HTTP_PARSE_INVALID_METHOD;
            }

            state = method;
            break;  /* case start */

        /* http 请求方法 */
        case method:

            //DBG("method.\n");

            if (ch == ' ') {
                rq->method_end = p - 1;
                m = rq->method_start;

                switch (p - m) { /* method_end - method_start + 1 */
                case 3:
                    /* GET 方法 */
                    if (str_method_cmp(m, 'G', 'E', 'T', ' ')) {
                        rq->method = HTTP_GET;
                        break;
                    }

                    break;
                
                case 4:
                    /* HEAD 方法 */
                    if (str_method_cmp(m, 'H', 'E', 'A', 'D')) {
                        rq->method = HTTP_HEAD;
                        break;
                    }
                    /* POST 方法 */
                    if (str_method_cmp(m, 'P', 'O', 'S', 'T')) {
                        rq->method = HTTP_POST;
                        break;
                    }

                    break;
                    
                default:
                    break;
                }

                state = spaces_before_uri;
                break;
            }

            if (ch < 'A' || ch > 'Z') {
                //DBG("");
                return HTTP_PARSE_INVALID_METHOD;
            }

            break;  /* case method */

        case spaces_before_uri:

            //DBG("spaces before uri.\n");
            switch (ch) {
            case ' ':
                break;

            case '/':
                rq->uri_start = p;
                state = after_slash_in_uri;
                break;

            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case spaces_before_uri */
        
        /* uri */
        case after_slash_in_uri:
            //DBG("after slash in uri.\n");
            switch (ch) {
            case ' ':
                rq->uri_end = p - 1;
                state = spaces_after_uri;
                break;
            
            case '?':
                rq->have_args = 1;
                rq->args_start = p + 1;
                break;

            default:
                break;
            }

            break;  /* case after_slash_in_uri */

        case spaces_after_uri:
            //DBG("spaces after uri.\n");
            switch (ch) {
            case ' ':
                break;
            
            case 'H':
                state = http_version_H;
                break;

            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case spaces_after_uri */

        /* http 版本号 */
        case http_version_H:
            //DBG("http version H.\n");
            switch (ch) {
            case 'T':
                state = http_version_HT;
                break;
            
            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case http_version_H */
        
        case http_version_HT:
            //DBG("http version HT.\n");
            switch (ch) {
            case 'T':
                state = http_version_HTT;
                break;
            
            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case http_version_HT */

        case http_version_HTT:
            //DBG("http version HTT.\n");
            switch (ch) {
            case 'P':
                state = http_version_HTTP;
                break;
            
            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case http_version_HTT */

        case http_version_HTTP:
            //DBG("http version HTTP.\n");
            switch (ch) {
            case '/':
                state = http_version_first_major_digit;
                break;
            
            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case http_version_HTTP */
        
        case http_version_first_major_digit:
            //DBG("http version first major digit.\n");
            if (ch < '0' || ch > '9') {
                return HTTP_PARSE_INVALID_REQUEST;
            }

            rq->http_version_major = ch - '0';
            state = http_version_major_digit;

            break;  /* case http_version_first_major_digit */
        
        case http_version_major_digit:
            //DBG("http version major digit.\n");
            if (ch == '.') {
                state = http_version_first_minor_digit;
                break;
            }

            if (ch < '0' || ch > '9') {
                return HTTP_PARSE_INVALID_REQUEST;
            }

            rq->http_version_major = rq->http_version_major * 10 + ch - '0';
            state = http_version_first_minor_digit;

            break;  /* case http_version_major_digit */

        case http_version_first_minor_digit:
            //DBG("http version first minor digit.\n");
            if (ch < '0' || ch > '9') {
                return HTTP_PARSE_INVALID_REQUEST;
            }

            rq->http_version_minor = ch - '0';
            state = http_version_minor_digit;

            break;  /* case http_version_first_minor_digit */

        case http_version_minor_digit:
            //DBG("http version minor digit.\n");
            
            if (ch < '0' || ch > '9') {
                switch (ch) {
                case ' ':
                    state = spaces_after_digit;
                    break;

                case CR:
                    state = almost_done;
                    break;

                case LF:
                    goto done;
                
                default:
                    return HTTP_PARSE_INVALID_REQUEST;
                }

                break;
            }

            rq->http_version_minor = rq->http_version_minor * 10 + ch - '0';
            state = spaces_after_digit;

            break;  /* case http_version_minor_digit */

        case spaces_after_digit:
            //DBG("apaces after digit.\n");
            switch (ch) {
            case ' ':
                break;
            
            case CR:
                state = almost_done;
                break;
            
            case LF:
                goto done;

            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            break;  /* case spaces_after_digit */

        case almost_done:
            //DBG("almost done.\n");
            switch (ch) {
            case LF:
                goto done;
            
            default:
                return HTTP_PARSE_INVALID_REQUEST;
            }

            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->request_end = p;
    rq->state = start;

    return REQUEST_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
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, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq -0x18(%rbp), %rcx
cmpq 0x20a0(%rcx), %rax
je 0x5212
movq -0x28(%rbp), %rax
movb (%rax), %al
movb %al, -0x19(%rbp)
movl -0x34(%rbp), %eax
movq %rax, -0x40(%rbp)
subq $0xe, %rax
ja 0x51fd
movq -0x40(%rbp), %rax
leaq 0x4d4d(%rip), %rcx      # 0x9ae0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movzbl -0x19(%rbp), %eax
cmpl $0xd, %eax
je 0x4dae
movzbl -0x19(%rbp), %eax
cmpl $0xa, %eax
jne 0x4db3
jmp 0x51ff
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x20(%rax)
movzbl -0x19(%rbp), %eax
cmpl $0x41, %eax
jl 0x4ddd
movzbl -0x19(%rbp), %eax
cmpl $0x5a, %eax
jle 0x4de9
movl $0xa, -0x4(%rbp)
jmp 0x5265
movl $0x1, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x20, %eax
jne 0x4e9d
movq -0x28(%rbp), %rcx
decq %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x48(%rbp)
subq $0x3, %rax
je 0x4e40
jmp 0x4e34
movq -0x48(%rbp), %rax
subq $0x4, %rax
je 0x4e5b
jmp 0x4e8f
movq -0x30(%rbp), %rax
cmpl $0x20544547, (%rax)     # imm = 0x20544547
jne 0x4e59
movq -0x18(%rbp), %rax
movl $0x2, 0x4c(%rax)
jmp 0x4e91
jmp 0x4e91
movq -0x30(%rbp), %rax
cmpl $0x44414548, (%rax)     # imm = 0x44414548
jne 0x4e74
movq -0x18(%rbp), %rax
movl $0x4, 0x4c(%rax)
jmp 0x4e91
movq -0x30(%rbp), %rax
cmpl $0x54534f50, (%rax)     # imm = 0x54534F50
jne 0x4e8d
movq -0x18(%rbp), %rax
movl $0x8, 0x4c(%rax)
jmp 0x4e91
jmp 0x4e91
jmp 0x4e91
movl $0x2, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x41, %eax
jl 0x4eaf
movzbl -0x19(%rbp), %eax
cmpl $0x5a, %eax
jle 0x4ebb
movl $0xa, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movzbl -0x19(%rbp), %eax
movl %eax, -0x4c(%rbp)
subl $0x20, %eax
je 0x4ed8
jmp 0x4ece
movl -0x4c(%rbp), %eax
subl $0x2f, %eax
je 0x4eda
jmp 0x4eef
jmp 0x4efb
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x30(%rax)
movl $0x3, -0x34(%rbp)
jmp 0x4efb
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movzbl -0x19(%rbp), %eax
movl %eax, -0x50(%rbp)
subl $0x20, %eax
je 0x4f18
jmp 0x4f0e
movl -0x50(%rbp), %eax
subl $0x3f, %eax
je 0x4f31
jmp 0x4f4e
movq -0x28(%rbp), %rcx
addq $-0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x40(%rax)
movl $0x4, -0x34(%rbp)
jmp 0x4f50
movq -0x18(%rbp), %rax
movl $0x1, 0x50(%rax)
movq -0x28(%rbp), %rcx
addq $0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x38(%rax)
jmp 0x4f50
jmp 0x4f50
jmp 0x51ff
movzbl -0x19(%rbp), %eax
movl %eax, -0x54(%rbp)
subl $0x20, %eax
je 0x4f6d
jmp 0x4f63
movl -0x54(%rbp), %eax
subl $0x48, %eax
je 0x4f6f
jmp 0x4f78
jmp 0x4f84
movl $0x5, -0x34(%rbp)
jmp 0x4f84
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movb -0x19(%rbp), %al
subb $0x54, %al
jne 0x4f9b
jmp 0x4f92
movl $0x6, -0x34(%rbp)
jmp 0x4fa7
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movb -0x19(%rbp), %al
subb $0x54, %al
jne 0x4fbe
jmp 0x4fb5
movl $0x7, -0x34(%rbp)
jmp 0x4fca
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movb -0x19(%rbp), %al
subb $0x50, %al
jne 0x4fe1
jmp 0x4fd8
movl $0x8, -0x34(%rbp)
jmp 0x4fed
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movb -0x19(%rbp), %al
subb $0x2f, %al
jne 0x5004
jmp 0x4ffb
movl $0x9, -0x34(%rbp)
jmp 0x5010
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x30, %eax
jl 0x5027
movzbl -0x19(%rbp), %eax
cmpl $0x39, %eax
jle 0x5033
movl $0xb, -0x4(%rbp)
jmp 0x5265
movzbl -0x19(%rbp), %edx
subl $0x30, %edx
movq -0x18(%rbp), %rax
movl 0x54(%rax), %ecx
andl $0xffff, %edx           # imm = 0xFFFF
shll $0x10, %edx
andl $0xffff, %ecx           # imm = 0xFFFF
orl %edx, %ecx
movl %ecx, 0x54(%rax)
movl $0xa, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x2e, %eax
jne 0x5076
movl $0xb, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x30, %eax
jl 0x5088
movzbl -0x19(%rbp), %eax
cmpl $0x39, %eax
jle 0x5094
movl $0xb, -0x4(%rbp)
jmp 0x5265
movq -0x18(%rbp), %rax
movl 0x54(%rax), %eax
shrl $0x10, %eax
imull $0xa, %eax, %edx
movzbl -0x19(%rbp), %eax
addl %eax, %edx
subl $0x30, %edx
movq -0x18(%rbp), %rax
movl 0x54(%rax), %ecx
andl $0xffff, %edx           # imm = 0xFFFF
shll $0x10, %edx
andl $0xffff, %ecx           # imm = 0xFFFF
orl %edx, %ecx
movl %ecx, 0x54(%rax)
movl $0xb, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x30, %eax
jl 0x50e3
movzbl -0x19(%rbp), %eax
cmpl $0x39, %eax
jle 0x50ef
movl $0xb, -0x4(%rbp)
jmp 0x5265
movzbl -0x19(%rbp), %edx
subl $0x30, %edx
movq -0x18(%rbp), %rax
movl 0x54(%rax), %ecx
andl $0xffff, %edx           # imm = 0xFFFF
andl $0xffff0000, %ecx       # imm = 0xFFFF0000
orl %edx, %ecx
movl %ecx, 0x54(%rax)
movl $0xc, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
cmpl $0x30, %eax
jl 0x512c
movzbl -0x19(%rbp), %eax
cmpl $0x39, %eax
jle 0x5176
movzbl -0x19(%rbp), %eax
movl %eax, -0x58(%rbp)
subl $0xa, %eax
je 0x5160
jmp 0x513a
movl -0x58(%rbp), %eax
subl $0xd, %eax
je 0x5157
jmp 0x5144
movl -0x58(%rbp), %eax
subl $0x20, %eax
jne 0x5165
jmp 0x514e
movl $0xd, -0x34(%rbp)
jmp 0x5171
movl $0xe, -0x34(%rbp)
jmp 0x5171
jmp 0x5234
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movq -0x18(%rbp), %rax
movl 0x54(%rax), %eax
andl $0xffff, %eax           # imm = 0xFFFF
imull $0xa, %eax, %edx
movzbl -0x19(%rbp), %eax
addl %eax, %edx
subl $0x30, %edx
movq -0x18(%rbp), %rax
movl 0x54(%rax), %ecx
andl $0xffff, %edx           # imm = 0xFFFF
andl $0xffff0000, %ecx       # imm = 0xFFFF0000
orl %edx, %ecx
movl %ecx, 0x54(%rax)
movl $0xd, -0x34(%rbp)
jmp 0x51ff
movzbl -0x19(%rbp), %eax
movl %eax, -0x5c(%rbp)
subl $0xa, %eax
je 0x51dc
jmp 0x51bd
movl -0x5c(%rbp), %eax
subl $0xd, %eax
je 0x51d3
jmp 0x51c7
movl -0x5c(%rbp), %eax
subl $0x20, %eax
jne 0x51de
jmp 0x51d1
jmp 0x51e7
movl $0xe, -0x34(%rbp)
jmp 0x51e7
jmp 0x5234
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
movb -0x19(%rbp), %al
subb $0xa, %al
jne 0x51f4
jmp 0x51f2
jmp 0x5234
movl $0xb, -0x4(%rbp)
jmp 0x5265
jmp 0x51ff
jmp 0x5201
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x4d59
movq -0x28(%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 0x5265
movq -0x28(%rbp), %rcx
addq $0x1, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x2098(%rax)
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rax
movl $0x0, 0x48(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
popq %rbp
retq
nopw (%rax,%rax)