static void color_line(const char *line, RStrpool *p, RList *ml){ int m_len, offset = 0; char *m_addr; RListIter *it; RRegexMatch *m; char *inv[2] = { R_CONS_INVERT (true, true), R_CONS_INVERT (false, true) }; int linv[2] = { strlen (inv[0]), strlen(inv[1]) }; r_strpool_empty (p); r_list_foreach (ml, it, m) { /* highlight a match */ r_strpool_memcat (p, line + offset, m->rm_so - offset); r_strpool_memcat (p, inv[0], linv[0]); m_len = m->rm_eo - m->rm_so; if (m_len<0) m_len = 0; m_addr = r_str_ndup (line + m->rm_so, m_len); if (m_addr) { /* in case there's a CSI in the middle of this match*/ m_len = r_str_ansi_filter (m_addr, NULL, NULL, m_len); if (m_len<0) m_len = 0; r_strpool_memcat (p, m_addr, m_len); r_strpool_memcat (p, inv[1], linv[1]); offset = m->rm_eo; free(m_addr); } }
static int all_matches(const char *s, RRegex *rx, RRegexMatch **ms, int *lines, int lcount){ int num, l, fnd, f = R_FALSE; RRegexMatch m; int slen; for(l = 0; l < lcount; l++){ num = 0; m.rm_so = 0; const char *loff = s + lines[l]; /* current line offset */ char *clean = strdup(loff); int *cpos; r_str_ansi_filter(clean, NULL, &cpos, 0); m.rm_eo = slen = strlen(clean); memset(ms[l], 0, NMATCHES * sizeof(RRegexMatch)); while(num < NMATCHES){ fnd = r_regex_exec(rx, clean, 1, &m, R_REGEX_STARTEND); if(!fnd) { ms[l][num].rm_so = cpos[m.rm_so]; ms[l][num].rm_eo = cpos[m.rm_eo]; m.rm_so = m.rm_eo; m.rm_eo = slen; f = R_TRUE; num++; } else break; /* no more on this line */ } free(cpos); free(clean); } return f; }
R_API char* r_str_replace_thunked(char *str, char *clean, int *thunk, int clen, const char *key, const char *val, int g) { int i, klen, vlen, slen, delta = 0, bias; char *newstr, *scnd, *p = clean, *str_p; if (!str || !key || !val || !clean || !thunk) return NULL; klen = strlen (key); vlen = strlen (val); if (klen == vlen && !strcmp (key, val)) return str; slen = strlen (str) + 1; for (i = 0; i < clen; ) { bias = 0; p = (char *)r_mem_mem ( (const ut8*)clean + i, clen - i, (const ut8*)key, klen); if (!p) break; i = (int)(size_t)(p - clean); /* as the original string changes size during replacement * we need delta to keep track of it*/ str_p = str + thunk[i] + delta; if (r_str_ansi_chrn(str_p, klen) - str_p > klen) { /* f**k, we're trying to highlight * a string with a CSI in the middle * avoid color breakage and disable this particular * CSIs */ int newo = thunk[i + klen] - thunk[i]; r_str_ansi_filter(str_p, NULL, NULL, newo); scnd = strdup (str_p + newo); bias = vlen - newo; } else { scnd = strdup (str_p + klen); bias = vlen - klen; } slen += bias; // HACK: this 32 avoids overwrites wtf newstr = realloc (str, slen + klen); if (!newstr) { eprintf ("realloc fail\n"); free (str); free (scnd); str = NULL; break; } str = newstr; str_p = str + thunk[i] + delta; memcpy (str_p, val, vlen); memcpy (str_p + vlen, scnd, strlen (scnd) + 1); i += klen; delta += bias; free (scnd); if (!g) break; } return str; }
/* replace the key in str with val. * * str - input string * clean - input string cleaned of ANSI chars * thunk - array of integers that map each char of the clean string into the * position in the str string * clen - number of elements in thunk * key - string to find in the clean string * val - string that replaces key in the str string * g - if true, replace all occurences of key * * It returns a pointer to the modified string */ R_API char* r_str_replace_thunked(char *str, char *clean, int *thunk, int clen, const char *key, const char *val, int g) { int i, klen, vlen, slen, delta = 0, bias; char *newstr, *scnd, *p = clean, *str_p; if (!str || !key || !val || !clean || !thunk) { return NULL; } klen = strlen (key); vlen = strlen (val); if (klen == vlen && !strcmp (key, val)) { return str; } slen = strlen (str) + 1; for (i = 0; i < clen; ) { int newo; bias = 0; p = (char *)r_mem_mem ( (const ut8*)clean + i, clen - i, (const ut8*)key, klen); if (!p) { break; } i = (int)(size_t)(p - clean); /* as the original string changes size during replacement * we need delta to keep track of it*/ str_p = str + thunk[i] + delta; newo = thunk[i + klen] - thunk[i]; r_str_ansi_filter(str_p, NULL, NULL, newo); scnd = strdup (str_p + newo); bias = vlen - newo; slen += bias; // HACK: this 32 avoids overwrites wtf newstr = realloc (str, slen + klen); if (!newstr) { eprintf ("realloc fail\n"); free (str); free (scnd); str = NULL; break; } str = newstr; str_p = str + thunk[i] + delta; memcpy (str_p, val, vlen); memcpy (str_p + vlen, scnd, strlen (scnd) + 1); i += klen; delta += bias; free (scnd); if (!g) { break; } } return str; }
R_API int r_cons_grepbuf(char *buf, int len) { RCons *cons = r_cons_singleton (); char *tline, *tbuf, *p, *out, *in = buf; int ret, buffer_len = 0, l = 0, tl = 0; if (!cons->buffer) { cons->buffer_len = len+20; cons->buffer = malloc (cons->buffer_len); cons->buffer[0] = 0; } out = tbuf = calloc (1, len); tline = malloc (len); cons->lines = 0; while (in-buf<len) { p = strchr (in, '\n'); if (!p) { free (tbuf); free (tline); return 0; } l = p-in; if (l > 0) { memcpy (tline, in, l); tl = r_str_ansi_filter (tline, l); if (tl < 0) ret = -1; else ret = r_cons_grep_line (tline, tl); if (ret > 0) { if (cons->grep.line == -1 || (cons->grep.line != -1 && cons->grep.line == cons->lines)) { memcpy (out, tline, ret); memcpy (out+ret, "\n", 1); out += ret+1; buffer_len += ret+1; } cons->lines++; } else if (ret < 0) { free (tbuf); free (tline); return 0; } in += l+1; } else in++; } memcpy (buf, tbuf, len); cons->buffer_len = buffer_len; free (tbuf); free (tline); if (cons->grep.counter) { if (cons->buffer_len<10) cons->buffer_len = 10; // HACK snprintf (cons->buffer, cons->buffer_len, "%d\n", cons->lines); cons->buffer_len = strlen (cons->buffer); } return cons->lines; }
R_API void r_cons_highlight (const char *word) { int l, *cpos; char *rword, *res, *clean; char *inv[2] = { R_CONS_INVERT (true, true), R_CONS_INVERT (false, true) }; int linv[2] = { strlen (inv[0]), strlen (inv[1]) }; if (word && *word && I.buffer) { int word_len = strlen (word); char *orig; clean = I.buffer; l = r_str_ansi_filter (clean, &orig, &cpos, 0); I.buffer = orig; if (I.highlight) { if (strcmp (word, I.highlight)) { free (I.highlight); I.highlight = strdup (word); } } else { I.highlight = strdup (word); } rword = malloc (word_len + linv[0] + linv[1] + 1); if (!rword) { free (cpos); return; } strcpy (rword, inv[0]); strcpy (rword + linv[0], word); strcpy (rword + linv[0] + word_len, inv[1]); res = r_str_replace_thunked (I.buffer, clean, cpos, l, word, rword, 1); if (res) { I.buffer = res; I.buffer_len = I.buffer_sz = strlen (res); } free (rword); free (clean); free (cpos); /* don't free orig - it's assigned * to I.buffer and possibly realloc'd */ } else { free (I.highlight); I.highlight = NULL; } }
static void color_line(const char *line, RStrpool *p, RRegexMatch *ms){ int i, m_len; int offset = 0; char *m_addr; char *inv[2] = {R_CONS_INVERT(R_TRUE, R_TRUE), R_CONS_INVERT(R_FALSE, R_TRUE)}; int linv[2] = {strlen(inv[0]), strlen(inv[1])}; r_strpool_empty(p); for (i = 0; i < NMATCHES; i++) { if (ms[i].rm_eo && (i < NMATCHES - 1)) { /* highlight a match */ r_strpool_memcat (p, line + offset, ms[i].rm_so - offset); r_strpool_memcat (p, inv[0], linv[0]); m_len = ms[i].rm_eo - ms[i].rm_so; m_addr = r_str_ndup (line + ms[i].rm_so, m_len); if (m_addr) { if(r_str_ansi_chrn (m_addr, m_len) - m_addr < m_len ){ /* there's a CSI in the middle of this match*/ m_len = r_str_ansi_filter(m_addr, NULL, NULL, m_len); } r_strpool_memcat (p, m_addr, m_len); r_strpool_memcat (p, inv[1], linv[1]); offset = ms[i].rm_eo; free(m_addr); } } else { /* append final part of string w/o matches */ r_strpool_append(p, line + offset); break; } } }
R_API int r_cons_grepbuf(char *buf, int len) { RCons *cons = r_cons_singleton (); char *tline, *tbuf, *p, *out, *in = buf; int ret, total_lines = 0, buffer_len = 0, l = 0, tl = 0; bool show = false; if (cons->filter) { cons->buffer_len = 0; R_FREE (cons->buffer); return 0; } if ((!len || !buf || buf[0] == '\0') && (cons->grep.json || cons->grep.less)) { cons->grep.json = 0; cons->grep.less = 0; return 0; } if (cons->grep.json) { if (cons->grep.json_path) { char *u = sdb_json_get_str (cons->buffer, cons->grep.json_path); if (u) { cons->buffer = u; cons->buffer_len = strlen (u); cons->buffer_sz = cons->buffer_len + 1; cons->grep.json = 0; r_cons_newline (); } R_FREE (cons->grep.json_path); } else { const char *palette[] = { cons->pal.graph_false, // f cons->pal.graph_true, // t cons->pal.num, // k cons->pal.comment, // v Color_RESET, NULL }; char *out = r_print_json_indent (buf, I (color), " ", palette); if (!out) { return 0; } free (cons->buffer); cons->buffer = out; cons->buffer_len = strlen (out); cons->buffer_sz = cons->buffer_len + 1; cons->grep.json = 0; if (cons->grep.less) { cons->grep.less = 0; r_cons_less_str (cons->buffer, NULL); } } return 3; } if (cons->grep.less) { int less = cons->grep.less; cons->grep.less = 0; if (less == 2) { char *res = r_cons_hud_string (buf); r_cons_println (res); free (res); } else { r_cons_less_str (buf, NULL); buf[0] = 0; cons->buffer_len = 0; if (cons->buffer) { cons->buffer[0] = 0; } R_FREE (cons->buffer); } return 0; } if (!cons->buffer) { cons->buffer_len = len + 20; cons->buffer = malloc (cons->buffer_len); cons->buffer[0] = 0; } out = tbuf = calloc (1, len); if (!out) { return 0; } tline = malloc (len); if (!tline) { free (out); return 0; } cons->lines = 0; // used to count lines and change negative grep.line values while ((int) (size_t) (in - buf) < len) { p = strchr (in, '\n'); if (!p) { break; } l = p - in; if (l > 0) { in += l + 1; } else { in++; } total_lines++; } if (!cons->grep.range_line && cons->grep.line < 0) { cons->grep.line = total_lines + cons->grep.line; } if (cons->grep.range_line == 1) { if (cons->grep.f_line < 0) { cons->grep.f_line = total_lines + cons->grep.f_line; } if (cons->grep.l_line < 0) { cons->grep.l_line = total_lines + cons->grep.l_line; } } in = buf; while ((int) (size_t) (in - buf) < len) { p = strchr (in, '\n'); if (!p) { free (tbuf); free (tline); return 0; } l = p - in; if (l > 0) { memcpy (tline, in, l); if (cons->grep_color) { tl = l; } else { tl = r_str_ansi_filter (tline, NULL, NULL, l); } if (tl < 0) { ret = -1; } else { ret = r_cons_grep_line (tline, tl); if (!cons->grep.range_line) { if (cons->grep.line == cons->lines) { show = true; } } else if (cons->grep.range_line == 1) { if (cons->grep.f_line == cons->lines) { show = true; } if (cons->grep.l_line == cons->lines) { show = false; } } else { show = true; } } if (ret > 0) { if (show) { memcpy (out, tline, ret); memcpy (out + ret, "\n", 1); out += ret + 1; buffer_len += ret + 1; } if (!cons->grep.range_line) { show = false; } cons->lines++; } else if (ret < 0) { free (tbuf); free (tline); return 0; } in += l + 1; } else { in++; } } memcpy (buf, tbuf, len); cons->buffer_len = buffer_len; free (tbuf); free (tline); if (cons->grep.counter) { int cnt = cons->grep.charCounter? strlen (cons->buffer): cons->lines; if (cons->buffer_len < 10) { cons->buffer_len = 10; // HACK } snprintf (cons->buffer, cons->buffer_len, "%d\n", cnt); cons->buffer_len = strlen (cons->buffer); cons->num->value = cons->lines; } if (cons->grep.sort != -1) { #define INSERT_LINES(list)\ do {\ r_list_foreach (list, iter, str) {\ int len = strlen (str);\ memcpy (ptr, str, len);\ memcpy (ptr + len, "\n", 2);\ ptr += len + 1;\ nl++;\ }\ }\ while (false) RListIter *iter; int nl = 0; char *ptr = cons->buffer; char *str; sorted_column = cons->grep.sort; r_list_sort (sorted_lines, cmp); if (cons->grep.sort_invert) { r_list_reverse (sorted_lines); } INSERT_LINES (unsorted_lines); INSERT_LINES (sorted_lines); cons->lines = nl; r_list_free (sorted_lines); sorted_lines = NULL; r_list_free (unsorted_lines); unsorted_lines = NULL; } return cons->lines; }
R_API int r_cons_grepbuf(char *buf, int len) { RCons *cons = r_cons_singleton (); char *tline, *tbuf, *p, *out, *in = buf; int ret, buffer_len = 0, l = 0, tl = 0; if ((len == 0 || buf == NULL || buf[0] == '\0') && (cons->grep.json || cons->grep.less)) { cons->grep.json = 0; cons->grep.less = 0; return 0; } if (cons->grep.json) { char *out = sdb_json_indent (buf); free (cons->buffer); cons->buffer = out; cons->buffer_len = strlen (out); cons->buffer_sz = cons->buffer_len + 1; cons->grep.json = 0; if (cons->grep.less) { cons->grep.less = 0; r_cons_less_str (cons->buffer, NULL); } return 3; } if (cons->grep.less) { cons->grep.less = 0; r_cons_less_str (buf, NULL); buf[0] = 0; cons->buffer_len = 0; if (cons->buffer) cons->buffer[0] = 0; free (cons->buffer); cons->buffer = NULL; return 0; } if (!cons->buffer) { cons->buffer_len = len + 20; cons->buffer = malloc (cons->buffer_len); cons->buffer[0] = 0; } out = tbuf = calloc (1, len); tline = malloc (len); cons->lines = 0; while ((int)(size_t)(in-buf) < len) { p = strchr (in, '\n'); if (!p) { free (tbuf); free (tline); return 0; } l = p - in; if (l > 0) { memcpy (tline, in, l); tl = r_str_ansi_filter (tline, NULL, NULL, l); if (tl < 0) ret = -1; else ret = r_cons_grep_line (tline, tl); if (ret > 0) { if (cons->grep.line == -1 || (cons->grep.line != -1 && cons->grep.line == cons->lines)) { memcpy (out, tline, ret); memcpy (out + ret, "\n", 1); out += ret + 1; buffer_len += ret + 1; } cons->lines++; } else if (ret < 0) { free (tbuf); free (tline); return 0; } in += l + 1; } else in++; } memcpy (buf, tbuf, len); cons->buffer_len = buffer_len; free (tbuf); free (tline); if (cons->grep.counter) { if (cons->buffer_len < 10) cons->buffer_len = 10; // HACK snprintf (cons->buffer, cons->buffer_len, "%d\n", cons->lines); cons->buffer_len = strlen (cons->buffer); } return cons->lines; }