From e6ddd00fedabeb470c7f3b132cb2289109688e73 Mon Sep 17 00:00:00 2001 From: FreeArtMan Date: Thu, 4 Aug 2016 21:54:05 +0100 Subject: Updated parser, new quoted string support. New command execution manager. --- cmd.c | 75 +++++++++++++++++++++++++-- cmd.h | 87 +++++++++++++++++++++++++++++-- cmd_parse.c | 158 +++++++++++++++++++++++++++++++++----------------------- cmd_parse.h | 2 +- cmd_parse.ragel | 57 ++++++++++++-------- 5 files changed, 282 insertions(+), 97 deletions(-) diff --git a/cmd.c b/cmd.c index c1d43fc..9ceab86 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,5 @@ #include "cmd.h" +#include "cmd_parse.h" cmd_tok_t* cmd_tok_create( char *s, char *e, int sz, int type ) { @@ -272,12 +273,16 @@ int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) cmd_arg_t *sub_arg = NULL; - if ( arg->argc < 1 ) + //there could be 0 arguments + if ( arg->argc < 0 ) { printf("Hm ... no arguments\n"); return -1; } + if ( arg->argc == 0 ) + return 0; + i = 0; while ( (tbl[i].cmd != NULL) && (tbl[i].clb != NULL) ) { @@ -315,9 +320,7 @@ int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ) } i++; - } - - + } return ret; } @@ -484,6 +487,70 @@ void cmd_acq_free( struct cmd_acq_head_t *acq ) return; } +char* cmd_mng_history( cmd_mng_t *cmng, int index ) +{ + char *ret=NULL; + + + + return ret; +} + +char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd ) +{ + char *ret=NULL; + + + + return ret; +} + +int cmd_mng_exec( cmd_mng_t *cmng, const char *cmd, size_t sz_cmd ) +{ + int ret = CMD_EOK; + int fret = 0; + cmd_tok_t tl, *ptr_tl = &tl, *iter = NULL; + cmd_arg_t *args = NULL; + + // Init values + memset( &tl, 0, sizeof( cmd_tok_t )); + + fret = parse_cmd( ptr_tl, cmd, sz_cmd ); + if ( fret != 0 ) + { + ret = CMD_EEXE; + goto error_exe; //if err memleak from parse_cmd? + } + + //printf("T:%d\n", ptr_tl->next); + iter = ptr_tl->next; + args = cmd_arg_create( iter ); + cmd_tok_destroy( ptr_tl->next ); + ptr_tl->next = NULL; + + //int i; + //for (i=0;iargc;i++) + //{ + // printf("A:%s\n",args->argv[i]); + //} + + if (cmd_exec(cmng->table, args) != 0) + { + ret = CMD_ECMD; + goto error_cmd; + } + + cmd_arg_destroy( args ); + + return ret; +error_cmd: + cmd_arg_destroy( args ); + +error_exe: + + return ret; +} + /* Clothest match function AA AB = (1) equile <100% diff --git a/cmd.h b/cmd.h index 736cb2b..a5e349a 100644 --- a/cmd.h +++ b/cmd.h @@ -13,14 +13,35 @@ #define CMDT_INT 1 #define CMDT_HEX 2 #define CMDT_BIN 3 -#define CMDT_STR 4 -#define CMDT_WORD 5 -#define CMDT_SP 6 +#define CMDT_QSTR 4 +#define CMDT_STR 5 +#define CMDT_WORD 6 +#define CMDT_SP 7 #define CMDE_NONE 0 //do nothing #define CMDE_AUTOCOMPLETE 1 //try to auto complete first command #define CMDE_ALIAS 2 //command aliases +#define CMD_EOK 0 //all ok +#define CMD_EEXE 1 //command execution error +#define CMD_ECMD 2 //unknown command + +#define CMD_HISTORY_SIZE 16 //fixed size history + +/* +Arch + +[CLI]------->[PARSE] +[FILE]----/ + +[PARSE]-------->[[EXEC]->[HISTORY] other extra features] +[CMDLIST]----/ +*/ + +/* +Token list that comes from parser +*/ + typedef struct cmd_tok_t { char *s,*e; @@ -29,6 +50,10 @@ typedef struct cmd_tok_t struct cmd_tok_t *next; } cmd_tok_t; +/* +Argument list passed to callback cmd functions +*/ + typedef struct cmd_arg_t { int argc; @@ -39,13 +64,21 @@ typedef struct cmd_arg_t int __sub_cmd; // if 1 then dont free argv stuff } cmd_arg_t; +/* +Table of defined commands +*/ typedef struct cmd_table_t { char *cmd; - int (*clb)(cmd_arg_t*); + int (*clb)(cmd_arg_t*); //callback to command + int (*hlp)(cmd_arg_t*); //help command + int (*pre)(cmd_arg_t*); //preconditions for execution } cmd_table_t; +/* +autocomplete suggestions from command list. Used for autcomplet "" +*/ struct cmd_acq_t { char *suggestion; @@ -53,6 +86,25 @@ struct cmd_acq_t }; SLIST_HEAD(cmd_acq_head_t,cmd_acq_t); +/* +Contain all non cli parsing execution things. +Manage history and logging +Manage command loading from file +Manage autocomplete +*/ +typedef struct cmd_mng_t +{ + int flag_history; + /*simple que*/ + int history_size; + char *history[CMD_HISTORY_SIZE]; + + //not yet ready + //int flag_logging; + + cmd_table_t *table; +} cmd_mng_t; + cmd_tok_t* cmd_tok_create( char *s, char *e, int sz, int type ); int cmd_tok_add( cmd_tok_t *tok, cmd_tok_t *next ); int cmd_tok_print( cmd_tok_t *tok ); @@ -70,6 +122,33 @@ char* cmd_ac( cmd_table_t *tbl, const char *s ); //autocomplete struct cmd_acq_head_t* cmd_acq( cmd_table_t *tbl, const char *s ); //autocomplete void cmd_acq_free( struct cmd_acq_head_t *acq ); +/* +If history is on. +PARAM: + cmng - cli manager + index - index value in history +RETURN: + [FREE] return value if there is under index +*/ +char* cmd_mng_history( cmd_mng_t *cmng, int index ); + +/* +PARAM: + cmng + cmd - non complete command, not to execute, seach for suggestions +RETURN: + [FREE] return string list of autocomplete commands +*/ +char* cmd_mng_autocomplete( cmd_mng_t *cmng, char *cmd ); +/* +PARAM: + cmng + cmd - command to execute expect NULL at the end +RETURN: + return result of execution +*/ +int cmd_mng_exec( cmd_mng_t *cmng, const char *cmd, size_t sz_cmd ); + #define STR_AC_EQ(A,B) (strncmp_ac((A),(B),strlen(A))==(strlen(A)+1)) #define STR_AC_PEQ(A,B) (strncmp_ac((A),(B),strlen(A))<(strlen(A))) diff --git a/cmd_parse.c b/cmd_parse.c index 0136782..96438c7 100644 --- a/cmd_parse.c +++ b/cmd_parse.c @@ -7,8 +7,8 @@ #define TADD(T,S,E,SZ) {cmd_tok_t *t=cmd_tok_create(S,E,SZ,T);cmd_tok_add(tl,t);tl=tl->next;} //#define TADD(T,S,E) -//#define PR_TK_DBG(S) printf(S);fwrite(ts,1,te-ts,stdout);printf("\n"); -#define PR_TK_DBG(S) ; +#define PR_TK_DBG(S) printf(S);fwrite(ts,1,te-ts,stdout);printf("\n"); +//#define PR_TK_DBG(S) ; char *new_string( const char *start, const char *end ) { @@ -32,103 +32,111 @@ int print_token( char *s, char *e, int tok) #line 34 "cmd_parse.c" static const char _cmd_actions[] = { - 0, 1, 0, 1, 1, 1, 2, 1, - 3, 1, 4, 1, 5, 1, 6, 1, - 7, 1, 8, 1, 9, 1, 10 + 0, 1, 0, 1, 1, 1, 7, 1, + 8, 1, 9, 1, 10, 1, 11, 2, + 2, 3, 2, 2, 4, 2, 2, 5, + 2, 2, 6 }; static const char _cmd_key_offsets[] = { - 0, 0, 8, 17, 19, 25, 39, 43, - 45, 47, 53 + 0, 0, 3, 7, 10, 23, 26, 33, + 38, 43, 52 }; static const char _cmd_trans_keys[] = { - 32, 39, 48, 57, 65, 90, 97, 122, - 32, 34, 39, 48, 57, 65, 90, 97, - 122, 48, 49, 48, 57, 65, 70, 97, - 102, 32, 34, 39, 44, 48, 59, 9, - 10, 49, 57, 65, 90, 97, 122, 98, - 120, 48, 57, 48, 57, 48, 49, 48, - 57, 65, 70, 97, 102, 48, 57, 65, - 90, 97, 122, 0 + 32, 34, 39, 32, 34, 39, 92, 32, + 34, 92, 32, 34, 39, 44, 48, 9, + 10, 49, 57, 65, 90, 97, 122, 32, + 34, 39, 32, 34, 39, 98, 120, 48, + 57, 32, 34, 39, 48, 57, 32, 34, + 39, 48, 49, 32, 34, 39, 48, 57, + 65, 70, 97, 102, 32, 34, 39, 48, + 57, 65, 90, 97, 122, 0 }; static const char _cmd_single_lengths[] = { - 0, 2, 3, 0, 0, 6, 2, 0, - 0, 0, 0 + 0, 3, 4, 3, 5, 3, 5, 3, + 3, 3, 3 }; static const char _cmd_range_lengths[] = { - 0, 3, 3, 1, 3, 4, 1, 1, + 0, 0, 0, 0, 4, 0, 1, 1, 1, 3, 3 }; static const char _cmd_index_offsets[] = { - 0, 0, 6, 13, 15, 19, 30, 34, - 36, 38, 42 + 0, 0, 4, 9, 13, 23, 27, 34, + 39, 44, 51 }; static const char _cmd_indicies[] = { - 0, 0, 0, 0, 0, 1, 0, 2, - 0, 0, 0, 0, 1, 4, 3, 5, - 5, 5, 3, 6, 7, 6, 6, 8, - 10, 6, 9, 11, 11, 1, 13, 14, - 9, 12, 9, 12, 4, 15, 5, 5, - 5, 16, 11, 11, 11, 17, 0 + 1, 1, 1, 0, 1, 3, 1, 4, + 2, 2, 2, 2, 1, 7, 2, 7, + 6, 8, 6, 9, 10, 10, 5, 11, + 11, 11, 0, 12, 12, 12, 13, 14, + 9, 0, 12, 12, 12, 9, 0, 11, + 11, 11, 15, 0, 11, 11, 11, 16, + 16, 16, 0, 17, 17, 17, 10, 10, + 10, 0, 0 }; static const char _cmd_trans_targs[] = { - 2, 0, 5, 5, 8, 9, 5, 1, - 6, 7, 5, 10, 5, 3, 4, 5, - 5, 5 + 5, 0, 2, 4, 3, 1, 5, 4, + 6, 7, 10, 4, 4, 8, 9, 8, + 9, 4 }; static const char _cmd_trans_actions[] = { - 0, 0, 9, 21, 0, 0, 7, 0, - 5, 0, 11, 0, 15, 0, 0, 17, - 13, 19 + 24, 0, 0, 5, 0, 0, 21, 7, + 0, 0, 0, 13, 9, 24, 24, 18, + 15, 11 }; static const char _cmd_to_state_actions[] = { - 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; static const char _cmd_from_state_actions[] = { - 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 }; static const char _cmd_eof_trans[] = { - 0, 0, 0, 4, 4, 0, 13, 13, - 16, 17, 18 + 0, 0, 0, 0, 0, 12, 13, 13, + 12, 12, 18 }; -static const int cmd_start = 5; -static const int cmd_first_final = 5; +static const int cmd_start = 4; +static const int cmd_first_final = 4; static const int cmd_error = 0; -static const int cmd_en_main = 5; +static const int cmd_en_main = 4; -#line 56 "cmd_parse.ragel" +#line 64 "cmd_parse.ragel" -int parse_cmd( cmd_tok_t *tl, const char *str ) +int parse_cmd( cmd_tok_t *tl, const char *str, size_t str_size ) { static uint8_t cs; const int stacksize = 10; - int res=0, *stack=NULL, act=0; + int res=0, *stack=NULL, act=0,top=0; stack = malloc( sizeof(stack)*stacksize ); - char *p=(char *)str, *pe = (char *)str + strlen( str ), *eof=NULL; + char *p=(char *)str, *pe = (char *)str + str_size, *eof=pe; char *ts, *te = 0; + /*save for cmd_begin state*/ + char *ts_cb=0, *te_cb=0; + + printf("PE:%s %02x\n",pe,(unsigned char)*pe); + /* variables used in state machine */ -#line 132 "cmd_parse.c" +#line 140 "cmd_parse.c" { cs = cmd_start; ts = 0; @@ -136,9 +144,9 @@ int parse_cmd( cmd_tok_t *tl, const char *str ) act = 0; } -#line 72 "cmd_parse.ragel" +#line 85 "cmd_parse.ragel" -#line 142 "cmd_parse.c" +#line 150 "cmd_parse.c" { int _klen; unsigned int _trans; @@ -159,7 +167,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 163 "cmd_parse.c" +#line 171 "cmd_parse.c" } } @@ -230,38 +238,56 @@ _eof_trans: {te = p+1;} break; case 3: -#line 45 "cmd_parse.ragel" - {te = p+1;{PR_TK_DBG("sp = ");}} +#line 52 "cmd_parse.ragel" + {act = 1;} break; case 4: -#line 46 "cmd_parse.ragel" - {te = p+1;{PR_TK_DBG("str = ");TADD(CMDT_STR, ts,te,te-ts);}} +#line 54 "cmd_parse.ragel" + {act = 3;} break; case 5: -#line 49 "cmd_parse.ragel" - {te = p+1;{PR_TK_DBG("sep = ");TADD(CMDT_SP, ts,te,te-ts);}} +#line 57 "cmd_parse.ragel" + {act = 6;} break; case 6: -#line 44 "cmd_parse.ragel" - {te = p;p--;{PR_TK_DBG("hex = ");TADD(CMDT_HEX, ts,te,te-ts);}} +#line 58 "cmd_parse.ragel" + {act = 7;} break; case 7: -#line 47 "cmd_parse.ragel" - {te = p;p--;{PR_TK_DBG("dec = ");TADD(CMDT_INT, ts,te,te-ts);}} +#line 55 "cmd_parse.ragel" + {te = p+1;{PR_TK_DBG("qstr = ");TADD(CMDT_QSTR, ts,te,te-ts);}} break; case 8: -#line 48 "cmd_parse.ragel" - {te = p;p--;{PR_TK_DBG("bin = ");TADD(CMDT_BIN, ts,te,te-ts);}} +#line 57 "cmd_parse.ragel" + {te = p+1;{PR_TK_DBG("sp = ");TADD(CMDT_SP, ts,te,te-ts);}} break; case 9: -#line 50 "cmd_parse.ragel" - {te = p;p--;{PR_TK_DBG("wrd = ");TADD(CMDT_WORD,ts,te,te-ts);}} +#line 53 "cmd_parse.ragel" + {te = p;p--;{PR_TK_DBG("dec = ");TADD(CMDT_INT, ts,te,te-ts);}} break; case 10: -#line 47 "cmd_parse.ragel" - {{p = ((te))-1;}{PR_TK_DBG("dec = ");TADD(CMDT_INT, ts,te,te-ts);}} +#line 56 "cmd_parse.ragel" + {te = p;p--;{PR_TK_DBG("word = ");TADD(CMDT_WORD, ts,te,te-ts);}} + break; + case 11: +#line 1 "NONE" + { switch( act ) { + case 1: + {{p = ((te))-1;}PR_TK_DBG("hex = ");TADD(CMDT_HEX, ts,te,te-ts);} + break; + case 3: + {{p = ((te))-1;}PR_TK_DBG("bin = ");TADD(CMDT_BIN, ts,te,te-ts);} + break; + case 6: + {{p = ((te))-1;}PR_TK_DBG("sp = ");TADD(CMDT_SP, ts,te,te-ts);} + break; + case 7: + {{p = ((te))-1;}PR_TK_DBG("str = ");TADD(CMDT_STR, ts,te,te-ts);} + break; + } + } break; -#line 265 "cmd_parse.c" +#line 291 "cmd_parse.c" } } @@ -274,7 +300,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 278 "cmd_parse.c" +#line 304 "cmd_parse.c" } } @@ -294,7 +320,7 @@ _again: _out: {} } -#line 73 "cmd_parse.ragel" +#line 86 "cmd_parse.ragel" if ( cs == cmd_error ) { diff --git a/cmd_parse.h b/cmd_parse.h index 88a02e8..2976f6d 100644 --- a/cmd_parse.h +++ b/cmd_parse.h @@ -5,4 +5,4 @@ #include "cmd.h" -int parse_cmd( cmd_tok_t *tl, const char *str ); \ No newline at end of file +int parse_cmd( cmd_tok_t *tl, const char *str, size_t sz_cmd ); \ No newline at end of file diff --git a/cmd_parse.ragel b/cmd_parse.ragel index a80d7d1..2fa030c 100644 --- a/cmd_parse.ragel +++ b/cmd_parse.ragel @@ -5,8 +5,8 @@ #define TADD(T,S,E,SZ) {cmd_tok_t *t=cmd_tok_create(S,E,SZ,T);cmd_tok_add(tl,t);tl=tl->next;} //#define TADD(T,S,E) -//#define PR_TK_DBG(S) printf(S);fwrite(ts,1,te-ts,stdout);printf("\n"); -#define PR_TK_DBG(S) ; +#define PR_TK_DBG(S) printf(S);fwrite(ts,1,te-ts,stdout);printf("\n"); +//#define PR_TK_DBG(S) ; char *new_string( const char *start, const char *end ) { @@ -29,41 +29,54 @@ int print_token( char *s, char *e, int tok) %%{ machine cmd; - - hex = '0x' [a-fA-F0-9]+; - decimal = [0-9]+; - binary = '0b' [0-1]+; - string = ('"' ([a-zA-Z0-9' '])+ '"'); - seperate = ';'; - word = [a-zA-Z] ([a-zA-Z0-9])*; - - sp = ([' ','\t','\n']); + hex = '0x' [a-fA-F0-9]+; + decimal = [0-9]+; + binary = '0b' [0-1]+; + quoted_string = '"' + ( + (any-['\\' '"' ' '])* + |'\\\\' + |'\\\"' + |'\\ ' + )* + '"'; + string = (any-['"' ' ']){1} + (any-['"' ' '])* + (any-['"' ' ']){1}; + #seperate = ';'; + word = [a-zA-Z] ([a-zA-Z0-9])*; + sp = ([' ','\t','\n']); main := |* - hex => {PR_TK_DBG("hex = ");TADD(CMDT_HEX, ts,te,te-ts);}; - sp => {PR_TK_DBG("sp = ");}; - string => {PR_TK_DBG("str = ");TADD(CMDT_STR, ts,te,te-ts);}; - decimal => {PR_TK_DBG("dec = ");TADD(CMDT_INT, ts,te,te-ts);}; - binary => {PR_TK_DBG("bin = ");TADD(CMDT_BIN, ts,te,te-ts);}; - seperate => {PR_TK_DBG("sep = ");TADD(CMDT_SP, ts,te,te-ts);}; - word => {PR_TK_DBG("wrd = ");TADD(CMDT_WORD,ts,te,te-ts);}; + hex {PR_TK_DBG("hex = ");TADD(CMDT_HEX, ts,te,te-ts);}; + decimal {PR_TK_DBG("dec = ");TADD(CMDT_INT, ts,te,te-ts);}; + binary {PR_TK_DBG("bin = ");TADD(CMDT_BIN, ts,te,te-ts);}; + quoted_string {PR_TK_DBG("qstr = ");TADD(CMDT_QSTR, ts,te,te-ts);}; + word {PR_TK_DBG("word = ");TADD(CMDT_WORD, ts,te,te-ts);}; + sp {PR_TK_DBG("sp = ");TADD(CMDT_SP, ts,te,te-ts);}; + string {PR_TK_DBG("str = ");TADD(CMDT_STR, ts,te,te-ts);}; *|; - #main := ( ' ' @{fcall lang}; ); + write data; }%% -int parse_cmd( cmd_tok_t *tl, const char *str ) +int parse_cmd( cmd_tok_t *tl, const char *str, size_t str_size ) { static uint8_t cs; const int stacksize = 10; - int res=0, *stack=NULL, act=0; + int res=0, *stack=NULL, act=0,top=0; stack = malloc( sizeof(stack)*stacksize ); - char *p=(char *)str, *pe = (char *)str + strlen( str ), *eof=NULL; + char *p=(char *)str, *pe = (char *)str + str_size, *eof=pe; char *ts, *te = 0; + /*save for cmd_begin state*/ + char *ts_cb=0, *te_cb=0; + + printf("PE:%s %02x\n",pe,(unsigned char)*pe); + /* variables used in state machine */ -- cgit v1.2.3