Rizin
unix-like reverse engineering framework and cli tools
grep.c File Reference
#include <rz_cons.h>
#include <rz_util/rz_print.h>
#include <sdb.h>

Go to the source code of this file.

Macros

#define I(x)   rz_cons_singleton()->x
 
#define RZ_CONS_GREP_BUFSIZE   4096
 
#define INSERT_LINES(list)
 

Functions

static char * strchr_ns (char *s, const char ch)
 
RZ_API void rz_cons_grep_help (void)
 
static void parse_grep_expression (const char *str)
 
static char * find_next_intgrep (char *cmd, const char *quotes)
 
static char * preprocess_filter_expr (char *cmd, const char *quotes)
 
RZ_API void rz_cons_grep_parsecmd (char *cmd, const char *quotestr)
 
RZ_API char * rz_cons_grep_strip (char *cmd, const char *quotestr)
 
RZ_API void rz_cons_grep_process (char *grep)
 
static int cmp (const void *a, const void *b)
 
RZ_API void rz_cons_grepbuf (void)
 
RZ_API int rz_cons_grep_line (char *buf, int len)
 
RZ_API void rz_cons_grep (const char *grep)
 

Variables

static const char * help_detail_tilde []
 
static RzListsorted_lines = NULL
 
static RzListunsorted_lines = NULL
 
static int sorted_column = -1
 

Macro Definition Documentation

◆ I

#define I (   x)    rz_cons_singleton()->x

Definition at line 9 of file grep.c.

◆ INSERT_LINES

#define INSERT_LINES (   list)
Value:
do { \
rz_list_foreach (list, iter, str) { \
int len = strlen(str); \
memcpy(ptr, str, len); \
memcpy(ptr + len, "\n", 2); \
ptr += len + 1; \
nl++; \
} \
} while (false)
size_t len
Definition: 6502dis.c:15
static void list(RzEgg *egg)
Definition: rz-gg.c:52

◆ RZ_CONS_GREP_BUFSIZE

#define RZ_CONS_GREP_BUFSIZE   4096

Definition at line 74 of file grep.c.

Function Documentation

◆ cmp()

static int cmp ( const void *  a,
const void *  b 
)
static

Definition at line 428 of file grep.c.

428  {
429  char *da = NULL;
430  char *db = NULL;
431  const char *ca = rz_str_trim_head_ro(a);
432  const char *cb = rz_str_trim_head_ro(b);
433  if (!a || !b) {
434  return (int)(size_t)((char *)a - (char *)b);
435  }
436  if (sorted_column > 0) {
437  da = strdup(ca);
438  db = strdup(cb);
439  int colsa = rz_str_word_set0(da);
440  int colsb = rz_str_word_set0(db);
441  ca = (colsa > sorted_column) ? rz_str_word_get0(da, sorted_column) : "";
442  cb = (colsb > sorted_column) ? rz_str_word_get0(db, sorted_column) : "";
443  }
444  if (IS_DIGIT(*ca) && IS_DIGIT(*cb)) {
445  ut64 na = rz_num_get(NULL, ca);
446  ut64 nb = rz_num_get(NULL, cb);
447  int ret = (na > nb) - (na < nb);
448  free(da);
449  free(db);
450  return ret;
451  }
452  if (da && db) {
453  int ret = strcmp(ca, cb);
454  free(da);
455  free(db);
456  return ret;
457  }
458  free(da);
459  free(db);
460  return strcmp(a, b);
461 }
#define NULL
Definition: cris-opc.c:27
static int sorted_column
Definition: grep.c:68
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API int rz_str_word_set0(char *str)
Definition: str.c:423
RZ_API const char * rz_str_word_get0(const char *str, int idx)
Definition: str.c:598
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
int size_t
Definition: sftypes.h:40
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176

References a, b, cb, free(), IS_DIGIT, NULL, rz_num_get(), rz_str_trim_head_ro(), rz_str_word_get0(), rz_str_word_set0(), sorted_column, strdup(), and ut64().

Referenced by rz_cons_grepbuf().

◆ find_next_intgrep()

static char* find_next_intgrep ( char *  cmd,
const char *  quotes 
)
static

Definition at line 338 of file grep.c.

338  {
339  char *p;
340  do {
341  p = (char *)rz_str_firstbut(cmd, '~', quotes);
342  if (!p) {
343  break;
344  }
345  if (p == cmd || *(p - 1) != '\\') {
346  return (char *)p;
347  }
348  // twiddle unescape
349  memmove(p - 1, p, strlen(p) + 1);
350  cmd = p + 1;
351  } while (*cmd);
352  return NULL;
353 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
void * p
Definition: libc.cpp:67
RZ_API const char * rz_str_firstbut(const char *s, char ch, const char *but)
Definition: str.c:2644

References cmd, NULL, p, and rz_str_firstbut().

Referenced by preprocess_filter_expr().

◆ parse_grep_expression()

static void parse_grep_expression ( const char *  str)
static

Definition at line 76 of file grep.c.

76  {
77  static char buf[RZ_CONS_GREP_BUFSIZE];
78  int wlen, len, is_range, num_is_parsed, fail = 0;
79  char *ptr, *optr, *ptr2, *ptr3, *end_ptr = NULL, last;
80  ut64 range_begin, range_end;
81 
82  if (!str || !*str) {
83  return;
84  }
85  RzCons *cons = rz_cons_singleton();
86  RzConsGrep *grep = &cons->context->grep;
87  sorted_column = 0;
88  bool first = true;
89  while (*str) {
90  switch (*str) {
91  case '.':
92  if (str[1] == '.') {
93  if (str[2] == '.') {
94  grep->less = 2;
95  } else {
96  grep->less = 1;
97  }
98  return;
99  }
100  str++;
101  break;
102  case '{':
103  if (str[1] == ':') {
104  grep->human = true; // human friendly indentation ij~{:
105  grep->json = 1;
106  if (!strncmp(str, "{:...", 5)) {
107  grep->hud = true;
108  } else if (!strncmp(str, "{:..", 4)) {
109  grep->less = 1;
110  }
111  } else if (str[1] == '}') {
112  // standard json indentation
113  grep->json = 1;
114  if (!strncmp(str, "{}...", 5)) {
115  grep->hud = true;
116  } else if (!strncmp(str, "{}..", 4)) {
117  grep->less = 1;
118  }
119  } else {
120  char *jsonPath = strdup(str + 1);
121  char *jsonPathEnd = strchr(jsonPath, '}');
122  if (jsonPathEnd) {
123  *jsonPathEnd = 0;
124  free(grep->json_path);
125  grep->json_path = jsonPath;
126  grep->json = 1;
127  } else {
128  free(jsonPath);
129  }
130  return;
131  }
132  str++;
133  break;
134  case '$':
135  str++;
136  if (*str == '!') {
137  grep->sort_invert = true;
138  str++;
139  } else {
140  grep->sort_invert = false;
141  }
142  grep->sort = atoi(str);
143  while (IS_DIGIT(*str)) {
144  str++;
145  }
146  if (*str == ':') {
147  grep->sort_row = atoi(++str);
148  str++;
149  }
150  break;
151  case '&':
152  str++;
153  grep->amp = 1;
154  break;
155  case '<':
156  grep->zoom = atoi(++str);
157  // grep->zoomy = atoi (arg);
158  break;
159  case '+':
160  if (first) {
161  str++;
162  grep->icase = 1;
163  } else {
164  goto while_end;
165  }
166  break;
167  case '^':
168  str++;
169  grep->begin = 1;
170  break;
171  case '!':
172  str++;
173  grep->neg = 1;
174  break;
175  case '?':
176  str++;
177  grep->counter = 1;
178  if (*str == '.') {
179  grep->charCounter = true;
180  str++;
181  } else if (*str == '?') {
182  cons->filter = true;
184  return;
185  }
186  break;
187  default:
188  goto while_end;
189  }
190  first = false;
191  }
192 while_end:
193 
194  len = strlen(str) - 1;
195  if (len > RZ_CONS_GREP_BUFSIZE - 1) {
196  eprintf("rz_cons_grep: too long!\n");
197  return;
198  }
199  if (len > 0 && str[len] == '?') {
200  grep->counter = 1;
201  strncpy(buf, str, RZ_MIN(len, sizeof(buf) - 1));
202  buf[len] = 0;
203  len--;
204  } else {
205  strncpy(buf, str, sizeof(buf) - 1);
206  }
207 
208  ptr = buf;
209  ptr2 = strchr(ptr, '[');
210  ptr3 = strchr(ptr, ']');
211  is_range = 0;
212  num_is_parsed = 0;
213  fail = 0;
214  range_begin = range_end = -1;
215 
216  if (ptr2 && ptr3) {
217  end_ptr = ptr2;
218  last = ptr3[1];
219  ptr3[1] = '\0';
220  ptr2++;
221  for (; ptr2 <= ptr3; ptr2++) {
222  if (fail) {
223  ZERO_FILL(grep->tokens);
224  grep->tokens_used = 0;
225  break;
226  }
227  switch (*ptr2) {
228  case '-':
229  is_range = 1;
230  num_is_parsed = 0;
231  range_end = -1;
232  break;
233  case ']': // fallthrough to handle ']' like ','
234  case ',':
235  for (; range_begin <= range_end; range_begin++) {
236  if (range_begin >= RZ_CONS_GREP_TOKENS) {
237  fail = 1;
238  break;
239  }
240  grep->tokens[range_begin] = 1;
241  grep->tokens_used = 1;
242  }
243  // case of [n-]
244  if (*ptr2 == ']' && is_range && !num_is_parsed) {
245  num_is_parsed = 1;
246  range_end = -1;
247  } else {
248  is_range = 0;
249  num_is_parsed = 0;
250  }
251  break;
252  default:
253  if (!num_is_parsed) {
254  if (is_range) {
255  range_end = rz_num_get(cons->num, ptr2);
256  // check for bad value, if range_end == 0, we check if ptr2 == '0'
257  if (range_end == 0 && *ptr != '0') {
258  range_end = -1; // this allow [n- ]
259  }
260  } else {
261  range_begin = range_end = rz_num_get(cons->num, ptr2);
262  }
263  num_is_parsed = 1;
264  }
265  }
266  }
267  ptr3[1] = last;
268  }
269 
270  ptr2 = strchr_ns(ptr, ':'); // line number
271  grep->range_line = 2; // there is not :
272  if (ptr2 && ptr2[1] != ':' && ptr2[1] && (IS_DIGIT(ptr2[1]) || ptr2[1] == '-' || ptr2[1] == '.')) {
273  end_ptr = end_ptr ? RZ_MIN(end_ptr, ptr2) : ptr2;
274  char *p, *token = ptr2 + 1;
275  p = strstr(token, "..");
276  if (!p) {
277  grep->line = rz_num_get(cons->num, ptr2 + 1);
278  grep->range_line = 0;
279  } else {
280  *p = '\0';
281  grep->range_line = 1;
282  if (*token) {
283  grep->f_line = rz_num_get(cons->num, token);
284  } else {
285  grep->f_line = 0;
286  }
287  if (p[2]) {
288  grep->l_line = rz_num_get(cons->num, p + 2);
289  } else {
290  grep->l_line = 0;
291  }
292  }
293  }
294  if (end_ptr) {
295  *end_ptr = '\0';
296  }
297 
298  len = strlen(buf) - 1;
299  if (len > 1 && buf[len] == '$' && buf[len - 1] != '\\') {
300  grep->end = 1;
301  buf[len] = '\0';
302  }
303 
304  free(grep->str);
305  if (*ptr) {
306  grep->str = (char *)strdup(ptr);
307  do {
308  optr = ptr;
309  ptr = strchr(ptr, ','); // grep keywords
310  if (ptr) {
311  *ptr++ = '\0';
312  }
313  wlen = strlen(optr);
314  if (!wlen) {
315  continue;
316  }
317  if (wlen >= RZ_CONS_GREP_WORD_SIZE - 1) {
318  eprintf("grep string too long\n");
319  continue;
320  }
321  grep->nstrings++;
322  if (grep->nstrings > RZ_CONS_GREP_WORDS - 1) {
323  eprintf("too many grep strings\n");
324  break;
325  }
326  rz_str_ncpy(grep->strings[grep->nstrings - 1],
327  optr, RZ_CONS_GREP_WORD_SIZE);
328  } while (ptr);
329  } else {
330  grep->str = strdup(ptr);
331  grep->nstrings++;
332  grep->strings[0][0] = 0;
333  }
334 }
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_grep_help(void)
Definition: grep.c:70
#define RZ_CONS_GREP_BUFSIZE
Definition: grep.c:74
static char * strchr_ns(char *s, const char ch)
Definition: grep.c:11
voidpf void * buf
Definition: ioapi.h:138
#define eprintf(x, y...)
Definition: rlcc.c:7
#define RZ_CONS_GREP_WORDS
Definition: rz_cons.h:49
#define RZ_CONS_GREP_TOKENS
Definition: rz_cons.h:51
#define RZ_CONS_GREP_WORD_SIZE
Definition: rz_cons.h:50
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
#define ZERO_FILL(x)
Definition: rz_types.h:281
#define RZ_MIN(x, y)
RzConsGrep grep
Definition: rz_cons.h:466
bool human
Definition: rz_cons.h:80
char * str
Definition: rz_cons.h:75
char * json_path
Definition: rz_cons.h:82
bool sort_invert
Definition: rz_cons.h:87
int tokens[RZ_CONS_GREP_TOKENS]
Definition: rz_cons.h:90
int nstrings
Definition: rz_cons.h:74
bool charCounter
Definition: rz_cons.h:77
char strings[RZ_CONS_GREP_WORDS][RZ_CONS_GREP_WORD_SIZE]
Definition: rz_cons.h:73
int tokens_used
Definition: rz_cons.h:91
int range_line
Definition: rz_cons.h:83
int sort_row
Definition: rz_cons.h:86
bool filter
Definition: rz_cons.h:569
RzNum * num
Definition: rz_cons.h:543
RzConsContext * context
Definition: rz_cons.h:502
#define fail(test)
Definition: tests.h:29

References rz_cons_grep_t::amp, rz_cons_grep_t::begin, rz_cons_grep_t::charCounter, rz_cons_t::context, rz_cons_grep_t::counter, rz_cons_grep_t::end, eprintf, rz_cons_grep_t::f_line, fail, rz_cons_t::filter, free(), rz_cons_context_t::grep, rz_cons_grep_t::hud, rz_cons_grep_t::human, rz_cons_grep_t::icase, IS_DIGIT, rz_cons_grep_t::json, rz_cons_grep_t::json_path, rz_cons_grep_t::l_line, len, rz_cons_grep_t::less, rz_cons_grep_t::line, rz_cons_grep_t::neg, rz_cons_grep_t::nstrings, NULL, rz_cons_t::num, p, rz_cons_grep_t::range_line, RZ_CONS_GREP_BUFSIZE, rz_cons_grep_help(), RZ_CONS_GREP_TOKENS, RZ_CONS_GREP_WORD_SIZE, RZ_CONS_GREP_WORDS, rz_cons_singleton(), RZ_MIN, rz_num_get(), rz_str_ncpy(), rz_cons_grep_t::sort, rz_cons_grep_t::sort_invert, rz_cons_grep_t::sort_row, sorted_column, cmd_descs_generate::str, rz_cons_grep_t::str, strchr_ns(), strdup(), rz_cons_grep_t::strings, rz_cons_grep_t::tokens, rz_cons_grep_t::tokens_used, ut64(), ZERO_FILL, and rz_cons_grep_t::zoom.

Referenced by rz_cons_grep(), rz_cons_grep_parsecmd(), and rz_cons_grep_process().

◆ preprocess_filter_expr()

static char* preprocess_filter_expr ( char *  cmd,
const char *  quotes 
)
static

Definition at line 363 of file grep.c.

363  {
364  char *p1, *p2, *ns = NULL;
365  const char *strsep = "&";
366  int len;
367  int i;
368 
369  p1 = find_next_intgrep(cmd, quotes);
370  if (!p1) {
371  return NULL;
372  }
373 
374  len = strlen(p1);
375  if (len > 4 && rz_str_endswith(p1, "~?") && p1[len - 3] != '\\') {
376  p1[len - 2] = '\0';
377  ns = rz_str_append(ns, "?");
378  }
379 
380  *p1 = '\0'; // remove grep part from cmd
381 
382  i = 0;
383  // parse words between '~'
384  while ((p2 = find_next_intgrep(p1 + 1, quotes))) {
385  ns = rz_str_append(ns, strsep);
386  ns = rz_str_appendlen(ns, p1 + 1, (int)(p2 - p1 - 1));
387  p1 = p2;
388  strsep = ",";
389  i++;
390  }
391 
392  if (i > 0) {
393  ns = rz_str_append(ns, ",");
394  }
395 
396  ns = rz_str_append(ns, p1 + 1);
397 
398  return ns;
399 }
lzma_index ** i
Definition: index.h:629
static char * find_next_intgrep(char *cmd, const char *quotes)
Definition: grep.c:338
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
RZ_API char * rz_str_appendlen(char *ptr, const char *string, int slen)
Definition: str.c:1043
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329

References cmd, find_next_intgrep(), i, len, NULL, rz_str_append(), rz_str_appendlen(), and rz_str_endswith().

Referenced by rz_cons_grep_parsecmd(), and rz_cons_grep_strip().

◆ rz_cons_grep()

RZ_API void rz_cons_grep ( const char *  grep)

Definition at line 874 of file grep.c.

874  {
875  parse_grep_expression(grep);
876  rz_cons_grepbuf();
877 }
static void parse_grep_expression(const char *str)
Definition: grep.c:76
RZ_API void rz_cons_grepbuf(void)
Definition: grep.c:463

References parse_grep_expression(), and rz_cons_grepbuf().

Referenced by rz_cons_bind().

◆ rz_cons_grep_help()

RZ_API void rz_cons_grep_help ( void  )

Definition at line 70 of file grep.c.

70  {
72 }
RZ_API void rz_cons_cmd_help(const char *help[], bool use_color)
Definition: cons.c:1954
static const char * help_detail_tilde[]
Definition: grep.c:23

References help_detail_tilde, and rz_cons_cmd_help().

Referenced by parse_grep_expression(), and rz_core_cmd_subst_i().

◆ rz_cons_grep_line()

RZ_API int rz_cons_grep_line ( char *  buf,
int  len 
)

Definition at line 746 of file grep.c.

746  {
747  RzCons *cons = rz_cons_singleton();
748  RzConsGrep *grep = &cons->context->grep;
749  const char *delims = " |,;=\t";
750  char *tok = NULL;
751  bool hit = grep->neg;
752  int outlen = 0;
753  bool use_tok = false;
754  size_t i;
755 
756  char *in = calloc(1, len + 1);
757  if (!in) {
758  return 0;
759  }
760  char *out = calloc(1, len + 2);
761  if (!out) {
762  free(in);
763  return 0;
764  }
765  memcpy(in, buf, len);
766 
767  if (grep->nstrings > 0) {
768  int ampfail = grep->amp;
769  if (grep->icase) {
770  rz_str_case(in, false);
771  }
772  for (i = 0; i < grep->nstrings; i++) {
773  char *str = grep->strings[i];
774  if (grep->icase) {
775  rz_str_case(str, false);
776  }
777  const char *p = rz_strstr_ansi(in, grep->strings[i]);
778  if (!p) {
779  ampfail = 0;
780  continue;
781  }
782  if (grep->begin) {
783  hit = (p == in);
784  if (grep->neg) {
785  hit = !hit;
786  }
787  } else {
788  hit = !grep->neg;
789  }
790  // TODO: optimize without strlen without breaking t/feat_grep (grep end)
791  if (grep->end && (strlen(grep->strings[i]) != strlen(p))) {
792  hit = 0;
793  }
794  if (!grep->amp) {
795  break;
796  }
797  }
798  if (grep->amp) {
799  hit = ampfail;
800  }
801  } else {
802  hit = 1;
803  }
804 
805  if (hit) {
806  if (!grep->range_line) {
807  if (grep->line == cons->lines) {
808  use_tok = true;
809  }
810  } else if (grep->range_line == 1) {
811  use_tok = RZ_BETWEEN(grep->f_line, cons->lines, grep->l_line);
812  } else {
813  use_tok = true;
814  }
815  if (use_tok && grep->tokens_used) {
816  for (i = 0; i < RZ_CONS_GREP_TOKENS; i++) {
817  tok = strtok(i ? NULL : in, delims);
818  if (tok) {
819  if (grep->tokens[i]) {
820  int toklen = strlen(tok);
821  memcpy(out + outlen, tok, toklen);
822  memcpy(out + outlen + toklen, " ", 2);
823  outlen += toklen + 1;
824  if (!(*out)) {
825  free(in);
826  free(out);
827  return -1;
828  }
829  }
830  } else {
831  if ((*out)) {
832  break;
833  }
834  free(in);
835  free(out);
836  return 0;
837  }
838  }
839  outlen = outlen > 0 ? outlen - 1 : 0;
840  if (outlen > len) { // should never happen
841  eprintf("rz_cons_grep_line: how you have reached this?\n");
842  free(in);
843  free(out);
844  return -1;
845  }
846  memcpy(buf, out, len);
847  len = outlen;
848  }
849  } else {
850  len = 0;
851  }
852  free(in);
853  free(out);
854  if (grep->sort != -1) {
855  char ch = buf[len];
856  buf[len] = 0;
857  if (!sorted_lines) {
859  }
860  if (!unsorted_lines) {
862  }
863  if (cons->lines >= grep->sort_row) {
865  } else {
867  }
868  buf[len] = ch;
869  }
870 
871  return len;
872 }
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static RzList * sorted_lines
Definition: grep.c:66
static RzList * unsorted_lines
Definition: grep.c:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static int hit(RzSearchKeyword *kw, void *user, ut64 addr)
Definition: rz-find.c:58
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
RZ_API void rz_str_case(char *str, bool up)
Definition: str.c:341
RZ_API const char * rz_strstr_ansi(const char *a, const char *b)
Definition: str.c:2742
#define RZ_BETWEEN(x, y, z)
int lines
Definition: rz_cons.h:507

References rz_cons_grep_t::amp, rz_cons_grep_t::begin, calloc(), rz_cons_t::context, rz_cons_grep_t::end, eprintf, rz_cons_grep_t::f_line, free(), rz_cons_context_t::grep, hit(), i, rz_cons_grep_t::icase, in, rz_cons_grep_t::l_line, len, rz_cons_grep_t::line, rz_cons_t::lines, memcpy(), rz_cons_grep_t::neg, rz_cons_grep_t::nstrings, NULL, out, p, rz_cons_grep_t::range_line, RZ_BETWEEN, RZ_CONS_GREP_TOKENS, rz_cons_singleton(), rz_list_append(), rz_list_newf(), rz_str_case(), rz_strstr_ansi(), rz_cons_grep_t::sort, rz_cons_grep_t::sort_row, sorted_lines, cmd_descs_generate::str, strdup(), rz_cons_grep_t::strings, rz_cons_grep_t::tokens, rz_cons_grep_t::tokens_used, and unsorted_lines.

Referenced by rz_cons_grepbuf().

◆ rz_cons_grep_parsecmd()

RZ_API void rz_cons_grep_parsecmd ( char *  cmd,
const char *  quotestr 
)

Definition at line 401 of file grep.c.

401  {
402  rz_return_if_fail(cmd && quotestr);
403  char *ptr = preprocess_filter_expr(cmd, quotestr);
404  if (ptr) {
405  rz_str_trim(cmd);
407  free(ptr);
408  }
409 }
static char * preprocess_filter_expr(char *cmd, const char *quotes)
Definition: grep.c:363
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190

References cmd, free(), parse_grep_expression(), preprocess_filter_expr(), rz_return_if_fail, and rz_str_trim().

Referenced by rz_core_cmd_pipe_old(), and rz_core_cmd_subst_i().

◆ rz_cons_grep_process()

RZ_API void rz_cons_grep_process ( char *  grep)

Definition at line 421 of file grep.c.

421  {
422  if (grep) {
423  parse_grep_expression(grep);
424  free(grep);
425  }
426 }

References free(), and parse_grep_expression().

Referenced by DEFINE_HANDLE_TS_FCN_AND_SYMBOL(), and rz_core_cmd_subst_i().

◆ rz_cons_grep_strip()

RZ_API char* rz_cons_grep_strip ( char *  cmd,
const char *  quotestr 
)

Definition at line 411 of file grep.c.

411  {
412  char *ptr = NULL;
413 
414  if (cmd) {
415  ptr = preprocess_filter_expr(cmd, quotestr);
416  rz_str_trim(cmd);
417  }
418  return ptr;
419 }

References cmd, NULL, preprocess_filter_expr(), and rz_str_trim().

Referenced by DEFINE_HANDLE_TS_FCN_AND_SYMBOL(), and rz_core_cmd_subst_i().

◆ rz_cons_grepbuf()

RZ_API void rz_cons_grepbuf ( void  )

Definition at line 463 of file grep.c.

463  {
464  RzCons *cons = rz_cons_singleton();
465  cons->context->row = 0;
466  cons->context->col = 0;
467  cons->context->rowcol_calc_start = 0;
468  const char *buf = cons->context->buffer;
469  const int len = cons->context->buffer_len;
470  RzConsGrep *grep = &cons->context->grep;
471  const char *in = buf;
472  int ret, total_lines = 0, l = 0, tl = 0;
473  bool show = false;
474  if (cons->filter) {
475  cons->context->buffer_len = 0;
476  RZ_FREE(cons->context->buffer);
477  return;
478  }
479 
480  if ((!len || !buf || buf[0] == '\0') && (grep->json || grep->less)) {
481  grep->json = 0;
482  grep->less = 0;
483  grep->hud = 0;
484  return;
485  }
486 
487  if (grep->zoom) {
488  char *in = calloc(cons->context->buffer_len + 2, 4);
489  strcpy(in, cons->context->buffer);
490  char *out = rz_str_scale(in, grep->zoom * 2, grep->zoomy ? grep->zoomy : grep->zoom);
491  if (out) {
492  free(cons->context->buffer);
493  cons->context->buffer = out;
494  cons->context->buffer_len = strlen(out);
495  cons->context->buffer_sz = cons->context->buffer_len;
496  }
497  grep->zoom = 0;
498  grep->zoomy = 0;
499  free(in);
500  return;
501  }
502  if (grep->json) {
503  if (grep->json_path) {
504  RzJson *json = rz_json_parse(cons->context->buffer);
505  if (!json) {
506  RZ_FREE(grep->json_path);
507  return;
508  }
509  const RzJson *excerpt;
510  // To simplify grep syntax we omit brackets in `[0]` for JSON paths
511  if (*grep->json_path != '[' && *grep->json_path != '.') {
512  char *tmppath = rz_str_newf("[%s]", grep->json_path);
513  excerpt = rz_json_get_path(json, tmppath);
514  free(tmppath);
515  } else {
516  excerpt = rz_json_get_path(json, grep->json_path);
517  }
518  if (excerpt) {
519  // When we receive the path, it's fetched with the key name
520  // We should get only the value
521  char *u = rz_json_as_string(excerpt, false);
522  if (!u) {
523  RZ_FREE(grep->json_path);
524  return;
525  }
526  cons->context->buffer = u;
527  cons->context->buffer_len = strlen(u);
528  cons->context->buffer_sz = cons->context->buffer_len + 1;
529  grep->json = 0;
530  rz_cons_newline();
531  }
532  RZ_FREE(grep->json_path);
533  } else {
534  const char *palette[] = {
535  cons->context->pal.graph_false, // f
536  cons->context->pal.graph_true, // t
537  cons->context->pal.num, // k
538  cons->context->pal.comment, // v
539  Color_RESET,
540  NULL
541  };
542  char *bb = strdup(buf);
543  rz_str_ansi_filter(bb, NULL, NULL, -1);
544  char *out = (cons->context->grep.human)
545  ? rz_print_json_human(bb)
546  : rz_print_json_indent(bb, I(context->color_mode), " ", palette);
547  free(bb);
548  if (!out) {
549  return;
550  }
551  free(cons->context->buffer);
552  cons->context->buffer = out;
553  cons->context->buffer_len = strlen(out);
554  cons->context->buffer_sz = cons->context->buffer_len + 1;
555  grep->json = 0;
556  if (grep->hud) {
557  grep->hud = false;
559  } else if (grep->less) {
560  grep->less = 0;
562  }
563  }
564  return;
565  // cons->lines = ?? return 3;
566  }
567  if (grep->less) {
568  int less = grep->less;
569  grep->less = 0;
570  if (less == 2) {
571  char *res = rz_cons_hud_string(buf);
572  if (res) {
573  rz_cons_println(res);
574  free(res);
575  }
576  } else {
578  cons->context->buffer_len = 0;
579  if (cons->context->buffer) {
580  cons->context->buffer[0] = 0;
581  }
582  RZ_FREE(cons->context->buffer);
583  }
584  return;
585  }
586  if (!cons->context->buffer) {
587  cons->context->buffer_len = len + 20;
588  cons->context->buffer = malloc(cons->context->buffer_len);
589  cons->context->buffer[0] = 0;
590  }
591  RzStrBuf *ob = rz_strbuf_new("");
592  // if we modify cons->lines we should update I.context->buffer too
593  cons->lines = 0;
594  // used to count lines and change negative grep.line values
595  while ((int)(size_t)(in - buf) < len) {
596  char *p = strchr(in, '\n');
597  if (!p) {
598  break;
599  }
600  l = p - in;
601  if (l > 0) {
602  in += l + 1;
603  } else {
604  in++;
605  }
606  total_lines++;
607  }
608  if (!grep->range_line && grep->line < 0) {
609  grep->line = total_lines + grep->line;
610  }
611  if (grep->range_line == 1) {
612  if (grep->f_line < 0) {
613  grep->f_line = total_lines + grep->f_line;
614  }
615  if (grep->l_line <= 0) {
616  grep->l_line = total_lines + grep->l_line;
617  }
618  }
619  bool is_range_line_grep_only = grep->range_line != 2 && !*grep->str;
620  in = buf;
621  while ((int)(size_t)(in - buf) < len) {
622  char *p = strchr(in, '\n');
623  if (!p) {
624  break;
625  }
626  l = p - in;
627  if ((!l && is_range_line_grep_only) || l > 0) {
628  char *tline = rz_str_ndup(in, l);
629  if (cons->grep_color) {
630  tl = l;
631  } else {
632  tl = rz_str_ansi_filter(tline, NULL, NULL, l);
633  }
634  if (tl < 0) {
635  ret = -1;
636  } else {
637  ret = rz_cons_grep_line(tline, tl);
638  if (!grep->range_line) {
639  if (grep->line == cons->lines) {
640  show = true;
641  }
642  } else if (grep->range_line == 1) {
643  if (grep->f_line == cons->lines) {
644  show = true;
645  }
646  if (grep->l_line == cons->lines) {
647  show = false;
648  }
649  } else {
650  show = true;
651  }
652  }
653  if ((!ret && is_range_line_grep_only) || ret > 0) {
654  if (show) {
655  char *str = rz_str_ndup(tline, ret);
656  if (cons->grep_highlight) {
657  int i;
658  for (i = 0; i < grep->nstrings; i++) {
659  char *newstr = rz_str_newf(Color_INVERT "%s" Color_RESET, grep->strings[i]);
660  if (str && newstr) {
661  if (grep->icase) {
662  str = rz_str_replace_icase(str, grep->strings[i], newstr, 1, 1);
663  } else {
664  str = rz_str_replace(str, grep->strings[i], newstr, 1);
665  }
666  }
667  free(newstr);
668  }
669  }
670  if (str) {
671  rz_strbuf_append(ob, str);
672  rz_strbuf_append(ob, "\n");
673  }
674  free(str);
675  }
676  if (!grep->range_line) {
677  show = false;
678  }
679  cons->lines++;
680  } else if (ret < 0) {
681  free(tline);
682  return;
683  }
684  free(tline);
685  in += l + 1;
686  } else {
687  in++;
688  }
689  }
690 
691  cons->context->buffer_len = rz_strbuf_length(ob);
692  if (grep->counter) {
693  int cnt = grep->charCounter ? strlen(cons->context->buffer) : cons->lines;
694  if (cons->context->buffer_len < 10) {
695  cons->context->buffer_len = 10; // HACK
696  }
697  snprintf(cons->context->buffer, cons->context->buffer_len, "%d\n", cnt);
698  cons->context->buffer_len = strlen(cons->context->buffer);
699  cons->num->value = cons->lines;
700  rz_strbuf_free(ob);
701  return;
702  }
703 
704  const int ob_len = rz_strbuf_length(ob);
705  if (ob_len >= cons->context->buffer_sz) {
706  cons->context->buffer_sz = ob_len + 1;
707  cons->context->buffer = rz_strbuf_drain(ob);
708  } else {
709  memcpy(cons->context->buffer, rz_strbuf_getbin(ob, NULL), ob_len);
710  cons->context->buffer[ob_len] = 0;
711  rz_strbuf_free(ob);
712  }
713  cons->context->buffer_len = ob_len;
714 
715  if (grep->sort != -1) {
716 #define INSERT_LINES(list) \
717  do { \
718  rz_list_foreach (list, iter, str) { \
719  int len = strlen(str); \
720  memcpy(ptr, str, len); \
721  memcpy(ptr + len, "\n", 2); \
722  ptr += len + 1; \
723  nl++; \
724  } \
725  } while (false)
726 
727  RzListIter *iter;
728  int nl = 0;
729  char *ptr = cons->context->buffer;
730  char *str;
731  sorted_column = grep->sort;
733  if (grep->sort_invert) {
735  }
738  cons->lines = nl;
740  sorted_lines = NULL;
743  }
744 }
static RASN1String * newstr(const char *string)
Definition: astr.c:23
static RzBinSourceLineInfo * lines(RzBinFile *bf)
Definition: bin_symbols.c:427
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
#define INSERT_LINES(list)
RZ_API int rz_cons_grep_line(char *buf, int len)
Definition: grep.c:746
#define I(x)
Definition: grep.c:9
static int cmp(const void *a, const void *b)
Definition: grep.c:428
RZ_API char * rz_cons_hud_string(const char *s)
Definition: hud.c:22
RZ_API char * rz_print_json_indent(const char *s, bool color, const char *tab, const char **palette)
Definition: json_indent.c:254
RZ_API char * rz_print_json_human(const char *s)
Definition: json_indent.c:155
snprintf
Definition: kernel.h:364
RZ_API int rz_cons_less_str(const char *str, const char *exitkeys)
Definition: less.c:10
RZ_API void rz_list_reverse(RZ_NONNULL RzList *list)
Reverses the list.
Definition: list.c:477
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
#define Color_RESET
Definition: rz_cons.h:617
#define Color_INVERT
Definition: rz_cons.h:606
RZ_API const RzJson * rz_json_get_path(const RzJson *json, const char *path)
Definition: json_parser.c:419
RZ_API RzJson * rz_json_parse(char *text)
Definition: json_parser.c:382
RZ_API RZ_OWN char * rz_json_as_string(const RzJson *json, bool with_key)
Definition: json_parser.c:546
RZ_API char * rz_str_replace_icase(char *str, const char *key, const char *val, int g, int keep_case)
Definition: str.c:1160
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API char * rz_str_scale(const char *r, int w, int h)
Definition: str.c:3921
RZ_API int rz_str_ansi_filter(char *str, char **out, int **cposs, int len)
Definition: str.c:2124
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API ut8 * rz_strbuf_getbin(RzStrBuf *sb, int *len)
Definition: strbuf.c:326
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
#define RZ_FREE(x)
Definition: rz_types.h:369
RzConsPrintablePalette pal
Definition: rz_cons.h:491
size_t buffer_sz
Definition: rz_cons.h:470
int rowcol_calc_start
Definition: rz_cons.h:496
size_t buffer_len
Definition: rz_cons.h:469
bool grep_highlight
Definition: rz_cons.h:568
bool grep_color
Definition: rz_cons.h:567
ut64 value
Definition: rz_num.h:63

References rz_cons_context_t::buffer, rz_cons_context_t::buffer_len, rz_cons_context_t::buffer_sz, calloc(), rz_cons_grep_t::charCounter, cmp(), rz_cons_context_t::col, Color_INVERT, Color_RESET, rz_cons_printable_palette_t::comment, rz_cons_t::context, rz_cons_grep_t::counter, rz_cons_grep_t::f_line, rz_cons_t::filter, free(), rz_cons_printable_palette_t::graph_false, rz_cons_printable_palette_t::graph_true, rz_cons_context_t::grep, rz_cons_t::grep_color, rz_cons_t::grep_highlight, rz_cons_grep_t::hud, rz_cons_grep_t::human, I, i, rz_cons_grep_t::icase, in, INSERT_LINES, rz_cons_grep_t::json, rz_cons_grep_t::json_path, rz_cons_grep_t::l_line, len, rz_cons_grep_t::less, rz_cons_grep_t::line, rz_cons_t::lines, malloc(), memcpy(), newstr(), rz_cons_grep_t::nstrings, NULL, rz_cons_printable_palette_t::num, rz_cons_t::num, out, p, rz_cons_context_t::pal, rz_cons_grep_t::range_line, rz_cons_context_t::row, rz_cons_context_t::rowcol_calc_start, rz_cons_grep_line(), rz_cons_hud_string(), rz_cons_less_str(), rz_cons_newline(), rz_cons_println(), rz_cons_singleton(), RZ_FREE, rz_json_as_string(), rz_json_get_path(), rz_json_parse(), rz_list_free(), rz_list_reverse(), rz_list_sort(), rz_print_json_human(), rz_print_json_indent(), rz_str_ansi_filter(), rz_str_ndup(), rz_str_newf(), rz_str_replace(), rz_str_replace_icase(), rz_str_scale(), rz_strbuf_append(), rz_strbuf_drain(), rz_strbuf_free(), rz_strbuf_getbin(), rz_strbuf_length(), rz_strbuf_new(), snprintf, rz_cons_grep_t::sort, rz_cons_grep_t::sort_invert, sorted_column, sorted_lines, cmd_descs_generate::str, rz_cons_grep_t::str, strdup(), rz_cons_grep_t::strings, unsorted_lines, rz_num_t::value, rz_cons_grep_t::zoom, and rz_cons_grep_t::zoomy.

Referenced by rz_cons_filter(), and rz_cons_grep().

◆ strchr_ns()

static char* strchr_ns ( char *  s,
const char  ch 
)
static

Definition at line 11 of file grep.c.

11  {
12  char *p = strchr(s, ch);
13  if (p && p > s) {
14  char *prev = p - 1;
15  if (*prev == '\\') {
16  memmove(prev, p, strlen(p) + 1);
17  return strchr_ns(p, ch);
18  }
19  }
20  return p;
21 }
static RzSocket * s
Definition: rtr.c:28

References p, and s.

Referenced by parse_grep_expression().

Variable Documentation

◆ help_detail_tilde

const char* help_detail_tilde[]
static

Definition at line 23 of file grep.c.

Referenced by rz_cons_grep_help().

◆ sorted_column

int sorted_column = -1
static

Definition at line 68 of file grep.c.

Referenced by cmp(), parse_grep_expression(), and rz_cons_grepbuf().

◆ sorted_lines

RzList* sorted_lines = NULL
static

Definition at line 66 of file grep.c.

Referenced by rz_cons_grep_line(), and rz_cons_grepbuf().

◆ unsorted_lines

RzList* unsorted_lines = NULL
static

Definition at line 67 of file grep.c.

Referenced by rz_cons_grep_line(), and rz_cons_grepbuf().