#include "cli_inter_preter.h" static char arg_str_list[CLI_IPT_ARG_NUM][CLI_IPT_ARG_STR_LEN]; unsigned int cli_ipt_arg_list[CLI_IPT_ARG_NUM][CLI_IPT_ARG_LEN]; void print_main_menu(command_entry *main_table); void array_map_input_to_byte(unsigned char *b, unsigned int *i, unsigned int len) { if (len > CLI_IPT_ARG_LEN) return; for (unsigned char index = 0; index < len; index++) { b[index] = i[index]; } } int len_of_menu(command_entry *entry) { int i, len = 0; for (i = 0; i < CLI_IPT_ENTRY_NUM_MAX; i++) { if (entry->action == NULL && entry->arg_desp == NULL && entry->arg_type == NULL && entry->desp == NULL && entry->name == NULL) { return len; } else { len++; entry++; } } return 0; } int cmd_to_param(const char *cmd, char *param, int param_len_max) { int state = 0, row = 0; char *base; base = param; while (*cmd != '\0') { if (*cmd != ' ') { if (state == 2 || state == 0) { row++; if (row > CLI_IPT_ARG_NUM) return row; param = base + param_len_max * (row - 1); memset(param, 0, param_len_max); state = 1; } state = 1; *param = *cmd; param++; if (param > base + param_len_max * (row)-1) { return 0; } } else { if (state == 1) { state = 2; } } cmd++; } return row; } void print_entry(command_entry *entry) { int len, i; len = len_of_menu(entry); for (i = 0; i < len; i++) { if (entry[i].action != NULL) { CLI_PRINTF("%-30s- (%s)%s\r\n", entry[i].name, entry[i].arg_type, entry[i].desp); } else { CLI_PRINTF("%-30s- (sub_menu)%s\r\n", entry[i].name, entry[i].desp); } } } void print_arg_desp(command_entry *entry) { int len, i; char *d[] = {"", "", "", "", ""}; char *desp; len = strlen(entry->arg_type); if (len == 0) { return; } for (i = 0; i < len; i++) { if (entry->arg_type[i] == 'u') desp = d[0]; else if (entry->arg_type[i] == 'v') desp = d[1]; else if (entry->arg_type[i] == 'w') desp = d[2]; else if (entry->arg_type[i] == 's') desp = d[3]; else if (entry->arg_type[i] == 'a') desp = d[4]; else desp = ""; if (entry->arg_desp == NULL) { CLI_PRINTF("arg%d - %c%s\r\n", i, entry->arg_type[i], desp); } else { CLI_PRINTF("arg%d - %c%s %s\r\n", i, entry->arg_type[i], desp, entry->arg_desp[i]); } } } static unsigned char hex_to_int(unsigned char ch) { return ch - (ch >= 'a' ? 'a' - 10 : (ch >= 'A' ? 'A' - 10 : (ch <= '9' ? '0' : 0))); } static unsigned int string_to_unsigned_int(char *str, unsigned int *array, int param_len_max) { int result = 0; int base = 10; int i; int length; int pflag = 0; length = strlen(str); if (length == 0) return 1; if (str[0] == '-') pflag = 1; for (i = 0; i < length; i++) { unsigned char next = str[i]; if (i == 0 && next == '-') { // do noting } else if ((next == 'x' || next == 'X') && result == 0 && (i == 1 || i == 2)) { base = 16; } else { unsigned char value = hex_to_int(next); if (value < base) { result = result * base + value; } else { return 1; } } } if (pflag == 1) { result = ~result + 1; } *array = result; return 0; } //"s" "abc" // "str\r\n" int string_to_s(char *str, unsigned int *array, int param_len_max) { int i = 0, j = 0; /*, bs=0*/ char *ps = (char *)array; if (str[0] != '"') return 1; j = 0; for (i = 0; str[i + 1] != '"';) { if (str[i + 1] == '\\') { if (str[i + 1 + 2] == 'n') { ps[j] = '\n'; i++; } else if (str[i + 1 + 2] == 'r') { ps[j] = '\r'; i++; } else { ps[j] = '\\'; } } else { ps[j] = str[i + 1]; } j++; if (j + 1 > param_len_max) { return 1; } i++; } ps[j] = 0; return 0; } // "a" {1,2,3} int string_to_a(char *str, unsigned int *array, int param_len_max) { int i, index = 0, count = 0, flag = 0; char s[CLI_IPT_ARG_LEN] = {0}; if (str[0] != '{') return 1; for (i = 0; str[i] != '\0'; i++) { if (str[i] == '{') { index = 0; } else if (str[i] == ',') { s[index] = 0; if (string_to_unsigned_int(s, array + count, CLI_IPT_ARG_LEN) != 0) return 1; index = 0; count++; } else if (str[i] == '}') { flag = 1; s[index] = 0; if (string_to_unsigned_int(s, array + count, CLI_IPT_ARG_LEN) != 0) return 1; } else { s[index++] = str[i]; } } if (flag == 0) return 1; return 0; } int command_action_exec(command_entry *entry, char *param, int param_len_max) { int len, i, res = 0; len = strlen(entry->arg_type); // CLI_PRINTF("arg is:"); for (i = 0; i < len; i++) { if (entry->arg_type[i] == 'u') res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN); else if (entry->arg_type[i] == 'v') res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN); else if (entry->arg_type[i] == 'w') res = string_to_unsigned_int(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN); else if (entry->arg_type[i] == 's') res = string_to_s(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN * sizeof(unsigned int)); else if (entry->arg_type[i] == 'a') res = string_to_a(param + param_len_max * i, cli_ipt_arg_list[i], CLI_IPT_ARG_LEN); else { } if (res == 1) { return res; } // CLI_PRINTF("%d ", cli_ipt_arg_list[i][0]); } // CLI_PRINTF("\r\n"); return res; } int stricmp(const char *a, const char *b) { int i, len; if (strlen(a) != strlen(b)) return 1; len = strlen(a); for (i = 0; i < len; i++) { if (toupper((unsigned int)a[i]) != toupper((unsigned int)b[i])) { return 1; } } return 0; } int command_match(const char *cmd, int param_len_max, int num, command_entry **entry_in, command_entry **entry_out) { int i, len, res = 0; len = len_of_menu(*entry_in); for (i = 0; i < len; i++) { if (stricmp(cmd, (*entry_in)->name) == 0) { if ((*entry_in)->action != NULL) { *entry_out = *entry_in; res = 1; } else { *entry_out = (command_entry *)((*entry_in)->arg_type); res = 2; } break; } (*entry_in)++; } if (i == len) { res = 0; } return res; } int command_entry_match(command_entry *main_table, const char *cmd) { static command_entry *ein, *eout, *ehint; int num, res = 2; char *plist; ein = main_table; eout = (command_entry *)NULL; ehint = ein; memset(arg_str_list, 0, sizeof(arg_str_list)); num = cmd_to_param(cmd, (char *)arg_str_list, CLI_IPT_ARG_STR_LEN); if (num == 0) { // print_main_menu(main_table); CLI_PRINTF("# "); return 0; } plist = (char *)arg_str_list; while (res == 2) { res = command_match((const char *)plist, CLI_IPT_ARG_STR_LEN, num, &ein, &eout); if (res == 0) { // printf("commands or params unmatched!\r\n"); print_entry(ehint); CLI_PRINTF("# "); return 0; } else if (res == 1) { if (command_action_exec(eout, plist + CLI_IPT_ARG_STR_LEN, CLI_IPT_ARG_STR_LEN) == 0) { eout->action(); } else { // printf("argument error!\r\n"); print_arg_desp(eout); } } else { plist = plist + CLI_IPT_ARG_STR_LEN; ein = eout; ehint = ein; } } CLI_PRINTF("# "); return 1; } void print_main_menu(command_entry *main_table) { print_entry(main_table); } int case_chg(char a) { if (a >= 'A' && a <= 'Z') a = a - 'A' + 'a'; return a; } int str_include(const char *s, const char *str) { int i; if (strlen(s) > strlen(str)) return -1; for (i = 0; i < strlen(s); i++) { if (case_chg(s[i]) != case_chg(str[i])) return -1; } return 0; } int command_entry_hint(command_entry *main_table, const char *cmd, char *out) { static command_entry *ein, *eout; int num, res = 2, i, len, cnt; char *plist, tmp[CLI_IPT_ARG_STR_LEN]; ein = main_table; eout = ein; memset(arg_str_list, 0, sizeof(arg_str_list)); num = cmd_to_param(cmd, (char *)arg_str_list, CLI_IPT_ARG_STR_LEN); if (num == 0) { // print_main_menu(main_table); // CLI_PRINTF("# "); return 0; } plist = (char *)arg_str_list; while (res == 2) { res = command_match((const char *)plist, CLI_IPT_ARG_STR_LEN, num, &ein, &eout); if (res == 0) { if (strlen(plist) == 0) { if (cmd[strlen(cmd) - 1] != ' ') //"s1" "s2" { strcpy(out, cmd); strcat(out, " "); return 3; } } len = len_of_menu(eout); cnt = 0; strcpy(out, ""); for (i = 0; i < len; i++) { if (str_include(plist, eout[i].name) == 0) { cnt++; strcpy(out, eout[i].name); strcat(out, " "); } } if (cnt == 1) { strcpy(tmp, out); strcpy(out, ""); for (i = 0; i < (num - 1); i++) { strcat(out, arg_str_list[i]); strcat(out, " "); } strcat(out, tmp); return 2; } else { return 1; } } else if (res == 1) // action { strcpy(out, ""); for (i = 0; i < num; i++) { strcat(out, arg_str_list[i]); strcat(out, " "); if (strlen(out) >= ((unsigned int)CLI_IPT_ARG_STR_LEN >> 1)) { strcat(out, "..."); break; } } return 3; } else // sub_menu { plist = plist + CLI_IPT_ARG_STR_LEN; ein = eout; } } return 1; }