Configuration option to define wether to follows GNU sed's behaviour

or the posix standard.
Put the cleanup code back the way it was.
This commit is contained in:
Glenn L McGrath 2003-09-16 05:25:43 +00:00
parent 204ff1cea4
commit 2570b43e82
5 changed files with 70 additions and 29 deletions

View File

@ -42,6 +42,19 @@ config CONFIG_FEATURE_SED_EMBEDED_NEWLINE
It works by translating '\n' to "\n" and back. It works by translating '\n' to "\n" and back.
It may introduce unexpected results if you use "\n" in your text. It may introduce unexpected results if you use "\n" in your text.
config CONFIG_FEATURE_SED_GNU_COMPATABILITY
bool " Behave consistent with GNU sed"
default y
depends on CONFIG_SED
help
Where GNU sed doesnt follow the posix standard, do as GNU sed does.
Current difference are in
- N command with odd number of lines (see GNU sed info page)
- Blanks before substitution flags eg.
GNU sed interprets 's/a/b/ g' as 's/a/b/g'
Standard says 's/a/b/ g' should be 's/a/b/;g'
- GNU sed allows blanks between a '!' and the function.
config CONFIG_VI config CONFIG_VI
bool "vi" bool "vi"
default n default n

View File

@ -45,9 +45,11 @@
- GNU extensions - GNU extensions
- and more. - and more.
Bugs: Todo:
- Create a wrapper around regex to make libc's regex conform with sed
- Fix bugs
- lots
Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
*/ */
@ -298,7 +300,15 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr)
} }
/* process the flags */ /* process the flags */
while (substr[++idx]) { #ifndef CONFIG_FEATURE_SED_GNU_COMPATABILITY
idx++;
#else
/* GNU sed allows blanks before the flag, this can lead to an incosistent
* interpretation of 's/a/b/ g' as being either 's/a/b/g' or 's/a/b/;g'.
* which results in very different behaviour.
*/
while (substr[++idx])
#endif
switch (substr[idx]) { switch (substr[idx]) {
case 'g': case 'g':
if (match[0] != '^') { if (match[0] != '^') {
@ -312,16 +322,20 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr)
case 'p': case 'p':
sed_cmd->sub_p = 1; sed_cmd->sub_p = 1;
break; break;
#ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
default: default:
/* any whitespace or semicolon trailing after a s/// is ok */ /* any whitespace or semicolon trailing after a s/// is ok */
if (strchr(semicolon_whitespace, substr[idx])) if (strchr(semicolon_whitespace, substr[idx]))
goto out; goto out;
/* else */
bb_error_msg_and_die("bad option in substitution expression"); bb_error_msg_and_die("bad option in substitution expression");
} #endif
} }
#ifndef CONFIG_FEATURE_SED_GNU_COMPATABILITY
idx++;
#else
out: out:
#endif
/* compile the match string into a regex */ /* compile the match string into a regex */
if (*match != '\0') { if (*match != '\0') {
/* If match is empty, we use last regex used at runtime */ /* If match is empty, we use last regex used at runtime */
@ -556,15 +570,12 @@ static char *add_cmd(char *cmdstr)
sed_cmd->invert = 1; sed_cmd->invert = 1;
cmdstr++; cmdstr++;
#ifdef SED_FEATURE_STRICT_CHECKING #ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
/* According to the spec /* According to the spec
* It is unspecified whether <blank>s can follow a '!' character, * It is unspecified whether <blank>s can follow a '!' character,
* and conforming applications shall not follow a '!' character * and conforming applications shall not follow a '!' character
* with <blank>s. * with <blank>s.
*/ */
if (isblank(cmdstr[idx]) {
bb_error_msg_and_die("blank follows '!'");}
#else
/* skip whitespace before the command */ /* skip whitespace before the command */
while (isspace(*cmdstr)) { while (isspace(*cmdstr)) {
cmdstr++; cmdstr++;
@ -931,7 +942,6 @@ static void process_file(FILE * file)
} }
/* we also print the line if we were given the 'p' flag /* we also print the line if we were given the 'p' flag
* (this is quite possibly the second printing) */ * (this is quite possibly the second printing) */
// if ((sed_cmd->sub_p) && (!altered || substituted)) {
if ((sed_cmd->sub_p) && (altered || substituted)) { if ((sed_cmd->sub_p) && (altered || substituted)) {
puts(pattern_space); puts(pattern_space);
} }
@ -1007,20 +1017,25 @@ static void process_file(FILE * file)
} }
break; break;
case 'N': /* Append the next line to the current line */ case 'N': /* Append the next line to the current line */
if (next_line) { if (next_line == NULL) {
pattern_space = /* Jump to end of script and exist */
realloc(pattern_space, deleted = 1;
strlen(pattern_space) + strlen(next_line) + 2); free(next_line);
#ifdef CONFIG_FEATURE_SED_GNU_COMPATABILITY
/* GNU sed will add the newline character
* The GNU sed info page labels this as a bug that wont be fixed
*/
next_line = calloc(1,1);
#else
next_line = NULL;
break;
#endif
}
pattern_space = realloc(pattern_space, strlen(pattern_space) + strlen(next_line) + 2);
strcat(pattern_space, "\n"); strcat(pattern_space, "\n");
strcat(pattern_space, next_line); strcat(pattern_space, next_line);
next_line = bb_get_chomped_line_from_file(file); next_line = bb_get_chomped_line_from_file(file);
linenum++; linenum++;
} else {
/* Jump to end of script and exist */
deleted = 1;
free(next_line);
next_line = NULL;
}
break; break;
case 't': case 't':
if (substituted) if (substituted)
@ -1164,12 +1179,10 @@ extern int sed_main(int argc, char **argv)
{ {
int opt, status = EXIT_SUCCESS; int opt, status = EXIT_SUCCESS;
#if 0 /* This doesnt seem to be working */
#ifdef CONFIG_FEATURE_CLEAN_UP #ifdef CONFIG_FEATURE_CLEAN_UP
/* destroy command strings on exit */ /* destroy command strings on exit */
if (atexit(destroy_cmd_strs) == -1) if (atexit(destroy_cmd_strs) == -1)
bb_perror_msg_and_die("atexit"); bb_perror_msg_and_die("atexit");
#endif
#endif #endif
/* do normal option parsing */ /* do normal option parsing */
@ -1223,8 +1236,5 @@ extern int sed_main(int argc, char **argv)
} }
} }
#ifdef CONFIG_FEATURE_CLEAN_UP
destroy_cmd_strs();
#endif
return status; return status;
} }

View File

@ -51,7 +51,6 @@ static char *private_get_line_from_file(FILE *file, int c)
break; break;
} }
} }
if (linebuf) { if (linebuf) {
if (ferror(file)) { if (ferror(file)) {
free(linebuf); free(linebuf);

View File

@ -1,4 +1,6 @@
busybox sed -n 'N;p'>output <<EOF # XFAIL
# This will fail if CONFIG_FEATURE_SED_GNU_COMPATABILITY is defined
busybox sed 'N;p'>output <<EOF
a a
b b
c c
@ -6,4 +8,7 @@ EOF
cmp -s output - <<EOF cmp -s output - <<EOF
a a
b b
a
b
c
EOF EOF

View File

@ -0,0 +1,14 @@
# FEATURE: CONFIG_FEATURE_SED_GNU_COMPATABILITY
busybox sed 'N;p'>output <<EOF
a
b
c
EOF
cmp -s output - <<EOF
a
b
a
b
c
EOF