2020-01-19 07:40:21 +01:00
|
|
|
/* radare - LGPL - Copyright 2009-2020 - pancake, nibble */
|
2009-02-05 22:08:46 +01:00
|
|
|
|
|
|
|
#include <r_cons.h>
|
2018-11-14 13:47:43 +01:00
|
|
|
#include <r_util/r_print.h>
|
2017-01-18 13:46:39 +01:00
|
|
|
#include <sdb.h>
|
2014-11-22 01:51:51 +01:00
|
|
|
|
2017-03-18 23:59:34 +01:00
|
|
|
#define I(x) r_cons_singleton ()->x
|
2017-09-12 02:05:24 -07:00
|
|
|
|
2017-11-04 12:57:12 +01:00
|
|
|
static char *strchr_ns (char *s, const char ch) {
|
|
|
|
char *p = strchr (s, ch);
|
|
|
|
if (p && p > s) {
|
|
|
|
char *prev = p - 1;
|
|
|
|
if (*prev == '\\') {
|
|
|
|
memmove (prev, p, strlen (p) + 1);
|
|
|
|
return strchr_ns (p, ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2017-09-12 02:05:24 -07:00
|
|
|
static const char *help_detail_tilde[] = {
|
|
|
|
"Usage: [command]~[modifier][word,word][endmodifier][[column]][:line]\n"
|
|
|
|
"modifier:", "", "",
|
|
|
|
" &", "", "all words must match to grep the line",
|
|
|
|
" $[n]", "", "sort numerically / alphabetically the Nth column",
|
2017-10-02 13:07:53 +03:00
|
|
|
" $!", "", "sort in inverse order",
|
2019-01-13 12:49:41 +01:00
|
|
|
" ,", "", "token to define another keyword",
|
2017-09-12 02:05:24 -07:00
|
|
|
" +", "", "case insensitive grep (grep -i)",
|
|
|
|
" ^", "", "words must be placed at the beginning of line",
|
2019-01-13 12:49:41 +01:00
|
|
|
" <", "", "perform zoom operation on the buffer",
|
2017-09-12 02:05:24 -07:00
|
|
|
" !", "", "negate grep",
|
|
|
|
" ?", "", "count number of matching lines",
|
|
|
|
" ?.", "", "count number chars",
|
|
|
|
" ??", "", "show this help message",
|
2018-07-16 18:59:20 +02:00
|
|
|
" :s..e", "", "show lines s-e",
|
2017-09-12 02:05:24 -07:00
|
|
|
" ..", "", "internal 'less'",
|
|
|
|
" ...", "", "internal 'hud' (like V_)",
|
2019-07-11 00:46:53 +02:00
|
|
|
" {:", "", "human friendly indentation (yes, it's a smiley)",
|
|
|
|
" {:..", "", "less the output of {:",
|
|
|
|
" {:...", "", "hud the output of {:",
|
2017-09-12 02:05:24 -07:00
|
|
|
" {}", "", "json indentation",
|
|
|
|
" {}..", "", "less json indentation",
|
2019-07-11 00:46:53 +02:00
|
|
|
" {}...", "", "hud json indentation",
|
|
|
|
" {path}", "", "json path grep",
|
2017-09-12 02:05:24 -07:00
|
|
|
"endmodifier:", "", "",
|
|
|
|
" $", "", "words must be placed at the end of line",
|
|
|
|
"column:", "", "",
|
|
|
|
" [n]", "", "show only column n",
|
|
|
|
" [n-m]", "", "show column n to m",
|
|
|
|
" [n-]", "", "show all columns starting from column n",
|
|
|
|
" [i,j,k]", "", "show the columns i, j and k",
|
|
|
|
"Examples:", "", "",
|
|
|
|
" i~:0", "", "show first line of 'i' output",
|
2018-07-16 18:59:20 +02:00
|
|
|
" i~:-2", "", "show the second to last line of 'i' output",
|
|
|
|
" i~:0..3", "", "show first three lines of 'i' output",
|
2017-09-12 02:05:24 -07:00
|
|
|
" pd~mov", "", "disasm and grep for mov",
|
|
|
|
" pi~[0]", "", "show only opcode",
|
|
|
|
" i~0x400$", "", "show lines ending with 0x400",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2016-10-25 12:39:36 +02:00
|
|
|
/* TODO: remove globals */
|
2016-10-25 12:03:55 +02:00
|
|
|
static RList *sorted_lines = NULL;
|
2016-10-25 14:37:25 +02:00
|
|
|
static RList *unsorted_lines = NULL;
|
2016-10-25 12:03:55 +02:00
|
|
|
static int sorted_column = -1;
|
|
|
|
|
2017-09-12 02:05:24 -07:00
|
|
|
R_API void r_cons_grep_help(void) {
|
|
|
|
r_cons_cmd_help (help_detail_tilde, true);
|
2012-08-09 18:19:00 +02:00
|
|
|
}
|
|
|
|
|
2014-04-23 01:57:14 +04:00
|
|
|
#define R_CONS_GREP_BUFSIZE 4096
|
|
|
|
|
2017-06-10 13:39:04 +03:00
|
|
|
static void parse_grep_expression(const char *str) {
|
2017-01-17 13:38:42 +01:00
|
|
|
static char buf[R_CONS_GREP_BUFSIZE];
|
2015-09-23 23:00:14 +02:00
|
|
|
int wlen, len, is_range, num_is_parsed, fail = 0;
|
2018-07-15 14:43:16 +02:00
|
|
|
char *ptr, *optr, *ptr2, *ptr3, *end_ptr = NULL, last;
|
2015-09-23 23:00:14 +02:00
|
|
|
ut64 range_begin, range_end;
|
2012-08-04 00:46:00 +02:00
|
|
|
|
2016-08-28 17:35:28 +02:00
|
|
|
if (!str || !*str) {
|
2012-08-08 10:56:25 +02:00
|
|
|
return;
|
2016-08-28 17:35:28 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
RCons *cons = r_cons_singleton ();
|
|
|
|
RConsGrep *grep = &cons->context->grep;
|
2016-10-25 12:39:36 +02:00
|
|
|
sorted_column = 0;
|
2017-05-29 02:52:53 +02:00
|
|
|
bool first = true;
|
2012-08-09 18:19:00 +02:00
|
|
|
while (*str) {
|
|
|
|
switch (*str) {
|
2014-02-11 02:32:37 +01:00
|
|
|
case '.':
|
2015-09-23 23:00:14 +02:00
|
|
|
if (str[1] == '.') {
|
2017-01-17 13:12:27 +01:00
|
|
|
if (str[2] == '.') {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->less = 2;
|
2017-01-17 13:12:27 +01:00
|
|
|
} else {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->less = 1;
|
2017-01-17 13:12:27 +01:00
|
|
|
}
|
2014-02-11 02:32:37 +01:00
|
|
|
return;
|
|
|
|
}
|
2014-03-10 14:19:29 +01:00
|
|
|
str++;
|
2014-02-11 02:32:37 +01:00
|
|
|
break;
|
2014-11-22 01:51:51 +01:00
|
|
|
case '{':
|
2019-07-11 00:46:53 +02:00
|
|
|
if (str[1] == ':') {
|
|
|
|
grep->human = true; // human friendly indentation ij~{:
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->json = 1;
|
2019-07-11 00:46:53 +02:00
|
|
|
if (!strncmp (str, "{:...", 5)) {
|
|
|
|
grep->hud = true;
|
|
|
|
} else if (!strncmp (str, "{:..", 4)) {
|
|
|
|
grep->less = 1;
|
|
|
|
}
|
|
|
|
} else if (str[1] == '}') {
|
|
|
|
// standard json indentation
|
|
|
|
grep->json = 1;
|
|
|
|
if (!strncmp (str, "{}...", 5)) {
|
|
|
|
grep->hud = true;
|
|
|
|
} else if (!strncmp (str, "{}..", 4)) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->less = 1;
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2017-01-17 13:12:27 +01:00
|
|
|
} else {
|
2017-01-17 13:38:42 +01:00
|
|
|
char *jsonPath = strdup (str + 1);
|
|
|
|
char *jsonPathEnd = strchr (jsonPath, '}');
|
|
|
|
if (jsonPathEnd) {
|
|
|
|
*jsonPathEnd = 0;
|
2018-06-23 12:10:13 +02:00
|
|
|
free (grep->json_path);
|
|
|
|
grep->json_path = jsonPath;
|
|
|
|
grep->json = 1;
|
2017-10-05 12:44:56 +02:00
|
|
|
} else {
|
|
|
|
free (jsonPath);
|
2017-01-17 13:38:42 +01:00
|
|
|
}
|
|
|
|
return;
|
2014-11-22 01:51:51 +01:00
|
|
|
}
|
|
|
|
str++;
|
|
|
|
break;
|
2016-10-25 12:03:55 +02:00
|
|
|
case '$':
|
|
|
|
str++;
|
2016-10-25 12:39:36 +02:00
|
|
|
if (*str == '!') {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->sort_invert = true;
|
2016-10-25 12:39:36 +02:00
|
|
|
str++;
|
|
|
|
} else {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->sort_invert = false;
|
2016-10-25 12:39:36 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->sort = atoi (str);
|
2017-02-06 00:50:54 +03:00
|
|
|
while (IS_DIGIT (*str)) {
|
2016-10-25 12:03:55 +02:00
|
|
|
str++;
|
|
|
|
}
|
2016-10-25 14:37:25 +02:00
|
|
|
if (*str == ':') {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->sort_row = atoi (++str);
|
2016-10-25 14:37:25 +02:00
|
|
|
str++;
|
|
|
|
}
|
2016-10-19 13:10:10 +02:00
|
|
|
break;
|
2016-10-25 12:03:55 +02:00
|
|
|
case '&':
|
|
|
|
str++;
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->amp = 1;
|
2016-10-19 13:10:10 +02:00
|
|
|
break;
|
2019-01-13 12:49:41 +01:00
|
|
|
case '<':
|
|
|
|
grep->zoom = atoi (++str);
|
|
|
|
//grep->zoomy = atoi (arg);
|
|
|
|
break;
|
2017-05-29 02:52:53 +02:00
|
|
|
case '+':
|
|
|
|
if (first) {
|
|
|
|
str++;
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->icase = 1;
|
2018-04-08 12:26:39 +02:00
|
|
|
} else {
|
|
|
|
goto while_end;
|
2017-05-29 02:52:53 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-10-25 12:03:55 +02:00
|
|
|
case '^':
|
|
|
|
str++;
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->begin = 1;
|
2016-10-25 12:03:55 +02:00
|
|
|
break;
|
|
|
|
case '!':
|
|
|
|
str++;
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->neg = 1;
|
2016-10-19 13:10:10 +02:00
|
|
|
break;
|
2016-11-23 12:52:36 +01:00
|
|
|
case '?':
|
|
|
|
str++;
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->counter = 1;
|
2016-11-23 12:52:36 +01:00
|
|
|
if (*str == '.') {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->charCounter = true;
|
2016-11-23 12:52:36 +01:00
|
|
|
str++;
|
|
|
|
} else if (*str == '?') {
|
2017-07-10 01:23:27 +02:00
|
|
|
cons->filter = true;
|
2012-08-09 18:19:00 +02:00
|
|
|
r_cons_grep_help ();
|
2014-01-12 01:34:11 +01:00
|
|
|
return;
|
2012-08-09 18:19:00 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-10-25 12:03:55 +02:00
|
|
|
default:
|
2016-10-19 13:10:10 +02:00
|
|
|
goto while_end;
|
2012-08-09 18:19:00 +02:00
|
|
|
}
|
2017-05-29 02:52:53 +02:00
|
|
|
first = false;
|
2016-10-25 12:03:55 +02:00
|
|
|
}
|
2017-03-18 23:59:34 +01:00
|
|
|
while_end:
|
2012-08-09 18:19:00 +02:00
|
|
|
|
2015-09-23 23:00:14 +02:00
|
|
|
len = strlen (str) - 1;
|
2014-04-23 01:57:14 +04:00
|
|
|
if (len > R_CONS_GREP_BUFSIZE - 1) {
|
2017-03-18 23:59:34 +01:00
|
|
|
eprintf ("r_cons_grep: too long!\n");
|
2014-04-23 01:57:14 +04:00
|
|
|
return;
|
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
if (len > 0 && str[len] == '?') {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->counter = 1;
|
2015-09-23 23:00:14 +02:00
|
|
|
strncpy (buf, str, R_MIN (len, sizeof (buf) - 1));
|
2017-01-17 13:38:42 +01:00
|
|
|
buf[len] = 0;
|
2012-08-04 00:46:00 +02:00
|
|
|
len--;
|
2016-10-19 13:10:10 +02:00
|
|
|
} else {
|
|
|
|
strncpy (buf, str, sizeof (buf) - 1);
|
|
|
|
}
|
2010-07-16 14:53:06 +02:00
|
|
|
|
|
|
|
ptr = buf;
|
2015-09-23 23:00:14 +02:00
|
|
|
ptr2 = strchr (ptr, '[');
|
|
|
|
ptr3 = strchr (ptr, ']');
|
|
|
|
is_range = 0;
|
|
|
|
num_is_parsed = 0;
|
|
|
|
fail = 0;
|
|
|
|
range_begin = range_end = -1;
|
|
|
|
|
2015-10-03 13:54:46 +02:00
|
|
|
if (ptr2 && ptr3) {
|
2018-07-15 14:43:16 +02:00
|
|
|
end_ptr = ptr2;
|
|
|
|
last = ptr3[1];
|
|
|
|
ptr3[1] = '\0';
|
2015-09-23 23:00:14 +02:00
|
|
|
ptr2++;
|
2020-03-05 19:06:59 +01:00
|
|
|
for (; ptr2 <= ptr3; ptr2++) {
|
2015-09-23 23:00:14 +02:00
|
|
|
if (fail) {
|
2018-06-23 12:10:13 +02:00
|
|
|
ZERO_FILL (grep->tokens);
|
|
|
|
grep->tokens_used = 0;
|
2015-09-23 23:00:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (*ptr2) {
|
|
|
|
case '-':
|
|
|
|
is_range = 1;
|
|
|
|
num_is_parsed = 0;
|
2018-01-07 04:00:59 +01:00
|
|
|
range_end = -1;
|
2015-09-23 23:00:14 +02:00
|
|
|
break;
|
|
|
|
case ']': // fallthrough to handle ']' like ','
|
|
|
|
case ',':
|
|
|
|
for (; range_begin <= range_end; range_begin++) {
|
|
|
|
if (range_begin >= R_CONS_GREP_TOKENS) {
|
|
|
|
fail = 1;
|
|
|
|
break;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->tokens[range_begin] = 1;
|
|
|
|
grep->tokens_used = 1;
|
2015-09-23 23:00:14 +02:00
|
|
|
}
|
2018-01-07 04:00:59 +01:00
|
|
|
// case of [n-]
|
|
|
|
if (*ptr2 == ']' && is_range && !num_is_parsed) {
|
|
|
|
num_is_parsed = 1;
|
|
|
|
range_end = -1;
|
|
|
|
} else {
|
|
|
|
is_range = 0;
|
|
|
|
num_is_parsed = 0;
|
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!num_is_parsed) {
|
|
|
|
if (is_range) {
|
|
|
|
range_end = r_num_get (cons->num, ptr2);
|
2018-01-07 04:00:59 +01:00
|
|
|
// check for bad value, if range_end == 0, we check if ptr2 == '0'
|
|
|
|
if (range_end == 0 && *ptr != '0') {
|
|
|
|
range_end = -1; // this allow [n- ]
|
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
} else {
|
|
|
|
range_begin = range_end = r_num_get (cons->num, ptr2);
|
|
|
|
}
|
|
|
|
num_is_parsed = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-15 14:43:16 +02:00
|
|
|
ptr3[1] = last;
|
2010-07-16 14:53:06 +02:00
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
|
2017-11-04 12:57:12 +01:00
|
|
|
ptr2 = strchr_ns (ptr, ':'); // line number
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->range_line = 2; // there is not :
|
2018-07-16 19:52:59 +02:00
|
|
|
if (ptr2 && ptr2[1] != ':' && ptr2[1] && (IS_DIGIT (ptr2[1]) || ptr2[1] == '-' || ptr2[1] == '.')) {
|
2018-07-15 14:43:16 +02:00
|
|
|
end_ptr = end_ptr ? R_MIN (end_ptr, ptr2) : ptr2;
|
2018-07-16 18:51:34 +02:00
|
|
|
char *p, *token = ptr2 + 1;
|
2016-10-19 16:18:04 +02:00
|
|
|
p = strstr (token, "..");
|
|
|
|
if (!p) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->line = r_num_get (cons->num, ptr2 + 1);
|
|
|
|
grep->range_line = 0;
|
2016-10-19 16:18:04 +02:00
|
|
|
} else {
|
|
|
|
*p = '\0';
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->range_line = 1;
|
2017-11-04 12:57:12 +01:00
|
|
|
if (*token) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->f_line = r_num_get (cons->num, token);
|
2017-03-18 23:59:34 +01:00
|
|
|
} else {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->f_line = 0;
|
2017-11-04 12:57:12 +01:00
|
|
|
}
|
|
|
|
if (p[2]) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->l_line = r_num_get (cons->num, p + 2);
|
2017-11-04 12:57:12 +01:00
|
|
|
} else {
|
2019-11-29 11:47:23 +02:00
|
|
|
grep->l_line = 0;
|
2016-10-19 16:18:04 +02:00
|
|
|
}
|
2015-10-22 04:48:56 +02:00
|
|
|
}
|
2010-07-16 14:53:06 +02:00
|
|
|
}
|
2018-07-15 14:43:16 +02:00
|
|
|
if (end_ptr) {
|
|
|
|
*end_ptr = '\0';
|
|
|
|
}
|
2019-01-29 16:29:12 -03:00
|
|
|
|
|
|
|
len = strlen (buf) - 1;
|
|
|
|
if (len > 1 && buf[len] == '$' && buf[len - 1] != '\\') {
|
|
|
|
grep->end = 1;
|
|
|
|
buf[len] = '\0';
|
|
|
|
}
|
|
|
|
|
2018-06-23 12:10:13 +02:00
|
|
|
free (grep->str);
|
2010-07-16 14:53:06 +02:00
|
|
|
if (*ptr) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->str = (char *) strdup (ptr);
|
2010-07-16 14:53:06 +02:00
|
|
|
do {
|
|
|
|
optr = ptr;
|
|
|
|
ptr = strchr (ptr, ','); // grep keywords
|
2016-10-19 13:10:10 +02:00
|
|
|
if (ptr) {
|
|
|
|
*ptr++ = '\0';
|
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
wlen = strlen (optr);
|
2016-10-19 13:10:10 +02:00
|
|
|
if (!wlen) {
|
|
|
|
continue;
|
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
if (wlen >= R_CONS_GREP_WORD_SIZE - 1) {
|
2012-08-09 18:19:00 +02:00
|
|
|
eprintf ("grep string too long\n");
|
|
|
|
continue;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->nstrings++;
|
|
|
|
if (grep->nstrings > R_CONS_GREP_WORDS - 1) {
|
2012-08-09 18:19:00 +02:00
|
|
|
eprintf ("too many grep strings\n");
|
|
|
|
break;
|
|
|
|
}
|
2019-07-31 19:21:13 +02:00
|
|
|
strncpy (grep->strings[grep->nstrings - 1],
|
|
|
|
optr, R_CONS_GREP_WORD_SIZE - 1);
|
2010-07-16 14:53:06 +02:00
|
|
|
} while (ptr);
|
2011-02-05 02:55:50 +01:00
|
|
|
} else {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->str = strdup (ptr);
|
|
|
|
grep->nstrings++;
|
|
|
|
grep->strings[0][0] = 0;
|
2010-01-30 14:02:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-10 13:39:04 +03:00
|
|
|
// Finds and returns next intgerp expression,
|
|
|
|
// unescapes escaped twiddles
|
|
|
|
static char *find_next_intgrep(char *cmd, const char *quotes) {
|
2017-06-12 17:20:28 +02:00
|
|
|
char *p;
|
2017-06-10 13:39:04 +03:00
|
|
|
do {
|
2017-06-12 17:20:28 +02:00
|
|
|
p = (char *)r_str_firstbut (cmd, '~', quotes);
|
|
|
|
if (!p) {
|
|
|
|
break;
|
2017-06-10 13:39:04 +03:00
|
|
|
}
|
|
|
|
if (p == cmd || *(p - 1) != '\\') {
|
|
|
|
return (char*)p;
|
|
|
|
}
|
2017-06-12 17:20:28 +02:00
|
|
|
//twiddle unescape
|
|
|
|
memmove (p - 1, p, strlen(p) + 1);
|
2017-06-10 13:39:04 +03:00
|
|
|
cmd = p + 1;
|
|
|
|
} while (*cmd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Removes grep part from *cmd* and returns newly allocated string
|
|
|
|
* with reshaped grep expression.
|
|
|
|
*
|
|
|
|
* Function converts multiple twiddle expressions into internal representation.
|
|
|
|
* For example:
|
|
|
|
* converts "~str1~str2~str3~?" into "?&str1,str2,str3"
|
|
|
|
*/
|
|
|
|
static char *preprocess_filter_expr(char *cmd, const char *quotes) {
|
|
|
|
char *p1, *p2, *ns = NULL;
|
|
|
|
const char *strsep = "&";
|
|
|
|
int len;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
p1 = find_next_intgrep (cmd, quotes);
|
|
|
|
if (!p1) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = strlen (p1);
|
|
|
|
if (len > 4 && r_str_endswith (p1, "~?") && p1[len - 3] != '\\') {
|
|
|
|
p1[len - 2] = '\0';
|
|
|
|
ns = r_str_append (ns, "?");
|
|
|
|
}
|
|
|
|
|
|
|
|
*p1 = '\0'; // remove grep part from cmd
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
// parse words between '~'
|
2017-06-12 17:20:28 +02:00
|
|
|
while ((p2 = find_next_intgrep (p1 + 1, quotes))) {
|
2017-06-10 13:39:04 +03:00
|
|
|
ns = r_str_append (ns, strsep);
|
|
|
|
ns = r_str_appendlen (ns, p1 + 1, (int)(p2 - p1 - 1));
|
|
|
|
p1 = p2;
|
|
|
|
strsep = ",";
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i > 0) {
|
|
|
|
ns = r_str_append (ns, ",");
|
|
|
|
}
|
|
|
|
|
|
|
|
ns = r_str_append (ns, p1 + 1);
|
|
|
|
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_grep_parsecmd(char *cmd, const char *quotestr) {
|
2018-12-27 06:23:10 +01:00
|
|
|
r_return_if_fail (cmd && quotestr);
|
|
|
|
char *ptr = preprocess_filter_expr (cmd, quotestr);
|
2017-06-10 13:39:04 +03:00
|
|
|
if (ptr) {
|
2018-01-08 03:22:26 +01:00
|
|
|
r_str_trim (cmd);
|
2017-06-10 13:39:04 +03:00
|
|
|
parse_grep_expression (ptr);
|
|
|
|
free (ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-27 06:23:10 +01:00
|
|
|
R_API char *r_cons_grep_strip(char *cmd, const char *quotestr) {
|
2017-12-14 19:06:16 -05:00
|
|
|
char *ptr = NULL;
|
|
|
|
|
|
|
|
if (cmd) {
|
|
|
|
ptr = preprocess_filter_expr (cmd, quotestr);
|
2018-01-08 03:22:26 +01:00
|
|
|
r_str_trim (cmd);
|
2017-12-14 19:06:16 -05:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_cons_grep_process(char * grep) {
|
|
|
|
if (grep) {
|
|
|
|
parse_grep_expression (grep);
|
|
|
|
free (grep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-18 23:59:34 +01:00
|
|
|
static int cmp(const void *a, const void *b) {
|
2016-10-25 12:03:55 +02:00
|
|
|
char *da = NULL;
|
|
|
|
char *db = NULL;
|
2020-03-02 21:39:37 +01:00
|
|
|
const char *ca = r_str_trim_head_ro (a);
|
|
|
|
const char *cb = r_str_trim_head_ro (b);
|
2016-10-25 12:03:55 +02:00
|
|
|
if (!a || !b) {
|
2017-05-09 14:25:57 +02:00
|
|
|
return (int) (size_t) ((char*) a - (char*) b);
|
2016-10-25 12:03:55 +02:00
|
|
|
}
|
|
|
|
if (sorted_column > 0) {
|
|
|
|
da = strdup (ca);
|
|
|
|
db = strdup (cb);
|
|
|
|
int colsa = r_str_word_set0 (da);
|
|
|
|
int colsb = r_str_word_set0 (db);
|
2017-03-18 23:59:34 +01:00
|
|
|
ca = (colsa > sorted_column)? r_str_word_get0 (da, sorted_column): "";
|
|
|
|
cb = (colsb > sorted_column)? r_str_word_get0 (db, sorted_column): "";
|
2016-10-25 12:03:55 +02:00
|
|
|
}
|
2017-02-06 00:50:54 +03:00
|
|
|
if (IS_DIGIT (*ca) && IS_DIGIT (*cb)) {
|
2016-10-25 12:03:55 +02:00
|
|
|
ut64 na = r_num_get (NULL, ca);
|
|
|
|
ut64 nb = r_num_get (NULL, cb);
|
2020-09-09 15:45:34 +02:00
|
|
|
int ret = (na > nb) - (na < nb);
|
2016-10-25 12:03:55 +02:00
|
|
|
free (da);
|
|
|
|
free (db);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (da && db) {
|
|
|
|
int ret = strcmp (ca, cb);
|
|
|
|
free (da);
|
|
|
|
free (db);
|
|
|
|
return ret;
|
|
|
|
}
|
2016-10-26 11:01:42 +02:00
|
|
|
free (da);
|
|
|
|
free (db);
|
2016-10-25 12:03:55 +02:00
|
|
|
return strcmp (a, b);
|
|
|
|
}
|
|
|
|
|
2020-06-14 16:08:32 +02:00
|
|
|
R_API void r_cons_grepbuf(void) {
|
2010-07-16 14:53:06 +02:00
|
|
|
RCons *cons = r_cons_singleton ();
|
2019-01-07 16:08:54 +01:00
|
|
|
const char *buf = cons->context->buffer;
|
|
|
|
const int len = cons->context->buffer_len;
|
2018-06-23 12:10:13 +02:00
|
|
|
RConsGrep *grep = &cons->context->grep;
|
2019-01-07 16:08:54 +01:00
|
|
|
const char *in = buf;
|
2016-10-19 16:18:04 +02:00
|
|
|
int ret, total_lines = 0, buffer_len = 0, l = 0, tl = 0;
|
|
|
|
bool show = false;
|
2017-07-10 01:23:27 +02:00
|
|
|
if (cons->filter) {
|
2018-06-23 12:10:13 +02:00
|
|
|
cons->context->buffer_len = 0;
|
|
|
|
R_FREE (cons->context->buffer);
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2017-07-10 01:23:27 +02:00
|
|
|
}
|
2010-07-16 14:53:06 +02:00
|
|
|
|
2019-01-07 16:08:54 +01:00
|
|
|
if ((!len || !buf || buf[0] == '\0') && (grep->json || grep->less)) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->json = 0;
|
|
|
|
grep->less = 0;
|
2019-07-11 00:46:53 +02:00
|
|
|
grep->hud = 0;
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2015-06-09 13:18:56 +03:00
|
|
|
}
|
2019-01-13 12:49:41 +01:00
|
|
|
|
|
|
|
if (grep->zoom) {
|
|
|
|
char *in = calloc (cons->context->buffer_len + 2, 4);
|
|
|
|
strcpy (in, cons->context->buffer);
|
|
|
|
char *out = r_str_scale (in, grep->zoom * 2, grep->zoomy?grep->zoomy:grep->zoom);
|
|
|
|
if (out) {
|
|
|
|
free (cons->context->buffer);
|
|
|
|
cons->context->buffer = out;
|
|
|
|
cons->context->buffer_len = strlen (out);
|
|
|
|
cons->context->buffer_sz = cons->context->buffer_len;
|
|
|
|
}
|
|
|
|
grep->zoom = 0;
|
|
|
|
grep->zoomy = 0;
|
|
|
|
free (in);
|
|
|
|
return;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->json) {
|
|
|
|
if (grep->json_path) {
|
|
|
|
char *u = sdb_json_get_str (cons->context->buffer, grep->json_path);
|
2017-01-17 13:38:42 +01:00
|
|
|
if (u) {
|
2018-06-23 12:10:13 +02:00
|
|
|
cons->context->buffer = u;
|
|
|
|
cons->context->buffer_len = strlen (u);
|
|
|
|
cons->context->buffer_sz = cons->context->buffer_len + 1;
|
|
|
|
grep->json = 0;
|
2017-02-20 02:31:49 +01:00
|
|
|
r_cons_newline ();
|
2017-01-17 13:38:42 +01:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
R_FREE (grep->json_path);
|
2017-01-17 13:38:42 +01:00
|
|
|
} else {
|
2017-08-11 12:23:57 +02:00
|
|
|
const char *palette[] = {
|
2019-01-18 11:58:49 +01:00
|
|
|
cons->context->pal.graph_false, // f
|
|
|
|
cons->context->pal.graph_true, // t
|
|
|
|
cons->context->pal.num, // k
|
|
|
|
cons->context->pal.comment, // v
|
2017-08-11 12:23:57 +02:00
|
|
|
Color_RESET,
|
|
|
|
NULL
|
|
|
|
};
|
2020-04-06 04:08:47 -04:00
|
|
|
char *bb = strdup (buf);
|
|
|
|
r_str_ansi_filter (bb, NULL, NULL, -1);
|
2019-07-11 00:46:53 +02:00
|
|
|
char *out = (cons->context->grep.human)
|
2020-04-06 04:08:47 -04:00
|
|
|
? r_print_json_human (bb)
|
|
|
|
: r_print_json_indent (bb, I (context->color_mode), " ", palette);
|
|
|
|
free (bb);
|
2017-05-15 23:32:46 +03:00
|
|
|
if (!out) {
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2017-05-15 23:32:46 +03:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
free (cons->context->buffer);
|
|
|
|
cons->context->buffer = out;
|
|
|
|
cons->context->buffer_len = strlen (out);
|
|
|
|
cons->context->buffer_sz = cons->context->buffer_len + 1;
|
|
|
|
grep->json = 0;
|
2019-07-11 00:46:53 +02:00
|
|
|
if (grep->hud) {
|
|
|
|
grep->hud = false;
|
|
|
|
r_cons_hud_string (cons->context->buffer);
|
|
|
|
} else if (grep->less) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->less = 0;
|
|
|
|
r_cons_less_str (cons->context->buffer, NULL);
|
2017-01-17 13:38:42 +01:00
|
|
|
}
|
2014-11-22 01:51:51 +01:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
|
|
|
// cons->lines = ?? return 3;
|
2014-11-22 01:51:51 +01:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->less) {
|
|
|
|
int less = grep->less;
|
|
|
|
grep->less = 0;
|
2017-01-17 13:12:27 +01:00
|
|
|
if (less == 2) {
|
2017-02-20 02:31:49 +01:00
|
|
|
char *res = r_cons_hud_string (buf);
|
2019-01-07 16:08:54 +01:00
|
|
|
if (res) {
|
|
|
|
r_cons_println (res);
|
|
|
|
free (res);
|
|
|
|
}
|
2017-01-17 13:12:27 +01:00
|
|
|
} else {
|
|
|
|
r_cons_less_str (buf, NULL);
|
2018-06-23 12:10:13 +02:00
|
|
|
cons->context->buffer_len = 0;
|
|
|
|
if (cons->context->buffer) {
|
|
|
|
cons->context->buffer[0] = 0;
|
2017-01-17 13:12:27 +01:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
R_FREE (cons->context->buffer);
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2014-02-11 02:32:37 +01:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!cons->context->buffer) {
|
|
|
|
cons->context->buffer_len = len + 20;
|
|
|
|
cons->context->buffer = malloc (cons->context->buffer_len);
|
|
|
|
cons->context->buffer[0] = 0;
|
2012-08-28 17:50:49 +02:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
RStrBuf *ob = r_strbuf_new ("");
|
|
|
|
// if we modify cons->lines we should update I.context->buffer too
|
2010-07-16 14:53:06 +02:00
|
|
|
cons->lines = 0;
|
2017-03-18 23:59:34 +01:00
|
|
|
// used to count lines and change negative grep.line values
|
|
|
|
while ((int) (size_t) (in - buf) < len) {
|
2019-01-07 16:08:54 +01:00
|
|
|
char *p = strchr (in, '\n');
|
2016-10-19 16:18:04 +02:00
|
|
|
if (!p) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
l = p - in;
|
|
|
|
if (l > 0) {
|
|
|
|
in += l + 1;
|
|
|
|
} else {
|
|
|
|
in++;
|
|
|
|
}
|
|
|
|
total_lines++;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!grep->range_line && grep->line < 0) {
|
|
|
|
grep->line = total_lines + grep->line;
|
2016-10-25 12:03:55 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->range_line == 1) {
|
|
|
|
if (grep->f_line < 0) {
|
|
|
|
grep->f_line = total_lines + grep->f_line;
|
2016-10-19 16:18:04 +02:00
|
|
|
}
|
2019-11-29 11:47:23 +02:00
|
|
|
if (grep->l_line <= 0) {
|
2018-06-23 12:10:13 +02:00
|
|
|
grep->l_line = total_lines + grep->l_line;
|
2016-10-19 16:18:04 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-01 08:17:55 +08:00
|
|
|
bool is_range_line_grep_only = grep->range_line != 2 && !*grep->str;
|
2016-10-19 16:18:04 +02:00
|
|
|
in = buf;
|
2017-03-18 23:59:34 +01:00
|
|
|
while ((int) (size_t) (in - buf) < len) {
|
2019-01-07 16:08:54 +01:00
|
|
|
char *p = strchr (in, '\n');
|
2010-07-16 18:44:39 +02:00
|
|
|
if (!p) {
|
2019-01-31 16:39:32 -03:00
|
|
|
break;
|
2010-07-16 18:44:39 +02:00
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
l = p - in;
|
2020-11-01 08:17:55 +08:00
|
|
|
if ((!l && is_range_line_grep_only) || l > 0) {
|
2019-01-07 16:08:54 +01:00
|
|
|
char *tline = r_str_ndup (in, l);
|
2018-01-19 19:50:29 +01:00
|
|
|
if (cons->grep_color) {
|
|
|
|
tl = l;
|
|
|
|
} else {
|
|
|
|
tl = r_str_ansi_filter (tline, NULL, NULL, l);
|
|
|
|
}
|
2016-10-19 13:10:10 +02:00
|
|
|
if (tl < 0) {
|
2010-08-13 01:18:06 +02:00
|
|
|
ret = -1;
|
2016-10-19 13:10:10 +02:00
|
|
|
} else {
|
|
|
|
ret = r_cons_grep_line (tline, tl);
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!grep->range_line) {
|
|
|
|
if (grep->line == cons->lines) {
|
2016-10-19 16:18:04 +02:00
|
|
|
show = true;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
} else if (grep->range_line == 1) {
|
|
|
|
if (grep->f_line == cons->lines) {
|
2016-10-19 16:18:04 +02:00
|
|
|
show = true;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->l_line == cons->lines) {
|
2016-10-19 16:18:04 +02:00
|
|
|
show = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
show = true;
|
|
|
|
}
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2020-11-01 08:17:55 +08:00
|
|
|
if ((!ret && is_range_line_grep_only) || ret > 0) {
|
2016-10-19 16:18:04 +02:00
|
|
|
if (show) {
|
2019-01-07 16:08:54 +01:00
|
|
|
char *str = r_str_ndup (tline, ret);
|
2019-01-31 16:39:32 -03:00
|
|
|
if (cons->grep_highlight) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < grep->nstrings; i++) {
|
2019-01-26 00:55:19 -03:00
|
|
|
char *newstr = r_str_newf (Color_INVERT"%s"Color_RESET, grep->strings[i]);
|
|
|
|
if (str && newstr) {
|
|
|
|
if (grep->icase) {
|
|
|
|
str = r_str_replace_icase (str, grep->strings[i], newstr, 1, 1);
|
|
|
|
} else {
|
|
|
|
str = r_str_replace (str, grep->strings[i], newstr, 1);
|
|
|
|
}
|
2019-01-06 20:23:23 -03:00
|
|
|
}
|
2019-01-26 00:55:19 -03:00
|
|
|
free (newstr);
|
2018-12-27 06:23:10 +01:00
|
|
|
}
|
2019-01-26 00:55:19 -03:00
|
|
|
}
|
|
|
|
if (str) {
|
2019-01-07 16:08:54 +01:00
|
|
|
r_strbuf_append (ob, str);
|
|
|
|
r_strbuf_append (ob, "\n");
|
2018-12-27 06:23:10 +01:00
|
|
|
}
|
2015-09-23 23:00:14 +02:00
|
|
|
buffer_len += ret + 1;
|
2019-01-07 16:08:54 +01:00
|
|
|
free (str);
|
2010-07-16 14:53:06 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!grep->range_line) {
|
2016-10-19 16:18:04 +02:00
|
|
|
show = false;
|
|
|
|
}
|
2010-07-16 14:53:06 +02:00
|
|
|
cons->lines++;
|
2010-07-16 18:44:39 +02:00
|
|
|
} else if (ret < 0) {
|
2010-08-03 13:30:58 +02:00
|
|
|
free (tline);
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2015-09-23 23:00:14 +02:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
free (tline);
|
2015-09-23 23:00:14 +02:00
|
|
|
in += l + 1;
|
2016-10-19 13:10:10 +02:00
|
|
|
} else {
|
|
|
|
in++;
|
|
|
|
}
|
2010-06-25 01:44:15 +02:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
|
|
|
|
cons->context->buffer_len = r_strbuf_length (ob);
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->counter) {
|
|
|
|
int cnt = grep->charCounter? strlen (cons->context->buffer): cons->lines;
|
|
|
|
if (cons->context->buffer_len < 10) {
|
|
|
|
cons->context->buffer_len = 10; // HACK
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
snprintf (cons->context->buffer, cons->context->buffer_len, "%d\n", cnt);
|
|
|
|
cons->context->buffer_len = strlen (cons->context->buffer);
|
2016-11-04 04:45:35 +01:00
|
|
|
cons->num->value = cons->lines;
|
2019-07-28 20:08:24 +03:00
|
|
|
r_strbuf_free (ob);
|
2019-01-07 16:08:54 +01:00
|
|
|
return;
|
2011-02-05 02:55:50 +01:00
|
|
|
}
|
2019-01-07 16:08:54 +01:00
|
|
|
|
|
|
|
const int ob_len = r_strbuf_length (ob);
|
|
|
|
if (ob_len >= cons->context->buffer_sz) {
|
|
|
|
cons->context->buffer_sz = ob_len + 1;
|
|
|
|
cons->context->buffer = r_strbuf_drain (ob);
|
|
|
|
} else {
|
|
|
|
memcpy (cons->context->buffer, r_strbuf_getbin (ob, NULL), ob_len);
|
|
|
|
cons->context->buffer[ob_len] = 0;
|
|
|
|
r_strbuf_free (ob);
|
|
|
|
}
|
|
|
|
cons->context->buffer_len = ob_len;
|
|
|
|
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->sort != -1) {
|
2017-03-18 23:59:34 +01:00
|
|
|
#define INSERT_LINES(list)\
|
2019-01-07 16:08:54 +01:00
|
|
|
do {\
|
|
|
|
r_list_foreach (list, iter, str) {\
|
|
|
|
int len = strlen (str);\
|
|
|
|
memcpy (ptr, str, len);\
|
|
|
|
memcpy (ptr + len, "\n", 2);\
|
|
|
|
ptr += len + 1;\
|
|
|
|
nl++;\
|
|
|
|
}\
|
2017-03-18 23:59:34 +01:00
|
|
|
}\
|
2019-01-07 16:08:54 +01:00
|
|
|
while (false)
|
2016-10-25 14:37:25 +02:00
|
|
|
|
2016-10-25 12:03:55 +02:00
|
|
|
RListIter *iter;
|
|
|
|
int nl = 0;
|
2018-06-23 12:10:13 +02:00
|
|
|
char *ptr = cons->context->buffer;
|
2016-10-25 12:03:55 +02:00
|
|
|
char *str;
|
2018-06-23 12:10:13 +02:00
|
|
|
sorted_column = grep->sort;
|
2016-10-25 12:03:55 +02:00
|
|
|
r_list_sort (sorted_lines, cmp);
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->sort_invert) {
|
2016-10-25 12:39:36 +02:00
|
|
|
r_list_reverse (sorted_lines);
|
|
|
|
}
|
2016-10-25 14:37:25 +02:00
|
|
|
INSERT_LINES (unsorted_lines);
|
|
|
|
INSERT_LINES (sorted_lines);
|
2016-10-25 12:03:55 +02:00
|
|
|
cons->lines = nl;
|
|
|
|
r_list_free (sorted_lines);
|
|
|
|
sorted_lines = NULL;
|
2016-10-25 14:37:25 +02:00
|
|
|
r_list_free (unsorted_lines);
|
|
|
|
unsorted_lines = NULL;
|
2016-10-25 12:03:55 +02:00
|
|
|
}
|
2010-06-25 01:44:15 +02:00
|
|
|
}
|
2010-07-16 14:53:06 +02:00
|
|
|
|
2010-06-25 01:44:15 +02:00
|
|
|
R_API int r_cons_grep_line(char *buf, int len) {
|
2010-02-21 20:21:36 +01:00
|
|
|
RCons *cons = r_cons_singleton ();
|
2018-06-23 12:10:13 +02:00
|
|
|
RConsGrep *grep = &cons->context->grep;
|
2015-09-23 23:00:14 +02:00
|
|
|
const char *delims = " |,;=\t";
|
2018-12-27 06:23:10 +01:00
|
|
|
char *tok = NULL;
|
|
|
|
bool hit = grep->neg;
|
2015-09-23 23:00:14 +02:00
|
|
|
int outlen = 0;
|
2016-10-19 16:18:04 +02:00
|
|
|
bool use_tok = false;
|
2015-09-23 23:00:14 +02:00
|
|
|
size_t i;
|
2010-01-30 14:02:53 +01:00
|
|
|
|
2018-12-27 06:23:10 +01:00
|
|
|
char *in = calloc (1, len + 1);
|
2016-10-19 13:10:10 +02:00
|
|
|
if (!in) {
|
|
|
|
return 0;
|
|
|
|
}
|
2018-12-27 06:23:10 +01:00
|
|
|
char *out = calloc (1, len + 2);
|
2016-05-19 16:20:35 +01:00
|
|
|
if (!out) {
|
|
|
|
free (in);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-08-03 13:30:58 +02:00
|
|
|
memcpy (in, buf, len);
|
|
|
|
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->nstrings > 0) {
|
|
|
|
int ampfail = grep->amp;
|
|
|
|
if (grep->icase) {
|
2017-05-29 02:52:53 +02:00
|
|
|
r_str_case (in, false);
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
for (i = 0; i < grep->nstrings; i++) {
|
|
|
|
char *str = grep->strings[i];
|
|
|
|
if (grep->icase) {
|
2017-05-29 02:52:53 +02:00
|
|
|
r_str_case (str, false);
|
|
|
|
}
|
2019-01-19 21:11:20 +08:00
|
|
|
const char *p = r_strstr_ansi (in, grep->strings[i]);
|
2012-08-09 18:19:00 +02:00
|
|
|
if (!p) {
|
|
|
|
ampfail = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->begin) {
|
2018-12-27 06:23:10 +01:00
|
|
|
hit = (p == in);
|
2016-10-19 13:10:10 +02:00
|
|
|
} else {
|
2018-06-23 12:10:13 +02:00
|
|
|
hit = !grep->neg;
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2014-07-17 04:45:32 +02:00
|
|
|
// TODO: optimize without strlen without breaking t/feat_grep (grep end)
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->end && (strlen (grep->strings[i]) != strlen (p))) {
|
2017-03-18 23:59:34 +01:00
|
|
|
hit = 0;
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!grep->amp) {
|
2012-08-09 18:19:00 +02:00
|
|
|
break;
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
2012-06-21 10:12:02 +02:00
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->amp) {
|
2012-08-09 18:19:00 +02:00
|
|
|
hit = ampfail;
|
2016-10-19 13:10:10 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hit = 1;
|
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
|
2010-07-16 14:53:06 +02:00
|
|
|
if (hit) {
|
2018-06-23 12:10:13 +02:00
|
|
|
if (!grep->range_line) {
|
|
|
|
if (grep->line == cons->lines) {
|
2016-10-19 16:18:04 +02:00
|
|
|
use_tok = true;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
} else if (grep->range_line == 1) {
|
2018-07-15 14:43:16 +02:00
|
|
|
use_tok = R_BETWEEN (grep->f_line, cons->lines, grep->l_line);
|
2016-10-19 16:18:04 +02:00
|
|
|
} else {
|
|
|
|
use_tok = true;
|
|
|
|
}
|
2018-06-23 12:10:13 +02:00
|
|
|
if (use_tok && grep->tokens_used) {
|
2015-09-23 23:00:14 +02:00
|
|
|
for (i = 0; i < R_CONS_GREP_TOKENS; i++) {
|
2017-03-18 23:59:34 +01:00
|
|
|
tok = strtok (i? NULL: in, delims);
|
2011-04-04 18:33:27 +02:00
|
|
|
if (tok) {
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->tokens[i]) {
|
2011-04-04 18:33:27 +02:00
|
|
|
int toklen = strlen (tok);
|
2015-09-23 23:00:14 +02:00
|
|
|
memcpy (out + outlen, tok, toklen);
|
|
|
|
memcpy (out + outlen + toklen, " ", 2);
|
|
|
|
outlen += toklen + 1;
|
|
|
|
if (!(*out)) {
|
|
|
|
free (in);
|
|
|
|
free (out);
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-04 18:33:27 +02:00
|
|
|
}
|
|
|
|
} else {
|
2018-12-27 06:23:10 +01:00
|
|
|
if ((*out)) {
|
2016-10-19 13:10:10 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-12-27 06:23:10 +01:00
|
|
|
free (in);
|
|
|
|
free (out);
|
|
|
|
return 0;
|
2010-08-03 11:36:41 +02:00
|
|
|
}
|
2010-01-30 14:02:53 +01:00
|
|
|
}
|
2017-03-18 23:59:34 +01:00
|
|
|
outlen = outlen > 0? outlen - 1: 0;
|
2015-09-23 23:00:14 +02:00
|
|
|
if (outlen > len) { // should never happen
|
2011-04-04 18:33:27 +02:00
|
|
|
eprintf ("r_cons_grep_line: wtf, how you reach this?\n");
|
2012-08-08 17:19:48 +02:00
|
|
|
free (in);
|
|
|
|
free (out);
|
2011-04-04 18:33:27 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2010-08-03 11:36:41 +02:00
|
|
|
memcpy (buf, out, len);
|
2011-04-04 18:33:27 +02:00
|
|
|
len = outlen;
|
2010-06-25 11:22:14 +02:00
|
|
|
}
|
2016-10-19 13:10:10 +02:00
|
|
|
} else {
|
|
|
|
len = 0;
|
|
|
|
}
|
2010-08-03 13:30:58 +02:00
|
|
|
free (in);
|
|
|
|
free (out);
|
2018-06-23 12:10:13 +02:00
|
|
|
if (grep->sort != -1) {
|
2016-10-25 12:03:55 +02:00
|
|
|
char ch = buf[len];
|
|
|
|
buf[len] = 0;
|
|
|
|
if (!sorted_lines) {
|
|
|
|
sorted_lines = r_list_newf (free);
|
|
|
|
}
|
2016-10-25 14:37:25 +02:00
|
|
|
if (!unsorted_lines) {
|
|
|
|
unsorted_lines = r_list_newf (free);
|
|
|
|
}
|
2019-06-02 09:22:41 -03:00
|
|
|
if (cons->lines >= grep->sort_row) {
|
2016-10-25 14:37:25 +02:00
|
|
|
r_list_append (sorted_lines, strdup (buf));
|
|
|
|
} else {
|
|
|
|
r_list_append (unsorted_lines, strdup (buf));
|
|
|
|
}
|
2016-10-25 12:03:55 +02:00
|
|
|
buf[len] = ch;
|
|
|
|
}
|
2010-08-03 13:30:58 +02:00
|
|
|
|
2010-07-16 14:53:06 +02:00
|
|
|
return len;
|
2010-01-30 14:02:53 +01:00
|
|
|
}
|
|
|
|
|
2020-01-19 07:40:21 +01:00
|
|
|
R_API void r_cons_grep(const char *grep) {
|
|
|
|
parse_grep_expression (grep);
|
|
|
|
r_cons_grepbuf ();
|
|
|
|
}
|