Date: Fri, 22 May 2009 13:30:42 +0200 (CEST) From: Jeremie Le Hen <jeremie@le-hen.org> To: FreeBSD-gnats-submit@FreeBSD.org Cc: jeremie@le-hen.org Subject: bin/134856: [PATCH] [sed] Implementation of "addr1,+N" ranges Message-ID: <20090522113042.BA81D50835@obiwan.tataz.chchile.org> Resent-Message-ID: <200905221150.n4MBo26u046589@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 134856 >Category: bin >Synopsis: [PATCH] [sed] Implementation of "addr1,+N" ranges >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri May 22 11:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Jeremie Le Hen >Release: FreeBSD 7.2-STABLE i386 >Organization: N/A >Environment: System: FreeBSD 7.2-STABLE >Description: This patch implements the "addr1,+N" range in sed(1). It is stated in the manpage that this is a non-standard extension (although both GNU sed and vim supports this). --- sed_range.diff begins here --- Index: compile.c =================================================================== RCS file: /mnt/space/cvsroot/src/usr.bin/sed/compile.c,v retrieving revision 1.33 diff -u -p -r1.33 compile.c --- compile.c 11 Nov 2008 17:15:57 -0000 1.33 +++ compile.c 22 May 2009 11:26:38 -0000 @@ -181,7 +181,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; @@ -775,6 +775,7 @@ compile_addr(char *p, struct s_addr *a) icase = 0; + a->type = 0; switch (*p) { case '\\': /* Context address */ ++p; @@ -798,10 +799,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: Index: defs.h =================================================================== RCS file: /mnt/space/cvsroot/src/usr.bin/sed/defs.h,v retrieving revision 1.7 diff -u -p -r1.7 defs.h --- defs.h 9 Feb 2008 09:12:02 -0000 1.7 +++ defs.h 22 May 2009 11:26:19 -0000 @@ -38,8 +38,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 */ }; @@ -91,6 +92,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 { */ @@ -100,7 +102,6 @@ struct s_command { } u; char code; /* Command code */ u_int nonsel:1; /* True if ! */ - u_int inrange:1; /* True if in range */ }; /* Index: process.c =================================================================== RCS file: /mnt/space/cvsroot/src/usr.bin/sed/process.c,v retrieving revision 1.49 diff -u -p -r1.49 process.c --- process.c 9 Feb 2008 09:12:02 -0000 1.49 +++ process.c 22 May 2009 11:29:47 -0000 @@ -275,8 +275,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) @@ -287,18 +287,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; @@ -308,12 +312,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; @@ -331,11 +338,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. Index: sed.1 =================================================================== RCS file: /mnt/space/cvsroot/src/usr.bin/sed/sed.1,v retrieving revision 1.48 diff -u -p -r1.48 sed.1 --- sed.1 1 Sep 2008 17:48:40 -0000 1.48 +++ sed.1 22 May 2009 11:03:04 -0000 @@ -211,6 +211,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 @@ -594,7 +597,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 >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090522113042.BA81D50835>