Fix #5986 - use RStack in r_cons_push/pop

clean up cons and stack code
extend RStack to have free function
use RStack in r_cons_push/pop
This commit is contained in:
Álvaro Felipe Melchor 2016-10-18 23:15:51 +02:00
parent b7ab1dbc07
commit 44d9048169
4 changed files with 139 additions and 79 deletions

View file

@ -18,6 +18,20 @@ R_LIB_VERSION (r_cons);
static RCons r_cons_instance;
#define I r_cons_instance
//this structure goes into cons_stack when r_cons_push/pop
typedef struct {
char *buf;
int buf_len;
int buf_size;
} RConsStack;
static void cons_stack_free(void *ptr) {
RConsStack *s = (RConsStack *)ptr;
free (s->buf);
free (s);
}
static void break_signal(int sig) {
I.breaked = true;
r_print_set_interrupted (I.breaked);
@ -26,7 +40,7 @@ static void break_signal(int sig) {
}
}
static inline void r_cons_write (const char *buf, int len) {
static inline void r_cons_write(const char *buf, int len) {
#if __WINDOWS__ && !__CYGWIN__
if (I.ansicon) {
(void) write (I.fdout, buf, len);
@ -210,7 +224,7 @@ static void r_cons_pal_null() {
}
}
R_API RCons *r_cons_new () {
R_API RCons *r_cons_new() {
I.refcnt++;
if (I.refcnt != 1) {
return &I;
@ -267,6 +281,7 @@ R_API RCons *r_cons_new () {
I.pager = NULL; /* no pager by default */
I.truecolor = 0;
I.mouse = 0;
I.cons_stack = r_stack_newf (6, cons_stack_free);
r_cons_pal_null ();
r_cons_pal_init (NULL);
r_cons_rgb_init ();
@ -274,7 +289,7 @@ R_API RCons *r_cons_new () {
return &I;
}
R_API RCons *r_cons_free () {
R_API RCons *r_cons_free() {
I.refcnt--;
if (I.refcnt != 0) {
return NULL;
@ -288,6 +303,7 @@ R_API RCons *r_cons_free () {
free (I.buffer);
I.buffer = NULL;
}
r_stack_free (I.cons_stack);
return NULL;
}
@ -330,19 +346,6 @@ R_API int r_cons_eof() {
}
R_API void r_cons_gotoxy(int x, int y) {
#if 0
#if __WINDOWS__
static HANDLE hStdout = NULL;
COORD coord;
coord.X = x;
coord.Y = y;
if (!hStdout)
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
SetConsoleCursorPosition (hStdout, coord);
#else
r_cons_printf ("\x1b[%d;%dH", y, x);
#endif
#endif
r_cons_printf ("\x1b[%d;%dH", y, x);
}
@ -375,9 +378,11 @@ R_API void r_cons_clear_line(int std_err) {
} else {
char white[1024];
memset (&white, ' ', sizeof (white));
if (I.columns<sizeof (white))
white[I.columns-1] = 0;
else white[sizeof (white)-1] = 0; // HACK
if (I.columns < sizeof (white)) {
white[I.columns - 1] = 0;
} else {
white[sizeof (white) - 1] = 0; // HACK
}
fprintf (std_err? stderr: stdout, "\r%s\r", white);
}
#else
@ -397,14 +402,13 @@ R_API void r_cons_reset_colors() {
R_API void r_cons_clear() {
r_cons_strcat (Color_RESET"\x1b[2J");
//r_cons_gotoxy (0, 0);
// r_cons_flush ();
I.lines = 0;
}
R_API void r_cons_reset() {
if (I.buffer)
if (I.buffer) {
I.buffer[0] = '\0';
}
I.buffer_len = 0;
I.lines = 0;
I.lastline = I.buffer;
@ -414,6 +418,8 @@ R_API void r_cons_reset() {
I.grep.str = NULL;
memset (I.grep.tokens, 0, R_CONS_GREP_TOKENS);
I.grep.tokens_used = 0;
r_stack_free (I.cons_stack);
I.cons_stack = r_stack_newf (6, cons_stack_free);
}
R_API const char *r_cons_get_buffer() {
@ -429,35 +435,37 @@ R_API void r_cons_filter() {
/* TODO */
}
static char *backup = NULL;
static int backup_len = 0;
static int backup_size = 0;
// XXX this must be a stack
R_API void r_cons_push() {
if (!backup) {
if (I.buffer_len < 1) {
I.buffer_len = 1;
}
backup = I.buffer; //malloc (I.buffer_len);
backup_len = I.buffer_len;
backup_size = I.buffer_sz;
I.buffer = malloc (I.buffer_sz);
if (!I.buffer) {
if (I.cons_stack) {
RConsStack *data = R_NEW0 (RConsStack);
data->buf = malloc (I.buffer_len);
if (!data->buf) {
free (data);
return;
}
memcpy (I.buffer, backup, I.buffer_len);
memcpy (data->buf, I.buffer, I.buffer_len);
data->buf_len = I.buffer_len;
data->buf_size = I.buffer_sz;
r_stack_push (I.cons_stack, data);
I.buffer_len = 0;
}
}
R_API void r_cons_pop() {
if (backup) {
free (I.buffer);
I.buffer = backup;
I.buffer_len = backup_len;
I.buffer_sz = backup_size;
backup = NULL;
if (I.cons_stack) {
RConsStack *data = (RConsStack *)r_stack_pop (I.cons_stack);
if (!data) {
return;
}
if (!data->buf) {
free (data);
return;
}
memcpy (I.buffer, data->buf, data->buf_len);
I.buffer_len = data->buf_len;
I.buffer_sz = data->buf_size;
cons_stack_free ((void *)data);
}
}
@ -482,11 +490,12 @@ R_API void r_cons_flush() {
} else if (I.buffer_len > CONS_MAX_USER) {
#if COUNT_LINES
int i, lines = 0;
for (i=0; I.buffer[i]; i++) {
if (I.buffer[i]=='\n')
for (i = 0; I.buffer[i]; i++) {
if (I.buffer[i]=='\n') {
lines ++;
}
}
if (lines>0 && !r_cons_yesno ('n',"Do you want to print %d lines? (y/N)", lines)) {
if (lines > 0 && !r_cons_yesno ('n',"Do you want to print %d lines? (y/N)", lines)) {
r_cons_reset ();
return;
}
@ -504,16 +513,21 @@ R_API void r_cons_flush() {
}
if (tee && *tee) {
FILE *d = r_sandbox_fopen (tee, "a+");
if (d != NULL) {
if (d) {
if (I.buffer_len != fwrite (I.buffer, 1, I.buffer_len, d))
eprintf ("r_cons_flush: fwrite: error (%s)\n", tee);
fclose (d);
} else eprintf ("Cannot write on '%s'\n", tee);
} else {
eprintf ("Cannot write on '%s'\n", tee);
}
}
r_cons_highlight (I.highlight);
// is_html must be a filter, not a write endpoint
if (I.is_html) r_cons_html_print (I.buffer);
else r_cons_write (I.buffer, I.buffer_len);
if (I.is_html) {
r_cons_html_print (I.buffer);
} else {
r_cons_write (I.buffer, I.buffer_len);
}
r_cons_reset ();
if (I.newline) {
@ -549,7 +563,9 @@ R_API void r_cons_visual_flush() {
ut64 diff = now-prev;
fps = (diff<1000000)? (1000000/diff): 0;
prev = now;
} else prev = r_sys_now ();
} else {
prev = r_sys_now ();
}
eprintf ("\x1b[0;%dH[%d FPS] \n", w-10, fps);
}
}
@ -571,7 +587,9 @@ R_API void r_cons_visual_write (char *buffer) {
const char *endptr;
char *nl, *ptr = buffer, *pptr;
if (I.null) return;
if (I.null) {
return;
}
memset (&white, ' ', sizeof (white));
while ((nl = strchr (ptr, '\n'))) {
int len = ((int)(size_t)(nl-ptr))+1;
@ -598,9 +616,10 @@ R_API void r_cons_visual_write (char *buffer) {
if (lines > 0) {
int w = cols - alen;
r_cons_write (pptr, plen);
if (I.blankline && w>0) {
if (w > sizeof (white) - 1)
if (I.blankline && w > 0) {
if (w > sizeof (white) - 1) {
w = sizeof (white) - 1;
}
r_cons_write (white, w);
}
}
@ -628,7 +647,9 @@ R_API void r_cons_printf(const char *format, ...) {
size_t size, written;
va_list ap;
if (I.null || !format) return;
if (I.null || !format) {
return;
}
if (strchr (format, '%')) {
palloc (MOAR + strlen (format) * 20);
size = I.buffer_sz - I.buffer_len - 1; /* remaining space in I.buffer */
@ -649,7 +670,9 @@ R_API void r_cons_printf(const char *format, ...) {
R_API int r_cons_get_column() {
char *line = strrchr (I.buffer, '\n');
if (!line) line = I.buffer;
if (!line) {
line = I.buffer;
}
I.buffer[I.buffer_len] = 0;
return r_str_ansi_len (line);
}
@ -712,10 +735,10 @@ R_API int r_cons_get_cursor(int *rows) {
if (ch2 == '\\') {
i++;
} else if (ch2 == ']') {
if (!strncmp (str+2+5, "rgb:", 4))
if (!strncmp (str + 2 + 5, "rgb:", 4))
i += 18;
} else if (ch2 == '[') {
for (++i; str[i]&&str[i]!='J'&& str[i]!='m'&&str[i]!='H';i++);
for (++i; str[i] && str[i] != 'J' && str[i] != 'm' && str[i] != 'H'; i++);
}
} else if (I.buffer[i] == '\n') {
row++;
@ -742,7 +765,7 @@ R_API bool r_cons_isatty() {
if (ioctl (1, TIOCGWINSZ, &win)) {
return false;
}
if ((win.ws_col == 0) || (win.ws_row == 0)) {
if (!win.ws_col || !win.ws_row) {
return false;
}
tty = ttyname (1);
@ -771,13 +794,13 @@ R_API int r_cons_get_size(int *rows) {
I.rows = 23;
#elif __UNIX__ || __CYGWIN__
struct winsize win = { 0 };
if (isatty (0) && ioctl (0, TIOCGWINSZ, &win) == 0) {
if ((win.ws_col == 0) || (win.ws_row == 0)) {
if (isatty (0) && !ioctl (0, TIOCGWINSZ, &win)) {
if ((!win.ws_col) || (!win.ws_row)) {
const char *tty = ttyname (1);
int fd = open (tty? tty: "/dev/tty", O_RDONLY);
if (fd != -1) {
int ret = ioctl (fd, TIOCGWINSZ, &win);
if ((ret != 0) || (win.ws_col == 0) || (win.ws_row == 0)) {
if (ret || !win.ws_col || !win.ws_row) {
win.ws_col = 80;
win.ws_row = 23;
}
@ -816,12 +839,21 @@ R_API int r_cons_get_size(int *rows) {
if (I.columns < 0) {
I.columns = 0;
}
if (I.force_columns) I.columns = I.force_columns;
if (I.force_rows) I.rows = I.force_rows;
if (I.fix_columns) I.columns += I.fix_columns;
if (I.fix_rows) I.rows += I.fix_rows;
if (rows)
if (I.force_columns) {
I.columns = I.force_columns;
}
if (I.force_rows) {
I.rows = I.force_rows;
}
if (I.fix_columns) {
I.columns += I.fix_columns;
}
if (I.fix_rows) {
I.rows += I.fix_rows;
}
if (rows) {
*rows = I.rows;
}
I.rows = R_MAX (0, I.rows);
return R_MAX (0, I.columns);
}
@ -925,7 +957,9 @@ R_API void r_cons_set_cup(int enable) {
R_API void r_cons_column(int c) {
char *b = malloc (I.buffer_len+1);
if (!b) return;
if (!b) {
return;
}
memcpy (b, I.buffer, I.buffer_len);
b[I.buffer_len] = 0;
r_cons_reset ();
@ -1011,7 +1045,7 @@ R_API void r_cons_highlight (const char *word) {
R_API char *r_cons_lastline () {
char *b = I.buffer+I.buffer_len;
while (b >I.buffer) {
if (*b=='\n') {
if (*b == '\n') {
b++;
break;
}
@ -1048,16 +1082,19 @@ R_API bool r_cons_drop (int n) {
}
R_API void r_cons_chop () {
while (I.buffer_len>0) {
while (I.buffer_len > 0) {
char ch = I.buffer[I.buffer_len-1];
if (ch != '\n' && !IS_WHITESPACE (ch))
if (ch != '\n' && !IS_WHITESPACE (ch)) {
break;
}
I.buffer_len--;
}
}
R_API void r_cons_bind(RConsBind *bind) {
if (!bind) return;
if (!bind) {
return;
}
bind->get_size = r_cons_get_size;
bind->get_cursor = r_cons_get_cursor;
}

View file

@ -165,6 +165,7 @@ r_cons_click_clear();
typedef struct r_cons_t {
RConsGrep grep;
RStack *cons_stack;
char *buffer;
//int line;
int buffer_len;

View file

@ -1,14 +1,18 @@
#ifndef R_STACK_H
#define R_STACK_H
typedef void (*RStackFree)(void *ptr);
typedef struct r_stack_t {
void **elems;
unsigned int n_elems;
int top;
RStackFree free;
} RStack;
R_API RStack *r_stack_new(unsigned int n);
R_API RStack *r_stack_new(ut32 n);
R_API void r_stack_free(RStack *s);
R_API RStack *r_stack_newf(ut32 n, RStackFree f);
R_API int r_stack_push(RStack *s, void *el);
R_API void *r_stack_pop(RStack *s);
R_API int r_stack_is_empty(RStack *s);

View file

@ -2,23 +2,40 @@
#include <r_util.h>
R_API RStack *r_stack_new(unsigned int n) {
R_API RStack *r_stack_new(ut32 n) {
RStack *s = R_NEW0 (RStack);
if (!s) return NULL;
if (!s) {
return NULL;
}
s->elems = R_NEWS0 (void *, n);
if (!s->elems) {
free (s);
return NULL;
}
s->n_elems = n;
s->top = -1;
return s;
}
R_API RStack *r_stack_newf(ut32 n, RStackFree f) {
RStack *s = r_stack_new (n);
if (s) {
s->free = f;
}
return s;
}
R_API void r_stack_free(RStack *s) {
free (s->elems);
free (s);
if (s) {
if (s->free && s->top > 0) {
int i = 0;
for (i = 0; i < s->top; i++) {
s->free (s->elems[i]);
}
}
free (s->elems);
free (s);
}
}
R_API int r_stack_push(RStack *s, void *el) {
@ -35,11 +52,12 @@ R_API int r_stack_push(RStack *s, void *el) {
return true;
}
//the caller should be take care of the object returned
R_API void *r_stack_pop(RStack *s) {
void *res;
if (s->top == -1)
if (s->top == -1) {
return NULL;
}
res = s->elems[s->top];
s->top--;
return res;