#include "cmd.h" cmd_tok_t* cmd_tok_create( char *s, char *e, int sz, int type ) { cmd_tok_t *ret = NULL; ret = malloc( sizeof(cmd_tok_t) ); if ( ret == NULL ) return ret; memset( ret, 0, sizeof(cmd_tok_t) ); ret->s = s; ret->e = e; ret->sz = sz; ret->type = type; ret->next = NULL; //no need, but sec programming says we need it return ret; } int cmd_tok_add( cmd_tok_t *tok, cmd_tok_t *next ) { int ret = 0; if ( tok == NULL ) { return -1; } if ( next == NULL ) { return -1; } if ( tok->next != NULL ) { printf("next token allready set\n"); return -1; } tok->next = next; return ret; } int cmd_tok_print( cmd_tok_t *tok ) { int ret = 0; printf("TOK %p\n",tok); if (tok) { printf("S:%p E:%p SZ:%d \n", tok->s, tok->e, tok->sz); printf("TYPE: "); switch (tok->type) { case CMDT_NONE: printf("NONE"); break; case CMDT_INT: printf("INT"); break; case CMDT_HEX: printf("HEX"); break; case CMDT_BIN: printf("BIN"); break; case CMDT_STR: printf("STR"); break; case CMDT_WORD: printf("WORD"); break; case CMDT_SP: printf("SP"); break; default: printf("UNKNOWN"); } printf("\n"); printf("NEXT: %p\n", tok->next ); } return ret; } void cmd_tok_destroy( cmd_tok_t *tok ) { cmd_tok_t *t=NULL, *n=NULL; if (tok == NULL) { return; } if ( tok->next == NULL ) { free( tok ); return; } t = tok; n = t; while ( n != NULL) { n = t->next; t->next = NULL; free(t); t = n; } } int cmd_tok_count( cmd_tok_t *tok ) { int ret = 0; cmd_tok_t *iter = NULL; if (tok == NULL) return 0; iter = tok; while( iter != NULL ) { ret += 1; iter = iter->next; } return ret; } cmd_arg_t* cmd_arg_create( cmd_tok_t *tok ) { cmd_arg_t *ret = NULL; int argc = -1; cmd_tok_t *iter = NULL; int i = 0; ret = malloc( sizeof(cmd_arg_t) ); if ( ret == NULL ) { return NULL; } memset( ret, 0, sizeof( cmd_arg_t )); //get number of arguments in command line argc = cmd_tok_count( tok ); ret->argc = argc; //alloc mem for argument string values ret->argv = malloc( sizeof(int*)*argc ); if ( ret->argv == NULL ) { //printf("ERR:err_malloc_argv\n"); goto err_malloc_argv; } memset( ret->argv, 0, sizeof(int*)*argc ); //alloc mem for argument type values ret->type = malloc( sizeof(int)*argc ); if ( ret->type == NULL ) { //printf("ERR:err_malloc_type\n"); goto err_malloc_type; } memset( ret->type, 0, sizeof(int)*argc ); //create for each cmd token string and set type iter = tok; for (i=0; inext) { ret->argv[i] = malloc( iter->sz+1 ); memcpy(ret->argv[i], iter->s, iter->sz ); ret->argv[i][iter->sz] = 0x0; ret->type[i] = iter->type; } return ret; err_malloc_type: free( ret->argv ); err_malloc_argv: free( ret ); err_exit: return NULL; } cmd_arg_t* cmd_arg_sub( cmd_arg_t *arg ) { cmd_arg_t *ret = NULL; int i=0; if ( arg == NULL ) return NULL; if ( arg->argc == 1 ) { ret = cmd_arg_sub_empty(); return ret; } ret = malloc( sizeof(cmd_arg_t) ); ret->argc = arg->argc-1; ret->type = malloc(sizeof(int)*(arg->argc-1)); memset(ret->type, 0, sizeof(int)*(arg->argc-1) ); ret->argv = malloc( sizeof(char*)*(arg->argc-1) ); memset(ret->argv, 0, sizeof(char*)*(arg->argc-1) ); ret->__sub_cmd = 1; for (i=0; iargc; i++) { ret->argv[i] = arg->argv[i+1]; ret->type[i] = arg->type[i+1]; } return ret; } cmd_arg_t* cmd_arg_sub_empty() { cmd_arg_t *ret = NULL; ret = malloc( sizeof(cmd_arg_t) ); ret->argc = 0; ret->argv = NULL; ret->type = NULL; ret->__sub_cmd = 1; return ret; } void cmd_arg_destroy( cmd_arg_t *arg ) { int i; if ( arg == NULL ) return; for ( i=0; iargc; i++) { if ( arg->__sub_cmd == 0 ) free( arg->argv[i] ); } free( arg->argv ); free( arg->type ); free( arg ); } int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) { int ret = -1; int fret = 0; int i; cmd_arg_t *sub_arg = NULL; if ( arg->argc < 1 ) { printf("Hm ... no arguments\n"); return -1; } i = 0; while ( (tbl[i].cmd != NULL) && (tbl[i].clb != NULL) ) { //printf("tbl.cmd %s\n", tbl[i].cmd ); if ((strlen(tbl[i].cmd) == strlen(arg->argv[0])) //if there is 0 args then here could be non-0 and we get troubles && (strlen(tbl[i].cmd) != 0)) //combo if if ( strncmp( tbl[i].cmd, arg->argv[0], strlen(arg->argv[0]) ) == 0 ) { //never will exec becouse of statment in while if ( tbl[i].clb == NULL ) { printf("Empty callback %s\n", tbl[i].cmd); ret = -1; break; } sub_arg = cmd_arg_sub( arg ); fret = tbl[i].clb( sub_arg ); //if command whent wrong or not still clean mem if ( sub_arg != NULL ) { cmd_arg_destroy( sub_arg ); } //command execution whent wrong lets go out if ( fret != 0 ) { printf("Command broken execution\n"); ret = -1; break; } ret = 0; //succesfull execution break; } i++; } return ret; } int cmd_exec_ev( cmd_table_t *tbl, cmd_arg_t *arg, int event ) { int ret = -1; int fret = 0; int i; cmd_arg_t *sub_arg = NULL; if ( arg->argc < 1 ) { printf("Hm ... no arguments\n"); return -1; } i = 0; while ( (tbl[i].cmd != NULL) && (tbl[i].clb != NULL) ) { //printf("tbl.cmd %s\n", tbl[i].cmd ); if ((strlen(tbl[i].cmd) == strlen(arg->argv[0])) //if there is 0 args then here could be non-0 and we get troubles && (strlen(tbl[i].cmd) != 0)) //combo if if ( strncmp( tbl[i].cmd, arg->argv[0], strlen(arg->argv[0]) ) == 0 ) { //never will exec becouse of statment in while if ( tbl[i].clb == NULL ) { printf("Empty callback %s\n", tbl[i].cmd); ret = -1; break; } sub_arg = cmd_arg_sub( arg ); if ( sub_arg == NULL ) sub_arg = cmd_arg_sub_empty(); fret = tbl[i].clb( sub_arg ); //if command whent wrong or not still clean mem if ( sub_arg != NULL ) { cmd_arg_destroy( sub_arg ); } //command execution whent wrong lets go out if ( fret != 0 ) { printf("Command broken execution\n"); ret = -1; break; } ret = 0; break; } i++; } return ret; } /* For now support only first command autocomplete, and return first cmd RETURN: string to command, dont modify it */ char* cmd_ac( cmd_table_t *tbl, const char *s ) { char *ret = NULL; int i = -1; int idx = -1, match=-1;//best match int ret_match; int str_ac_sz = strlen(s); i = 0; while ( (tbl[i].cmd != NULL) && (tbl[i].clb != NULL) ) { ret_match = strncmp_ac( s, tbl[i].cmd, str_ac_sz ); if (ret_match > 0) { if (ret_match == str_ac_sz+1) { idx = i; break; } else { if (ret_match > match) { idx = i; match = ret_match; } } } i++; } if ( idx >= 0 ) { ret = tbl[idx].cmd; } return ret; } struct cmd_acq_head_t* cmd_acq( cmd_table_t *tbl, const char *s ) { struct cmd_acq_head_t *ret = NULL; int i = -1; int ret_match; int str_ac_sz = strlen(s); struct cmd_acq_head_t *ac = malloc(sizeof(struct cmd_acq_t)); SLIST_INIT(ac); i = 0; while ( (tbl[i].cmd != NULL) && (tbl[i].clb != NULL) ) { ret_match = strncmp_ac( s, tbl[i].cmd, str_ac_sz ); if (ret_match > 0) { //found 100% match if (ret_match == str_ac_sz+1) { PRINT("Unknown state\n"); break; //partial match } else { struct cmd_acq_t *acq = malloc(sizeof(struct cmd_acq_t)); acq->suggestion = tbl[i].cmd; SLIST_INSERT_HEAD(ac,acq,next_sugg); } } i++; } ret = ac; return ret; } void cmd_acq_free( struct cmd_acq_head_t *acq ) { struct cmd_acq_t *iter; struct cmd_acq_t *prev; prev = NULL; iter = NULL; SLIST_FOREACH(iter,acq,next_sugg) { if ( prev != NULL ) { free( prev ); prev = NULL; } prev = iter; } return; } /* Clothest match function AA AB = (1) equile <100% AA AA = (3) equite 100% AA AAA = (2) equile 100% but there is more A B = (0) not equile at all */ int strncmp_ac(const char *s1, const char *s2, const int n) { int i=0; if (n<0) { printf("n<0 wrong argument value\n"); return 0; } /* not equile at all */ /* A B */ if ( s1[0] != s2[0] ) { return 0; } i = 0; while ( (s1[i] == s2[i]) && (i