Upon reviewing the series a bit better, I'll let David validate patches 5 (this one) and 6, and I'll only commit patches 1 through 4 for now.<br><br>Sorry David for the little mess I made by committing the whole series earlier.<br>
<br><br>Raphaël<br><br><br><br><div class="gmail_quote">On Sat, Oct 8, 2011 at 1:08 PM, Michael Chapman <span dir="ltr"><<a href="mailto:mike@very.puzzling.org">mike@very.puzzling.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
This patch fixes:<br>
<br>
/[\/]/<br>
<br>
Previously, this matched either a backslash or a slash, since \/ was not<br>
an escape sequence known to unescape(). Now this matches only a slash.<br>
<br>
We pass an extra argument to escape() and unescape() listing the extra<br>
characters that should be handled. STR_ESCAPES and RX_ESCAPES provide<br>
the extra characters for strings and regexps respectively, and NULL may<br>
be passed if no extra characters should be handled.<br>
<br>
Signed-off-by: Michael Chapman <<a href="mailto:mike@very.puzzling.org">mike@very.puzzling.org</a>><br>
---<br>
src/augeas.c | 2 +-<br>
src/get.c | 2 +-<br>
src/internal.c | 26 ++++++++++++++++++--------<br>
src/internal.h | 8 ++++++--<br>
src/lens.c | 14 +++++++-------<br>
src/lexer.l | 4 ++--<br>
src/regexp.c | 4 ++--<br>
7 files changed, 37 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/src/augeas.c b/src/augeas.c<br>
index 4b17384..35721fc 100644<br>
--- a/src/augeas.c<br>
+++ b/src/augeas.c<br>
@@ -1366,7 +1366,7 @@ static int print_one(FILE *out, const char *path, const char *value) {<br>
if (r < 0)<br>
return -1;<br>
if (value != NULL) {<br>
- char *val = escape(value, -1);<br>
+ char *val = escape(value, -1, STR_ESCAPES);<br>
r = fprintf(out, " = \"%s\"", val);<br>
free(val);<br>
if (r < 0)<br>
diff --git a/src/get.c b/src/get.c<br>
index f9ac6fb..143403b 100644<br>
--- a/src/get.c<br>
+++ b/src/get.c<br>
@@ -243,7 +243,7 @@ static void get_expected_error(struct state *state, struct lens *l) {<br>
for (p = word; *p != '\0' && *p != '\n'; p++);<br>
*p = '\0';<br>
<br>
- pat = escape(l->ctype->pattern->str, -1);<br>
+ pat = escape(l->ctype->pattern->str, -1, NULL);<br>
get_error(state, l, "expected %s at '%s'", pat, word);<br>
free(pat);<br>
}<br>
diff --git a/src/internal.c b/src/internal.c<br>
index 9f4b697..6ce24dd 100644<br>
--- a/src/internal.c<br>
+++ b/src/internal.c<br>
@@ -148,10 +148,10 @@ char* xread_file(const char *path) {<br>
/*<br>
* Escape/unescape of string literals<br>
*/<br>
-static const char *const escape_chars = "\"\a\b\t\n\v\f\r\\";<br>
-static const char *const escape_names = "\"abtnvfr\\";<br>
+static const char *const escape_chars = "\a\b\t\n\v\f\r";<br>
+static const char *const escape_names = "abtnvfr";<br>
<br>
-char *unescape(const char *s, int len) {<br>
+char *unescape(const char *s, int len, const char *extra) {<br>
size_t size;<br>
const char *n;<br>
char *result, *t;<br>
@@ -162,7 +162,9 @@ char *unescape(const char *s, int len) {<br>
<br>
size = 0;<br>
for (i=0; i < len; i++, size++)<br>
- if (s[i] == '\\' && strchr(escape_names, s[i+1]) != NULL) {<br>
+ if (s[i] == '\\' && (n = strchr(escape_names, s[i+1])) != NULL) {<br>
+ i += 1;<br>
+ } else if (s[i] == '\\' && extra && strchr(extra, s[i+1]) != NULL) {<br>
i += 1;<br>
}<br>
<br>
@@ -173,6 +175,9 @@ char *unescape(const char *s, int len) {<br>
if (s[i] == '\\' && (n = strchr(escape_names, s[i+1])) != NULL) {<br>
*t++ = escape_chars[n - escape_names];<br>
i += 1;<br>
+ } else if (s[i] == '\\' && extra && strchr(extra, s[i+1]) != NULL) {<br>
+ *t++ = s[i+1];<br>
+ i += 1;<br>
} else {<br>
*t++ = s[i];<br>
}<br>
@@ -180,7 +185,7 @@ char *unescape(const char *s, int len) {<br>
return result;<br>
}<br>
<br>
-char *escape(const char *text, int cnt) {<br>
+char *escape(const char *text, int cnt, const char *extra) {<br>
<br>
int len = 0;<br>
char *esc = NULL, *e;<br>
@@ -191,6 +196,8 @@ char *escape(const char *text, int cnt) {<br>
for (int i=0; i < cnt; i++) {<br>
if (text[i] && (strchr(escape_chars, text[i]) != NULL))<br>
len += 2; /* Escaped as '\x' */<br>
+ else if (text[i] && extra && (strchr(extra, text[i]) != NULL))<br>
+ len += 2; /* Escaped as '\x' */<br>
else if (! isprint(text[i]))<br>
len += 4; /* Escaped as '\ooo' */<br>
else<br>
@@ -204,6 +211,9 @@ char *escape(const char *text, int cnt) {<br>
if (text[i] && ((p = strchr(escape_chars, text[i])) != NULL)) {<br>
*e++ = '\\';<br>
*e++ = escape_names[p - escape_chars];<br>
+ } else if (text[i] && extra && (strchr(extra, text[i]) != NULL)) {<br>
+ *e++ = '\\';<br>
+ *e++ = text[i];<br>
} else if (! isprint(text[i])) {<br>
sprintf(e, "\\%03o", (unsigned char) text[i]);<br>
e += 4;<br>
@@ -225,7 +235,7 @@ int print_chars(FILE *out, const char *text, int cnt) {<br>
if (cnt < 0)<br>
cnt = strlen(text);<br>
<br>
- esc = escape(text, cnt);<br>
+ esc = escape(text, cnt, NULL);<br>
total = strlen(esc);<br>
if (out != NULL)<br>
fprintf(out, "%s", esc);<br>
@@ -243,10 +253,10 @@ char *format_pos(const char *text, int pos) {<br>
<br>
if (before > window)<br>
before = window;<br>
- left = escape(text + pos - before, before);<br>
+ left = escape(text + pos - before, before, NULL);<br>
if (left == NULL)<br>
goto done;<br>
- right = escape(text + pos, window);<br>
+ right = escape(text + pos, window, NULL);<br>
if (right == NULL)<br>
goto done;<br>
<br>
diff --git a/src/internal.h b/src/internal.h<br>
index 411a540..8c58d37 100644<br>
--- a/src/internal.h<br>
+++ b/src/internal.h<br>
@@ -253,10 +253,14 @@ int pathjoin(char **path, int nseg, ...);<br>
* Escape nonprintable characters within TEXT, similar to how it's done in<br>
* C string literals. Caller must free the returned string.<br>
*/<br>
-char *escape(const char *text, int cnt);<br>
+char *escape(const char *text, int cnt, const char *extra);<br>
<br>
/* Function: unescape */<br>
-char *unescape(const char *s, int len);<br>
+char *unescape(const char *s, int len, const char *extra);<br>
+<br>
+/* Extra characters to be escaped in strings and regexps respectively */<br>
+#define STR_ESCAPES "\"\\"<br>
+#define RX_ESCAPES "/\\"<br>
<br>
/* Function: print_chars */<br>
int print_chars(FILE *out, const char *text, int cnt);<br>
diff --git a/src/lens.c b/src/lens.c<br>
index 4e13811..d5c60bb 100644<br>
--- a/src/lens.c<br>
+++ b/src/lens.c<br>
@@ -115,7 +115,7 @@ static struct value *str_to_fa(struct info *info, const char *pattern,<br>
return NULL;<br>
}<br>
<br>
- re_str = escape(pattern, -1);<br>
+ re_str = escape(pattern, -1, RX_ESCAPES);<br>
ERR_NOMEM(re_str == NULL, info);<br>
<br>
exn = make_exn_value(info, "Invalid regular expression /%s/", re_str);<br>
@@ -542,7 +542,7 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info,<br>
const char *dflt = string->str;<br>
cnt = regexp_match(regexp, dflt, strlen(dflt), 0, NULL);<br>
if (cnt != strlen(dflt)) {<br>
- char *s = escape(dflt, -1);<br>
+ char *s = escape(dflt, -1, RX_ESCAPES);<br>
char *r = regexp_escape(regexp);<br>
exn = make_exn_value(info,<br>
"del: the default value '%s' does not match /%s/",<br>
@@ -709,11 +709,11 @@ ambig_check(struct info *info, struct fa *fa1, struct fa *fa2,<br>
lns_format_atype(l1, &s1);<br>
lns_format_atype(l2, &s2);<br>
} else {<br>
- e_u = escape(upv, pv - upv);<br>
- e_up = escape(upv, v - upv);<br>
- e_upv = escape(upv, -1);<br>
- e_pv = escape(pv, -1);<br>
- e_v = escape(v, -1);<br>
+ e_u = escape(upv, pv - upv, RX_ESCAPES);<br>
+ e_up = escape(upv, v - upv, RX_ESCAPES);<br>
+ e_upv = escape(upv, -1, RX_ESCAPES);<br>
+ e_pv = escape(pv, -1, RX_ESCAPES);<br>
+ e_v = escape(v, -1, RX_ESCAPES);<br>
s1 = regexp_escape(ltype(l1, typ));<br>
s2 = regexp_escape(ltype(l2, typ));<br>
}<br>
diff --git a/src/lexer.l b/src/lexer.l<br>
index acd83f2..cb8d506 100644<br>
--- a/src/lexer.l<br>
+++ b/src/lexer.l<br>
@@ -55,7 +55,7 @@ static void loc_update(YYLTYPE *yylloc, const char *s, int len) {<br>
}<br>
<br>
static char *regexp_literal(const char *s, int len) {<br>
- char *u = unescape(s, len);<br>
+ char *u = unescape(s, len, RX_ESCAPES);<br>
size_t u_len = strlen(u);<br>
<br>
if (u == NULL)<br>
@@ -89,7 +89,7 @@ ARROW -><br>
{<br>
\"([^\"]|\\\")*\" {<br>
loc_update(yylloc, yytext, yyleng);<br>
- yylval->string = unescape(yytext+1, yyleng-2);<br>
+ yylval->string = unescape(yytext+1, yyleng-2, STR_ESCAPES);<br>
return DQUOTED;<br>
}<br>
<br>
diff --git a/src/regexp.c b/src/regexp.c<br>
index 2cd47cb..51d8703 100644<br>
--- a/src/regexp.c<br>
+++ b/src/regexp.c<br>
@@ -56,7 +56,7 @@ char *regexp_escape(const struct regexp *r) {<br>
#endif<br>
<br>
if (pat == NULL)<br>
- pat = escape(r->pattern->str, -1);<br>
+ pat = escape(r->pattern->str, -1, RX_ESCAPES);<br>
<br>
if (pat == NULL)<br>
return NULL;<br>
@@ -115,7 +115,7 @@ void print_regexp(FILE *out, struct regexp *r) {<br>
<br>
struct regexp *<br>
make_regexp_unescape(struct info *info, const char *pat, int nocase) {<br>
- char *p = unescape(pat, strlen(pat));<br>
+ char *p = unescape(pat, strlen(pat), NULL);<br>
<br>
if (p == NULL)<br>
return NULL;<br>
<font color="#888888">--<br>
1.7.6.4<br>
<br>
_______________________________________________<br>
augeas-devel mailing list<br>
<a href="mailto:augeas-devel@redhat.com">augeas-devel@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/augeas-devel" target="_blank">https://www.redhat.com/mailman/listinfo/augeas-devel</a><br>
</font></blockquote></div><br>