From root@gits.dyndns.org  Tue Jul 30 05:40:43 2002
Return-Path: <root@gits.dyndns.org>
Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 4ED0337B405
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 30 Jul 2002 05:40:43 -0700 (PDT)
Received: from smtp.noos.fr (claudel.noos.net [212.198.2.83])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 8349443E67
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 30 Jul 2002 05:40:41 -0700 (PDT)
	(envelope-from root@gits.dyndns.org)
Received: (qmail 36762977 invoked by uid 0); 30 Jul 2002 12:40:39 -0000
Received: from unknown (HELO gits.gits.dyndns.org) ([212.198.229.153]) (envelope-sender <root@gits.dyndns.org>)
          by 212.198.2.83 (qmail-ldap-1.03) with SMTP
          for <FreeBSD-gnats-submit@freebsd.org>; 30 Jul 2002 12:40:39 -0000
Received: from gits.gits.dyndns.org (liharbv08t3mp5yw@localhost [127.0.0.1])
	by gits.gits.dyndns.org (8.12.5/8.12.5) with ESMTP id g6UCeYq4040005;
	Tue, 30 Jul 2002 14:40:34 +0200 (CEST)
	(envelope-from root@gits.dyndns.org)
Received: (from root@localhost)
	by gits.gits.dyndns.org (8.12.5/8.12.5/Submit) id g6UCeXLo040004;
	Tue, 30 Jul 2002 14:40:33 +0200 (CEST)
	(envelope-from root)
Message-Id: <200207301240.g6UCeXLo040004@gits.gits.dyndns.org>
Date: Tue, 30 Jul 2002 14:40:33 +0200 (CEST)
From: Cyrille Lefevre <cyrille.lefevre@laposte.net>
Reply-To: Cyrille Lefevre <cyrille.lefevre@laposte.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc: "Tim J. Robbins" <tjr@freebsd.org>
Subject: new sed -c option to allow ; as a separator for b, t and : functions
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         41159
>Category:       bin
>Synopsis:       [patch] new sed(1) -c option to allow ; as a separator for b, t and : functions
>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:   Tue Jul 30 05:50:01 PDT 2002
>Closed-Date:    
>Last-Modified:  Wed May 21 21:46:11 UTC 2008
>Originator:     Cyrille Lefevre
>Release:        FreeBSD 4.6-STABLE i386
>Organization:
ACME
>Environment:
System: FreeBSD gits 4.6-STABLE FreeBSD 4.6-STABLE #21: Sun Jul 28 09:42:24 CEST 2002 root@gits:/disk2/freebsd/stable/src/sys/compile/CUSTOM i386
>Description:
	the current sed implementation can't handle the ; separator for
	b, t and : functions. this patch set add a new -c (compat) option
	to allow sed to parse such constructions. maybe -C is better then -c ?
>How-To-Repeat:
	fetch http://queen.rett.polimi.it/~paolob/seders/scripts/sokoban.sed
	sed -f sokoban.sed
	sed: 2266: /root/sokoban.sed: unexpected EOF (pending }'s)
	sed -cf sokoban.sed
	(weel, it doesn't work yet, but at least, it can be parsed :)
>Fix:
Index: compile.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/sed/compile.c,v
retrieving revision 1.13.2.7
diff -u -r1.13.2.7 compile.c
--- compile.c	17 Jul 2002 09:35:56 -0000	1.13.2.7
+++ compile.c	30 Jul 2002 12:08:25 -0000
@@ -76,7 +76,7 @@
 static char	 *compile_tr(char *, char **);
 static struct s_command
 		**compile_stream(struct s_command **);
-static char	 *duptoeol(char *, const char *);
+static char	 *duptoeol(char **, const char *, int);
 static void	  enterlabel(struct s_command *);
 static struct s_command
 		 *findlabel(char *);
@@ -274,39 +274,43 @@
 		case WFILE:			/* w */
 			p++;
 			EATSPACE();
-			if (*p == '\0')
+			cmd->t = duptoeol(&p, "w command", 0);
+			if (cmd->t == NULL)
 				errx(1, "%lu: %s: filename expected", linenum, fname);
-			cmd->t = duptoeol(p, "w command");
 			if (aflag)
 				cmd->u.fd = -1;
-			else if ((cmd->u.fd = open(p, 
+			else if ((cmd->u.fd = open(cmd->t, 
 			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
 			    DEFFILEMODE)) == -1)
-				err(1, "%s", p);
+				err(1, "%s", cmd->t);
 			break;
 		case RFILE:			/* r */
 			p++;
 			EATSPACE();
-			if (*p == '\0')
+			cmd->t = duptoeol(&p, "read command", 0);
+			if (cmd->t == NULL)
 				errx(1, "%lu: %s: filename expected", linenum, fname);
-			else
-				cmd->t = duptoeol(p, "read command");
 			break;
 		case BRANCH:			/* b t */
 			p++;
 			EATSPACE();
-			if (*p == '\0')
-				cmd->t = NULL;
-			else
-				cmd->t = duptoeol(p, "branch");
+			cmd->t = duptoeol(&p, "branch", 1);
+			if (*p == ';') {
+				p++;
+				goto semicolon;
+			}
 			break;
 		case LABEL:			/* : */
 			p++;
 			EATSPACE();
-			cmd->t = duptoeol(p, "label");
-			if (strlen(p) == 0)
+			cmd->t = duptoeol(&p, "label", 1);
+			if (cmd->t == NULL)
 				errx(1, "%lu: %s: empty label", linenum, fname);
 			enterlabel(cmd);
+			if (*p == ';') {
+				p++;
+				goto semicolon;
+			}
 			break;
 		case SUBST:			/* s */
 			p++;
@@ -738,27 +742,36 @@
 
 /*
  * duptoeol --
- *	Return a copy of all the characters up to \n or \0.
+ *	Return a copy of all the characters up to \n or \0 and maybe `;'.
  */
 static char *
-duptoeol(s, ctype)
-	char *s;
+duptoeol(sp, ctype, semi)
+	char **sp;
 	const char *ctype;
+	int semi;
 {
 	size_t len;
 	int ws;
-	char *p, *start;
+	char *p, *start, *s;
+	char c;
 
+	c = semi && cflag ? ';' : '\0';
 	ws = 0;
-	for (start = s; *s != '\0' && *s != '\n'; ++s)
+	for (start = s = *sp; *s != '\0' && *s != '\n' && *s != c; ++s)
 		ws = isspace((unsigned char)*s);
-	*s = '\0';
+	*sp = s;
+	if (*s != c)
+		*s = '\0';
+	if (start == s)
+		return (NULL);
 	if (ws)
 		warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
 	len = s - start + 1;
 	if ((p = malloc(len)) == NULL)
 		err(1, "malloc");
-	return (memmove(p, start, len));
+	s = memmove(p, start, len);
+	s [len-1] = '\0';
+	return (s);
 }
 
 /*
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/sed/extern.h,v
retrieving revision 1.3.6.4
diff -u -r1.3.6.4 extern.h
--- extern.h	17 Jul 2002 09:35:56 -0000	1.3.6.4
+++ extern.h	30 Jul 2002 01:59:12 -0000
@@ -45,6 +45,7 @@
 extern u_long linenum;
 extern int appendnum;
 extern int aflag, eflag, nflag;
+extern int cflag;
 extern const char *fname;
 extern int rflags;	/* regex flags to use */
 
Index: main.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/sed/main.c,v
retrieving revision 1.9.2.6
diff -u -r1.9.2.6 main.c
--- main.c	17 Jul 2002 09:35:56 -0000	1.9.2.6
+++ main.c	30 Jul 2002 01:59:12 -0000
@@ -99,6 +99,7 @@
 static FILE *curfile;		/* Current open file */
 
 int aflag, eflag, nflag;
+int cflag;			/* allow ; to behave as \n for b and t */
 int rflags = 0;
 static int rval;		/* Exit status */
 
@@ -128,7 +129,7 @@
 	fflag = 0;
 	inplace = NULL;
 
-	while ((c = getopt(argc, argv, "Eae:f:i:n")) != -1)
+	while ((c = getopt(argc, argv, "Eace:f:i:n")) != -1)
 		switch (c) {
 		case 'E':
 			rflags = REG_EXTENDED;
@@ -136,6 +137,9 @@
 		case 'a':
 			aflag = 1;
 			break;
+		case 'c':
+			cflag = 1;
+			break;
 		case 'e':
 			eflag = 1;
 			if ((temp_arg = malloc(strlen(optarg) + 2)) == NULL)
@@ -186,8 +190,8 @@
 usage()
 {
 	(void)fprintf(stderr, "%s\n%s\n",
-		"usage: sed script [-Ean] [-i extension] [file ...]",
-		"       sed [-an] [-i extension] [-e script] ... [-f script_file] ... [file ...]");
+		"usage: sed script [-Eacn] [-i extension] [file ...]",
+		"       sed [-acn] [-i extension] [-e script] ... [-f script_file] ... [file ...]");
 	exit(1);
 }
 
Index: sed.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/sed/sed.1,v
retrieving revision 1.9.2.9
diff -u -r1.9.2.9 sed.1
--- sed.1	27 Jun 2002 13:03:33 -0000	1.9.2.9
+++ sed.1	30 Jul 2002 11:41:57 -0000
@@ -43,11 +43,11 @@
 .Nd stream editor
 .Sh SYNOPSIS
 .Nm
-.Op Fl Ean
+.Op Fl Eacn
 .Ar command
 .Op Ar
 .Nm
-.Op Fl Ean
+.Op Fl Eacn
 .Op Fl e Ar command
 .Op Fl f Ar command_file
 .Op Fl i Ar extension
@@ -89,6 +89,17 @@
 to delay opening each file until a command containing the related
 .Dq w
 function is applied to a line of input.
+.It Fl c
+Compatible mode to allow the
+.Dq \&;
+command separator for
+.Dq b ,
+.Dq t
+and
+.Dq \&:
+functions instead of reading the
+.Em label
+until the eof of line.
 .It Fl e Ar command
 Append the editing commands specified by the
 .Ar command
>Release-Note:
>Audit-Trail:

From: Giorgos Keramidas <keramida@FreeBSD.org>
To: Cyrille Lefevre <cyrille.lefevre@laposte.net>
Cc: bug-followup@FreeBSD.org, "Tim J. Robbins" <tjr@FreeBSD.org>
Subject: Re: bin/41159: new sed -c option to allow ; as a separator for b, t and : functions
Date: Wed, 21 Aug 2002 00:04:10 +0300

 Adding to audit trail:
 :
 : Message-Id: <20020801122653.A4231@dilbert.robbins.dropbear.id.au>
 : Date: Thu, 1 Aug 2002 12:26:53 +1000
 : From: Tim Robbins <tjr@FreeBSD.ORG>
 : Subject: Re: new sed -c option to allow ; as a separator for b, t and : functions
 :
 : On Tue, Jul 30, 2002 at 02:40:33PM +0200, Cyrille Lefevre wrote:
 : > 	the current sed implementation can't handle the ; separator for
 : > 	b, t and : functions. this patch set add a new -c (compat) option
 : > 	to allow sed to parse such constructions. maybe -C is better then -c ?
 :
 : If I understand SUSv3 correctly, file names or label names can contain
 : semicolons:
 :
 : 32406	Command verbs other than {, a, b, c, i, r, t, w, :, and # can be
 : 	followed by a semicolon, optional
 : 32407	<blank>s, and another command verb. However, when the s command verb
 : 	is used with the w
 : 32408	flag, following it with another command in this manner produces
 : 	undefined results.
 :
 : GNU sed, which by default accepts semicolons after (at least) the : and t
 : commands does not strictly conform. I'd rather that our sed was by default
 : as close as possible to what the standard requires, so we probably do need
 : a command line option like you suggested.
 :
 : I think -g would be a better choice (similar to m4's -g option) to
 : emphasise the fact that accepting semicolons after these commands is a GNU
 : extension, and possibly adding more GNU compatibility features if
 : they're needed/useful. BSD, 7th Edition and System V all behave the same
 : way, and treat semicolons as part of the label/filename.

From: Cyrille Lefevre <cyrille.lefevre@laposte.net>
To: freebsd gnats <freebsd-gnats-submit@freebsd.org>,
	Giorgos Keramidas <keramida@freebsd.org>
Cc:  
Subject: Re: bin/41159: new sed -c option to allow ;
	as a separator for b, t and : functions
Date: Thu, 4 Mar 2004 17:58:50 +0100

 Hi Giorgos,
 
 you wish has been exhausted, -c has been replaced by -g :)
 
 feature added: unexpected EOF (pending }'s) displays the right openning {
 line number
 
 so, could you commit this PR ?
 
 thanks in advance.
 
 cvs diff against -current (FreeBSD 5.2-CURRENT #1: Sat Jan 31 15:17:05 CET 2004)
 
 Index: compile.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/sed/compile.c,v
 retrieving revision 1.24
 diff -u -I$Id.*$ -I$.+BSD.*$ -r1.24 compile.c
 --- compile.c	4 Nov 2003 12:16:47 -0000	1.24
 +++ compile.c	4 Mar 2004 16:48:40 -0000
 @@ -76,7 +76,7 @@
  static char	 *compile_tr(char *, char **);
  static struct s_command
  		**compile_stream(struct s_command **);
 -static char	 *duptoeol(char *, const char *);
 +static char	 *duptoeol(char **, const char *, int);
  static void	  enterlabel(struct s_command *);
  static struct s_command
  		 *findlabel(char *);
 @@ -164,9 +164,12 @@
  	stack = 0;
  	for (;;) {
  		if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) {
 -			if (stack != 0)
 +			if (stack != 0) {
 +				for (cmd = stack; cmd->next; cmd = cmd->next)
 +					/* nothing */ ;
  				errx(1, "%lu: %s: unexpected EOF (pending }'s)",
 -							linenum, fname);
 +							cmd->linenum, fname);
 +			}
  			return (link);
  		}
  
 @@ -231,6 +234,7 @@
  			p++;
  			EATSPACE();
  			cmd->next = stack;
 +			cmd->linenum = linenum;
  			stack = cmd;
  			link = &cmd->u.c;
  			if (*p)
 @@ -279,39 +283,43 @@
  		case WFILE:			/* w */
  			p++;
  			EATSPACE();
 -			if (*p == '\0')
 +			cmd->t = duptoeol(&p, "w command", 0);
 +			if (cmd->t == NULL)
  				errx(1, "%lu: %s: filename expected", linenum, fname);
 -			cmd->t = duptoeol(p, "w command");
  			if (aflag)
  				cmd->u.fd = -1;
 -			else if ((cmd->u.fd = open(p,
 +			else if ((cmd->u.fd = open(cmd->t, 
  			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
  			    DEFFILEMODE)) == -1)
 -				err(1, "%s", p);
 +				err(1, "%s", cmd->t);
  			break;
  		case RFILE:			/* r */
  			p++;
  			EATSPACE();
 -			if (*p == '\0')
 +			cmd->t = duptoeol(&p, "read command", 0);
 +			if (cmd->t == NULL)
  				errx(1, "%lu: %s: filename expected", linenum, fname);
 -			else
 -				cmd->t = duptoeol(p, "read command");
  			break;
  		case BRANCH:			/* b t */
  			p++;
  			EATSPACE();
 -			if (*p == '\0')
 -				cmd->t = NULL;
 -			else
 -				cmd->t = duptoeol(p, "branch");
 +			cmd->t = duptoeol(&p, "branch", 1);
 +			if (*p == ';') {
 +				p++;
 +				goto semicolon;
 +			}
  			break;
  		case LABEL:			/* : */
  			p++;
  			EATSPACE();
 -			cmd->t = duptoeol(p, "label");
 -			if (strlen(p) == 0)
 +			cmd->t = duptoeol(&p, "label", 1);
 +			if (cmd->t == NULL)
  				errx(1, "%lu: %s: empty label", linenum, fname);
  			enterlabel(cmd);
 +			if (*p == ';') {
 +				p++;
 +				goto semicolon;
 +			}
  			break;
  		case SUBST:			/* s */
  			p++;
 @@ -730,25 +738,33 @@
  
  /*
   * duptoeol --
 - *	Return a copy of all the characters up to \n or \0.
 + *	Return a copy of all the characters up to \n or \0 and maybe `;'.
   */
  static char *
 -duptoeol(char *s, const char *ctype)
 +duptoeol(char **sp, const char *ctype, int semi)
  {
  	size_t len;
  	int ws;
 -	char *p, *start;
 +	char *p, *start, *s;
 +	char c;
  
 +	c = semi && gflag ? ';' : '\0';
  	ws = 0;
 -	for (start = s; *s != '\0' && *s != '\n'; ++s)
 +	for (start = s = *sp; *s != '\0' && *s != '\n' && *s != c; ++s)
  		ws = isspace((unsigned char)*s);
 -	*s = '\0';
 +	*sp = s;
 +	if (*s != c)
 +		*s = '\0';
 +	if (start == s)
 +		return (NULL);
  	if (ws)
  		warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
  	len = s - start + 1;
  	if ((p = malloc(len)) == NULL)
  		err(1, "malloc");
 -	return (memmove(p, start, len));
 +	s = memmove(p, start, len);
 +	s [len-1] = '\0';
 +	return (s);
  }
  
  /*
 Index: defs.h
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/sed/defs.h,v
 retrieving revision 1.3
 diff -u -I$Id.*$ -I$.+BSD.*$ -r1.3 defs.h
 --- defs.h	11 Aug 1997 07:21:00 -0000	1.3
 +++ defs.h	31 Jul 2002 01:23:53 -0000
 @@ -90,6 +90,7 @@
  	char code;				/* Command code */
  	u_int nonsel:1;				/* True if ! */
  	u_int inrange:1;			/* True if in range */
 +	u_int linenum;
  };
  
  /*
 Index: extern.h
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/sed/extern.h,v
 retrieving revision 1.12
 diff -u -I$Id.*$ -I$.+BSD.*$ -r1.12 extern.h
 --- extern.h	4 Nov 2003 13:09:16 -0000	1.12
 +++ extern.h	4 Mar 2004 16:48:43 -0000
 @@ -45,6 +45,7 @@
  extern u_long linenum;
  extern int appendnum;
  extern int aflag, eflag, nflag;
 +extern int gflag;
  extern const char *fname, *outfname;
  extern FILE *infile, *outfile;
  extern int rflags;	/* regex flags to use */
 Index: main.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/sed/main.c,v
 retrieving revision 1.31
 diff -u -I$Id.*$ -I$.+BSD.*$ -r1.31 main.c
 --- main.c	4 Nov 2003 22:39:25 -0000	1.31
 +++ main.c	4 Mar 2004 16:48:27 -0000
 @@ -100,6 +100,7 @@
  FILE *outfile;			/* Current output file */
  
  int aflag, eflag, nflag;
 +int gflag;			/* allow ; to behave as \n for b and t */
  int rflags = 0;
  static int rval;		/* Exit status */
  
 @@ -130,7 +131,7 @@
  	fflag = 0;
  	inplace = NULL;
  
 -	while ((c = getopt(argc, argv, "Eae:f:i:n")) != -1)
 +	while ((c = getopt(argc, argv, "Eae:f:gi:n")) != -1)
  		switch (c) {
  		case 'E':
  			rflags = REG_EXTENDED;
 @@ -150,6 +151,9 @@
  			fflag = 1;
  			add_compunit(CU_FILE, optarg);
  			break;
 +		case 'g':
 +			gflag = 1;
 +			break;
  		case 'i':
  			inplace = optarg;
  			break;
 @@ -188,8 +192,8 @@
  usage(void)
  {
  	(void)fprintf(stderr, "%s\n%s\n",
 -		"usage: sed script [-Ean] [-i extension] [file ...]",
 -		"       sed [-an] [-i extension] [-e script] ... [-f script_file] ... [file ...]");
 +		"usage: sed script [-Eagn] [-i extension] [file ...]",
 +		"       sed [-acn] [-i extension] [-e script] ... [-f script_file] ... [file ...]");
  	exit(1);
  }
  
 Index: sed.1
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/sed/sed.1,v
 retrieving revision 1.31
 diff -u -I$Id.*$ -I$.+BSD.*$ -r1.31 sed.1
 --- sed.1	4 Jan 2004 15:33:06 -0000	1.31
 +++ sed.1	4 Mar 2004 16:47:21 -0000
 @@ -43,11 +43,11 @@
  .Nd stream editor
  .Sh SYNOPSIS
  .Nm
 -.Op Fl Ean
 +.Op Fl Eagn
  .Ar command
  .Op Ar
  .Nm
 -.Op Fl Ean
 +.Op Fl Eagn
  .Op Fl e Ar command
  .Op Fl f Ar command_file
  .Op Fl i Ar extension
 @@ -99,6 +99,17 @@
  .Ar command_file
  to the list of commands.
  The editing commands should each be listed on a separate line.
 +.It Fl g
 +Activate the GNU-sed compatible mode which allow the
 +.Dq \&;
 +command separator for
 +.Dq b ,
 +.Dq t
 +and
 +.Dq \&:
 +functions instead of reading the
 +.Em label
 +until the eof of line.
  .It Fl i Ar extension
  Edit files in-place, saving backups with the specified
  .Ar extension .
 
 Cyrille Lefevre
 -- 
 mailto:cyrille.lefevre@laposte.net

From: Cyrille Lefevre <cyrille.lefevre@laposte.net>
To: freebsd gnats <freebsd-gnats-submit@freebsd.org>,
	Giorgos Keramidas <keramida@freebsd.org>
Cc:  
Subject: Re: bin/41159: new sed -c option to allow ;
	as a separator for b, t and : functions
Date: Thu, 4 Mar 2004 18:01:38 +0100

 oops, I forgot to change the second usage string at line 196 in main.c
 
 should be :
 sed [-agn] [-i extension] [-e script] ...
 
 instead of :
 sed [-acn] [-i extension] [-e script] ...
 
 sorry.
 
 Cyrille Lefevre
 -- 
 mailto:cyrille.lefevre@laposte.net

From: Cyrille Lefevre <cyrille.lefevre@laposte.net>
To: freebsd gnats <freebsd-gnats-submit@freebsd.org>,
	Giorgos Keramidas <keramida@freebsd.org>
Cc:  
Subject: Re: bin/41159: new sed -c option to allow ;
	as a separator for b, t and : functions
Date: Thu, 4 Mar 2004 18:04:28 +0100

 well, in fact, the added feature already has it's own PR which is bin/41190
 intituled : in sed, report the { linenum instead of EOF linenum on pending }
 
 forgot about that, sorry again.
 
 Cyrille Lefevre
 -- 
 mailto:cyrille.lefevre@laposte.net
>Unformatted:
