From: Sascha Wildner Date: Sat, 13 Jun 2009 11:39:15 +0000 (+0200) Subject: sed(1): Sync with FreeBSD. X-Git-Tag: v2.3.2~175^2~3 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/d2af8296ab6d4e1e5051eccb7f51815bbda7a71f sed(1): Sync with FreeBSD. * Add workaround for a back reference when no corresponding parenthesized subexpression is defined. For example, the following command line caused unexpected behavior like segmentation fault: % echo test | sed -e 's/test/\1/' * Fix the code to conform to the "or more" part of the following POSIX specification. "A function can be preceded by one or more '!' characters, in which case the function shall be applied if the addresses do not select the pattern space." * Implement "addr1,+N" ranges - not dissimilar to grep's -A switch. --- diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c index 819ef40a3f..a06df77c67 100644 --- a/usr.bin/sed/compile.c +++ b/usr.bin/sed/compile.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)compile.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/sed/compile.c,v 1.31 2008/02/09 09:12:02 dwmalone Exp $ + * $FreeBSD: src/usr.bin/sed/compile.c,v 1.34 2009/05/25 06:45:33 brian Exp $ * $DragonFly: src/usr.bin/sed/compile.c,v 1.4 2008/04/08 13:23:38 swildner Exp $ */ @@ -178,7 +178,7 @@ semicolon: EATSPACE(); if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL) err(1, "malloc"); link = &cmd->next; - cmd->nonsel = cmd->inrange = 0; + cmd->startline = cmd->nonsel = 0; /* First parse the addresses */ naddr = 0; @@ -221,7 +221,7 @@ nonsel: /* Now parse the command */ case NONSEL: /* ! */ p++; EATSPACE(); - cmd->nonsel = ! cmd->nonsel; + cmd->nonsel = 1; goto nonsel; case GROUP: /* { */ p++; @@ -321,9 +321,17 @@ nonsel: /* Now parse the command */ if (p == NULL) errx(1, "%lu: %s: unterminated substitute pattern", linenum, fname); + + /* Compile RE with no case sensitivity temporarily */ + if (*re == '\0') + cmd->u.s->re = NULL; + else + cmd->u.s->re = compile_re(re, 0); --p; p = compile_subst(p, cmd->u.s); p = compile_flags(p, cmd->u.s); + + /* Recompile RE with case sensitivity from "I" flag if any */ if (*re == '\0') cmd->u.s->re = NULL; else @@ -764,6 +772,7 @@ compile_addr(char *p, struct s_addr *a) icase = 0; + a->type = 0; switch (*p) { case '\\': /* Context address */ ++p; @@ -787,10 +796,16 @@ compile_addr(char *p, struct s_addr *a) case '$': /* Last line */ a->type = AT_LAST; return (p + 1); + + case '+': /* Relative line number */ + a->type = AT_RELLINE; + p++; + /* FALLTHROUGH */ /* Line number */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - a->type = AT_LINE; + if (a->type == 0) + a->type = AT_LINE; a->u.l = strtol(p, &end, 10); return (end); default: diff --git a/usr.bin/sed/defs.h b/usr.bin/sed/defs.h index d44b33ab56..73dff7ec36 100644 --- a/usr.bin/sed/defs.h +++ b/usr.bin/sed/defs.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)defs.h 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/sed/defs.h,v 1.7 2008/02/09 09:12:02 dwmalone Exp $ + * $FreeBSD: src/usr.bin/sed/defs.h,v 1.8 2009/05/25 06:45:33 brian Exp $ * $DragonFly: src/usr.bin/sed/defs.h,v 1.2 2008/04/08 13:23:38 swildner Exp $ */ @@ -39,8 +39,9 @@ * Types of address specifications */ enum e_atype { - AT_RE, /* Line that match RE */ + AT_RE = 1, /* Line that match RE */ AT_LINE, /* Specific line */ + AT_RELLINE, /* Relative line */ AT_LAST, /* Last line */ }; @@ -92,6 +93,7 @@ struct s_tr { struct s_command { struct s_command *next; /* Pointer to next command */ struct s_addr *a1, *a2; /* Start and end address */ + u_long startline; /* Start line number or zero */ char *t; /* Text for : a c i r w */ union { struct s_command *c; /* Command(s) for b t { */ @@ -101,7 +103,6 @@ struct s_command { } u; char code; /* Command code */ u_int nonsel:1; /* True if ! */ - u_int inrange:1; /* True if in range */ }; /* diff --git a/usr.bin/sed/misc.c b/usr.bin/sed/misc.c index 3961b72fac..2949402587 100644 --- a/usr.bin/sed/misc.c +++ b/usr.bin/sed/misc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)misc.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/sed/misc.c,v 1.9 2004/07/14 10:06:22 tjr Exp $ + * $FreeBSD: src/usr.bin/sed/misc.c,v 1.10 2004/08/09 15:29:41 dds Exp $ * $DragonFly: src/usr.bin/sed/misc.c,v 1.4 2008/04/08 13:23:38 swildner Exp $ */ diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c index b389aaec9c..9e131450e6 100644 --- a/usr.bin/sed/process.c +++ b/usr.bin/sed/process.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)process.c 8.6 (Berkeley) 4/20/94 - * $FreeBSD: src/usr.bin/sed/process.c,v 1.49 2008/02/09 09:12:02 dwmalone Exp $ + * $FreeBSD: src/usr.bin/sed/process.c,v 1.50 2009/05/25 06:45:33 brian Exp $ * $DragonFly: src/usr.bin/sed/process.c,v 1.6 2008/04/08 13:23:38 swildner Exp $ */ @@ -272,8 +272,8 @@ new: if (!nflag && !pd) (a)->type == AT_LINE ? linenum == (a)->u.l : lastline()) /* - * Return TRUE if the command applies to the current line. Sets the inrange - * flag to process ranges. Interprets the non-select (``!'') flag. + * Return TRUE if the command applies to the current line. Sets the start + * line for process ranges. Interprets the non-select (``!'') flag. */ static __inline int applies(struct s_command *cp) @@ -284,18 +284,22 @@ applies(struct s_command *cp) if (cp->a1 == NULL && cp->a2 == NULL) r = 1; else if (cp->a2) - if (cp->inrange) { + if (cp->startline > 0) { if (MATCH(cp->a2)) { - cp->inrange = 0; + cp->startline = 0; lastaddr = 1; r = 1; - } else if (cp->a2->type == AT_LINE && - linenum > cp->a2->u.l) { + } else if (linenum - cp->startline <= cp->a2->u.l) + r = 1; + else if ((cp->a2->type == AT_LINE && + linenum > cp->a2->u.l) || + (cp->a2->type == AT_RELLINE && + linenum - cp->startline > cp->a2->u.l)) { /* * We missed the 2nd address due to a branch, * so just close the range and return false. */ - cp->inrange = 0; + cp->startline = 0; r = 0; } else r = 1; @@ -305,12 +309,15 @@ applies(struct s_command *cp) * equal to the line number first selected, only * one line shall be selected. * -- POSIX 1003.2 + * Likewise if the relative second line address is zero. */ - if (cp->a2->type == AT_LINE && - linenum >= cp->a2->u.l) + if ((cp->a2->type == AT_LINE && + linenum >= cp->a2->u.l) || + (cp->a2->type == AT_RELLINE && cp->a2->u.l == 0)) lastaddr = 1; - else - cp->inrange = 1; + else { + cp->startline = linenum; + } r = 1; } else r = 0; @@ -328,11 +335,11 @@ resetstate(void) struct s_command *cp; /* - * Reset all inrange markers. + * Reset all in-range markers. */ for (cp = prog; cp; cp = cp->code == '{' ? cp->u.c : cp->next) if (cp->a2) - cp->inrange = 0; + cp->startline = 0; /* * Clear out the hold space. @@ -628,7 +635,7 @@ lputs(char *s, size_t len) static __inline int regexec_e(regex_t *preg, const char *string, int eflags, int nomatch, - size_t slen) + size_t slen) { int eval; diff --git a/usr.bin/sed/sed.1 b/usr.bin/sed/sed.1 index c6301161fd..4b1394f1f4 100644 --- a/usr.bin/sed/sed.1 +++ b/usr.bin/sed/sed.1 @@ -29,10 +29,10 @@ .\" SUCH DAMAGE. .\" .\" @(#)sed.1 8.2 (Berkeley) 12/30/93 -.\" $FreeBSD: src/usr.bin/sed/sed.1,v 1.46 2007/07/04 16:42:41 ssouhlal Exp $ +.\" $FreeBSD: src/usr.bin/sed/sed.1,v 1.50 2009/05/25 21:29:06 brian Exp $ .\" $DragonFly: src/usr.bin/sed/sed.1,v 1.6 2008/09/06 09:38:33 thomas Exp $ .\" -.Dd April 8, 2008 +.Dd June 13, 2009 .Dt SED 1 .Os .Sh NAME @@ -213,6 +213,9 @@ that matches the second address. If the second address is a number less than or equal to the line number first selected, only that line is selected. +The number in the second address may be prefixed with a +.Pq Dq \&+ +to specify the number of lines to match after the first pattern. In the case when the second address is a context address, .Nm @@ -245,20 +248,17 @@ has the following two additions to regular expressions: In a context address, any character other than a backslash .Pq Dq \e or newline character may be used to delimit the regular expression. -The opening delimiter need to be preceede by a backslash -unless it is a slash -.Pq Dq / . -For example the context address -.Dq \exabcx +The opening delimiter needs to be preceded by a backslash +unless it is a slash. +For example, the context address +.Li \exabcx is equivalent to -.Dq /abc/ . +.Li /abc/ . Also, putting a backslash character before the delimiting character -within the regular expression -causes the character to be treated literally. +within the regular expression causes the character to be treated literally. For example, in the context address -.Dq \exabc\exdefx , -the RE delimiter -is an +.Li \exabc\exdefx , +the RE delimiter is an .Dq x and the second .Dq x @@ -599,7 +599,10 @@ The .Fl E , I , a and .Fl i -options, as well as the +options, the prefixing +.Dq \&+ +in the second member of an address range, +as well as the .Dq I flag to the address regular expression and substitution command are non-standard