// File: /workspace/github_c_makefile_star2_O1/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, %rbx
movq %rdi, %r15
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1cb4
movq %rax, %rdx
xorps %xmm0, %xmm0
movups %xmm0, 0xec3c(%rip)     # 0x126b8
movups %xmm0, 0xec45(%rip)     # 0x126c8
movups %xmm0, 0xec4e(%rip)     # 0x126d8
movups %xmm0, 0xec57(%rip)     # 0x126e8
movups %xmm0, 0xec60(%rip)     # 0x126f8
movups %xmm0, 0xec69(%rip)     # 0x12708
movl $0x0, 0xec6f(%rip)      # 0x12718
movl $0x3, %r14d
movq %rbx, 0x10(%rsp)
testq %rbx, %rbx
setne %bpl
je 0x3c94
movq %rdx, %rdi
addq $0x60, %rdi
movq (%r15), %rsi
movq %rdx, %r13
callq 0x3429
movl $0x4, %r12d
testq %rax, %rax
je 0x3c9b
movl $0x3, 0x4(%rsp)
movl $0x1, %r12d
xorl %ebx, %ebx
movq %rax, %r14
movl (%rax), %eax
cmpl $0x2, %eax
je 0x3c4f
cmpl $0x1, %eax
jne 0x3c57
movq %r13, 0x8(%rsp)
movq 0x8(%r14), %rdi
movl (%rdi), %eax
movq -0x8(%r15,%r12,8), %rsi
leaq 0xb950(%rip), %rcx      # 0xf470
callq *(%rcx,%rax,8)
testl %eax, %eax
jne 0x3cab
movq -0x8(%r15,%r12,8), %rdi
testq %rdi, %rdi
je 0x4089
movq 0x8(%r14), %rax
movq 0x48(%rax), %rax
testq %rax, %rax
je 0x3b50
callq *%rax
testl %eax, %eax
jne 0x3cb9
movq 0x8(%r14), %rbp
movl (%rbp), %eax
movl %eax, 0xeb5b(%rip)      # 0x126b8
addq $0x50, %rbp
movq %rbp, %rdi
callq 0x10c0
cmpq $0x20, %rax
jb 0x3b74
movl $0x20, %eax
leaq 0xeb41(%rip), %rdi      # 0x126bc
movq %rbp, %rsi
movq %rax, %rdx
callq 0x1060
movq -0x8(%r15,%r12,8), %r13
movq %r13, %rdi
callq 0x10c0
movl $0x40, %ecx
cmpq %rcx, %rax
jb 0x3ba2
movl $0x40, %eax
leaq 0xeb33(%rip), %rdi      # 0x126dc
movq %r13, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%r14), %rbp
movq -0x8(%r15,%r12,8), %r13
movq %r13, %rdi
callq 0x10c0
cmpq $0x40, %rax
jb 0x3bd0
movl $0x40, %eax
addq $0x4, %rbp
movq %rbp, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%r14), %r13
movq -0x8(%r15,%r12,8), %rdi
callq 0x10c0
movb $0x0, 0x4(%r13,%rax)
leaq 0xb863(%rip), %rax      # 0xf460
movq (%rax), %rdi
leaq 0xeab1(%rip), %rsi      # 0x126b8
movl $0x64, %edx
callq 0x48db
xorps %xmm0, %xmm0
movups %xmm0, 0xeaed(%rip)     # 0x12708
movups %xmm0, 0xead6(%rip)     # 0x126f8
movups %xmm0, 0xeabf(%rip)     # 0x126e8
movups %xmm0, 0xeaa8(%rip)     # 0x126d8
movups %xmm0, 0xea91(%rip)     # 0x126c8
movups %xmm0, 0xea7a(%rip)     # 0x126b8
movl $0x0, 0xead0(%rip)      # 0x12718
movq 0x8(%rsp), %r13
jmp 0x3c57
movl $0x0, 0x4(%rsp)
cmpq 0x10(%rsp), %r12
setb %bpl
je 0x3ca1
leaq 0x60(%r14), %rdi
movq (%r15,%r12,8), %rsi
callq 0x3429
incq %r12
incq %rbx
movq %r14, %r13
testq %rax, %rax
jne 0x3af2
decq %r12
xorl %edx, %edx
movq %r12, %rbx
movq %r14, %r13
movl $0x4, %r12d
jmp 0x3cc7
xorl %ebx, %ebx
xorl %r13d, %r13d
jmp 0x3ccc
xorl %ebx, %ebx
xorl %edx, %edx
jmp 0x3ccc
xorl %r12d, %r12d
movq 0x10(%rsp), %rbx
jmp 0x3cc4
decq %r12
movq %r12, %rbx
movl $0x2, %r12d
jmp 0x3cbf
movl $0x3, %r12d
movq 0x8(%rsp), %r13
movq %r14, %rdx
movl 0x4(%rsp), %r14d
testb $0x1, %bpl
jne 0x3ce0
xorl %eax, %eax
cmpq $0x0, 0x10(%rdx)
sete %al
leal (%rax,%rax,4), %r12d
cmpl $0x5, %r12d
ja 0x3e11
movl %r12d, %eax
leaq 0x4cc4(%rip), %rcx      # 0x89b8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl %r14d, %ebp
leaq 0x4ed6(%rip), %rdi      # 0x8bdd
xorl %eax, %eax
movq %rdx, %r14
callq 0x10e0
callq 0x1b84
cmpq %rax, %r14
je 0x3e9e
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1b2c
cmpq %rax, %r14
je 0x3f46
xorl %eax, %eax
callq 0x1b24
cmpq %rax, %r14
je 0x3fbf
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1b34
cmpq %rax, %r14
je 0x406d
movq %r14, %rdi
callq 0x2cd3
movq %rax, %r15
callq 0x1b64
cmpq %rax, %r15
sete %al
testl %ebp, %ebp
setne %cl
movl $0x1, %ebx
testb %cl, %al
jne 0x3d89
callq 0x1b64
cmpq %rax, %r15
movl $0x2, %ebx
cmovel %ebp, %ebx
callq 0x1b7c
cmpq %rax, %r15
je 0x3df6
callq 0x1b64
cmpq %rax, %r14
je 0x3df6
xorps %xmm0, %xmm0
movups %xmm0, 0xe8fd(%rip)     # 0x126a4
movups %xmm0, 0xe8e6(%rip)     # 0x12694
movups %xmm0, 0xe8cf(%rip)     # 0x12684
movups %xmm0, 0xe8b8(%rip)     # 0x12674
leaq 0xe88d(%rip), %r15      # 0x12650
leaq 0xe8aa(%rip), %rdi      # 0x12674
movl 0xf0(%r14), %edx
leaq 0x4ca2(%rip), %rsi      # 0x8a7a
xorl %eax, %eax
callq 0x1240
leaq 0xb67a(%rip), %rax      # 0xf460
movq (%rax), %rdi
movq %r15, %rsi
movl $0x64, %edx
callq 0x48db
leaq 0xb663(%rip), %rax      # 0xf460
movq (%rax), %rsi
movq %r14, %rdi
movl %ebx, %edx
callq *0x10(%r14)
xorl %r12d, %r12d
jmp 0x3f34
leaq 0x4e4a(%rip), %rdi      # 0x8c62
xorl %eax, %eax
callq 0x10e0
jmp 0x3f34
movq (%r15,%rbx,8), %rbx
movq 0x8(%rdx), %rax
movl (%rax), %edi
callq 0x1cfd
leaq 0x4d48(%rip), %rdi      # 0x8b82
movq %rbx, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x10e0
movl $0x2, %r12d
jmp 0x3f34
movq 0x8(%rdx), %rsi
addq $0x50, %rsi
leaq 0x4dba(%rip), %rdi      # 0x8c1b
xorl %eax, %eax
callq 0x10e0
leaq 0x4d82(%rip), %rdi      # 0x8bf1
xorl %eax, %eax
callq 0x10e0
movl $0x3, %r12d
jmp 0x3f34
movq (%r15,%rbx,8), %rsi
leaq 0x4cc0(%rip), %rdi      # 0x8b4c
xorl %eax, %eax
callq 0x10e0
movl $0x4, %r12d
jmp 0x3f34
cmpq $0x0, 0x10(%r13)
je 0x3f20
movq %r14, %rdi
leaq 0xb5b1(%rip), %rbx      # 0xf460
movq (%rbx), %rsi
movl $0x2, %edx
callq *0x10(%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 0xe7b0(%rip)     # 0x12674
movups %xmm0, 0xe7b9(%rip)     # 0x12684
movups %xmm0, 0xe7c2(%rip)     # 0x12694
movups %xmm0, 0xe7cb(%rip)     # 0x126a4
leaq 0xe770(%rip), %r14      # 0x12650
leaq 0xe78d(%rip), %rdi      # 0x12674
movl 0xf0(%r13), %edx
leaq 0x4b85(%rip), %rsi      # 0x8a7a
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1240
movq (%rbx), %rdi
movq %r14, %rsi
movl $0x64, %edx
callq 0x48db
movq (%rbx), %rsi
movq %r13, %rdi
movl $0x2, %edx
callq *0x10(%r13)
jmp 0x3f34
leaq 0x4ccf(%rip), %rdi      # 0x8bf6
xorl %eax, %eax
callq 0x10e0
movl $0x5, %r12d
movl %r12d, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorps %xmm0, %xmm0
movups %xmm0, 0xe754(%rip)     # 0x126a4
movups %xmm0, 0xe73d(%rip)     # 0x12694
movups %xmm0, 0xe726(%rip)     # 0x12684
movups %xmm0, 0xe70f(%rip)     # 0x12674
leaq 0xe708(%rip), %rdi      # 0x12674
movl 0xf0(%r13), %edx
leaq 0x4b00(%rip), %rsi      # 0x8a7a
xorl %eax, %eax
callq 0x1240
leaq 0xb4d8(%rip), %rbx      # 0xf460
movq (%rbx), %rdi
callq 0x4557
movq (%rbx), %rsi
movq %r13, %rdi
movl $0x3, %edx
callq 0x531a
movq %r13, %rdi
callq 0x1c87
callq 0x1b3c
cmpq %rax, %r13
je 0x3f34
movq %r13, %rdi
callq 0x2fc4
jmp 0x3f34
movq %r13, %rdi
callq 0x2cd3
movq %rax, %rbx
callq 0x1b64
cmpq %rax, %rbx
sete %al
movl %ebp, %r14d
testl %ebp, %ebp
setne %cl
movl $0x1, %ebp
testb %cl, %al
jne 0x3ff7
callq 0x1b64
cmpq %rax, %rbx
movl $0x2, %ebp
cmovel %r14d, %ebp
xorps %xmm0, %xmm0
movups %xmm0, 0xe6a3(%rip)     # 0x126a4
movups %xmm0, 0xe68c(%rip)     # 0x12694
movups %xmm0, 0xe675(%rip)     # 0x12684
movups %xmm0, 0xe65e(%rip)     # 0x12674
leaq 0xe633(%rip), %r14      # 0x12650
leaq 0xe650(%rip), %rdi      # 0x12674
movl 0xf0(%r13), %edx
leaq 0x4a48(%rip), %rsi      # 0x8a7a
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1240
leaq 0xb41d(%rip), %rbx      # 0xf460
movq (%rbx), %rdi
callq 0x4557
movq (%rbx), %rdi
movq %r14, %rsi
movl $0x64, %edx
callq 0x48db
movq (%rbx), %rsi
movq %r13, %rdi
movl %ebp, %edx
callq 0x52c8
jmp 0x3f34
leaq 0xb3ec(%rip), %rax      # 0xf460
movq (%rax), %rsi
movq %r13, %rdi
movl $0x3, %edx
callq 0x5412
jmp 0x3f34
leaq 0x4c3f(%rip), %rdi      # 0x8ccf
leaq 0x4bef(%rip), %rsi      # 0x8c86
leaq 0x4bf5(%rip), %rcx      # 0x8c93
movl $0x92, %edx
callq 0x10f0