R_API void r_cons_grep(const char *str) { int wlen, len; RCons *cons; char buf[4096]; char *ptr, *optr, *ptr2, *ptr3; if (!str || !*str) return; cons = r_cons_singleton (); cons->grep.str = NULL; cons->grep.neg = 0; cons->grep.amp = 0; cons->grep.end = 0; cons->grep.begin = 0; cons->grep.nstrings = 0; cons->grep.tokenfrom = 0; cons->grep.tokento = ST32_MAX; cons->grep.line = -1; cons->grep.counter = cons->grep.neg = 0; while (*str) { switch (*str) { case '&': str++; cons->grep.amp = 1; break; case '^': str++; cons->grep.begin = 1; break; case '!': str++; cons->grep.neg = 1; break; case '?': str++; cons->grep.counter = 1; if (*str=='?') { r_cons_grep_help (); return; } break; default: goto while_end; } } while_end: len = strlen (str)-1; if (len>0 && str[len] == '?') { cons->grep.counter = 1; strncpy (buf, str, R_MIN (len, sizeof (buf)-1)); buf[len]=0; len--; } else strncpy (buf, str, sizeof (buf)-1); if (len>1 && buf[len]=='$' && buf[len-1]!='\\') { cons->grep.end = 1; buf[len] = 0; } ptr = buf; ptr3 = strchr (ptr, '['); // column number if (ptr3) { ptr3[0] = '\0'; cons->grep.tokenfrom = r_num_get (cons->num, ptr3+1); ptr3 = strchr (ptr3+1, '-'); if (ptr3) { cons->grep.tokento = r_num_get (cons->num, ptr3+1); if (cons->grep.tokento == 0) cons->grep.tokento = ST32_MAX; } else cons->grep.tokento = cons->grep.tokenfrom; if (cons->grep.tokenfrom<0) cons->grep.tokenfrom = 0; if (cons->grep.tokento<0) cons->grep.tokento = ST32_MAX; } ptr2 = strchr (ptr, ':'); // line number if (ptr2) { *ptr2 = '\0'; cons->grep.line = r_num_get (cons->num, ptr2+1); if (cons->grep.line<0) cons->grep.line = -1; } free (cons->grep.str); if (*ptr) { cons->grep.str = (char *)strdup (ptr); do { optr = ptr; ptr = strchr (ptr, ','); // grep keywords if (ptr) *ptr++ = '\0'; wlen = strlen (optr); if (wlen==0) continue; if (wlen>=R_CONS_GREP_WORD_SIZE-1) { eprintf ("grep string too long\n"); continue; } strncpy (cons->grep.strings[cons->grep.nstrings], optr, R_CONS_GREP_WORD_SIZE-1); cons->grep.nstrings++; if (cons->grep.nstrings>R_CONS_GREP_WORDS-1) { eprintf ("too many grep strings\n"); break; } } while (ptr); } else { cons->grep.str = strdup (ptr); cons->grep.nstrings++; cons->grep.strings[0][0] = 0; } }
static void parse_grep_expression(const char *str) { static char buf[R_CONS_GREP_BUFSIZE]; int wlen, len, is_range, num_is_parsed, fail = 0; char *ptr, *optr, *ptr2, *ptr3; ut64 range_begin, range_end; RCons *cons; if (!str || !*str) { return; } cons = r_cons_singleton (); memset (&(cons->grep), 0, sizeof (cons->grep)); sorted_column = 0; cons->grep.sort = -1; cons->grep.line = -1; bool first = true; while (*str) { switch (*str) { case '.': if (str[1] == '.') { if (str[2] == '.') { cons->grep.less = 2; } else { cons->grep.less = 1; } return; } str++; break; case '{': if (str[1] == '}') { cons->grep.json = 1; if (!strncmp (str, "{}..", 4)) { cons->grep.less = 1; } } else { char *jsonPath = strdup (str + 1); char *jsonPathEnd = strchr (jsonPath, '}'); if (jsonPathEnd) { *jsonPathEnd = 0; free (cons->grep.json_path); cons->grep.json_path = jsonPath; cons->grep.json = 1; } else { free (jsonPath); } return; } str++; break; case '$': str++; if (*str == '!') { cons->grep.sort_invert = true; str++; } else { cons->grep.sort_invert = false; } cons->grep.sort = atoi (str); while (IS_DIGIT (*str)) { str++; } if (*str == ':') { cons->grep.sort_row = atoi (++str); str++; } break; case '&': str++; cons->grep.amp = 1; break; case '+': if (first) { str++; cons->grep.icase = 1; } else { goto while_end; } break; case '^': str++; cons->grep.begin = 1; break; case '!': str++; cons->grep.neg = 1; break; case '?': str++; cons->grep.counter = 1; if (*str == '.') { cons->grep.charCounter = true; str++; } else if (*str == '?') { cons->filter = true; r_cons_grep_help (); return; } break; default: goto while_end; } first = false; } while_end: len = strlen (str) - 1; if (len > R_CONS_GREP_BUFSIZE - 1) { eprintf ("r_cons_grep: too long!\n"); return; } if (len > 0 && str[len] == '?') { cons->grep.counter = 1; strncpy (buf, str, R_MIN (len, sizeof (buf) - 1)); buf[len] = 0; len--; } else { strncpy (buf, str, sizeof (buf) - 1); } if (len > 1 && buf[len] == '$' && buf[len - 1] != '\\') { cons->grep.end = 1; buf[len] = 0; } ptr = buf; ptr2 = strchr (ptr, '['); ptr3 = strchr (ptr, ']'); is_range = 0; num_is_parsed = 0; fail = 0; range_begin = range_end = -1; if (ptr2 && ptr3) { ptr2[0] = '\0'; ptr2++; for (; ptr2 <= ptr3; ++ptr2) { if (fail) { ZERO_FILL (cons->grep.tokens); cons->grep.tokens_used = 0; fail = 0; break; } switch (*ptr2) { case '-': is_range = 1; num_is_parsed = 0; range_end = -1; break; case ']': // fallthrough to handle ']' like ',' case ',': for (; range_begin <= range_end; range_begin++) { if (range_begin >= R_CONS_GREP_TOKENS) { fail = 1; break; } cons->grep.tokens[range_begin] = 1; cons->grep.tokens_used = 1; } // 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; } break; default: if (!num_is_parsed) { if (is_range) { range_end = r_num_get (cons->num, ptr2); // 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- ] } } else { range_begin = range_end = r_num_get (cons->num, ptr2); } num_is_parsed = 1; } } } } ptr2 = strchr_ns (ptr, ':'); // line number cons->grep.range_line = 2; // there is not : if (ptr2 && ptr2[1] != ':' && ptr2[1]) { *ptr2 = '\0'; char *p, *token = ptr + 1; p = strstr (token, ".."); if (!p) { cons->grep.line = r_num_get (cons->num, ptr2 + 1); cons->grep.range_line = 0; } else { *p = '\0'; cons->grep.range_line = 1; if (*token) { cons->grep.f_line = r_num_get (cons->num, token); } else { cons->grep.f_line = 0; } if (p[2]) { cons->grep.l_line = r_num_get (cons->num, p + 2); } else { cons->grep.l_line = -1; } } } free (cons->grep.str); if (*ptr) { cons->grep.str = (char *) strdup (ptr); do { optr = ptr; ptr = strchr (ptr, ','); // grep keywords if (ptr) { *ptr++ = '\0'; } wlen = strlen (optr); if (!wlen) { continue; } if (wlen >= R_CONS_GREP_WORD_SIZE - 1) { eprintf ("grep string too long\n"); continue; } strncpy (cons->grep.strings[cons->grep.nstrings], optr, R_CONS_GREP_WORD_SIZE - 1); cons->grep.nstrings++; if (cons->grep.nstrings > R_CONS_GREP_WORDS - 1) { eprintf ("too many grep strings\n"); break; } } while (ptr); } else { cons->grep.str = strdup (ptr); cons->grep.nstrings++; cons->grep.strings[0][0] = 0; } }
R_API void r_cons_grep(const char *str) { int wlen, len, is_range, num_is_parsed, fail = 0; ut64 range_begin, range_end; RCons *cons; char buf[R_CONS_GREP_BUFSIZE]; char *ptr, *optr, *ptr2, *ptr3; if (!str || !*str) return; cons = r_cons_singleton (); memset (&(cons->grep), 0, sizeof (cons->grep)); cons->grep.line = -1; while (*str) { switch (*str) { case '.': if (str[1] == '.') { cons->grep.less = 1; return; } str++; break; case '{': if (str[1] == '}') { cons->grep.json = 1; if (!strncmp (str, "{}..", 4)) cons->grep.less = 1; str++; return; } str++; break; case '&': str++; cons->grep.amp = 1; break; case '^': str++; cons->grep.begin = 1; break; case '!': str++; cons->grep.neg = 1; break; case '?': str++; cons->grep.counter = 1; if (*str == '?') { r_cons_grep_help (); return; } break; default: goto while_end; } } while_end: len = strlen (str) - 1; if (len > R_CONS_GREP_BUFSIZE - 1) { eprintf("r_cons_grep: too long!\n"); return; } if (len > 0 && str[len] == '?') { cons->grep.counter = 1; strncpy (buf, str, R_MIN (len, sizeof (buf) - 1)); buf[len]=0; len--; } else strncpy (buf, str, sizeof (buf) - 1); if (len > 1 && buf[len] == '$' && buf[len - 1] != '\\') { cons->grep.end = 1; buf[len] = 0; } ptr = buf; ptr2 = strchr (ptr, '['); ptr3 = strchr (ptr, ']'); is_range = 0; num_is_parsed = 0; fail = 0; range_begin = range_end = -1; if (ptr2 && ptr3) { ptr2[0] = '\0'; ptr2++; for (; ptr2 <= ptr3; ++ptr2) { if (fail) { memset (cons->grep.tokens, 0, R_CONS_GREP_TOKENS); cons->grep.tokens_used = 0; fail = 0; break; } switch (*ptr2) { case '-': is_range = 1; num_is_parsed = 0; break; case ']': // fallthrough to handle ']' like ',' case ',': for (; range_begin <= range_end; range_begin++) { if (range_begin >= R_CONS_GREP_TOKENS) { fail = 1; break; } cons->grep.tokens[range_begin] = 1; cons->grep.tokens_used = 1; } is_range = 0; num_is_parsed = 0; break; default: if (!num_is_parsed) { if (is_range) { range_end = r_num_get (cons->num, ptr2); } else { range_begin = range_end = r_num_get (cons->num, ptr2); } num_is_parsed = 1; } } } } ptr2 = strchr (ptr, ':'); // line number if (ptr2 && ptr2[1] != ':') { *ptr2 = '\0'; cons->grep.line = r_num_get (cons->num, ptr2 + 1); if (cons->grep.line < 0) { eprintf ("Negative line grep not yet implented\n"); cons->grep.line = -1; } } free (cons->grep.str); if (*ptr) { cons->grep.str = (char *)strdup (ptr); do { optr = ptr; ptr = strchr (ptr, ','); // grep keywords if (ptr) *ptr++ = '\0'; wlen = strlen (optr); if (wlen == 0) continue; if (wlen >= R_CONS_GREP_WORD_SIZE - 1) { eprintf ("grep string too long\n"); continue; } strncpy (cons->grep.strings[cons->grep.nstrings], optr, R_CONS_GREP_WORD_SIZE - 1); cons->grep.nstrings++; if (cons->grep.nstrings > R_CONS_GREP_WORDS - 1) { eprintf ("too many grep strings\n"); break; } } while (ptr); } else { cons->grep.str = strdup (ptr); cons->grep.nstrings++; cons->grep.strings[0][0] = 0; } }