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>