summaryrefslogtreecommitdiff
path: root/usr.bin/sed
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2018-08-14 18:10:10 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2018-08-14 18:10:10 +0000
commit74287fbea780d3b4119e84f8716b97ccdd161840 (patch)
tree76d544e3b7be7d15344d30e67f07932db5945fc3 /usr.bin/sed
parent5b3dcf844aa7211d6323510ef13487e744620969 (diff)
Improve consistency of the substitution command further.
When the opening square bracket ('[') is abused as the delimiter, the regular expression contains a bracket expression, and the bracket expression contains another opening square bracket (sick! - i mean, sic!), then do not require escaping that innermost bracket and treat a preceding backslash as a literal backslash character, in accordance with POSIX: $ printf 'x[x\\x\n' | sed 's[\[[][R[g' xRx\x $ printf 'x[x\\x\n' | sed 's[\[\[][R[g' xRxRx While here, also make the implementation more readable and insert some comments. Joint work with martijn@ (started during g2k18) and OK martijn@.
Diffstat (limited to 'usr.bin/sed')
-rw-r--r--usr.bin/sed/compile.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c
index f15dd9f9303..64e31cd9b44 100644
--- a/usr.bin/sed/compile.c
+++ b/usr.bin/sed/compile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compile.c,v 1.48 2018/07/09 09:43:54 schwarze Exp $ */
+/* $OpenBSD: compile.c,v 1.49 2018/08/14 18:10:09 schwarze Exp $ */
/*-
* Copyright (c) 1992 Diomidis Spinellis.
@@ -362,28 +362,40 @@ compile_delimited(char *p, char *d)
error(COMPILE, "\\ can not be used as a string delimiter");
else if (c == '\n')
error(COMPILE, "newline can not be used as a string delimiter");
- while (*p) {
- if (*p == '[' && *p != c) {
- if ((d = compile_ccl(&p, d)) == NULL)
- error(COMPILE, "unbalanced brackets ([])");
- continue;
- } else if (*p == '\\' && p[1] == c) {
- p++;
- } else if (*p == '\\' && p[1] == '[') {
- *d++ = *p++;
- } else if (*p == '\\' && p[1] == 'n') {
- *d++ = '\n';
- p += 2;
- continue;
- } else if (*p == '\\' && p[1] == '\\') {
- *d++ = *p++;
- } else if (*p == c) {
+
+ while (p[0]) {
+ /* Unescaped delimiter: We are done. */
+ if (p[0] == c) {
*d = '\0';
- return (p + 1);
+ return p + 1;
}
- *d++ = *p++;
+ if (p[0] == '\\') {
+ /* Escaped delimiter: Skip the backslash. */
+ if (p[1] == c) {
+ p++;
+ } else {
+ /* Backslash-n: Match linefeed. */
+ if (p[1] == 'n') {
+ *d++ = '\n';
+ p += 2;
+ /* Other escapes remain unchanged. */
+ } else {
+ *d++ = *p++;
+ *d++ = *p++;
+ }
+ continue;
+ }
+ }
+ if (p[0] != '[')
+ *d++ = *p++;
+ /*
+ * Bracket expression:
+ * It may contain the delimiter without escaping.
+ */
+ else if ((d = compile_ccl(&p, d)) == NULL)
+ error(COMPILE, "unbalanced brackets ([])");
}
- return (NULL);
+ return NULL;
}