char *regexp_escape(const struct regexp *r) { char *pat = NULL; if (r == NULL) return strdup(""); #if !HAVE_USELOCALE char *nre = NULL; int ret; size_t nre_len; /* Use a range with from > to to force conversion of ranges into * short form */ ret = fa_restrict_alphabet(r->pattern->str, strlen(r->pattern->str), &nre, &nre_len, 2, 1); if (ret == 0) { pat = escape(nre, nre_len, RX_ESCAPES); free(nre); } #endif if (pat == NULL) pat = escape(r->pattern->str, -1, RX_ESCAPES); if (pat == NULL) return NULL; /* Remove unneeded '()' from pat */ for (int changed = 1; changed;) { changed = 0; for (char *p = pat; *p != '\0'; p++) { if (*p == '(' && p[1] == ')') { memmove(p, p+2, strlen(p+2)+1); changed = 1; } } } if (pat[0] == '(' && pat[strlen(pat)-1] == ')') { int level = 1; for (int i=1; i < strlen(pat)-1; i++) { if (pat[i] == '(') level += 1; if (pat[i] == ')') level -= 1; if (level == 0) break; } if (level == 1) { memmove(pat, pat+1, strlen(pat+1)+1); pat[strlen(pat)-1] = '\0'; } } return pat; }
void print_regexp(FILE *out, struct regexp *r) { if (r == NULL) { fprintf(out, "<NULL>"); return; } fputc('/', out); if (r->pattern == NULL) fprintf(out, "%p", r); else { char *rx; size_t rx_len; fa_restrict_alphabet(r->pattern->str, strlen(r->pattern->str), &rx, &rx_len, 2, 1); print_chars(out, rx, rx_len); FREE(rx); } fputc('/', out); if (r->nocase) fputc('i', out); }
char *regexp_escape(const struct regexp *r) { char *pat = NULL; if (r == NULL) return strdup(""); #if !HAVE_USELOCALE char *nre = NULL; int ret; size_t nre_len; /* Use a range with from > to to force conversion of ranges into * short form */ ret = fa_restrict_alphabet(r->pattern->str, strlen(r->pattern->str), &nre, &nre_len, 2, 1); if (ret == 0) { pat = escape(nre, nre_len, RX_ESCAPES); free(nre); } #endif if (pat == NULL) { /* simplify the regexp by removing some artifacts of reserving chanaracters for internal purposes */ if (index(r->pattern->str, RESERVED_FROM_CH)) { char *s = strdup(r->pattern->str); char *t = s; for (char *p = s; *p; p++) { if (STREQLEN(p, RESERVED_RANGE_RX, strlen(RESERVED_RANGE_RX))) { /* Completely eliminate mentions of the reserved range */ p += strlen(RESERVED_RANGE_RX); } else if (STREQLEN(p, RESERVED_DOT_RX, strlen(RESERVED_DOT_RX))) { /* Replace what amounts to a '.' by one */ p += strlen(RESERVED_DOT_RX); *t++ = '.'; } *t++ = *p; } *t = '\0'; pat = escape(s, -1, RX_ESCAPES); free(s); } else { pat = escape(r->pattern->str, -1, RX_ESCAPES); } } if (pat == NULL) return NULL; /* Remove unneeded '()' from pat */ for (int changed = 1; changed;) { changed = 0; for (char *p = pat; *p != '\0'; p++) { if (*p == '(' && p[1] == ')') { memmove(p, p+2, strlen(p+2)+1); changed = 1; } } } if (pat[0] == '(' && pat[strlen(pat)-1] == ')') { int level = 1; for (int i=1; i < strlen(pat)-1; i++) { if (pat[i] == '(') level += 1; if (pat[i] == ')') level -= 1; if (level == 0) break; } if (level == 1) { memmove(pat, pat+1, strlen(pat+1)+1); pat[strlen(pat)-1] = '\0'; } } return pat; }