diff options
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | cmd.c | 168 | ||||
| -rw-r--r-- | cmd.h | 33 | ||||
| -rw-r--r-- | core.c | 71 | ||||
| -rw-r--r-- | core.h | 21 | ||||
| -rw-r--r-- | ihe.c | 558 | ||||
| -rw-r--r-- | ihe.h | 8 | ||||
| -rw-r--r-- | libcmd/Makefile | 43 | ||||
| -rw-r--r-- | libcmd/cmd.c | 544 | ||||
| -rw-r--r-- | libcmd/cmd.h | 85 | ||||
| -rw-r--r-- | libcmd/cmd_parse.c | 309 | ||||
| -rw-r--r-- | libcmd/cmd_parse.h | 8 | ||||
| -rw-r--r-- | libcmd/cmd_parse.ragel | 86 | ||||
| -rw-r--r-- | libcmd/debug.h | 69 | ||||
| -rw-r--r-- | libcmd/queue.h | 533 | ||||
| -rw-r--r-- | libterm/debug.h | 69 | ||||
| -rw-r--r-- | libterm/screen_modes.h | 15 | ||||
| -rw-r--r-- | libterm/term.h | 70 | ||||
| -rw-r--r-- | libterm/term_gui.h | 24 | ||||
| -rw-r--r-- | libterm/term_io.h | 32 | 
20 files changed, 2481 insertions, 273 deletions
| @@ -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 @@ -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;i<strlen(str);i++) -	{ -		if (str[i]==' ') -		{ -			sz = (str+i)-last; -			ret->argv[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;i<ret->argc;i++) -		ret->argv[i] = arg->argv[i+1]; - -	return ret;  -} - @@ -1,33 +0,0 @@ -#ifndef __IHE_CMD_H -#define __IHE_CMD_H - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -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 @@ -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 @@ -6,14 +6,15 @@  #include <stdint.h>  #include <sys/types.h>  #include <sys/stat.h> +#include <dirent.h>  #include <fcntl.h>  #include <unistd.h>  #include <string.h>  #include <errno.h> -/* +/*******************************************************************************  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 @@ -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;(i<buf->cur_sz)&&(i<CMD_IN_BUF_SIZE);i++) +	{ +		if (type == 1) +		{ +			if (isprint(buf->buf[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; i<args->argc; 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;i<size;i++) +	{ +		printf("|%c|",ch[i]); +	} printf("\n"); +	*/ + +	i=buf->cur_sz; +	for ( j=0; +		j<size; +		j+=1 ) +	{ +		if ( (i+j) < CMD_IN_BUF_SIZE ) +		{ +			//printf("%d %c",(i+j),ch[j]); +			buf->buf[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 <FILENAME>  */ -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; i<g_buf->size; 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; i<strlen(argv[0]); i+=2)  	{ -		printf("%02x ",hex2u8(&argv[0][i])); +		printf("%02x ",(unsigned char)hex2u8((unsigned char*)&argv[0][i]));  	}  	printf("\n"); @@ -376,7 +615,7 @@ int c_write( cmd_arg *arg )  	buf = malloc(strlen(argv[0])/2);  	for (i=0; i<(strlen(argv[0])/2); i++)  	{ -		buf[i] = hex2u8(&argv[0][i*2]); +		buf[i] = hex2u8((unsigned char*)&argv[0][i*2]);  	}  	memcpy( g_buf->buf, 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 @@ -1,12 +1,18 @@  #ifndef __IHE_H  #define __IHE_H +#define _GNU_SOURCE  #include <stdio.h>  #include <stdlib.h>  #include <ctype.h>  #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; i<argc; i++,iter=iter->next) +	{ +		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; i<ret->argc; 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; i<arg->argc; 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<n)) +	{ +		i++; +	} + +	//printf("i"); +	/* AA AA */ +	if ( (s1[i]==0x00) && (s2[i]==0x0) && (i==n) ) +	{ +		//printf("1 "); +		return i+1; +	/* AA AAA */ +	} else if ( (s1[i]==0x0) && (s2[i]!=0x0) && (i==n) ) +	{ +		//printf("2 "); +		return i; +	/* AAA AA */ +	} else if ( (s1[i]!=0x0) && (s2[i]==0x0) && (i<n) ) +	{ +		//printf("3 "); +		return -i; +	/* AA AB */ +	} else if ( (s1[i]!=0x0) && (s2[i]!=0x0) && (s1[i]!=s2[i]) && (i<n) ) +	{ +		//printf("4 "); +		return -i; +	} else  +	{ +		printf("Unknown condition\n"); +	} + +	return 0; +}
\ No newline at end of file diff --git a/libcmd/cmd.h b/libcmd/cmd.h new file mode 100644 index 0000000..736cb2b --- /dev/null +++ b/libcmd/cmd.h @@ -0,0 +1,85 @@ +#ifndef __CMD_H +#define __CMD_H + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#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 functions. + */ +#define	TAILQ_INIT(head) do {						\ +	(head)->tqh_first = NULL;					\ +	(head)->tqh_last = &(head)->tqh_first;				\ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do {			\ +	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\ +		(head)->tqh_first->field.tqe_prev =			\ +		    &(elm)->field.tqe_next;				\ +	else								\ +		(head)->tqh_last = &(elm)->field.tqe_next;		\ +	(head)->tqh_first = (elm);					\ +	(elm)->field.tqe_prev = &(head)->tqh_first;			\ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do {			\ +	(elm)->field.tqe_next = NULL;					\ +	(elm)->field.tqe_prev = (head)->tqh_last;			\ +	*(head)->tqh_last = (elm);					\ +	(head)->tqh_last = &(elm)->field.tqe_next;			\ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\ +	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ +		(elm)->field.tqe_next->field.tqe_prev =			\ +		    &(elm)->field.tqe_next;				\ +	else								\ +		(head)->tqh_last = &(elm)->field.tqe_next;		\ +	(listelm)->field.tqe_next = (elm);				\ +	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\ +} while (0) + +#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\ +	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\ +	(elm)->field.tqe_next = (listelm);				\ +	*(listelm)->field.tqe_prev = (elm);				\ +	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do {				\ +	if (((elm)->field.tqe_next) != NULL)				\ +		(elm)->field.tqe_next->field.tqe_prev =			\ +		    (elm)->field.tqe_prev;				\ +	else								\ +		(head)->tqh_last = (elm)->field.tqe_prev;		\ +	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\ +	_Q_INVALIDATE((elm)->field.tqe_prev);				\ +	_Q_INVALIDATE((elm)->field.tqe_next);				\ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do {			\ +	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\ +		(elm2)->field.tqe_next->field.tqe_prev =		\ +		    &(elm2)->field.tqe_next;				\ +	else								\ +		(head)->tqh_last = &(elm2)->field.tqe_next;		\ +	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\ +	*(elm2)->field.tqe_prev = (elm2);				\ +	_Q_INVALIDATE((elm)->field.tqe_prev);				\ +	_Q_INVALIDATE((elm)->field.tqe_next);				\ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do {				\ +	if (!TAILQ_EMPTY(head2)) {					\ +		*(head1)->tqh_last = (head2)->tqh_first;		\ +		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\ +		(head1)->tqh_last = (head2)->tqh_last;			\ +		TAILQ_INIT((head2));					\ +	}								\ +} while (0) + +#endif	/* !_SYS_QUEUE_H_ */ diff --git a/libterm/debug.h b/libterm/debug.h new file mode 100644 index 0000000..a79ea77 --- /dev/null +++ b/libterm/debug.h @@ -0,0 +1,69 @@ +#ifndef __LIBTERM_DEBUG_UTILS_H +#define __LIBTERM_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/libterm/screen_modes.h b/libterm/screen_modes.h new file mode 100644 index 0000000..261cbf5 --- /dev/null +++ b/libterm/screen_modes.h @@ -0,0 +1,15 @@ +#ifndef __LIBTERM_SCREEN_MODES_H +#define __LIBTERM_SCREEN_MODES_H + +typedef enum  +{ +	SCREEN_MODE_NONE=0, +	SCREEN_MODE_80x25 +} screen_mode_e; + +typedef struct term_screen_mode +{ +	screen_mode_e mode; +} term_screen_mode; + +#endif diff --git a/libterm/term.h b/libterm/term.h new file mode 100644 index 0000000..df3d7b1 --- /dev/null +++ b/libterm/term.h @@ -0,0 +1,70 @@ +#ifndef __LIBTERM_TERM_H +#define __LIBTERM_TERM_H + +#include <termios.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include "screen_modes.h" +#include "debug.h" + +enum TERM_KEY_ACTION { +	KEY_NULL = 0,	    /* NULL */ +	CTRL_A = 1,         /* Ctrl+a */ +	CTRL_B = 2,         /* Ctrl-b */ +	CTRL_C = 3,         /* Ctrl-c */ +	CTRL_D = 4,         /* Ctrl-d */ +	CTRL_E = 5,         /* Ctrl-e */ +	CTRL_F = 6,         /* Ctrl-f */ +	CTRL_H = 8,         /* Ctrl-h */ +	TAB    = 9,         /* Tab */ +	CTRL_K = 11,        /* Ctrl+k */ +	CTRL_L = 12,        /* Ctrl+l */ +	ENTER  = 13,        /* Enter */ +	CTRL_N = 14,        /* Ctrl-n */ +	CTRL_P = 16,        /* Ctrl-p */ +	CTRL_T = 20,        /* Ctrl-t */ +	CTRL_U = 21,        /* Ctrl+u */ +	CTRL_W = 23,        /* Ctrl+w */ +	ESC    = 27,        /* Escape */ +	QMARK  = 63,        /* ? */ +	BACKSPACE =  127    /* Backspace */ +}; + +      +#define TK_ENTER     13 +#define TK_ESC       27 +#define TK_BACKSPACE 8 + +typedef struct term_screen +{ +	int ifd, ofd; +	struct termios orig_i, orig_o; +	struct termios raw_i, raw_o; +	screen_mode_e mode; +} term_screen; + +int term_init( term_screen *ts ); +int term_set_speed( term_screen *ts, speed_t speed); +int term_get_maxcol( term_screen *ts ); +int term_get_maxrow( term_screen *ts ); +int term_cur_get_c( term_screen *ts ); +int term_cur_get_r( term_screen *ts ); +int term_cur_set_c( term_screen *ts, unsigned int pc ); +int term_cur_set_r( term_screen *ts, unsigned int pr ); +int term_cur_set_cr( term_screen *ts, unsigned int pc , unsigned int pr ); +int term_clr_scr( term_screen *ts ); +int term_set_raw_mode( term_screen *ts ); +int term_mode_rows( term_screen *ts ); +int term_mode_columns( term_screen *ts ); +void term_set_orig_mode( term_screen *ts ); + +#endif diff --git a/libterm/term_gui.h b/libterm/term_gui.h new file mode 100644 index 0000000..408382e --- /dev/null +++ b/libterm/term_gui.h @@ -0,0 +1,24 @@ +#ifndef __LIBTERM_TERM_GUI_H +#define __LIBTERM_TERM_GUI_H + +#include "term.h" +#include "term_io.h" + +typedef struct term_gui +{ +	term_screen *ts; +	int w; +	int h; +	int abs_x; +	int abs_y; +} term_gui; + +int term_gui_init( term_gui *tg, term_screen *ts ); +int term_set_wh( term_screen *tg, int width, int height ); +int term_gui_input_box( term_gui *ts, int x, int y, int w, int h, char *prompt,  +		char *str, size_t sz ); +int term_gui_draw( term_gui *tg ); +int term_gui_destroy( term_gui *tg ); + + +#endif
\ No newline at end of file diff --git a/libterm/term_io.h b/libterm/term_io.h new file mode 100644 index 0000000..48deb67 --- /dev/null +++ b/libterm/term_io.h @@ -0,0 +1,32 @@ +#ifndef __LIBTERM_PRINT_UTILS_H +#define __LIBTERM_PRINT_UTILS_H + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdint.h> + +#include "screen_modes.h" +#include "term.h" + +#define READLINE_NONE     0 //none +#define READLINE_ALPHA    1 //isalpsha +#define READLINE_TEXT     2 //[a-zA-Z0-9] + ispunct +#define READLINE_HIDDEN   3 //[a-zA-Z] +#define READLINE_NUMBER   4 //[0-9] +#define READLINE_SYMBOL   5 //not yet +#define READLINE_ALPHANUM 6 //not yet + + +int term_fprint( screen_mode_e mode, FILE *f ); +int term_print( term_screen *ts, const char *s, size_t n ); +int term_print_xy( term_screen *ts, const char *buf, size_t size,  +                   int init_column, int init_row); +int term_draw_hline( term_screen *ts, int pc, int pr, int sz, char ch ); +int term_getc( term_screen *ts ); +int64_t term_getb( term_screen *ts ); +int term_putc( term_screen *ts, char c ); +int term_readline( term_screen *ts, char *str, size_t str_size, int flag ); +int term_printf( term_screen *ts, const char *format, ...); + +#endif | 
