* Fix lot of bugs with cons+grep for @@=`` or stuff like that

* The grepping algorithm in r_cons has been rewritten from scratch
  - Grepped at memcat() which is the root entrypoint for console IO
  - Faster than before (200 less LOC)
  - Not yet working at all, but it is quite better than before
* Fix history bug when using @@
* Use return value of filtercmd function to not invoke children core_cmd
* Fix some random segfaults
This commit is contained in:
pancake 2009-03-21 22:59:35 +00:00
parent 692cefa68b
commit 448d76a5e7
3 changed files with 144 additions and 208 deletions

4
TODO
View File

@ -1,7 +1,3 @@
* BUG: r_core_cmd_str doesnt works with grep strings because
uses the get_buffer method. we have to refactor r_cons to
filter strings at runtime instead of doing it at flush()
* Add maxrows option for r_print (fix visual problem)
* Drop #if conditionals to use #ifdef ones
- fits better with plan9 compiler

View File

@ -34,6 +34,7 @@ FILE *r_cons_stdin_fd = NULL; // TODO use int fd here too!
static int r_cons_buffer_sz = 0;
static int r_cons_buffer_len = 0;
static char *r_cons_buffer = NULL;
static char *r_cons_lastline = NULL;
char *r_cons_filterline = NULL;
char *r_cons_teefile = NULL;
int r_cons_is_html = 0;
@ -171,6 +172,11 @@ void r_cons_reset()
r_cons_buffer[0] = '\0';
r_cons_buffer_len = 0;
r_cons_lines = 0;
r_cons_lastline = r_cons_buffer;
grepstrings_n = 0; // XXX
grepline = -1;
grepstr = NULL;
greptoken = -1;
}
const char *r_cons_get_buffer()
@ -180,6 +186,7 @@ const char *r_cons_get_buffer()
void r_cons_grep(const char *str)
{
char *optr, *tptr;
char *ptr, *ptr2, *ptr3;
grepcounter=0;
/* set grep string */
@ -214,10 +221,10 @@ void r_cons_grep(const char *str)
free(grepstr);
grepstr = (char *)strdup(ptr);
/* set the rest of words to grep */
grepstrings_n = 0;
{ // TODO: refactor this ugly loop
char *optr = grepstr;
char *tptr = strchr(optr, '!');
grepstrings_n = 0;
// TODO: refactor this ugly loop
optr = grepstr;
tptr = strchr(optr, '!');
while(tptr) {
tptr[0] = '\0';
// TODO: check if keyword > 64
@ -230,13 +237,11 @@ void r_cons_grep(const char *str)
grepstrings_n++;
ptr = optr;
}
}
} else {
greptoken = -1;
grepline = -1;
//free(grepstr);
grepstr = NULL;
grepstrings_n = 0;
}
}
@ -247,6 +252,7 @@ void r_cons_flush()
char buf[1024];
int i,j;
int lines_counter = 0;
char *tee = r_cons_teefile;
if (r_cons_noflush)
return;
@ -260,9 +266,19 @@ void r_cons_flush()
}
}
if (!STR_IS_NULL(r_cons_buffer)) {
if (tee&&tee[0]) {
FILE *d = fopen(tee, "a+");
if (d != NULL) {
fwrite(r_cons_buffer, strlen(r_cons_buffer), 1, d);
fclose(d);
}
} else write(1, r_cons_buffer, r_cons_buffer_len);
// TODO: make 'write' portable
r_cons_reset();
return;
#if 0
char *file = r_cons_filterline;
char *tee = r_cons_teefile;
if (!STR_IS_NULL(file)) {
fd = fopen(file, "r");
if (fd) {
@ -282,166 +298,12 @@ void r_cons_flush()
fclose(fd);
}
}
#endif
if (tee&&tee[0]) {
FILE *d = fopen(tee, "a+");
if (d != NULL) {
fwrite(r_cons_buffer, strlen(r_cons_buffer),1, d);
fclose(d);
}
}
// XXX merge grepstr with r_cons_lines loop //
r_cons_lines += r_str_nchr(buf, '\n');
// XXX buggy! this needs a major cleanup here!
if (grepstr != NULL) {
int line, len;
char *one = r_cons_buffer;
char *two;
char *ptr, *tok;
char delims[6][2] = {"|", "/", "\\", ",", ";", "\t"};
for(line=0;;) {
two = strchr(one, '\n');
if (two) {
int grepstr_match = 0;
two[0] = '\0';
len = two-one;
// len = strlen(one);
// if (strstr(one, grepstr)) {
for(i=0;i<grepstrings_n;i++) {
grepstr=grepstrings[i];
if ( (!grepneg && strstr(one, grepstr))
|| (grepneg && !strstr(one, grepstr))) {
grepstr_match=1;
break;
}
}
if (grepstr_match) {
if (grepline ==-1 || grepline==line) {
if (greptoken != -1) {
ptr = alloca(len+1);
strcpy(ptr, one);
for (i=0; i<len; i++)
for (j=0;j<6;j++)
if (ptr[i] == delims[j][0])
ptr[i] = ' ';
tok = ptr;
if (greptoken<0) {
int i, idx = greptoken+1;
for(i = 0;ptr[i]; i++) {
if (ptr[i]==' ')
idx++;
if (idx == 0) {
ptr = ptr +i;
r_cons_buffer_len = strlen(ptr);
break;
}
}
} else {
for (i=0;tok != NULL && i<=greptoken;i++) {
if (i==0)
tok = (char *)strtok(ptr, " ");
else tok = (char *)strtok(NULL, " ");
}
}
if (tok) {
ptr = tok;
r_cons_buffer_len=strlen(tok);
}
} else {
ptr = one;
r_cons_buffer_len=len;
}
if (grepcounter==0) {
r_cons_print_real(ptr);
r_cons_buffer_len=1;
r_cons_print_real("\n");
} else lines_counter++;
}
line++;
}
two[0] = '\n';
one = two + 1;
} else break;
}
} else {
if (grepline != -1 || grepcounter || greptoken != -1) {
int len, line;
char *one = r_cons_buffer;
char *two;
char *ptr, *tok;
char delims[6][2] = {"|", "/", "\\", ",", ";", "\t"};
for(line=0;;line++) {
two = strchr(one, '\n');
if (two) {
two[0] = '\0';
len=two-one;
if (grepline ==-1 || grepline==line) {
if (greptoken != -1) {
ptr = alloca(len+1);
strcpy(ptr, one);
for (i=0; i<len; i++)
for (j=0;j<6;j++)
if (ptr[i] == delims[j][0])
ptr[i] = ' ';
tok = ptr;
if (greptoken<0) {
int i, idx = greptoken+1;
for(i = 0;ptr[i]; i++) {
if (ptr[i]==' ')
idx++;
if (idx == 0) {
ptr = ptr +i;
r_cons_buffer_len = strlen(ptr);
break;
}
}
} else {
for (i=0;tok != NULL && i<=greptoken;i++) {
if (i==0)
tok = (char *)strtok(ptr, " ");
else tok = (char *)strtok(NULL," ");
}
}
if (tok) {
ptr = tok;
r_cons_buffer_len=strlen(tok);
}
} else {
ptr = one;
r_cons_buffer_len=len;
}
if (grepcounter==0) {
r_cons_print_real(ptr);
r_cons_buffer_len=1;
r_cons_print_real("\n");
} else lines_counter++;
}
two[0] = '\n';
one = two + 1;
} else break;
}
} else r_cons_print_real(r_cons_buffer);
}
r_cons_buffer[0] = '\0';
}
if (grepcounter) {
char buf[32];
sprintf(buf, "%d\n", lines_counter);
r_cons_buffer_len = strlen(buf);
r_cons_print_real(buf);
}
r_cons_buffer_len = 0;
}
#if 0
// UNUSED
/* stream is ignored */
void r_cons_fprintf(FILE *stream, const char *format, ...)
{
@ -462,6 +324,7 @@ void r_cons_fprintf(FILE *stream, const char *format, ...)
va_end(ap);
}
#endif
void r_cons_printf(const char *format, ...)
{
@ -477,21 +340,90 @@ void r_cons_printf(const char *format, ...)
va_start(ap, format);
len = vsnprintf(buf, CONS_BUFSZ-1, format, ap);
if (len>0) {
palloc(len);
// r_cons_lines += r_cons_lines_count(buf);
memcpy(r_cons_buffer+r_cons_buffer_len, buf, len+1);
r_cons_buffer_len += len;
}
if (len>0)
r_cons_memcat(buf, len);
va_end(ap);
}
int r_cons_grepbuf(const char *buf, int len)
{
int donotline = 0;
int i, j, hit = 0;
char delims[6][2] = {"|", "/", "\\", ",", ";", "\t"};
char *n = memchr(buf, '\n', len);
if (grepstrings_n==0) {
if (n) r_cons_lines++;
return len;
}
if (r_cons_lastline==NULL)
r_cons_lastline = r_cons_buffer;
if (!n) return len;
for(i=0;i<grepstrings_n;i++) {
grepstr = grepstrings[i];
if ( (!grepneg && strstr(buf, grepstr))
|| (grepneg && !strstr(buf, grepstr))) {
hit = 1;
break;
}
}
if (hit) {
if (grepline != -1) {
if (grepline==r_cons_lines) {
r_cons_lastline = buf+len;
//r_cons_lines++;
} else {
donotline = 1;
r_cons_lines++;
}
}
} else donotline = 1;
if (donotline) {
r_cons_buffer_len -= strlen(r_cons_lastline)-len;
r_cons_lastline[0]='\0';
len = 0;
} else {
if (greptoken != -1) {
//ptr = alloca(strlen(r_cons_lastline));
char *tok = NULL;
char *ptr = alloca(1024); // XXX
strcpy(ptr, r_cons_lastline);
for (i=0; i<len; i++) for (j=0;j<6;j++)
if (ptr[i] == delims[j][0])
ptr[i] = ' ';
tok = ptr;
for (i=0;tok != NULL && i<=greptoken;i++) {
if (i==0) tok = (char *)strtok(ptr, " ");
else tok = (char *)strtok(NULL, " ");
}
if (tok) {
// XXX remove strlen here!
r_cons_buffer_len -= strlen(r_cons_lastline)-len;
len = strlen(tok);
memcpy(r_cons_lastline, tok, len);
if (r_cons_lastline[len-1]!='\n')
memcpy(r_cons_lastline+len, "\n", 2);
len++;
r_cons_lastline +=len;
}
} else r_cons_lastline = buf+len;
r_cons_lines++;
}
return len;
}
/* final entrypoint for adding stuff in the buffer screen */
void r_cons_memcat(const char *str, int len)
{
palloc(len);
memcpy(r_cons_buffer+r_cons_buffer_len, str, len+1);
r_cons_buffer_len += len;
memcpy(r_cons_buffer+r_cons_buffer_len, str, len+1); // XXX +1??
r_cons_buffer_len += r_cons_grepbuf(r_cons_buffer+r_cons_buffer_len, len);
}
void r_cons_strcat(const char *str)

View File

@ -788,7 +788,8 @@ static int cmd_eval(void *data, const char *input)
r_config_list(&core->config, NULL, 0);
break;
case '-':
r_config_init(&core->config, core);
r_core_config_init(core);
eprintf("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
break;
case '*':
r_config_list(&core->config, NULL, 1);
@ -1027,23 +1028,6 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd, int *rs, int *rfd,
for(str=ptr+1; str[0]== ' '; str=str+1);
*rfd = r_cons_pipe_open(str, ptr[1]=='>');
}
ptr = strchr(cmd, '@');
if (ptr) {
char *pt = ptr;
ptr[0]='\0';
while(pt[0]==' '||pt[0]=='\t') {
pt[0]='\0';
pt = pt-1;
}
*rs = 1;
if (ptr[1]=='@') {
// TODO: remove temporally seek (should be done by cmd_foreach)
u64 tmpoff = core->seek;
r_core_cmd_foreach(core, cmd, ptr+2);
r_core_seek(core, tmpoff);
return 0;
} else r_core_seek(core, r_num_math(&core->num, ptr+1));
}
while(((ptr = strchr(cmd, '`')))) {
ptr2 = strchr(ptr+1, '`');
@ -1058,6 +1042,30 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd, int *rs, int *rfd,
free(str);
}
ptr = strchr(cmd, '~');
if (ptr) {
ptr[0]='\0';
r_cons_grep(ptr+1);
} else r_cons_grep(NULL);
ptr = strchr(cmd, '@');
if (ptr) {
char *pt = ptr;
ptr[0]='\0';
while(pt[0]==' '||pt[0]=='\t') {
pt[0]='\0';
pt = pt-1;
}
*rs = 1;
if (ptr[1]=='@') {
// TODO: remove temporally seek (should be done by cmd_foreach)
u64 tmpoff = core->seek;
r_core_cmd_foreach(core, cmd, ptr+2);
r_core_seek(core, tmpoff);
return -1; /* do not run out-of-foreach cmd */
} else r_core_seek(core, r_num_math(&core->num, ptr+1));
}
return 0;
}
@ -1067,7 +1075,7 @@ int r_core_cmd_foreach(struct r_core_t *core, const char *cmd, char *each)
int i=0,j;
char ch;
char *word = NULL;
char *str;
char *str, *ostr;
struct list_head *pos;
u64 oseek, addr;
@ -1075,7 +1083,7 @@ int r_core_cmd_foreach(struct r_core_t *core, const char *cmd, char *each)
for(;*cmd==' ';cmd=cmd+1);
oseek = core->seek;
str = strdup(each);
ostr = str = strdup(each);
//radare_controlc();
switch(each[0]) {
@ -1089,19 +1097,21 @@ int r_core_cmd_foreach(struct r_core_t *core, const char *cmd, char *each)
break;
case '=':
/* foreach list of items */
each = each+1;
each = str+1;
do {
while(each[0]==' ') each=each+1;
if (!*each) break;
str = strchr(each, ' ');
if (str) {
str[0]='\0';
addr = r_num_math(&core->num, each);
str[0]=' ';
} else addr = r_num_math(&core->num, each);
eprintf("; 0x%08llx:\n", addr);
each = str+1;
r_core_seek(core, addr);
eprintf("\n"); //eprintf("===(%s)at(0x%08llx)\n", cmd, addr);
r_core_cmd(core, cmd, 0);
r_cons_flush();
} while(str != NULL);
break;
case '.':
@ -1218,7 +1228,7 @@ printf("No flags foreach implemented\n");
free(word);
word = NULL;
free(str);
free(ostr);
}
int r_core_cmd(struct r_core_t *core, const char *command, int log)
@ -1255,10 +1265,7 @@ int r_core_cmd(struct r_core_t *core, const char *command, int log)
}
ret = r_core_cmd_subst(core, cmd, &restoreseek, &newfd, &times);
if (ret == -1) {
fprintf(stderr, "Invalid conversion: '%s'\n", command);
ret = -1;
} else {
if (ret != -1) {
for(i=0;i<times;i++) {
if (quoted) {
ret = r_cmd_call(&core->cmd, cmd);
@ -1286,9 +1293,10 @@ int r_core_cmd(struct r_core_t *core, const char *command, int log)
ret = 1;
} else
if (log) r_line_hist_add(command);
if (restoreseek)
r_core_seek(core, tmpseek);
}
if (log) r_line_hist_add(command);
if (restoreseek)
r_core_seek(core, tmpseek);
if (newfd != 1) {
r_cons_flush();
@ -1299,7 +1307,7 @@ int r_core_cmd(struct r_core_t *core, const char *command, int log)
core->oobi = NULL;
core->oobi_len = 0;
return ret;
return 0;
}
int r_core_cmd_file(struct r_core_t *core, const char *file)