summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreeArtMan <dos21h@gmail.com>2016-05-10 22:42:11 +0100
committerFreeArtMan <dos21h@gmail.com>2016-05-10 22:42:11 +0100
commit44dedb90f005bb0de9bddbd592a5c78f28bc67d1 (patch)
tree274b9cea44df3f96a965c564e26cdac42d3af94f
parentbb426577c85f6d97cc28ab677e98e2b1f73eadac (diff)
downloadihe-44dedb90f005bb0de9bddbd592a5c78f28bc67d1.tar.gz
ihe-44dedb90f005bb0de9bddbd592a5c78f28bc67d1.zip
Replace cmd first part
-rw-r--r--Makefile8
-rw-r--r--cmd.c168
-rw-r--r--cmd.h33
-rw-r--r--core.c71
-rw-r--r--core.h21
-rw-r--r--ihe.c558
-rw-r--r--ihe.h8
-rw-r--r--libcmd/Makefile43
-rw-r--r--libcmd/cmd.c544
-rw-r--r--libcmd/cmd.h85
-rw-r--r--libcmd/cmd_parse.c309
-rw-r--r--libcmd/cmd_parse.h8
-rw-r--r--libcmd/cmd_parse.ragel86
-rw-r--r--libcmd/debug.h69
-rw-r--r--libcmd/queue.h533
-rw-r--r--libterm/debug.h69
-rw-r--r--libterm/screen_modes.h15
-rw-r--r--libterm/term.h70
-rw-r--r--libterm/term_gui.h24
-rw-r--r--libterm/term_io.h32
20 files changed, 2481 insertions, 273 deletions
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;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;
-}
-
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 <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
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 <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
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;(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
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 <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