// File: /workspace/github_c_makefile_star2_O3/sachinites[P]CommandParser/parser.c
// Function: build_tlv_buffer
static CMD_PARSE_STATUS
build_tlv_buffer(char **tokens, 
                 size_t token_cnt){ 

    int i = 0; 
    param_t *parent = NULL;
    param_t *curr_hook;
    param_t *param = get_cmd_tree_cursor();
    CMD_PARSE_STATUS status = COMPLETE;
    op_mode enable_or_disable = MODE_UNKNOWN; 


    memset(&tlv, 0, sizeof(tlv_struct_t));

    for(; i < token_cnt; i++){
        
        parent = param;    
        param = find_matching_param(get_child_array_ptr(param), *(tokens +i));
    
        if(param){
            if(IS_PARAM_LEAF(param)){

                /*If it is a leaf, collect the leaf value and continue to parse. Below function performs
                 * basic standard sanity checks on the leaf value input by the user */ 
                if(INVOKE_LEAF_LIB_VALIDATION_CALLBACK(param, *(tokens +i)) == VALIDATION_SUCCESS){

                    /*Standard librray checks have passed, now call user validation callback function*/
                    if(INVOKE_LEAF_USER_VALIDATION_CALLBACK(param, *(tokens +i)) == VALIDATION_SUCCESS){
                        /*Now collect this leaf information into TLV*/
                        prepare_tlv_from_leaf(GET_PARAM_LEAF(param), (&tlv));
                        put_value_in_tlv((&tlv), *(tokens +i));
                        strncpy(GET_LEAF_VALUE_PTR(param), *(tokens +i), MIN(strlen(*(tokens +i)), LEAF_VALUE_HOLDER_SIZE));
                        GET_LEAF_VALUE_PTR(param)[strlen(*(tokens +i))] = '\0';
                        collect_tlv(tlv_buff, &tlv);
                        memset(&tlv, 0, sizeof(tlv_struct_t));
                        continue;
                    }
                    else{
                        status = USER_INVALID_LEAF;
                    }
                }
                else{
                    /*If leaf is not a valid value, terminate the command parsing immediately*/
                    status = INVALID_LEAF;
                }
                break;
            }
            else{
                if(IS_PARAM_NO_CMD(param)){
                    enable_or_disable = CONFIG_DISABLE;
                }
                continue;
            }
        }

        status = CMD_NOT_FOUND;
        break;
    }

    if(status == COMPLETE){
        if(!IS_APPLICATION_CALLBACK_HANDLER_REGISTERED(param))
            status = INCOMPLETE_COMMAND;
    }

    switch(status){
        case MULTIPLE_MATCHING_COMMANDS:
            break;

        case CMD_NOT_FOUND:
            printf(ANSI_COLOR_RED "Error : Following Token not registered : %s\n"
                        ANSI_COLOR_RESET, *(tokens +i));
            break;

        case INVALID_LEAF:
            printf(ANSI_COLOR_RED "Error : Following leaf value could not be validated"
                    ": %s, Expected Data type = %s\n" 
                    ANSI_COLOR_RESET, *(tokens +i), GET_LEAF_TYPE_STR(param));
            break;

        case COMPLETE:
            printf(ANSI_COLOR_GREEN "Parse Success.\n" ANSI_COLOR_RESET);
            if(param == libcli_get_show_brief_extension_param()){
                if(!IS_APPLICATION_CALLBACK_HANDLER_REGISTERED(parent)){
                    status = INCOMPLETE_COMMAND;
                    printf(ANSI_COLOR_YELLOW "Error : Incomplete Command\n" ANSI_COLOR_RESET);
                    break;
                }
                enable_or_disable = OPERATIONAL;
                /*Add the show extension param TLV to tlv buffer, this is really not an
                 * application callback*/
                INVOKE_APPLICATION_CALLBACK_HANDLER(param, tlv_buff, enable_or_disable);
                memset(command_code_tlv.value, 0, LEAF_VALUE_HOLDER_SIZE);
                sprintf(command_code_tlv.value, "%d", parent->CMDCODE);
                collect_tlv(tlv_buff, &command_code_tlv); 
                /*Now invoke the pplication handler*/
                INVOKE_APPLICATION_CALLBACK_HANDLER(parent, tlv_buff, enable_or_disable);
            }

            else if(param == libcli_get_suboptions_param()){
                memset(command_code_tlv.value, 0, LEAF_VALUE_HOLDER_SIZE);
                sprintf(command_code_tlv.value, "%d", parent->CMDCODE);
                mark_checkpoint_serialize_buffer(tlv_buff);
                display_sub_options_callback(parent, tlv_buff, MODE_UNKNOWN);
                set_cmd_tree_cursor(parent);
		if (parent == libcli_get_root()) break;
                build_mode_console_name(parent);
                break;
            }

            else if(param == libcli_get_mode_param()){
               
                curr_hook = get_current_branch_hook(parent);

                if (curr_hook == libcli_get_config_hook() &&
                        enable_or_disable != CONFIG_DISABLE)
                    enable_or_disable = CONFIG_ENABLE;

                else if (curr_hook != libcli_get_config_hook())
                    enable_or_disable = OPERATIONAL;

                memset(command_code_tlv.value, 0, LEAF_VALUE_HOLDER_SIZE);
                sprintf(command_code_tlv.value, "%d", parent->CMDCODE);
                /*Let us checkpoint the ser buffer before adding the commandcode, 
                 * because we would not want cmd code in subsequent comds in mode*/
                mark_checkpoint_serialize_buffer(tlv_buff);
                collect_tlv(tlv_buff, &command_code_tlv);
                mode_enter_callback(parent, tlv_buff, enable_or_disable);
            }

            else if(param == libcli_get_cmd_expansion_param())
                display_cmd_expansion_callback(parent, tlv_buff, MODE_UNKNOWN);

            else{
                curr_hook = get_current_branch_hook(param);

                if(curr_hook == libcli_get_config_hook() &&
                        enable_or_disable != CONFIG_DISABLE)
                    enable_or_disable = CONFIG_ENABLE;

                else if(curr_hook != libcli_get_config_hook())
                    enable_or_disable = OPERATIONAL;

                if(curr_hook != libcli_get_repeat_hook() &&
                    param != libcli_get_config_hook()){
                    /*Add command code here*/
                    memset(command_code_tlv.value, 0, LEAF_VALUE_HOLDER_SIZE);
                    sprintf(command_code_tlv.value, "%d", param->CMDCODE);
                    collect_tlv(tlv_buff, &command_code_tlv); 
                }
                INVOKE_APPLICATION_CALLBACK_HANDLER(param, tlv_buff, enable_or_disable);
            }
            break;

        case USER_INVALID_LEAF:
            printf(ANSI_COLOR_YELLOW "Error : User validation has failed : Invalid value for Leaf : %s\n", GET_LEAF_ID(param));
            printf(ANSI_COLOR_RESET);
            break;

        case INCOMPLETE_COMMAND:
            printf(ANSI_COLOR_YELLOW "Error : Incomplete Command\n" ANSI_COLOR_RESET);
            break;

        default:
            printf(ANSI_COLOR_RED "FATAL : Unknown case fall\n" ANSI_COLOR_RESET);
    }
    return status;;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbp
movq %rdi, %r15
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x1ca1
movq %rax, %r14
xorps %xmm0, %xmm0
movups %xmm0, 0xecc0(%rip)     # 0x126b8
movups %xmm0, 0xecc9(%rip)     # 0x126c8
movups %xmm0, 0xecd2(%rip)     # 0x126d8
movups %xmm0, 0xecdb(%rip)     # 0x126e8
movups %xmm0, 0xece4(%rip)     # 0x126f8
movups %xmm0, 0xeced(%rip)     # 0x12708
movl $0x0, 0xecf3(%rip)      # 0x12718
testq %rbp, %rbp
je 0x3bc9
movl $0x3, 0x4(%rsp)
xorl %r12d, %r12d
movq %rbp, 0x8(%rsp)
movq %r14, %rbx
leaq 0x60(%r14), %rdi
movq (%r15,%r12,8), %rsi
callq 0x33e9
testq %rax, %rax
je 0x3cee
movq %rax, %r14
movl (%rax), %eax
cmpl $0x2, %eax
je 0x3bb3
cmpl $0x1, %eax
jne 0x3bbb
movq 0x8(%r14), %rdi
movl (%rdi), %eax
movq (%r15,%r12,8), %rsi
leaq 0xb9f1(%rip), %rcx      # 0xf470
callq *(%rcx,%rax,8)
movq (%r15,%r12,8), %r13
testl %eax, %eax
jne 0x3e21
testq %r13, %r13
je 0x3f4c
movq 0x8(%r14), %rbp
movq 0x48(%rbp), %rax
testq %rax, %rax
je 0x3ab5
movq %r13, %rdi
callq *%rax
movq 0x8(%r14), %rbp
testl %eax, %eax
jne 0x3efa
movl (%rbp), %eax
movl %eax, 0xebfa(%rip)      # 0x126b8
addq $0x50, %rbp
movq %rbp, %rdi
callq 0x10c0
cmpq $0x20, %rax
movl $0x20, %ecx
cmovaeq %rcx, %rax
leaq 0xebde(%rip), %rdi      # 0x126bc
movq %rbp, %rsi
movq %rax, %rdx
callq 0x1060
movq (%r15,%r12,8), %r13
movq %r13, %rdi
callq 0x10c0
movq %rbx, 0x10(%rsp)
movl $0x40, %ebx
cmpq %rbx, %rax
cmovaeq %rbx, %rax
leaq 0xebcf(%rip), %rdi      # 0x126dc
movq %r13, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%r14), %r13
addq $0x4, %r13
movq (%r15,%r12,8), %rbp
movq %rbp, %rdi
callq 0x10c0
cmpq $0x40, %rax
cmovaeq %rbx, %rax
movq 0x10(%rsp), %rbx
movq %r13, %rdi
movq %rbp, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%r14), %r13
movq (%r15,%r12,8), %rdi
callq 0x10c0
movb $0x0, 0x4(%r13,%rax)
leaq 0xb8ff(%rip), %rax      # 0xf460
movq (%rax), %rdi
leaq 0xeb4d(%rip), %rsi      # 0x126b8
movl $0x64, %edx
callq 0x477d
xorps %xmm0, %xmm0
movups %xmm0, 0xeb89(%rip)     # 0x12708
movups %xmm0, 0xeb72(%rip)     # 0x126f8
movups %xmm0, 0xeb5b(%rip)     # 0x126e8
movups %xmm0, 0xeb44(%rip)     # 0x126d8
movups %xmm0, 0xeb2d(%rip)     # 0x126c8
movups %xmm0, 0xeb16(%rip)     # 0x126b8
movl $0x0, 0xeb6c(%rip)      # 0x12718
movq 0x8(%rsp), %rbp
jmp 0x3bbb
movl $0x0, 0x4(%rsp)
incq %r12
cmpq %r12, %rbp
jne 0x3a3e
jmp 0x3bd1
movl $0x3, 0x4(%rsp)
cmpq $0x0, 0x10(%r14)
je 0x3d8d
leaq 0x4fbd(%rip), %rdi      # 0x8ba0
xorl %eax, %eax
callq 0x10e0
callq 0x1b84
cmpq %rax, %r14
je 0x3d0a
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1b2c
cmpq %rax, %r14
je 0x3da5
xorl %eax, %eax
callq 0x1b24
cmpq %rax, %r14
je 0x3e4a
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1b34
cmpq %rax, %r14
movl 0x4(%rsp), %r12d
je 0x3f24
movq %r14, %rdi
callq 0x2cb9
movq %rax, %r15
callq 0x1b64
cmpq %rax, %r15
sete %al
testl %r12d, %r12d
setne %cl
movl $0x1, %ebx
testb %cl, %al
jne 0x3c67
callq 0x1b64
cmpq %rax, %r15
movl $0x2, %ebx
cmovel %r12d, %ebx
callq 0x1b7c
cmpq %rax, %r15
je 0x3cd4
callq 0x1b64
cmpq %rax, %r14
je 0x3cd4
xorps %xmm0, %xmm0
movups %xmm0, 0xea1f(%rip)     # 0x126a4
movups %xmm0, 0xea08(%rip)     # 0x12694
movups %xmm0, 0xe9f1(%rip)     # 0x12684
movups %xmm0, 0xe9da(%rip)     # 0x12674
leaq 0xe9af(%rip), %r15      # 0x12650
leaq 0xe9cc(%rip), %rdi      # 0x12674
movl 0xf0(%r14), %edx
leaq 0x4d8a(%rip), %rsi      # 0x8a40
xorl %eax, %eax
callq 0x1240
leaq 0xb79c(%rip), %rax      # 0xf460
movq (%rax), %rdi
movq %r15, %rsi
movl $0x64, %edx
callq 0x477d
leaq 0xb785(%rip), %rax      # 0xf460
movq (%rax), %rsi
movq %r14, %rdi
movl %ebx, %edx
callq *0x10(%r14)
xorl %ebp, %ebp
jmp 0x3f3b
movq (%r15,%r12,8), %rsi
leaq 0x4e16(%rip), %rdi      # 0x8b0f
xorl %eax, %eax
callq 0x10e0
movl $0x4, %ebp
jmp 0x3f3b
cmpq $0x0, 0x10(%rbx)
je 0x3d8d
leaq 0xb748(%rip), %r15      # 0xf460
movq (%r15), %rsi
movq %r14, %rdi
movl $0x2, %edx
callq *0x10(%r14)
xorps %xmm0, %xmm0
movups %xmm0, 0xe943(%rip)     # 0x12674
movups %xmm0, 0xe94c(%rip)     # 0x12684
movups %xmm0, 0xe955(%rip)     # 0x12694
movups %xmm0, 0xe95e(%rip)     # 0x126a4
leaq 0xe903(%rip), %r14      # 0x12650
leaq 0xe920(%rip), %rdi      # 0x12674
movl 0xf0(%rbx), %edx
leaq 0x4cdf(%rip), %rsi      # 0x8a40
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1240
movq (%r15), %rdi
movq %r14, %rsi
movl $0x64, %edx
callq 0x477d
movq (%r15), %rsi
movq %rbx, %rdi
movl $0x2, %edx
callq *0x10(%rbx)
jmp 0x3f3b
leaq 0x4e25(%rip), %rdi      # 0x8bb9
xorl %eax, %eax
callq 0x10e0
movl $0x5, %ebp
jmp 0x3f3b
xorps %xmm0, %xmm0
movups %xmm0, 0xe8f5(%rip)     # 0x126a4
movups %xmm0, 0xe8de(%rip)     # 0x12694
movups %xmm0, 0xe8c7(%rip)     # 0x12684
movups %xmm0, 0xe8b0(%rip)     # 0x12674
leaq 0xe8a9(%rip), %rdi      # 0x12674
movl 0xf0(%rbx), %edx
leaq 0x4c68(%rip), %rsi      # 0x8a40
xorl %eax, %eax
callq 0x1240
leaq 0xb67a(%rip), %r14      # 0xf460
movq (%r14), %rdi
callq 0x440a
movq (%r14), %rsi
movq %rbx, %rdi
movl $0x3, %edx
callq 0x51d2
movq %rbx, %rdi
callq 0x1c74
callq 0x1b3c
cmpq %rax, %rbx
je 0x3f3b
movq %rbx, %rdi
callq 0x2faa
jmp 0x3f3b
movq 0x8(%r14), %rax
movl (%rax), %edi
callq 0x1cea
leaq 0x4d12(%rip), %rdi      # 0x8b45
movq %r13, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x10e0
movl $0x2, %ebp
jmp 0x3f3b
movq %rbx, %rdi
callq 0x2cb9
movq %rax, %r15
callq 0x1b64
cmpq %rax, %r15
sete %al
movl 0x4(%rsp), %ebp
testl %ebp, %ebp
setne %cl
movl $0x1, %r14d
testb %cl, %al
jne 0x3e85
callq 0x1b64
cmpq %rax, %r15
movl $0x2, %r14d
cmovel %ebp, %r14d
xorps %xmm0, %xmm0
movups %xmm0, 0xe815(%rip)     # 0x126a4
movups %xmm0, 0xe7fe(%rip)     # 0x12694
movups %xmm0, 0xe7e7(%rip)     # 0x12684
movups %xmm0, 0xe7d0(%rip)     # 0x12674
leaq 0xe7a5(%rip), %r15      # 0x12650
leaq 0xe7c2(%rip), %rdi      # 0x12674
movl 0xf0(%rbx), %edx
leaq 0x4b81(%rip), %rsi      # 0x8a40
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1240
leaq 0xb591(%rip), %r12      # 0xf460
movq (%r12), %rdi
callq 0x440a
movq (%r12), %rdi
movq %r15, %rsi
movl $0x64, %edx
callq 0x477d
movq (%r12), %rsi
movq %rbx, %rdi
movl %r14d, %edx
callq 0x5180
jmp 0x3f3b
addq $0x50, %rbp
leaq 0x4cd9(%rip), %rdi      # 0x8bde
movq %rbp, %rsi
xorl %eax, %eax
callq 0x10e0
leaq 0x4c9e(%rip), %rdi      # 0x8bb4
xorl %eax, %eax
callq 0x10e0
movl $0x3, %ebp
jmp 0x3f3b
leaq 0xb535(%rip), %rax      # 0xf460
movq (%rax), %rsi
movq %rbx, %rdi
movl $0x3, %edx
callq 0x52ca
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4d1b(%rip), %rdi      # 0x8c6e
leaq 0x4ccb(%rip), %rsi      # 0x8c25
leaq 0x4cd1(%rip), %rcx      # 0x8c32
movl $0x92, %edx
callq 0x10f0