// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movq $0x0, -0x20(%rbp)
movb $0x0, %al
callq 0x2020
movq %rax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl $0x3, -0x38(%rbp)
leaq 0xff42(%rip), %rdi      # 0x14694
xorl %esi, %esi
movl $0x64, %edx
callq 0x10d0
movslq -0x14(%rbp), %rax
cmpq -0x10(%rbp), %rax
jae 0x49db
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x30(%rbp), %rdi
callq 0x5290
movq %rax, %rdi
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3f20
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x49c4
movq -0x30(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x49b2
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax), %eax
movl %eax, %ecx
leaq 0xcc90(%rip), %rax      # 0x11450
movq (%rax,%rcx,8), %rax
movq -0x30(%rbp), %rcx
movq 0x8(%rcx), %rdi
movq -0x8(%rbp), %rcx
movslq -0x14(%rbp), %rdx
movq (%rcx,%rdx,8), %rsi
callq *%rax
cmpl $0x0, %eax
jne 0x49a9
movq -0x30(%rbp), %rdi
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x52b0
cmpl $0x0, %eax
jne 0x49a0
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax), %eax
movl %eax, 0xfe83(%rip)      # 0x14694
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
addq $0x50, %rax
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
addq $0x50, %rdi
callq 0x1090
movq %rax, %rcx
movl $0x20, %eax
cmpq %rcx, %rax
jae 0x484a
movl $0x20, %eax
movq %rax, -0x48(%rbp)
jmp 0x485f
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
addq $0x50, %rdi
callq 0x1090
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
leaq 0xfe26(%rip), %rdi      # 0x14694
addq $0x4, %rdi
callq 0x1050
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1090
movq %rax, %rcx
movl $0x40, %eax
cmpq %rcx, %rax
jae 0x48b0
movl $0x40, %eax
movq %rax, -0x58(%rbp)
jmp 0x48c5
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1090
movq %rax, -0x58(%rbp)
movq -0x50(%rbp), %rsi
movq -0x58(%rbp), %rdx
leaq 0xfdc0(%rip), %rdi      # 0x14694
addq $0x24, %rdi
callq 0x1050
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
addq $0x4, %rax
movq %rax, -0x68(%rbp)
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1090
cmpq $0x40, %rax
jae 0x492b
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1090
movq %rax, -0x70(%rbp)
jmp 0x4936
movl $0x40, %eax
movq %rax, -0x70(%rbp)
jmp 0x4936
movq -0x60(%rbp), %rsi
movq -0x68(%rbp), %rdi
movq -0x70(%rbp), %rdx
callq 0x1050
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1090
movq %rax, %rcx
movq -0x78(%rbp), %rax
movb $0x0, 0x4(%rax,%rcx)
leaq 0xcac9(%rip), %rax      # 0x11440
movq (%rax), %rdi
leaq 0xfd13(%rip), %rsi      # 0x14694
movl $0x64, %edx
callq 0x5da0
leaq 0xfd02(%rip), %rdi      # 0x14694
xorl %esi, %esi
movl $0x64, %edx
callq 0x10d0
jmp 0x49cd
movl $0x3, -0x34(%rbp)
jmp 0x49b0
movl $0x2, -0x34(%rbp)
jmp 0x49db
movq -0x30(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x49c2
movl $0x0, -0x38(%rbp)
jmp 0x49cd
movl $0x4, -0x34(%rbp)
jmp 0x49db
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x475e
cmpl $0x0, -0x34(%rbp)
jne 0x49f5
movq -0x30(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x49f3
movl $0x5, -0x34(%rbp)
jmp 0x49f5
movl -0x34(%rbp), %eax
movq %rax, -0x80(%rbp)
subq $0x6, %rax
ja 0x4ec3
movq -0x80(%rbp), %rax
leaq 0x6017(%rip), %rcx      # 0xaa28
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x4ed1
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
leaq 0x61c7(%rip), %rdi      # 0xabf9
movb $0x0, %al
callq 0x10b0
jmp 0x4ed1
movq -0x8(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x88(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movl (%rax), %edi
callq 0x20a0
movq -0x88(%rbp), %rsi
movq %rax, %rdx
leaq 0x61be(%rip), %rdi      # 0xac2f
movb $0x0, %al
callq 0x10b0
jmp 0x4ed1
leaq 0x6206(%rip), %rdi      # 0xac8a
movb $0x0, %al
callq 0x10b0
movq -0x30(%rbp), %rax
movq %rax, -0x90(%rbp)
callq 0x1e10
movq %rax, %rcx
movq -0x90(%rbp), %rax
cmpq %rcx, %rax
jne 0x4b6a
movq -0x20(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x4ad3
movl $0x5, -0x34(%rbp)
leaq 0x61dc(%rip), %rdi      # 0xaca3
movb $0x0, %al
callq 0x10b0
jmp 0x4ed1
movl $0x2, -0x38(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x30(%rbp), %rdi
leaq 0xc953(%rip), %rcx      # 0x11440
movq (%rcx), %rsi
movl -0x38(%rbp), %edx
callq *%rax
leaq 0xfb34(%rip), %rdi      # 0x14630
addq $0x24, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x10d0
movq -0x20(%rbp), %rax
movl 0xf0(%rax), %edx
leaq 0xfb13(%rip), %rdi      # 0x14630
addq $0x24, %rdi
leaq 0x5fa5(%rip), %rsi      # 0xaacd
movb $0x0, %al
callq 0x1200
leaq 0xc90a(%rip), %rax      # 0x11440
movq (%rax), %rdi
leaq 0xfaf0(%rip), %rsi      # 0x14630
movl $0x64, %edx
callq 0x5da0
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x20(%rbp), %rdi
leaq 0xc8e3(%rip), %rcx      # 0x11440
movq (%rcx), %rsi
movl -0x38(%rbp), %edx
callq *%rax
jmp 0x4e87
movq -0x30(%rbp), %rax
movq %rax, -0x98(%rbp)
movb $0x0, %al
callq 0x1d60
movq %rax, %rcx
movq -0x98(%rbp), %rax
cmpq %rcx, %rax
jne 0x4c2b
leaq 0xfa9a(%rip), %rdi      # 0x14630
addq $0x24, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x10d0
movq -0x20(%rbp), %rax
movl 0xf0(%rax), %edx
leaq 0xfa79(%rip), %rdi      # 0x14630
addq $0x24, %rdi
leaq 0x5f0b(%rip), %rsi      # 0xaacd
movb $0x0, %al
callq 0x1200
leaq 0xc870(%rip), %rax      # 0x11440
movq (%rax), %rdi
callq 0x5630
movq -0x20(%rbp), %rdi
leaq 0xc85d(%rip), %rax      # 0x11440
movq (%rax), %rsi
movl $0x3, %edx
callq 0x6e40
movq -0x20(%rbp), %rdi
callq 0x1fd0
movq -0x20(%rbp), %rax
movq %rax, -0xa0(%rbp)
callq 0x1d80
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jne 0x4c1d
jmp 0x4ed1
movq -0x20(%rbp), %rdi
callq 0x3850
jmp 0x4ed1
movq -0x30(%rbp), %rax
movq %rax, -0xa8(%rbp)
movb $0x0, %al
callq 0x1d50
movq %rax, %rcx
movq -0xa8(%rbp), %rax
cmpq %rcx, %rax
jne 0x4d32
movq -0x20(%rbp), %rdi
callq 0x3450
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0xb0(%rbp)
callq 0x1dd0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
cmpq %rcx, %rax
jne 0x4c8b
cmpl $0x0, -0x38(%rbp)
je 0x4c8b
movl $0x1, -0x38(%rbp)
jmp 0x4cb3
movq -0x28(%rbp), %rax
movq %rax, -0xb8(%rbp)
callq 0x1dd0
movq %rax, %rcx
movq -0xb8(%rbp), %rax
cmpq %rcx, %rax
je 0x4cb1
movl $0x2, -0x38(%rbp)
jmp 0x4cb3
leaq 0xf976(%rip), %rdi      # 0x14630
addq $0x24, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x10d0
movq -0x20(%rbp), %rax
movl 0xf0(%rax), %edx
leaq 0xf955(%rip), %rdi      # 0x14630
addq $0x24, %rdi
leaq 0x5de7(%rip), %rsi      # 0xaacd
movb $0x0, %al
callq 0x1200
leaq 0xc74c(%rip), %rax      # 0x11440
movq (%rax), %rdi
callq 0x5630
leaq 0xc73d(%rip), %rax      # 0x11440
movq (%rax), %rdi
leaq 0xf923(%rip), %rsi      # 0x14630
movl $0x64, %edx
callq 0x5da0
movq -0x20(%rbp), %rdi
leaq 0xc71e(%rip), %rax      # 0x11440
movq (%rax), %rsi
movl -0x38(%rbp), %edx
callq 0x6db0
jmp 0x4e83
movq -0x30(%rbp), %rax
movq %rax, -0xc0(%rbp)
movb $0x0, %al
callq 0x1d70
movq %rax, %rcx
movq -0xc0(%rbp), %rax
cmpq %rcx, %rax
jne 0x4d70
movq -0x20(%rbp), %rdi
leaq 0xc6e2(%rip), %rax      # 0x11440
movq (%rax), %rsi
movl $0x3, %edx
callq 0x6fd0
jmp 0x4e81
movq -0x30(%rbp), %rdi
callq 0x3450
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0xc8(%rbp)
callq 0x1dd0
movq %rax, %rcx
movq -0xc8(%rbp), %rax
cmpq %rcx, %rax
jne 0x4dab
cmpl $0x0, -0x38(%rbp)
je 0x4dab
movl $0x1, -0x38(%rbp)
jmp 0x4dd3
movq -0x28(%rbp), %rax
movq %rax, -0xd0(%rbp)
callq 0x1dd0
movq %rax, %rcx
movq -0xd0(%rbp), %rax
cmpq %rcx, %rax
je 0x4dd1
movl $0x2, -0x38(%rbp)
jmp 0x4dd3
movq -0x28(%rbp), %rax
movq %rax, -0xd8(%rbp)
callq 0x1e00
movq %rax, %rcx
movq -0xd8(%rbp), %rax
cmpq %rcx, %rax
je 0x4e66
movq -0x30(%rbp), %rax
movq %rax, -0xe0(%rbp)
callq 0x1dd0
movq %rax, %rcx
movq -0xe0(%rbp), %rax
cmpq %rcx, %rax
je 0x4e66
leaq 0xf818(%rip), %rdi      # 0x14630
addq $0x24, %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x10d0
movq -0x30(%rbp), %rax
movl 0xf0(%rax), %edx
leaq 0xf7f7(%rip), %rdi      # 0x14630
addq $0x24, %rdi
leaq 0x5c89(%rip), %rsi      # 0xaacd
movb $0x0, %al
callq 0x1200
leaq 0xc5ee(%rip), %rax      # 0x11440
movq (%rax), %rdi
leaq 0xf7d4(%rip), %rsi      # 0x14630
movl $0x64, %edx
callq 0x5da0
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x30(%rbp), %rdi
leaq 0xc5c7(%rip), %rcx      # 0x11440
movq (%rcx), %rsi
movl -0x38(%rbp), %edx
callq *%rax
jmp 0x4e83
jmp 0x4e85
jmp 0x4e87
jmp 0x4ed1
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rsi
addq $0x50, %rsi
leaq 0x5e2c(%rip), %rdi      # 0xacc8
movb $0x0, %al
callq 0x10b0
leaq 0x5df4(%rip), %rdi      # 0xac9e
movb $0x0, %al
callq 0x10b0
jmp 0x4ed1
leaq 0x5de9(%rip), %rdi      # 0xaca3
movb $0x0, %al
callq 0x10b0
jmp 0x4ed1
leaq 0x5e45(%rip), %rdi      # 0xad0f
movb $0x0, %al
callq 0x10b0
movl -0x34(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nopl (%rax)