// File: /workspace/github_c_makefile_star2_O2/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 %r12d, %r12d
xorl %eax, %eax
callq 0x1c24
movq %rax, %r14
xorps %xmm0, %xmm0
movups %xmm0, 0xdf99(%rip)     # 0x116b8
movups %xmm0, 0xdfa2(%rip)     # 0x116c8
movups %xmm0, 0xdfab(%rip)     # 0x116d8
movups %xmm0, 0xdfb4(%rip)     # 0x116e8
andl $0x0, 0xdfdd(%rip)      # 0x11718
movups %xmm0, 0xdfb6(%rip)     # 0x116f8
movups %xmm0, 0xdfbf(%rip)     # 0x11708
pushq $0x3
popq %rax
movl %eax, 0x4(%rsp)
xorl %r13d, %r13d
movq %rbp, 0x8(%rsp)
cmpq %r12, %rbp
je 0x38e2
leaq 0x60(%r14), %rdi
movq (%r15,%r12,8), %rsi
callq 0x311f
testq %rax, %rax
je 0x396e
movq %rax, %rbx
movl (%rax), %eax
cmpl $0x2, %eax
je 0x38cc
cmpl $0x1, %eax
jne 0x38d4
movq %r14, 0x10(%rsp)
movq 0x8(%rbx), %rdi
movl (%rdi), %eax
movq (%r15,%r12,8), %rsi
leaq 0xaccc(%rip), %rcx      # 0xe470
callq *(%rcx,%rax,8)
movq (%r15,%r12,8), %rbp
testl %eax, %eax
jne 0x3987
testq %rbp, %rbp
je 0x3c48
movq 0x8(%rbx), %r13
movq 0x48(%r13), %rax
testq %rax, %rax
je 0x37da
movq %rbp, %rdi
callq *%rax
movq 0x8(%rbx), %r13
testl %eax, %eax
jne 0x3a3c
movl (%r13), %eax
movl %eax, 0xded4(%rip)      # 0x116b8
addq $0x50, %r13
movq %r13, %rdi
callq 0x10c0
cmpq $0x20, %rax
pushq $0x20
popq %rcx
cmovaeq %rcx, %rax
leaq 0xdeba(%rip), %rdi      # 0x116bc
movq %r13, %rsi
movq %rax, %rdx
callq 0x1060
movq (%r15,%r12,8), %r13
movq %r13, %rdi
callq 0x10c0
pushq $0x40
popq %r14
cmpq %r14, %rax
cmovaeq %r14, %rax
leaq 0xdeb1(%rip), %rdi      # 0x116dc
movq %r13, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%rbx), %r13
addq $0x4, %r13
movq (%r15,%r12,8), %rbp
movq %rbp, %rdi
callq 0x10c0
cmpq $0x40, %rax
cmovaeq %r14, %rax
movq %r13, %rdi
movq %rbp, %rsi
movq %rax, %rdx
callq 0x1060
movq 0x8(%rbx), %r13
movq (%r15,%r12,8), %rdi
callq 0x10c0
movb $0x0, 0x4(%r13,%rax)
leaq 0xabe6(%rip), %rax      # 0xe460
movq (%rax), %rdi
leaq 0xde34(%rip), %rsi      # 0x116b8
pushq $0x64
popq %rdx
callq 0x43d2
xorps %xmm0, %xmm0
movups %xmm0, 0xde72(%rip)     # 0x11708
movups %xmm0, 0xde5b(%rip)     # 0x116f8
movups %xmm0, 0xde44(%rip)     # 0x116e8
movups %xmm0, 0xde2d(%rip)     # 0x116d8
movups %xmm0, 0xde16(%rip)     # 0x116c8
movups %xmm0, 0xddff(%rip)     # 0x116b8
andl $0x0, 0xde58(%rip)      # 0x11718
movq 0x8(%rsp), %rbp
movq 0x10(%rsp), %r14
jmp 0x38d4
movl $0x0, 0x4(%rsp)
incq %r12
movq %r14, %r13
movq %rbx, %r14
jmp 0x3758
cmpq $0x0, 0x10(%r14)
je 0x3a2a
leaq 0x42cd(%rip), %rdi      # 0x7bc1
xorl %eax, %eax
callq 0x10e0
callq 0x1b04
cmpq %rax, %r14
je 0x39ad
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1aac
cmpq %rax, %r14
je 0x3a73
xorl %eax, %eax
callq 0x1aa4
cmpq %rax, %r14
je 0x3aea
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1ab4
cmpq %rax, %r14
movl 0x4(%rsp), %r12d
je 0x3b19
movq %r14, %rdi
callq 0x2a44
movq %rax, %r15
callq 0x1ae4
cmpq %rax, %r15
sete %al
testl %r12d, %r12d
setne %cl
testb %cl, %al
je 0x3b33
pushq $0x1
popq %rbx
jmp 0x3b42
movq (%r15,%r12,8), %rsi
leaq 0x41b7(%rip), %rdi      # 0x7b30
xorl %eax, %eax
callq 0x10e0
pushq $0x4
jmp 0x3a61
movq 0x8(%rbx), %rax
movl (%rax), %edi
callq 0x1c6d
leaq 0x41cd(%rip), %rdi      # 0x7b66
movq %rbp, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x10e0
pushq $0x2
jmp 0x3a61
cmpq $0x0, 0x10(%r13)
je 0x3a2a
leaq 0xaaa5(%rip), %r15      # 0xe460
movq (%r15), %rsi
pushq $0x2
popq %rbx
movq %r14, %rdi
movl %ebx, %edx
callq *0x10(%r14)
xorps %xmm0, %xmm0
movups %xmm0, 0xdca0(%rip)     # 0x11674
movups %xmm0, 0xdca9(%rip)     # 0x11684
movups %xmm0, 0xdcb2(%rip)     # 0x11694
movups %xmm0, 0xdcbb(%rip)     # 0x116a4
leaq 0xdc60(%rip), %r14      # 0x11650
leaq 0xdc7d(%rip), %rdi      # 0x11674
movl 0xf0(%r13), %edx
leaq 0x405c(%rip), %rsi      # 0x7a61
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1250
movq (%r15), %rdi
pushq $0x64
popq %rdx
movq %r14, %rsi
callq 0x43d2
movq (%r15), %rsi
movq %r13, %rdi
movl %ebx, %edx
callq *0x10(%r13)
jmp 0x3a62
leaq 0x41a9(%rip), %rdi      # 0x7bda
xorl %eax, %eax
callq 0x10e0
pushq $0x5
jmp 0x3a61
addq $0x50, %r13
leaq 0x41b8(%rip), %rdi      # 0x7bff
movq %r13, %rsi
xorl %eax, %eax
callq 0x10e0
leaq 0x417d(%rip), %rdi      # 0x7bd5
xorl %eax, %eax
callq 0x10e0
pushq $0x3
popq %rbp
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorps %xmm0, %xmm0
movups %xmm0, 0xdc27(%rip)     # 0x116a4
movups %xmm0, 0xdc10(%rip)     # 0x11694
movups %xmm0, 0xdbf9(%rip)     # 0x11684
movups %xmm0, 0xdbe2(%rip)     # 0x11674
leaq 0xdbdb(%rip), %rdi      # 0x11674
movl 0xf0(%r13), %edx
leaq 0x3fba(%rip), %rsi      # 0x7a61
xorl %eax, %eax
callq 0x1250
leaq 0xa9ab(%rip), %rbx      # 0xe460
movq (%rbx), %rdi
callq 0x404e
movq (%rbx), %rsi
pushq $0x3
popq %rdx
movq %r13, %rdi
callq 0x4d4a
movq %r13, %rdi
callq 0x1bf7
callq 0x1abc
cmpq %rax, %r13
je 0x3a62
movq %r13, %rdi
callq 0x2ced
jmp 0x3a62
movq %r13, %rdi
callq 0x2a44
movq %rax, %rbx
callq 0x1ae4
cmpq %rax, %rbx
sete %al
movl 0x4(%rsp), %ebp
testl %ebp, %ebp
setne %cl
testb %cl, %al
je 0x3bc7
pushq $0x1
popq %rbx
jmp 0x3bd5
leaq 0xa940(%rip), %rax      # 0xe460
movq (%rax), %rsi
pushq $0x3
popq %rdx
movq %r13, %rdi
callq 0x4e3d
jmp 0x3a62
callq 0x1ae4
cmpq %rax, %r15
pushq $0x2
popq %rbx
cmovel %r12d, %ebx
callq 0x1afc
cmpq %rax, %r15
je 0x3bad
callq 0x1ae4
cmpq %rax, %r14
je 0x3bad
xorps %xmm0, %xmm0
movups %xmm0, 0xdb44(%rip)     # 0x116a4
movups %xmm0, 0xdb2d(%rip)     # 0x11694
movups %xmm0, 0xdb16(%rip)     # 0x11684
movups %xmm0, 0xdaff(%rip)     # 0x11674
leaq 0xdad4(%rip), %r15      # 0x11650
leaq 0xdaf1(%rip), %rdi      # 0x11674
movl 0xf0(%r14), %edx
leaq 0x3ed0(%rip), %rsi      # 0x7a61
xorl %eax, %eax
callq 0x1250
leaq 0xa8c1(%rip), %rax      # 0xe460
movq (%rax), %rdi
pushq $0x64
popq %rdx
movq %r15, %rsi
callq 0x43d2
leaq 0xa8ac(%rip), %rax      # 0xe460
movq (%rax), %rsi
movq %r14, %rdi
movl %ebx, %edx
callq *0x10(%r14)
xorl %ebp, %ebp
jmp 0x3a62
callq 0x1ae4
cmpq %rax, %rbx
pushq $0x2
popq %rbx
cmovel %ebp, %ebx
xorps %xmm0, %xmm0
movups %xmm0, 0xdac5(%rip)     # 0x116a4
movups %xmm0, 0xdaae(%rip)     # 0x11694
movups %xmm0, 0xda97(%rip)     # 0x11684
movups %xmm0, 0xda80(%rip)     # 0x11674
leaq 0xda55(%rip), %r14      # 0x11650
leaq 0xda72(%rip), %rdi      # 0x11674
movl 0xf0(%r13), %edx
leaq 0x3e51(%rip), %rsi      # 0x7a61
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x1250
leaq 0xa840(%rip), %r15      # 0xe460
movq (%r15), %rdi
callq 0x404e
movq (%r15), %rdi
pushq $0x64
popq %rdx
movq %r14, %rsi
callq 0x43d2
movq (%r15), %rsi
movq %r13, %rdi
movl %ebx, %edx
callq 0x4cf8
jmp 0x3a62
leaq 0x4040(%rip), %rdi      # 0x7c8f
leaq 0x3ff0(%rip), %rsi      # 0x7c46
leaq 0x3ff6(%rip), %rcx      # 0x7c53
movl $0x92, %edx
callq 0x10f0