From 44dedb90f005bb0de9bddbd592a5c78f28bc67d1 Mon Sep 17 00:00:00 2001 From: FreeArtMan Date: Tue, 10 May 2016 22:42:11 +0100 Subject: Replace cmd first part --- Makefile | 8 +- cmd.c | 168 --------------- cmd.h | 33 --- core.c | 71 ++++++- core.h | 21 +- ihe.c | 558 ++++++++++++++++++++++++++++++++++++++++++++----- ihe.h | 8 +- libcmd/Makefile | 43 ++++ libcmd/cmd.c | 544 +++++++++++++++++++++++++++++++++++++++++++++++ libcmd/cmd.h | 85 ++++++++ libcmd/cmd_parse.c | 309 +++++++++++++++++++++++++++ libcmd/cmd_parse.h | 8 + libcmd/cmd_parse.ragel | 86 ++++++++ libcmd/debug.h | 69 ++++++ libcmd/queue.h | 533 ++++++++++++++++++++++++++++++++++++++++++++++ libterm/debug.h | 69 ++++++ libterm/screen_modes.h | 15 ++ libterm/term.h | 70 +++++++ libterm/term_gui.h | 24 +++ libterm/term_io.h | 32 +++ 20 files changed, 2481 insertions(+), 273 deletions(-) delete mode 100644 cmd.c delete mode 100644 cmd.h create mode 100644 libcmd/Makefile create mode 100644 libcmd/cmd.c create mode 100644 libcmd/cmd.h create mode 100644 libcmd/cmd_parse.c create mode 100644 libcmd/cmd_parse.h create mode 100644 libcmd/cmd_parse.ragel create mode 100644 libcmd/debug.h create mode 100644 libcmd/queue.h create mode 100644 libterm/debug.h create mode 100644 libterm/screen_modes.h create mode 100644 libterm/term.h create mode 100644 libterm/term_gui.h create mode 100644 libterm/term_io.h diff --git a/Makefile b/Makefile index 7a35c26..4a6b232 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ PROJECT=ihe CC=gcc CFLAGS= -SOURCES=buf.c cmd.c core.c -OBJECTS=$(SOURCES:.c=.o) +SOURCES=buf.c core.c +OBJECTS=$(SOURCES:.c=.o) +LIB_OBJECTS=libcmd/libcmd.o libterm/libterm.o all: clean $(OBJECTS) $(PROJECT) $(PROJECT): - $(CC) $(CFLAGS) $(OBJECTS) $(PROJECT).c -o $(PROJECT) + $(CC) $(CFLAGS) $(OBJECTS) $(LIB_OBJECTS) $(PROJECT).c -o $(PROJECT) %.o: %.c $(CC) $(CFLAGS) -c $< @@ -18,5 +19,4 @@ clean: leak: valgrind --leak-check=full --track-origins=yes --log-file=log.txt ./ihe - #valgrind --track-origins=yes --log-file=log.txt ./dm -f test/test.bin -m test/one_byte.dm diff --git a/cmd.c b/cmd.c deleted file mode 100644 index 2fb1a76..0000000 --- a/cmd.c +++ /dev/null @@ -1,168 +0,0 @@ -#include "cmd.h" - - -int cnt_sep( char *s ) -{ - int cnt=0; - char *p=s; - while ( *p++ ) - { - if (p[0]==' ') - { - cnt++; - } - } - - return cnt; - -} - - -char* cmd_line( char *prompt ) -{ - char *ret = NULL; - char *pmt = ">"; - const int buf_sz = 32; - int ret_sz; - char buf[buf_sz]; - - - if ( prompt != NULL ) - { - pmt = prompt; - } - - memset( buf, 0, buf_sz ); - write( 1, pmt, strlen(pmt) ); - ret_sz = read( 2, buf,buf_sz); - if (ret_sz < 1) - return ret; - - ret = malloc(ret_sz-1); - memcpy( ret, buf, ret_sz-1 ); - - return ret; -} - - -cmd_arg* cmd_parse( char *str ) -{ - int cnt=0; - cmd_arg *ret = NULL; - int i,j; - char *last=str; - int sz; - - - //count white spaces - cnt = cnt_sep( str )+1; - - ret = malloc( sizeof(cmd_arg) ); - ret->argv = malloc( sizeof(void*)*cnt ); - - ret->argc = cnt; - - if ( cnt == 1 ) - { - ret->argv[0] = malloc( strlen(str) ); - memcpy( ret->argv[0], str, strlen(str) ); - return ret; - } - - //best practices - j = 0; - for (i=0;iargv[j] = malloc( sz+1 ); - memcpy(ret->argv[j],last,sz); - ret->argv[j][sz] = '\0'; - last = str+i+1; - j++; - } - } - sz = str + i - last; - ret->argv[j] = malloc(sz+1); - memcpy( ret->argv[j], last, sz ); - ret->argv[j][sz] = '\0'; - - return ret; -} - -int cmd_exec( cmd_arg *cmd, cmd_table *table ) -{ - int ret = 0; - int fret = 0; - int i; - cmd_arg *sub_arg; - - if (cmd->argc < 1) - { - printf("Hm ... no arguments\n"); - return -1; - } - - i = 0; - while ( (table[i].cmd != NULL) && (table[i].clb != NULL) ) - { - if ((strlen(table[i].cmd) == strlen(cmd->argv[0])) - && (strlen(table[i].cmd) != 0)) - if( strncmp( table[i].cmd, cmd->argv[0], strlen(cmd->argv[0]) ) == 0 ) - { - if ( table[i].clb == NULL ) - { - printf("Empty callback for %s\n",table[i].cmd); - ret = -1; - break; - } - - sub_arg = sub_cmd( cmd ); - fret = table[i].clb( sub_arg ); - if ( fret != 0 ) - { - printf("Command unsuccesfull execution\n"); - ret = -1; - break; - } - break; - - } - - i++; - } - - - return ret; -} - - -void cmd_arg_free( cmd_arg *arg ) -{ - -} - -void cmd_sub_arg_free( cmd_arg *arg ) -{ - -} - - -cmd_arg* sub_cmd( cmd_arg *arg ) -{ - int i; - cmd_arg *ret=NULL; - - if ( arg->argc < 1) - return NULL; - - ret = malloc( sizeof(cmd_arg) ); - ret->argc = arg->argc-1; - ret->argv = malloc( sizeof(void*)*ret->argc ); - for (i=0;iargc;i++) - ret->argv[i] = arg->argv[i+1]; - - return ret; -} - diff --git a/cmd.h b/cmd.h deleted file mode 100644 index 436feac..0000000 --- a/cmd.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __IHE_CMD_H -#define __IHE_CMD_H - -#include -#include -#include -#include -#include - -typedef struct cmd_arg -{ - int argc; - char **argv; -} cmd_arg; - - -typedef struct cmd_table -{ - char *cmd; - int (*clb)(cmd_arg*); -} cmd_table; - - -int cnt_sep( char *s ); -char* cmd_line( char *prompt ); -cmd_arg* cmd_parse( char *str ); -int cmd_exec( cmd_arg *cmd, cmd_table *table ); -void cmd_arg_free( cmd_arg *arg ); -void cmd_sub_arg_free( cmd_arg *arg ); -cmd_arg* sub_cmd( cmd_arg *arg ); - - -#endif diff --git a/core.c b/core.c index 2711111..a152656 100644 --- a/core.c +++ b/core.c @@ -32,6 +32,7 @@ int fd_seek( int fd, off_t offset, int whence ) errno = 0; //why i need to reset it? return -1; } + ret = off_new; return ret; } @@ -82,7 +83,6 @@ ssize_t fd_write( int fd, void *buf, size_t count ) { ssize_t ret; - printf("%d %x %d\n", fd, buf, count); ret = write( fd, buf, count ); if ( errno != 0) { @@ -165,6 +165,18 @@ int file_seek( file_t *ft, off_t offset ) } +int file_seekp( file_t *ft, off_t offset ) +{ + int ret = 0; + off_t new_off = 0; + + ret = fd_seek( ft->fd, offset, FD_SEEK_SET ); + ft->offset = fd_seek( ft->fd, 0, FD_SEEK_CUR ); //cul be errors? + + return ret; +} + + int file_pos( file_t *ft ) { int ret = 0; @@ -239,7 +251,7 @@ int file_read( file_t *ft, uint8_t *buf, size_t count ) printf("Cannot read\n"); } else if ( ret < count ) { - printf("Requestd %d readed %d\n", count, ret); + printf("Requestd %zu readed %d\n", count, ret); } return ret; @@ -259,7 +271,7 @@ int file_write_blk( file_t *ft, uint8_t *buf ) { sz = ft->size - ft->position; //when pos 0 ans size 1 then will write 1 byte } - printf(" %d %x %u \n", ft->fd, buf, sz); + ret = fd_write( ft->fd, buf, sz ); if ( ret < 0 ) { @@ -283,7 +295,7 @@ int file_write( file_t *ft, uint8_t *buf, size_t count ) printf("Cannot write\n"); } else if ( ret < count ) { - printf("Requested %d written %d\n", count, ret); + printf("Requested %zu written %d\n", count, ret); } return ret; @@ -324,3 +336,54 @@ int file_close( file_t *ft ) return ret; } + + +uint8_t **dir_list( char *path) +{ + uint8_t **ret = NULL, **new_ptr; + int cnt=0; + DIR *dp; + struct dirent *ep; + int str_sz = 0; + + /* lets use libc example. they know what they are doing */ + dp = opendir( path ); + if ( dp != NULL ) + { + while ( (ep = readdir( dp )) != NULL ) + { + //count one more in da list + cnt += 1; + //lets alloc pointer on pointer where we put pointer + new_ptr = realloc( ret, sizeof(uint8_t*)*(cnt) ); + if ( new_ptr == NULL ) + goto failed_realloc; + ret = new_ptr; + str_sz = strlen(ep->d_name); + ret[cnt-1] = malloc( str_sz+1 ); + memcpy( ret[cnt-1], ep->d_name, str_sz ); + ret[cnt-1][str_sz] = 0; + } + closedir( dp ); + dp = NULL; + } else + { + perror("Couldnt list directory files"); + *ret = NULL; + } + + //add NULL element at the end + new_ptr = realloc( ret, sizeof(uint8_t*)*(cnt+1) ); + if ( new_ptr == NULL ) + goto failed_add_entry; + ret = new_ptr; + ret[cnt] = NULL; + + return ret; + +failed_realloc: + closedir( dp ); +failed_add_entry: + //forgot to free ret + return NULL; +} \ No newline at end of file diff --git a/core.h b/core.h index 02f072b..11ba289 100644 --- a/core.h +++ b/core.h @@ -6,14 +6,15 @@ #include #include #include +#include #include #include #include #include -/* +/******************************************************************************* BASIC FILE OPERATIONS ON FILE -*/ + ******************************************************************************/ #define FD_RO O_RDONLY #define FD_WO O_WRONLY @@ -76,9 +77,9 @@ search and check for more */ -/* +/******************************************************************************* FILE OPERATION MANAGMENT STRUCTURE -*/ + ******************************************************************************/ #define DEFAULT_BLK_SIZE 256 @@ -101,10 +102,20 @@ int file_read_blk( file_t *ft, uint8_t *buf ); int file_read( file_t *ft, uint8_t *buf, size_t count ); int file_write_blk( file_t *ft, uint8_t *buf ); int file_write( file_t *ft, uint8_t *buf, size_t count ); -int file_seek( file_t *ft, off_t offset ); +int file_seek( file_t *ft, off_t offset ); //seek by offset +int file_seekp( file_t *ft, off_t offset ); int file_pos( file_t *ft ); int file_size( file_t *ft ); int file_s_mode( file_t *ft, int mode ); int file_close( file_t *ft ); +/******************************************************************************* +UTILITITIES + ******************************************************************************/ + +/* +LIST DIRECTORY FILES +*/ +uint8_t **dir_list( char *path ); + #endif \ No newline at end of file diff --git a/ihe.c b/ihe.c index d838b5c..c38380b 100644 --- a/ihe.c +++ b/ihe.c @@ -1,9 +1,198 @@ #include "ihe.h" -#include "cmd.h" #include "core.h" static int cmd_loop = 1; -extern cmd_table tab[]; +extern cmd_table_t tab[]; + +#define CMK_KEYMAP1(KEY) (in_buf[0]==(KEY)&&(ret_read==1)) + +#define CMD_IN_BUF_SIZE 32 +typedef struct cmd_in_buf_t +{ + char buf[CMD_IN_BUF_SIZE+2];//enought space to put "'\n',NULL" + int cur_sz; +} cmd_in_buf_t; + +int cmd_buf_clean( cmd_in_buf_t *buf ); +/* +type == 1, usual printable chars +type == 2, print in hex +*/ +int cmd_buf_print( cmd_in_buf_t *buf, int type ); +int cmd_buf_add( cmd_in_buf_t *buf, char *ch, int size ); + +int cmd_buf_clean( cmd_in_buf_t *buf ) +{ + memset( buf, 0, sizeof(cmd_in_buf_t)); + return 0; +} + + +int cmd_buf_print( cmd_in_buf_t *buf, int type ) +{ + int i; + //printf("sz:%d\n",buf->cur_sz); + for (i=0;(icur_sz)&&(ibuf[i])) + { + printf("%c",(char)(buf->buf[i]&0xff)); + } else + { + printf("."); + } + } else if (type == 2) + { + printf("%02x ", (unsigned char)(buf->buf[i]&0xff) ); + } + } + printf("\n"); + return 0; +} + +int term_set_std_mode( term_screen *ts ) +{ + int ret = 0; + + if ( tcgetattr( ts->ifd, &ts->orig_i ) == -1 ) + { + ERROR("Cannot get input terminal attributes\n"); + goto exit_error; + } + + ts->raw_i = ts->orig_i; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + //ts->raw_i.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + ts->raw_i.c_iflag = IUTF8|ICRNL; + /* output modes - disable post raw */ + //ts->raw_i.c_oflag &= ~(OPOST); + ts->raw_i.c_oflag = OPOST|ONLCR; + /* control modes - set 8 bit chars */ + //ts->raw_i.c_cflag |= (CS8); + ts->raw_i.c_cflag = CS8|CREAD; + /* local modes - choing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + //ts->raw_i.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + //if ICANNON ignore ESC char + //ts->raw_i.c_lflag = ISIG|ECHO; + ts->raw_i.c_lflag = ISIG; + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + ts->raw_i.c_cc[VMIN] = 1; + ts->raw_i.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr( ts->ifd, TCSAFLUSH, &ts->raw_i) < 0) + { + ERROR("Cannot set new terminal input attribures\n"); + goto exit_error; + } + + return ret; + +exit_error: + errno = ENOTTY; + return -1; + +} + + +int custom_term_echo( char *keybuf ) +{ + if (isprint(keybuf[0])) + { + write(1,keybuf,1); + } + if (keybuf[0]=='\n') + { + write(1,"\r\n",2); + } + return 0; +} + + +int cmd_tab_autocomplete( char *in_buf ) +{ + cmd_arg_t *args; + cmd_tok_t tl, *ptr = &tl, *iter = NULL; + struct cmd_acq_t *iter_sugg = NULL; + memset( &tl, 0, sizeof( cmd_tok_t )); + //int i; + + //printf("[%s]\n", in_buf); + if ( parse_cmd( ptr, in_buf) == -1) + { + printf("Cmd problems\n"); + return -1; + } + + iter = ptr->next; + args = cmd_arg_create( iter ); + + /* + for (i=0; iargc; i++) + { + printf("ARG:%d TYPE:%d %s\n", i, args->type[i], args->argv[i]); + } + */ + + //printf("Unkn command\n"); + //if command not found offer auto complete options + if (args->argc > 0) + { + //printf("asd\n"); + struct cmd_acq_head_t *ac = cmd_acq(tab,args->argv[0]); + if (ac != NULL) + { + //printf("Did you mean "); + SLIST_FOREACH(iter_sugg,ac,next_sugg) + { + printf("%s ", iter_sugg->suggestion); + } + printf("\n"); + } + cmd_acq_free( ac ); + } + + cmd_tok_destroy( ptr->next ); + ptr->next = NULL; + cmd_arg_destroy( args ); + + return 0; +} + + +int cmd_buf_add( cmd_in_buf_t *buf, char *ch, int size ) +{ + int i,j; + + /* + for (i=0;icur_sz; + for ( j=0; + jbuf[i+j] = ch[j]; + buf->cur_sz = i+j+1; + //printf("%d\n", buf->cur_sz ); + //printf("\n"); + } + } + + return 0; +} /* GLOBAL VARIABLES @@ -13,7 +202,7 @@ static buf_t *g_buf = NULL; static int g_flags = FD_RW; -int c_version(cmd_arg *arg) +int c_version( cmd_arg_t *arg ) { int argc = arg->argc; @@ -23,13 +212,13 @@ int c_version(cmd_arg *arg) return -1; } - printf("Version 0.0.1\n"); + printf("Version 0.0.2\n"); return 0; } -int c_arg( cmd_arg *arg ) +int c_arg( cmd_arg_t *arg ) { int i; int argc = arg->argc; @@ -44,14 +233,14 @@ int c_arg( cmd_arg *arg ) } -int c_quit( cmd_arg *arg ) +int c_quit( cmd_arg_t *arg ) { cmd_loop = 0; return 0; } -int c_help( cmd_arg *arg ) +int c_help( cmd_arg_t *arg ) { int i = 0; printf("Command list\n"); @@ -67,7 +256,7 @@ int c_help( cmd_arg *arg ) /* OPEN */ -int c_open( cmd_arg *arg ) +int c_open( cmd_arg_t *arg ) { int argc = arg->argc; @@ -99,7 +288,7 @@ int c_open( cmd_arg *arg ) /* CLOSE */ -int c_close( cmd_arg *arg ) +int c_close( cmd_arg_t *arg ) { int fret = 0; @@ -117,7 +306,7 @@ int c_close( cmd_arg *arg ) /* FILE */ -int c_info( cmd_arg *arg ) +int c_info( cmd_arg_t *arg ) { if ( g_file == NULL ) @@ -131,7 +320,7 @@ int c_info( cmd_arg *arg ) printf("FLAGS : 0x%08x\n", g_file->flags ); printf("MODE : 0x%08x\n", g_file->mode ); printf("OFFSET : %zd\n", g_file->offset ); - printf("POSITION: %d\n", g_file->position ); + printf("POSITION: %ld\n", g_file->position ); printf("SIZE : %zd\n", g_file->size ); printf("BLOCK : %u\n", g_file->blk_size ); } @@ -142,7 +331,7 @@ int c_info( cmd_arg *arg ) } else { printf("BUF:\n"); - printf("ADDR : %08x\n", g_buf->buf); + printf("ADDR : %p\n", g_buf->buf); printf("SIZE : %d\n", g_buf->size); printf("BUFSIZE: %d\n", g_buf->buf_size); } @@ -151,12 +340,13 @@ int c_info( cmd_arg *arg ) } -int c_seek( cmd_arg *arg ) +int c_seek( cmd_arg_t *arg ) { int fret; int argc = arg->argc; char **argv = arg->argv; off_t offset; + int off_type = 0; //-1 seek down, 0 set pos, +1 seek up if (argc != 1) { @@ -170,8 +360,29 @@ int c_seek( cmd_arg *arg ) return -1; } + //set seek type + switch( argv[0][0] ) + { + case '+': + off_type = 1; + break; + case '-': + off_type = -1; + break; + default: + off_type = 0; + } + offset = atoi( argv[0] ); //!fix that to strtol at least - fret = file_seek( g_file, offset ); + + if (off_type == 0) + { + //g_file offset maybe wrong + fret = file_seekp( g_file, offset ); + } else + { + fret = file_seek( g_file, offset ); + } if ( fret != 0 ) { printf("Cannot seek postion to %zd\n", offset); @@ -182,7 +393,7 @@ int c_seek( cmd_arg *arg ) } -int c_pos( cmd_arg *arg ) +int c_pos( cmd_arg_t *arg ) { int fret = 0; @@ -199,7 +410,7 @@ int c_pos( cmd_arg *arg ) } -int c_size( cmd_arg *arg ) +int c_size( cmd_arg_t *arg ) { off_t size; @@ -216,7 +427,7 @@ int c_size( cmd_arg *arg ) } -int c_blk( cmd_arg *arg ) +int c_blk( cmd_arg_t *arg ) { printf("FILE BLOCK SIZE %u\n", g_file->blk_size ); printf("BUFFER BLOCK SIZE %d (MAX %d)\n", g_buf->size, g_buf->buf_size ); @@ -225,7 +436,7 @@ int c_blk( cmd_arg *arg ) } -int c_read( cmd_arg *arg ) +int c_read( cmd_arg_t *arg ) { int ret; @@ -246,7 +457,7 @@ int c_read( cmd_arg *arg ) } -int c_dump( cmd_arg *arg ) +int c_dump( cmd_arg_t *arg ) { int i; @@ -266,7 +477,7 @@ int c_dump( cmd_arg *arg ) } -int c_dumpx( cmd_arg *arg ) +int c_dumpx( cmd_arg_t *arg ) { int i,j; @@ -310,8 +521,36 @@ int c_dumpx( cmd_arg *arg ) } +int c_dumps( cmd_arg_t *arg ) +{ + int argc = arg->argc; + char **argv = arg->argv; + int i=0; + + if ( argc != 0 ) + { + printf("No arguments plz\n"); + return -1; + } + + for (i=0; isize; i++) + { + if (isprint(g_buf->buf[i])) + { + printf("%c", g_buf->buf[i]); + } else + { + printf("\e[7m.\e[0m"); + } + } + printf("\n"); + + return 0; +} + + //support masks -int c_write( cmd_arg *arg ) +int c_write( cmd_arg_t *arg) { /* anonymous function @@ -368,7 +607,7 @@ int c_write( cmd_arg *arg ) for (i=0; ibuf, buf, strlen(argv[0])/2 ); @@ -394,7 +633,7 @@ int c_write( cmd_arg *arg ) //white spaces should be supported -int c_writes( cmd_arg *arg ) +int c_writes( cmd_arg_t *arg ) { int argc = arg->argc; char **argv = arg->argv; @@ -423,7 +662,7 @@ int c_writes( cmd_arg *arg ) } } else { - printf("Input bigger then buffer buf %d input %d\n", g_buf->size, strlen(argv[0])); + printf("Input bigger then buffer buf %d input %zu\n", g_buf->size, strlen(argv[0])); return -1; } @@ -431,7 +670,7 @@ int c_writes( cmd_arg *arg ) } -int c_flags( cmd_arg *arg ) +int c_flags( cmd_arg_t *arg ) { int argc = arg->argc; char **argv = arg->argv; @@ -467,7 +706,7 @@ int c_flags( cmd_arg *arg ) } -int c_manifesto( cmd_arg *arg ) +int c_manifesto( cmd_arg_t *arg ) { printf("""\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\ @@ -510,29 +749,169 @@ int c_manifesto( cmd_arg *arg ) return 0; } + +int c_ls( cmd_arg_t *arg ) +{ + int argc = arg->argc; + //char **argv = arg->argv; + uint8_t **f_ls = NULL; + int i=0; + + if (argc > 0) + { + printf("Plz dont use arguments\n"); + return -1; + } + + f_ls = dir_list("./"); + if ( f_ls == NULL ) + { + printf("Cannot list current directory\n"); + return -1; + } + + i = 0; + while ( f_ls[i] != NULL ) + { + printf("%s\n",f_ls[i]); + free( f_ls[i] ); + i++; + } + free( f_ls ); + + return 0; +} + +int c_pwd( cmd_arg_t *arg ) +{ + int argc = arg->argc; + //char **argv = arg->argv; + char *cur_dir; + + if ( argc > 0 ) + { + printf("PLZ no arguments\n"); + return -1; + } + + cur_dir = get_current_dir_name(); + if ( errno != 0 ) + { + printf("Cannot get current dir\n"); + free( cur_dir ); //on failure content unknown; + return -1; + } + + printf("%s\n", cur_dir); + free( cur_dir ); + cur_dir = NULL; + + return 0; +} + + +int c_cd( cmd_arg_t *arg ) +{ + int argc = arg->argc; + char **argv = arg->argv; + int fret = -1; + + if ( argc != 1 ) + { + printf("Only 1 argument needed\n"); + return -1; + } + + //printf("[%s]\n", argv[0]); + fret = chdir( argv[0] ); + if ( fret == -1 ) + { + printf("Cannot set dir to %s\n", argv[0]); + return -1; + } + + return 0; +} + + +int c_th( cmd_arg_t *arg ) +{ + /* + int argc = arg->argc; + int th = -1; + + if ( argc > 0 ) + { + printf("No arguments needed\n"); + return -1; + } + + th = term_cur_get_r(); + if (th == -1) + { + printf("Cannot get current term height\n"); + return -1; + } + printf("%d\n",th); + */ + + return 0; +} + + +int c_tw( cmd_arg_t *arg ) +{ + /* + int argc = arg->argc; + int tw = -1; + + if ( argc > 0 ) + { + printf("No arguments needed\n"); + return -1; + } + + tw = term_cur_get_c(); + if (tw == -1) + { + printf("Cannot get current term width\n"); + return -1; + } + printf("%d\n",tw); + */ + + return 0; +} /* CMD COMMANDS */ -cmd_table tab[] = { - {"version", c_version }, - {"arg", c_arg }, - {"quit", c_quit}, - {"help", c_help}, - {"?", c_help}, - {"open", c_open}, - {"close", c_close}, - {"info", c_info}, - {"seek", c_seek}, - {"pos", c_pos}, - {"size", c_size}, - {"blk", c_blk}, - {"read", c_read}, - {"dump", c_dump}, - {"dumpx", c_dumpx}, - {"write", c_write}, - {"writes", c_writes}, - {"flags", c_flags}, +cmd_table_t tab[] = { + /* + {"version", c_version }, + {"arg", c_arg }, + {"quit", c_quit}, + {"help", c_help}, + {"?", c_help}, + {"open", c_open}, + {"close", c_close}, + {"info", c_info}, + {"seek", c_seek}, + {"pos", c_pos}, + {"size", c_size}, + {"blk", c_blk}, + {"read", c_read}, + {"dump", c_dump}, + {"dumpx", c_dumpx}, + {"dumps", c_dumps}, + {"write", c_write}, + {"writes", c_writes}, + {"flags", c_flags}, {"manifesto", c_manifesto}, + {"ls", c_ls}, + {"pwd", c_pwd}, + {"cd", c_cd},*/ + //{"th", c_th}, + //{"tw", c_tw}, {NULL, NULL } }; @@ -540,9 +919,11 @@ cmd_table tab[] = { int main( int argc, char **argv ) { - char *cmd = NULL; - cmd_arg *tok = NULL; - + const int sz_buf = 1024; + uint8_t in_buf[sz_buf]; + int ret_read; + int new_c=0, new_r=0, old_r=0, old_c=0; + //preapre global stuff g_file = file_init(); @@ -550,20 +931,81 @@ int main( int argc, char **argv ) g_buf = buf_init(); buf_size( g_buf, DEFAULT_BLK_SIZE ); - //read line from cmd - while( cmd_loop ) + + struct term_screen ts; memset( &ts, 0, sizeof(ts) ); + + cmd_in_buf_t cmd_in; + cmd_buf_clean( &cmd_in ); + + if ( term_init( &ts ) == -1 ) + printf("Some err when init\n"); + + //term_set_raw_mode( &ts ); + term_set_std_mode( &ts ); + + term_clr_scr( &ts ); + + new_c = term_get_maxcol( &ts ); + new_r = term_get_maxrow( &ts ); + old_r = new_r; + old_c = new_c; + + term_cur_set_c( &ts, 0); + term_cur_set_r( &ts, old_r); + + while ( 1 == 1 ) { - cmd = cmd_line(NULL); - //printf("cmd [%s]\n", cmd); - //printf("cnt %d\n",cnt_sep(cmd)); + + ret_read = read(2, in_buf, sz_buf ); + if (ret_read < 0) + { + printf("Cannot read\n"); + continue; + } + in_buf[ret_read] = 0; + + //custom echoing service to ignore some special chars like TAB + custom_term_echo( (char *)in_buf ); - tok = cmd_parse( cmd ); - free( cmd ); + //printf("(%d)%s\n",ret_read,in_buf); + if ( (isprint(in_buf[0])) && (in_buf[0]!='?') && (in_buf[0]!='\t')) + { + //printf("asd %d\n", ret_read); + cmd_buf_add( &cmd_in, (char *)in_buf, ret_read ); + } + + //auto complete advice + if (CMK_KEYMAP1(9)) + { + //cmd_buf_print( &cmd_in, 2 ); + cmd_in.buf[cmd_in.cur_sz] = '\n'; + cmd_in.buf[cmd_in.cur_sz+1] = 0; + cmd_tab_autocomplete( cmd_in.buf ); + cmd_buf_print( &cmd_in, 1 ); + continue; + } + + if (CMK_KEYMAP1('?')) + { + cmd_buf_print( &cmd_in, 1 ); + } - cmd_exec( tok, tab ); + if (CMK_KEYMAP1(27)) + { + cmd_buf_print( &cmd_in, 1 ); + break; + } - cmd_arg_free( tok ); + if (CMK_KEYMAP1('\n')) + { + cmd_buf_clean( &cmd_in ); + } + } + term_clr_scr( &ts ); + + term_set_orig_mode( &ts ); + return 0; } \ No newline at end of file diff --git a/ihe.h b/ihe.h index 9589236..5331e55 100644 --- a/ihe.h +++ b/ihe.h @@ -1,12 +1,18 @@ #ifndef __IHE_H #define __IHE_H +#define _GNU_SOURCE #include #include #include #include "buf.h" -#include "cmd.h" #include "core.h" +#include "libcmd/cmd.h" +#include "libcmd/cmd_parse.h" + +#include "libterm/term.h" +#include "libterm/term_io.h" + #endif \ No newline at end of file diff --git a/libcmd/Makefile b/libcmd/Makefile new file mode 100644 index 0000000..86f0ae6 --- /dev/null +++ b/libcmd/Makefile @@ -0,0 +1,43 @@ +PROJ=libcmd +CC=gcc +CFLAGS=-g3 +LDFLAGS= +RAGEL=ragel +DOT=dot + +SOURCE=cmd cmd_parse +OBJECTS=$(SOURCE:=.o) +SOURCES=$(SOURCE:=.c) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + + +make: dynamic static object + +dynamic: CFLAGS+=-fPIC +dynamic: clean $(OBJECTS) + $(CC) $(CFLAGS) $(OBJECTS) -shared -o $(PROJ).so + +static: clean $(OBJECTS) + ar rcs $(PROJ).a $(OBJECTS) + +object: clean $(OBJECTS) + ld -r $(OBJECTS) -o $(PROJ).o + +ragel: + $(RAGEL) cmd_parse.ragel + +cli: + $(CC) $(CFLAGS) -L./ -I./ -lcmd ./test/cmd_cli.c -o ./cmd_cli + +pdf: + $(RAGEL) -V cmd_parse.ragel -o cmd_parse.dot + $(DOT) -Tpdf cmd_parse.dot -o cmd_parse.pdf + +leak: + valgrind --leak-check=full --track-origins=yes --log-file=log.txt ./cmd_cli + +clean: + rm -f cmd_cli + rm -rf *.so *.o *.dot *.pdf diff --git a/libcmd/cmd.c b/libcmd/cmd.c new file mode 100644 index 0000000..c1d43fc --- /dev/null +++ b/libcmd/cmd.c @@ -0,0 +1,544 @@ +#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 +#include +#include +#include + +#include "debug.h" +#include "queue.h" + +#define CMDT_NONE 0 +#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 CMDE_NONE 0 //do nothing +#define CMDE_AUTOCOMPLETE 1 //try to auto complete first command +#define CMDE_ALIAS 2 //command aliases + +typedef struct cmd_tok_t +{ + char *s,*e; + int sz; + int type; + struct cmd_tok_t *next; +} cmd_tok_t; + +typedef struct cmd_arg_t +{ + int argc; + char **argv; + int *type; + + /* bad practice stuff */ + int __sub_cmd; // if 1 then dont free argv stuff +} cmd_arg_t; + + +typedef struct cmd_table_t +{ + char *cmd; + int (*clb)(cmd_arg_t*); +} cmd_table_t; + +struct cmd_acq_t +{ + char *suggestion; + SLIST_ENTRY(cmd_acq_t) next_sugg; +}; +SLIST_HEAD(cmd_acq_head_t,cmd_acq_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 ); +void cmd_tok_destroy( cmd_tok_t *tok ); //clean token by ->next token +int cmd_tok_count( cmd_tok_t *tok ); + +cmd_arg_t* cmd_arg_create( cmd_tok_t *tok ); +cmd_arg_t* cmd_arg_sub( cmd_arg_t *arg ); //just return without first arg +cmd_arg_t* cmd_arg_sub_empty(); +void cmd_arg_destroy( cmd_arg_t *arg ); + +int cmd_exec( cmd_table_t *tbl, cmd_arg_t *arg ); +int cmd_exec_ev( cmd_table_t *tbl, cmd_arg_t *arg, int event ); //auto complete and all other +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 ); + +#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))) + +/* +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); + +#endif \ No newline at end of file diff --git a/libcmd/cmd_parse.c b/libcmd/cmd_parse.c new file mode 100644 index 0000000..ee6b3ca --- /dev/null +++ b/libcmd/cmd_parse.c @@ -0,0 +1,309 @@ + +#line 1 "cmd_parse.ragel" +#include "cmd_parse.h" + +//#define CTS(X) {if (!dm_current_tok)token_s = p; printf("%s ",#X);if (!dm_current_tok) dm_current_tok = TOK_##X;} +//#define CTE() {token_e = p;} +#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) + +char *new_string( const char *start, const char *end ) +{ + int str_s = end-start+1; + char *new_str=malloc( str_s+1 ); + memcpy( new_str, start, str_s ); + if ( new_str != NULL ) + new_str[str_s]=0x0; + return new_str; +} + +int print_token( char *s, char *e, int tok) +{ + char *p = new_string( s, e ); + printf("t=%d,p=%s\n",tok,p); + free( p ); + return 0; +} + + + +#line 31 "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 +}; + +static const char _cmd_key_offsets[] = { + 0, 0, 8, 17, 19, 25, 31, 43, + 47, 49, 51, 57 +}; + +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, 48, 57, 65, 90, 97, 122, 32, + 34, 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 +}; + +static const char _cmd_single_lengths[] = { + 0, 2, 3, 0, 0, 0, 4, 2, + 0, 0, 0, 0 +}; + +static const char _cmd_range_lengths[] = { + 0, 3, 3, 1, 3, 3, 4, 1, + 1, 1, 3, 3 +}; + +static const char _cmd_index_offsets[] = { + 0, 0, 6, 13, 15, 19, 23, 32, + 36, 38, 40, 44 +}; + +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, 6, 6, 1, 7, + 8, 9, 11, 7, 10, 12, 12, 1, + 14, 15, 10, 13, 10, 13, 4, 16, + 5, 5, 5, 17, 6, 6, 6, 18, + 0 +}; + +static const char _cmd_trans_targs[] = { + 2, 0, 6, 6, 9, 10, 11, 6, + 1, 7, 8, 6, 5, 6, 3, 4, + 6, 6, 6 +}; + +static const char _cmd_trans_actions[] = { + 0, 0, 9, 21, 0, 0, 0, 7, + 0, 5, 0, 11, 0, 15, 0, 0, + 17, 13, 19 +}; + +static const char _cmd_to_state_actions[] = { + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0 +}; + +static const char _cmd_from_state_actions[] = { + 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0 +}; + +static const char _cmd_eof_trans[] = { + 0, 0, 0, 4, 4, 0, 0, 14, + 14, 17, 18, 19 +}; + +static const int cmd_start = 6; +static const int cmd_first_final = 6; +static const int cmd_error = 0; + +static const int cmd_en_main = 6; + + +#line 53 "cmd_parse.ragel" + + +int parse_cmd( cmd_tok_t *tl, const char *str ) +{ + static uint8_t cs; + const int stacksize = 10; + int res=0, *stack=NULL, act=0; + stack = malloc( sizeof(stack)*stacksize ); + char *p=(char *)str, *pe = (char *)str + strlen( str ), *eof=NULL; + char *ts, *te = 0; + + /* + variables used in state machine + */ + + +#line 130 "cmd_parse.c" + { + cs = cmd_start; + ts = 0; + te = 0; + act = 0; + } + +#line 69 "cmd_parse.ragel" + +#line 140 "cmd_parse.c" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _acts = _cmd_actions + _cmd_from_state_actions[cs]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 1: +#line 1 "NONE" + {ts = p;} + break; +#line 161 "cmd_parse.c" + } + } + + _keys = _cmd_trans_keys + _cmd_key_offsets[cs]; + _trans = _cmd_index_offsets[cs]; + + _klen = _cmd_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _cmd_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + _trans = _cmd_indicies[_trans]; +_eof_trans: + cs = _cmd_trans_targs[_trans]; + + if ( _cmd_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _cmd_actions + _cmd_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 2: +#line 1 "NONE" + {te = p+1;} + break; + case 3: +#line 42 "cmd_parse.ragel" + {te = p+1;} + break; + case 4: +#line 43 "cmd_parse.ragel" + {te = p+1;{printf("str = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_STR,ts,te,te-ts);}} + break; + case 5: +#line 46 "cmd_parse.ragel" + {te = p+1;{printf("sep = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_SP,ts,te,te-ts);}} + break; + case 6: +#line 41 "cmd_parse.ragel" + {te = p;p--;{printf("hex = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_HEX,ts,te,te-ts);}} + break; + case 7: +#line 44 "cmd_parse.ragel" + {te = p;p--;{printf("dec = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_INT,ts,te,te-ts);}} + break; + case 8: +#line 45 "cmd_parse.ragel" + {te = p;p--;{printf("bin = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_BIN,ts,te,te-ts);}} + break; + case 9: +#line 47 "cmd_parse.ragel" + {te = p;p--;{printf("wrd = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_WORD,ts,te,te-ts);}} + break; + case 10: +#line 44 "cmd_parse.ragel" + {{p = ((te))-1;}{printf("dec = ");fwrite(ts,1,te-ts,stdout);printf("\n");TADD(CMDT_INT,ts,te,te-ts);}} + break; +#line 263 "cmd_parse.c" + } + } + +_again: + _acts = _cmd_actions + _cmd_to_state_actions[cs]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: +#line 1 "NONE" + {ts = 0;} + break; +#line 276 "cmd_parse.c" + } + } + + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + if ( _cmd_eof_trans[cs] > 0 ) { + _trans = _cmd_eof_trans[cs] - 1; + goto _eof_trans; + } + } + + _out: {} + } + +#line 70 "cmd_parse.ragel" + + if ( cs == cmd_error ) + { + printf("CLIPARSE ERR state [%d] pos[%d]:[%s]\n", res, p-str, p); + res = -1; + } + + free( stack ); + + return res; +} + + + diff --git a/libcmd/cmd_parse.h b/libcmd/cmd_parse.h new file mode 100644 index 0000000..88a02e8 --- /dev/null +++ b/libcmd/cmd_parse.h @@ -0,0 +1,8 @@ +#include +#include +#include +#include + +#include "cmd.h" + +int parse_cmd( cmd_tok_t *tl, const char *str ); \ No newline at end of file diff --git a/libcmd/cmd_parse.ragel b/libcmd/cmd_parse.ragel new file mode 100644 index 0000000..85aa7d8 --- /dev/null +++ b/libcmd/cmd_parse.ragel @@ -0,0 +1,86 @@ +#include "cmd_parse.h" + +//#define CTS(X) {if (!dm_current_tok)token_s = p; printf("%s ",#X);if (!dm_current_tok) dm_current_tok = TOK_##X;} +//#define CTE() {token_e = p;} +#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) + +char *new_string( const char *start, const char *end ) +{ + int str_s = end-start+1; + char *new_str=malloc( str_s+1 ); + memcpy( new_str, start, str_s ); + if ( new_str != NULL ) + new_str[str_s]=0x0; + return new_str; +} + +int print_token( char *s, char *e, int tok) +{ + char *p = new_string( s, e ); + printf("t=%d,p=%s\n",tok,p); + free( p ); + return 0; +} + + +%%{ + 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'); + + main := |* + hex {PR_TK_DBG("hex = ");TADD(CMDT_HEX, ts,te,te-ts);}; + 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);}; + *|; + + #main := lang; + + write data; +}%% + +int parse_cmd( cmd_tok_t *tl, const char *str ) +{ + static uint8_t cs; + const int stacksize = 10; + int res=0, *stack=NULL, act=0; + stack = malloc( sizeof(stack)*stacksize ); + char *p=(char *)str, *pe = (char *)str + strlen( str ), *eof=NULL; + char *ts, *te = 0; + + /* + variables used in state machine + */ + + %%write init; + %%write exec; + + if ( cs == cmd_error ) + { + printf("CLIPARSE ERR state [%d] pos[%d]:[%s]\n", res, p-str, p); + res = -1; + } + + free( stack ); + + return res; +} + + + diff --git a/libcmd/debug.h b/libcmd/debug.h new file mode 100644 index 0000000..a8bf211 --- /dev/null +++ b/libcmd/debug.h @@ -0,0 +1,69 @@ +#ifndef __RB_DEBUG_UTILS_H +#define __RB_DEBUG_UTILS_H + +//what about kprintf? + +//config options +#define PRINTF printf +#define COLORIZE +#define PRINT_LINENUM +#define PRINT_FILENAME +#define PRINT_DEBUG + + +//use color +#ifdef COLORIZE + #define D_COLOR "1;32m" + #define D_COLOR_S "\033[" D_COLOR + #define D_COLOR_E "\033[0m" + #define E_COLOR "1;31m" + #define E_COLOR_S "\033[" E_COLOR + #define E_COLOR_E "\033[0m" +#else + #define D_COLOR + #define D_COLOR_S + #define D_COLOR_E + #define E_COLOR + #define E_COLOR_S + #define E_COLOR_E +#endif + +//print debug line +#ifdef PRINT_LINENUM + #define PRINT_LINE_F "LINE:%d " + #define PRINT_LINE_D __LINE__ +#else + #define PRINT_LINE_F "" + #define PRINT_LINE_D "" +#endif + +//print +#ifdef PRINT_FILENAME + #define PRINT_FILE_F "FILE:%s " + #define PRINT_FILE_D __FILE__ +#else + #define PRINT_FILE_F "" + #define PRINT_FILE_D "" +#endif + +//print debug string +#ifdef PRINT_DEBUG + #define PRINT_DEBUG_F "Debug: " +#else + #define PRINT_DEBUG_F "" +#endif + +#define PRINT( format, args ... ) PRINTF( D_COLOR_S PRINT_DEBUG_F \ + PRINT_FILE_F PRINT_LINE_F format D_COLOR_E, PRINT_FILE_D, \ + PRINT_LINE_D, ##args); + +#define ERROR( format, args ... ) PRINTF( E_COLOR_S PRINT_DEBUG_F \ + PRINT_FILE_F PRINT_LINE_F format E_COLOR_E, PRINT_FILE_D, \ + PRINT_LINE_D, ##args); + +#define PNL() PRINT("\n"); + +#define ENL() ERROR("\n"); + + +#endif diff --git a/libcmd/queue.h b/libcmd/queue.h new file mode 100644 index 0000000..cc2b25e --- /dev/null +++ b/libcmd/queue.h @@ -0,0 +1,533 @@ +/* $OpenBSD: queue.h,v 1.43 2015/12/28 19:38:40 millert Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues and XOR simple queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * An XOR simple queue is used in the same way as a regular simple queue. + * The difference is that the head structure also includes a "cookie" that + * is XOR'd with the queue pointer (first, last or next) to generate the + * real pointer value. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALIDATE(a) (a) = ((void *)-1) +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do {\n \ + (elm)->field.sle_next = (slistelm)->field.sle_next;\n \ + (slistelm)->field.sle_next = (elm);\n \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ + _Q_INVALIDATE((elm)->field.sle_next); \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods. + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue access methods. + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue