/* BEGIN: Added by weizengke, 2013/12/12 for display command-tree*/ void cmd_show_command_tree() { int i; int used_size; cmd_vector_t *cmd_vec_copy = cmd_vector_copy(cmd_vec); if (NULL == cmd_vec_copy) { return ; } used_size = cmd_vector_max(cmd_vec_copy); cmd_outstring("Command active (%u):\r\n", used_size); for (i = 0; i < cmd_vector_max(cmd_vec_copy); i++) { struct cmd_elem_st * cmd_elem = (struct cmd_elem_st *)cmd_vector_slot(cmd_vec_copy, i); if (NULL == cmd_elem) { continue; } cmd_outstring(" %s\r\n", cmd_elem->string); } }
static int cmd_filter_command(char *cmd, cmd_vector_t *v, int index) { int i; int match_cmd = CMD_ERR; struct cmd_elem_st *elem; struct para_desc *desc; // For each command, check the 'index'th parameter if it matches the // 'index' paramter in command, set command vector which does not // match cmd NULL /* BEGIN: Added by weizengke, 2013/10/4 PN:check cmd valid*/ if (cmd == NULL || 0 == strlen(cmd)) { return CMD_ERR; } /* <CR> 不参与过滤,防止命令行子串也属于命令行时误过滤 */ if (0 == strcmp(cmd, CMD_END)) { return CMD_OK; } /* END: Added by weizengke, 2013/10/4 PN:None */ for (i = 0; i < cmd_vector_max(v); i++) { if ((elem = (struct cmd_elem_st*)cmd_vector_slot(v, i)) != NULL) { if (index >= cmd_vector_max(elem->para_vec)) { cmd_vector_slot(v, i) = NULL; continue; } desc = (struct para_desc *)cmd_vector_slot(elem->para_vec, index); /* match STRING , INTEGER */ if (CMD_OK != cmd_match_special_string(cmd, desc->para)) { if(strncmp(cmd, desc->para, strlen(cmd)) != 0) { cmd_vector_slot(v, i) = NULL; continue; } } /* BEGIN: Added by weizengke, 2013/11/19 for support unkown cmd pos*/ match_cmd = CMD_OK; /* END: Added by weizengke, 2013/11/19 */ } } return match_cmd; }
void cmd_vector_deinit(cmd_vector_t *v, int freeall) { if (v == NULL) { return; } if (v->data) { if (freeall) { int i; for (i = 0; i < cmd_vector_max(v); i++) { if (cmd_vector_slot(v, i)) { free(cmd_vector_slot(v, i)); } } } free(v->data); } free(v); }
void install_element(struct cmd_elem_st *elem) { if (cmd_vec == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "Command Vector Not Exist"); exit(1); } debug_print_ex(CMD_DEBUG_TYPE_FUNC, "install_element, string(%s), doc(%s).", elem->string, elem->doc); cmd_vector_insert(cmd_vec, elem); elem->para_vec = cmd2vec(elem->string, elem->doc); elem->para_num = cmd_vector_max(elem->para_vec); debug_print_ex(CMD_DEBUG_TYPE_FUNC, "install_element ok, string(%s), generate para_num(%d). ", elem->string, elem->para_num); }
/***************************************************************************** 函 数 名 : cmd_resolve_tab 功能描述 : 适配TAB键,命令补全 输入参数 : struct cmd_vty *vty 输出参数 : 无 返 回 值 : void 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2013年11月17日 作 者 : weizengke 修改内容 : 新生成函数 *****************************************************************************/ void cmd_resolve_tab(struct cmd_vty *vty) { int i; cmd_vector_t *v; struct para_desc *match[CMD_MAX_MATCH_SIZE] = {0}; // matched string int match_size = 0; int match_type = CMD_NO_MATCH; int isNeedMatch = 1; /* 非TAB场景(无空格),不需要匹配 */ char lcd_str[1024] = {0}; // if part match, then use this char *last_word = NULL; /* 1: 取pos 之前的buf 2: 需要覆盖当前光标后的buf */ /* BEGIN: Added by weizengke, 2013/11/17 bug for left and tab*/ memset(&(vty->buffer[vty->cur_pos]), 0 ,strlen(vty->buffer) - vty->cur_pos); vty->used_len = strlen(vty->buffer); /* END: Added by weizengke, 2013/11/17 */ if (g_InputMachine_prev == CMD_KEY_CODE_TAB) { cmd_delete_word(vty); cmd_insert_word(vty, g_tabbingString); } else { memset(g_tabString,0,sizeof(g_tabString)); g_tabStringLenth = 0; } v = str2vec(vty->buffer); if (v == NULL) { /* v = cmd_vector_init(1); cmd_vector_insert(v, '\0'); */ isNeedMatch = 0; } if (isspace((int)vty->buffer[vty->used_len - 1])) { isNeedMatch = 0; } if (1 == isNeedMatch && NULL != v) { match_type = cmd_match_command(v, vty, match, &match_size, lcd_str); last_word = (char*)cmd_vector_slot(v, cmd_vector_max(v) - 1); if (g_InputMachine_prev != CMD_KEY_CODE_TAB) { strcpy(g_tabbingString, last_word); } cmd_vector_deinit(v, 1); } cmd_outstring("%s", CMD_ENTER); switch (match_type) { case CMD_NO_MATCH: cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; case CMD_FULL_MATCH: cmd_delete_word(vty); if (NULL != match[0]) { cmd_insert_word(vty, match[0]->para); } /* BEGIN: Added by weizengke, 2013/10/14 for full match then next input*/ cmd_insert_word(vty, " "); /* END: Added by weizengke, 2013/10/14 */ cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); /* BEGIN: Added by weizengke, 2013/10/27 PN: fix the bug of CMD_FULL_MATCH and then continue TAB*/ memset(g_tabString,0,sizeof(g_tabString)); memset(g_tabbingString,0,sizeof(g_tabbingString)); g_tabStringLenth = 0; /* END: Added by weizengke, 2013/10/27 */ break; case CMD_PART_MATCH: /* delete at 2013-10-05, CMD_PART_MATCH will never reach, CMD_LIST_MATCH instead. case like this: disable , display >di TAB >dis ==> CMD_PART_MATCH */ cmd_delete_word(vty); cmd_insert_word(vty, lcd_str); cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; case CMD_LIST_MATCH: if (g_InputMachine_prev != CMD_KEY_CODE_TAB) { memset(g_tabString,0,sizeof(g_tabString)); strcpy(g_tabString, match[0]->para); g_tabStringLenth = strlen(g_tabString); /* cmd_outstring("%s", CMD_ENTER); */ } else { for (i = 0; i < match_size; i++) { if (0 == strcmp(g_tabString, match[i]->para)) { break; } } if (i == match_size) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "TAB for completing command. bug of tab continue. (g_tabString=%s)", g_tabString); } i++; if (i == match_size) { i = 0; } memset(g_tabString,0,sizeof(g_tabString)); strcpy(g_tabString, match[i]->para); g_tabStringLenth = strlen(g_tabString); } /*for (i = 0; i < match_size; i++) { if (ANOTHER_LINE(i)) cmd_outstring("%s", CMD_ENTER); cmd_outstring("%-25s", match[i]->para); } */ cmd_delete_word(vty); cmd_insert_word(vty, g_tabString); cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; default: break; } }
int cmd_match_command(cmd_vector_t *icmd_vec, struct cmd_vty *vty, struct para_desc **match, int *match_size, char *lcd_str) { int i; cmd_vector_t *cmd_vec_copy = cmd_vector_copy(cmd_vec); int isize = 0; int size = 0; CMD_NOUSED(vty); CMD_NOUSED(lcd_str); // Three steps to find matched commands in 'cmd_vec' // 1. for input command vector 'icmd_vec', check if it is matching cmd_vec // 2. store last matching command parameter in cmd_vec into match_vec // 3. according to match_vec, do no match, one match, part match, list match if (icmd_vec == NULL) { return CMD_NO_MATCH; } isize = cmd_vector_max(icmd_vec) - 1; // Step 1 for (i = 0; i < isize; i++) { char *ipara = (char*)cmd_vector_slot(icmd_vec, i); cmd_filter_command(ipara, cmd_vec_copy, i); } // Step 2 // insert matched command word into match_vec, only insert the next word for(i = 0; i < cmd_vector_max(cmd_vec_copy); i++) { struct cmd_elem_st *elem = NULL; elem = (struct cmd_elem_st *)cmd_vector_slot(cmd_vec_copy, i); if(elem != NULL) { if (elem->para_vec == NULL) { continue; } if (isize >= cmd_vector_max(elem->para_vec)) { cmd_vector_slot(cmd_vec_copy, i) = NULL; continue; } struct para_desc *desc = (struct para_desc *)cmd_vector_slot(elem->para_vec, isize); char *str = (char*)cmd_vector_slot(icmd_vec, isize); if (str == NULL || strncmp(str, desc->para, strlen(str)) == 0) { if (match_unique_string(match, desc->para, size)) match[size++] = desc; } } } cmd_vector_deinit(cmd_vec_copy, 0); // free cmd_vec_copy, no longer use // Step 3 // No command matched if (size == 0) { *match_size = size; return CMD_NO_MATCH; } // Only one command matched if (size == 1) { *match_size = size; return CMD_FULL_MATCH; } #if 0 /* dele the part match */ // Make it sure last element is NULL if (cmd_vector_slot(icmd_vec, isize) != NULL) { int lcd = match_lcd(match, size); if(lcd) { int len = strlen((char*)cmd_vector_slot(icmd_vec, isize)); if (len < lcd) { memcpy(lcd_str, match[0]->para, lcd); lcd_str[lcd] = '\0'; *match_size = size = 1; return CMD_PART_MATCH; } } } #endif *match_size = size; return CMD_LIST_MATCH; }
int cmd_execute_command(cmd_vector_t *icmd_vec, struct cmd_vty *vty, struct para_desc **match, int *match_size, int *nomatch_pos) { int i; cmd_vector_t *cmd_vec_copy = cmd_vector_copy(cmd_vec); struct cmd_elem_st *match_elem = NULL; int match_num = 0; /* Two steps to find matched commands in 'cmd_vec' 1. for input command vector 'icmd_vec', check if it is matching cmd_vec 2. check last matching command parameter in cmd_vec match cmd_vec */ *nomatch_pos = -1; /* Step 1 */ for (i = 0; i < cmd_vector_max(icmd_vec); i++) { if (CMD_OK != cmd_filter_command((char*)cmd_vector_slot(icmd_vec, i), cmd_vec_copy, i)) { /* BEGIN: Added by weizengke, 2013/11/19 不命中可以不需要再匹配了 */ /* 保存在第几个命令字无法匹配 */ *nomatch_pos = (*nomatch_pos == -1)?(i):(*nomatch_pos); } } /* Step 2 */ /* insert matched command word into match_vec, only insert the next word */ if (*nomatch_pos == -1) { /* BEGIN: Added by weizengke, 2014/3/9 修复命令行不完全时,错误位置提示不准确的问题 */ *nomatch_pos = cmd_vector_max(icmd_vec) - 1; for(i = 0; i < cmd_vector_max(cmd_vec_copy); i++) { char *str; struct para_desc *desc; struct cmd_elem_st *elem = NULL; elem = (struct cmd_elem_st *)cmd_vector_slot(cmd_vec_copy, i); if(elem != NULL) { str = (char*)cmd_vector_slot(icmd_vec, cmd_vector_max(icmd_vec) - 1); desc = (struct para_desc *)cmd_vector_slot(elem->para_vec, cmd_vector_max(icmd_vec) - 1); /* modified for command without argv */ if (cmd_vector_max(icmd_vec) == cmd_vector_max(elem->para_vec)) { /* BEGIN: Added by weizengke, 2013/10/5 PN:for support STRING<a-b> & INTEGER<a-b> */ if (CMD_OK == cmd_match_special_string(str, desc->para) || str != NULL && strncmp(str, desc->para, strlen(str)) == 0) { /* BEGIN: Added by weizengke, 2013/10/6 PN:command exec ambigous, return the last elem (not the <CR>) */ match[match_num] = (struct para_desc *)cmd_vector_slot(elem->para_vec, cmd_vector_max(icmd_vec) - 2); /* END: Added by weizengke, 2013/10/6 PN:None */ match_num++; match_elem = elem; } } } } } *match_size = match_num; cmd_vector_deinit(cmd_vec_copy, 0); /* check if exactly match */ if (match_num == 0) { return CMD_NO_MATCH; } /* BEGIN: Added by weizengke, 2013/10/6 PN:command exec ambigous */ if (match_num > 1) { return CMD_ERR_AMBIGOUS; } /* END: Added by weizengke, 2013/10/6 PN:None */ /* BEGIN: Added by weizengke, 2013/10/5 for support argv. PN:push param into function stack */ /* now icmd_vec and match_elem will be the same vector ,can push into function stack */ int argc = 0; char *argv[CMD_MAX_CMD_NUM]; if (NULL == match_elem || match_elem->para_vec == NULL) { return CMD_NO_MATCH; } for (i = 0, argc = 0; i < match_elem->para_num; i ++) { struct para_desc *desc = (struct para_desc *)cmd_vector_slot(match_elem->para_vec, i); if (NULL == desc) { return CMD_NO_MATCH; } /* <CR> no need to push */ if (desc->elem_tpye == CMD_ELEM_TYPE_END) { continue; } /* push param to argv and full command*/ if (CMD_YES == cmd_elem_is_para_type(desc->elem_tpye)) { argv[argc++] = (char*)cmd_vector_slot(icmd_vec, i); } else { argv[argc++] = desc->para; } } /* END: Added by weizengke, 2013/10/5 PN:None */ /* execute command */ (*match_elem->func)(match_elem, vty, argc, argv); return CMD_FULL_MATCH; }
/***************************************************************************** Prototype : cmd_complete_command Description : complete command for ? complete Input : cmd_vector_t *icmd_vec input cmd vector struct cmd_vty *vty the input vty Output : char **doc the return doc Return Value : Calls : Called By : History : 1.Date : 2013/10/4 Author : weizengke Modification : Created function *****************************************************************************/ int cmd_complete_command(cmd_vector_t *icmd_vec, struct cmd_vty *vty, struct para_desc **match, int *match_size, int *match_pos) { int i; cmd_vector_t *cmd_vec_copy = cmd_vector_copy(cmd_vec); int match_num = 0; char *str; struct para_desc *para_desc_; struct cmd_elem_st *elem; if (icmd_vec == NULL || vty == NULL || match == NULL || match_size == NULL) { return 1; } // Two steps to find matched commands in 'cmd_vec' // 1. for input command vector 'icmd_vec', check if it is matching cmd_vec // 2. check last matching command parameter in cmd_vec match cmd_vec *match_pos = -1; // Step 1 /* BEGIN: Modified by weizengke, 2013/10/4 PN:循环过滤每一个向量 */ for (i = 0; i < cmd_vector_max(icmd_vec); i++) { if (CMD_OK != cmd_filter_command((char*)cmd_vector_slot(icmd_vec, i), cmd_vec_copy, i)) { /* BEGIN: Added by weizengke, 2013/11/19 这里可以优化,不命中可以不需要再匹配了 */ /* 保存在第几个命令字无法匹配 */ *match_pos = (*match_pos == -1)?(i):(*match_pos); } } /* END: Modified by weizengke, 2013/10/4 PN:None */ // Step 2 // insert matched command word into match_vec, only insert the next word /* BEGIN: Added by weizengke, 2013/10/4 PN:only the last vector we need */ for(i = 0; i < cmd_vector_max(cmd_vec_copy); i++) { elem = (struct cmd_elem_st *)cmd_vector_slot(cmd_vec_copy, i); if(elem != NULL) { if (cmd_vector_max(icmd_vec) - 1 >= cmd_vector_max(elem->para_vec)) { cmd_vector_slot(cmd_vec_copy, i) = NULL; continue; } str = (char*)cmd_vector_slot(icmd_vec, cmd_vector_max(icmd_vec) - 1); para_desc_ = (struct para_desc*)cmd_vector_slot(elem->para_vec, cmd_vector_max(icmd_vec) - 1); if (para_desc_ == NULL) { continue; } /* BEGIN: Added by weizengke, 2013/11/19 */ /* match STRING , INTEGER */ if (CMD_OK == cmd_match_special_string(str, para_desc_->para)) { match[match_num++] = para_desc_; continue; } /* END: Added by weizengke, 2013/11/19 */ /* match key */ if (strncmp(str, CMD_END, strlen(str)) == 0 ||(strncmp(str, para_desc_->para, strlen(str)) == 0)) { if (match_unique_string(match, para_desc_->para, match_num)) { match[match_num++] = para_desc_; } } } } cmd_vector_deinit(cmd_vec_copy, 0); // free cmd_vec_copy, no longer use /* BEGIN: Added by weizengke, 2013/10/27 sort for ? complete */ { int j; for (i = 0; i < match_num - 1; i++) { for (j = i; j < match_num; j++) { struct para_desc *para_desc__ = NULL; if (0 == strncmp(match[i]->para, CMD_END, strlen(match[i]->para)) || ( 1 == strcmp(match[i]->para, match[j]->para) && 0 != strncmp(match[j]->para, CMD_END, strlen(match[j]->para))) ) { para_desc__ = match[i]; match[i] = match[j]; match[j] = para_desc__; } } } } /* END: Added by weizengke, 2013/10/27 sort for ? complete */ *match_size = match_num; return 0; }