aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-09-16 05:25:43 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-09-16 05:25:43 +0000
commit2570b43e829ccfc0f199fe61aafc24b1bd3fc7b1 (patch)
treede00e748021d3078ea21bb90017ded81129cb4bd
parent204ff1cea49c958846cd49175fa9318b81b5756f (diff)
downloadbusybox-w32-2570b43e829ccfc0f199fe61aafc24b1bd3fc7b1.tar.gz
busybox-w32-2570b43e829ccfc0f199fe61aafc24b1bd3fc7b1.tar.bz2
busybox-w32-2570b43e829ccfc0f199fe61aafc24b1bd3fc7b1.zip
Configuration option to define wether to follows GNU sed's behaviour
or the posix standard. Put the cleanup code back the way it was.
-rw-r--r--editors/Config.in13
-rw-r--r--editors/sed.c62
-rw-r--r--libbb/get_line_from_file.c3
-rw-r--r--testsuite/sed/sed-append-next-line7
-rw-r--r--testsuite/sed/sed-append-next-line-gnu14
5 files changed, 70 insertions, 29 deletions
diff --git a/editors/Config.in b/editors/Config.in
index 14b698f5d..bced12cb1 100644
--- a/editors/Config.in
+++ b/editors/Config.in
@@ -42,6 +42,19 @@ config CONFIG_FEATURE_SED_EMBEDED_NEWLINE
42 It works by translating '\n' to "\n" and back. 42 It works by translating '\n' to "\n" and back.
43 It may introduce unexpected results if you use "\n" in your text. 43 It may introduce unexpected results if you use "\n" in your text.
44 44
45config CONFIG_FEATURE_SED_GNU_COMPATABILITY
46 bool " Behave consistent with GNU sed"
47 default y
48 depends on CONFIG_SED
49 help
50 Where GNU sed doesnt follow the posix standard, do as GNU sed does.
51 Current difference are in
52 - N command with odd number of lines (see GNU sed info page)
53 - Blanks before substitution flags eg.
54 GNU sed interprets 's/a/b/ g' as 's/a/b/g'
55 Standard says 's/a/b/ g' should be 's/a/b/;g'
56 - GNU sed allows blanks between a '!' and the function.
57
45config CONFIG_VI 58config CONFIG_VI
46 bool "vi" 59 bool "vi"
47 default n 60 default n
diff --git a/editors/sed.c b/editors/sed.c
index a5a9d41a0..8b98a3182 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -45,9 +45,11 @@
45 - GNU extensions 45 - GNU extensions
46 - and more. 46 - and more.
47 47
48 Bugs: 48 Todo:
49 49
50 - lots 50 - Create a wrapper around regex to make libc's regex conform with sed
51 - Fix bugs
52
51 53
52 Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html 54 Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
53*/ 55*/
@@ -298,7 +300,15 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr)
298 } 300 }
299 301
300 /* process the flags */ 302 /* process the flags */
301 while (substr[++idx]) { 303#ifndef CONFIG_FEATURE_SED_GNU_COMPATABILITY
304 idx++;
305#else
306 /* GNU sed allows blanks before the flag, this can lead to an incosistent
307 * interpretation of 's/a/b/ g' as being either 's/a/b/g' or 's/a/b/;g'.
308 * which results in very different behaviour.
309 */
310 while (substr[++idx])
311#endif
302 switch (substr[idx]) { 312 switch (substr[idx]) {
303 case 'g': 313 case 'g':
304 if (match[0] != '^') { 314 if (match[0] != '^') {
@@ -312,16 +322,20 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr)
312 case 'p': 322 case 'p':
313 sed_cmd->sub_p = 1; 323 sed_cmd->sub_p = 1;
314 break; 324 break;
325#ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
315 default: 326 default:
316 /* any whitespace or semicolon trailing after a s/// is ok */ 327 /* any whitespace or semicolon trailing after a s/// is ok */
317 if (strchr(semicolon_whitespace, substr[idx])) 328 if (strchr(semicolon_whitespace, substr[idx]))
318 goto out; 329 goto out;
319 /* else */
320 bb_error_msg_and_die("bad option in substitution expression"); 330 bb_error_msg_and_die("bad option in substitution expression");
331#endif
321 } 332 }
322 }
323 333
324 out: 334#ifndef CONFIG_FEATURE_SED_GNU_COMPATABILITY
335 idx++;
336#else
337out:
338#endif
325 /* compile the match string into a regex */ 339 /* compile the match string into a regex */
326 if (*match != '\0') { 340 if (*match != '\0') {
327 /* If match is empty, we use last regex used at runtime */ 341 /* If match is empty, we use last regex used at runtime */
@@ -556,15 +570,12 @@ static char *add_cmd(char *cmdstr)
556 sed_cmd->invert = 1; 570 sed_cmd->invert = 1;
557 cmdstr++; 571 cmdstr++;
558 572
559#ifdef SED_FEATURE_STRICT_CHECKING 573#ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
560 /* According to the spec 574 /* According to the spec
561 * It is unspecified whether <blank>s can follow a '!' character, 575 * It is unspecified whether <blank>s can follow a '!' character,
562 * and conforming applications shall not follow a '!' character 576 * and conforming applications shall not follow a '!' character
563 * with <blank>s. 577 * with <blank>s.
564 */ 578 */
565 if (isblank(cmdstr[idx]) {
566 bb_error_msg_and_die("blank follows '!'");}
567#else
568 /* skip whitespace before the command */ 579 /* skip whitespace before the command */
569 while (isspace(*cmdstr)) { 580 while (isspace(*cmdstr)) {
570 cmdstr++; 581 cmdstr++;
@@ -931,7 +942,6 @@ static void process_file(FILE * file)
931 } 942 }
932 /* we also print the line if we were given the 'p' flag 943 /* we also print the line if we were given the 'p' flag
933 * (this is quite possibly the second printing) */ 944 * (this is quite possibly the second printing) */
934// if ((sed_cmd->sub_p) && (!altered || substituted)) {
935 if ((sed_cmd->sub_p) && (altered || substituted)) { 945 if ((sed_cmd->sub_p) && (altered || substituted)) {
936 puts(pattern_space); 946 puts(pattern_space);
937 } 947 }
@@ -1007,20 +1017,25 @@ static void process_file(FILE * file)
1007 } 1017 }
1008 break; 1018 break;
1009 case 'N': /* Append the next line to the current line */ 1019 case 'N': /* Append the next line to the current line */
1010 if (next_line) { 1020 if (next_line == NULL) {
1011 pattern_space =
1012 realloc(pattern_space,
1013 strlen(pattern_space) + strlen(next_line) + 2);
1014 strcat(pattern_space, "\n");
1015 strcat(pattern_space, next_line);
1016 next_line = bb_get_chomped_line_from_file(file);
1017 linenum++;
1018 } else {
1019 /* Jump to end of script and exist */ 1021 /* Jump to end of script and exist */
1020 deleted = 1; 1022 deleted = 1;
1021 free(next_line); 1023 free(next_line);
1024#ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
1025 /* GNU sed will add the newline character
1026 * The GNU sed info page labels this as a bug that wont be fixed
1027 */
1028 next_line = calloc(1,1);
1029#else
1022 next_line = NULL; 1030 next_line = NULL;
1031 break;
1032#endif
1023 } 1033 }
1034 pattern_space = realloc(pattern_space, strlen(pattern_space) + strlen(next_line) + 2);
1035 strcat(pattern_space, "\n");
1036 strcat(pattern_space, next_line);
1037 next_line = bb_get_chomped_line_from_file(file);
1038 linenum++;
1024 break; 1039 break;
1025 case 't': 1040 case 't':
1026 if (substituted) 1041 if (substituted)
@@ -1164,13 +1179,11 @@ extern int sed_main(int argc, char **argv)
1164{ 1179{
1165 int opt, status = EXIT_SUCCESS; 1180 int opt, status = EXIT_SUCCESS;
1166 1181
1167#if 0 /* This doesnt seem to be working */
1168#ifdef CONFIG_FEATURE_CLEAN_UP 1182#ifdef CONFIG_FEATURE_CLEAN_UP
1169 /* destroy command strings on exit */ 1183 /* destroy command strings on exit */
1170 if (atexit(destroy_cmd_strs) == -1) 1184 if (atexit(destroy_cmd_strs) == -1)
1171 bb_perror_msg_and_die("atexit"); 1185 bb_perror_msg_and_die("atexit");
1172#endif 1186#endif
1173#endif
1174 1187
1175 /* do normal option parsing */ 1188 /* do normal option parsing */
1176 while ((opt = getopt(argc, argv, "ne:f:")) > 0) { 1189 while ((opt = getopt(argc, argv, "ne:f:")) > 0) {
@@ -1223,8 +1236,5 @@ extern int sed_main(int argc, char **argv)
1223 } 1236 }
1224 } 1237 }
1225 1238
1226#ifdef CONFIG_FEATURE_CLEAN_UP
1227 destroy_cmd_strs();
1228#endif
1229 return status; 1239 return status;
1230} 1240}
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index 3b6e1e778..9a831f184 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -40,7 +40,7 @@ static char *private_get_line_from_file(FILE *file, int c)
40 40
41 while ((ch = getc(file)) != EOF) { 41 while ((ch = getc(file)) != EOF) {
42 /* grow the line buffer as necessary */ 42 /* grow the line buffer as necessary */
43 if (idx > linebufsz-2) { 43 if (idx > linebufsz - 2) {
44 linebuf = xrealloc(linebuf, linebufsz += GROWBY); 44 linebuf = xrealloc(linebuf, linebufsz += GROWBY);
45 } 45 }
46 linebuf[idx++] = (char)ch; 46 linebuf[idx++] = (char)ch;
@@ -51,7 +51,6 @@ static char *private_get_line_from_file(FILE *file, int c)
51 break; 51 break;
52 } 52 }
53 } 53 }
54
55 if (linebuf) { 54 if (linebuf) {
56 if (ferror(file)) { 55 if (ferror(file)) {
57 free(linebuf); 56 free(linebuf);
diff --git a/testsuite/sed/sed-append-next-line b/testsuite/sed/sed-append-next-line
index 380b7935d..e7f72f476 100644
--- a/testsuite/sed/sed-append-next-line
+++ b/testsuite/sed/sed-append-next-line
@@ -1,4 +1,6 @@
1busybox sed -n 'N;p'>output <<EOF 1# XFAIL
2# This will fail if CONFIG_FEATURE_SED_GNU_COMPATABILITY is defined
3busybox sed 'N;p'>output <<EOF
2a 4a
3b 5b
4c 6c
@@ -6,4 +8,7 @@ EOF
6cmp -s output - <<EOF 8cmp -s output - <<EOF
7a 9a
8b 10b
11a
12b
13c
9EOF 14EOF
diff --git a/testsuite/sed/sed-append-next-line-gnu b/testsuite/sed/sed-append-next-line-gnu
new file mode 100644
index 000000000..d7aba8c2c
--- /dev/null
+++ b/testsuite/sed/sed-append-next-line-gnu
@@ -0,0 +1,14 @@
1# FEATURE: CONFIG_FEATURE_SED_GNU_COMPATABILITY
2busybox sed 'N;p'>output <<EOF
3a
4b
5c
6EOF
7cmp -s output - <<EOF
8a
9b
10a
11b
12c
13
14EOF