From tataz@obiwan.tataz.chchile.org  Fri May 22 11:47:00 2009
Return-Path: <tataz@obiwan.tataz.chchile.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id BAE9310656AD
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 22 May 2009 11:47:00 +0000 (UTC)
	(envelope-from tataz@obiwan.tataz.chchile.org)
Received: from smtpfb2-g21.free.fr (smtpfb2-g21.free.fr [212.27.42.10])
	by mx1.freebsd.org (Postfix) with ESMTP id 2D8938FC19
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 22 May 2009 11:46:58 +0000 (UTC)
	(envelope-from tataz@obiwan.tataz.chchile.org)
Received: from smtp6-g21.free.fr (smtp6-g21.free.fr [212.27.42.6])
	by smtpfb2-g21.free.fr (Postfix) with ESMTP id 14F13CB2D37
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 22 May 2009 13:31:28 +0200 (CEST)
Received: from smtp6-g21.free.fr (localhost [127.0.0.1])
	by smtp6-g21.free.fr (Postfix) with ESMTP id 99E04E08038;
	Fri, 22 May 2009 13:31:22 +0200 (CEST)
Received: from endor.tataz.chchile.org (tataz.chchile.org [82.233.239.98])
	by smtp6-g21.free.fr (Postfix) with ESMTP id A4D83E080A5;
	Fri, 22 May 2009 13:31:19 +0200 (CEST)
Received: from obiwan.tataz.chchile.org (obiwan.tataz.chchile.org [192.168.1.222])
	by endor.tataz.chchile.org (Postfix) with ESMTP id E362333E5F;
	Fri, 22 May 2009 11:30:42 +0000 (UTC)
Received: by obiwan.tataz.chchile.org (Postfix, from userid 1000)
	id BA81D50835; Fri, 22 May 2009 13:30:42 +0200 (CEST)
Message-Id: <20090522113042.BA81D50835@obiwan.tataz.chchile.org>
Date: Fri, 22 May 2009 13:30:42 +0200 (CEST)
From: Jeremie Le Hen <jeremie@le-hen.org>
Reply-To: Jeremie Le Hen <jeremie@le-hen.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc: jeremie@le-hen.org
Subject: [PATCH] [sed] Implementation of "addr1,+N" ranges
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         134856
>Category:       bin
>Synopsis:       [patch] sed(1) Implementation of "addr1,+N" ranges
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 22 11:50:01 UTC 2009
>Closed-Date:    Mon May 25 07:00:22 UTC 2009
>Last-Modified:  Mon May 25 07:10:01 UTC 2009
>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:
State-Changed-From-To: open->closed 
State-Changed-By: brian 
State-Changed-When: Mon May 25 06:40:51 UTC 2009 
State-Changed-Why:  
Submitted to head - r192732 

http://www.freebsd.org/cgi/query-pr.cgi?pr=134856 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/134856: commit references a PR
Date: Mon, 25 May 2009 06:45:44 +0000 (UTC)

 Author: brian
 Date: Mon May 25 06:45:33 2009
 New Revision: 192732
 URL: http://svn.freebsd.org/changeset/base/192732
 
 Log:
   Implement "addr1,+N" ranges - not dissimilar to grep's -A switch.
   
   PR:		134856
   Submitted by:	Jeremie Le Hen - jeremie at le-hen dot org
 
 Modified:
   head/usr.bin/sed/compile.c
   head/usr.bin/sed/defs.h
   head/usr.bin/sed/process.c
   head/usr.bin/sed/sed.1
 
 Modified: head/usr.bin/sed/compile.c
 ==============================================================================
 --- head/usr.bin/sed/compile.c	Mon May 25 06:39:48 2009	(r192731)
 +++ head/usr.bin/sed/compile.c	Mon May 25 06:45:33 2009	(r192732)
 @@ -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:
 
 Modified: head/usr.bin/sed/defs.h
 ==============================================================================
 --- head/usr.bin/sed/defs.h	Mon May 25 06:39:48 2009	(r192731)
 +++ head/usr.bin/sed/defs.h	Mon May 25 06:45:33 2009	(r192732)
 @@ -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 */
  };
  
  /*
 
 Modified: head/usr.bin/sed/process.c
 ==============================================================================
 --- head/usr.bin/sed/process.c	Mon May 25 06:39:48 2009	(r192731)
 +++ head/usr.bin/sed/process.c	Mon May 25 06:45:33 2009	(r192732)
 @@ -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.
 
 Modified: head/usr.bin/sed/sed.1
 ==============================================================================
 --- head/usr.bin/sed/sed.1	Mon May 25 06:39:48 2009	(r192731)
 +++ head/usr.bin/sed/sed.1	Mon May 25 06:45:33 2009	(r192732)
 @@ -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
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
