svn commit: r303662 - head/usr.bin/sed

Pedro F. Giffuni pfg at FreeBSD.org
Tue Aug 2 15:35:55 UTC 2016


Author: pfg
Date: Tue Aug  2 15:35:53 2016
New Revision: 303662
URL: https://svnweb.freebsd.org/changeset/base/303662

Log:
  sed(1): Revert r303047 "cleanup" and therefore r303572.
  
  While big, the change was meant to have no effect on behavior and instead
  so far we have found two regressions: one in the etcupdate tests and
  another one in the games/openttd port[1].
  
  Revert to a known working state. We will likely have to split the patch in
  functional parts before bringing back the changes.
  
  PR:		195929
  Reported by:	danfe, madpilot [1]

Modified:
  head/usr.bin/sed/Makefile
  head/usr.bin/sed/compile.c
  head/usr.bin/sed/defs.h
  head/usr.bin/sed/extern.h
  head/usr.bin/sed/main.c
  head/usr.bin/sed/misc.c
  head/usr.bin/sed/process.c

Modified: head/usr.bin/sed/Makefile
==============================================================================
--- head/usr.bin/sed/Makefile	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/Makefile	Tue Aug  2 15:35:53 2016	(r303662)
@@ -6,7 +6,7 @@
 PROG=	sed
 SRCS=	compile.c main.c misc.c process.c
 
-WARNS?=	5
+WARNS?=	2
 
 .if ${MK_TESTS} != "no"
 SUBDIR+= tests

Modified: head/usr.bin/sed/compile.c
==============================================================================
--- head/usr.bin/sed/compile.c	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/compile.c	Tue Aug  2 15:35:53 2016	(r303662)
@@ -64,21 +64,21 @@ static struct labhash {
 	int	lh_ref;
 } *labels[LHSZ];
 
-static const char	 *compile_addr(const char *, struct s_addr *);
-static       char	 *compile_ccl(const char **, char *);
-static const char	 *compile_delimited(const char *, char *, int);
-static const char	 *compile_flags(const char *, struct s_subst *);
-static const regex_t	 *compile_re(const char *, int);
-static const char	 *compile_subst(const char *, struct s_subst *);
-static       char	 *compile_text(size_t *);
-static const char	 *compile_tr(const char *, struct s_tr **);
+static char	 *compile_addr(char *, struct s_addr *);
+static char	 *compile_ccl(char **, char *);
+static char	 *compile_delimited(char *, char *, int);
+static char	 *compile_flags(char *, struct s_subst *);
+static regex_t	 *compile_re(char *, int);
+static char	 *compile_subst(char *, struct s_subst *);
+static char	 *compile_text(void);
+static char	 *compile_tr(char *, struct s_tr **);
 static struct s_command
 		**compile_stream(struct s_command **);
-static char	 *duptoeol(const char *, const char *, size_t *);
+static char	 *duptoeol(char *, const char *);
 static void	  enterlabel(struct s_command *);
 static struct s_command
-		 *findlabel(const char *);
-static void	  fixuplabel(struct s_command *, const struct s_command *);
+		 *findlabel(char *);
+static void	  fixuplabel(struct s_command *, struct s_command *);
 static void	  uselabel(void);
 
 /*
@@ -144,20 +144,17 @@ compile(void)
 		err(1, "malloc");
 }
 
-#define	EATSPACE() do {						\
-	while (*p && isspace((unsigned char)*p))		\
-		p++;						\
-	} while (0)
-
-#define	EATSPACEN() do {					\
-	while (*p && *p != '\n' && isspace((unsigned char)*p))  \
-		p++;						\
+#define EATSPACE() do {							\
+	if (p)								\
+		while (*p && isspace((unsigned char)*p))                \
+			p++;						\
 	} while (0)
 
 static struct s_command **
 compile_stream(struct s_command **link)
 {
-	const char *p;
+	char *p;
+	static char lbuf[_POSIX2_LINE_MAX + 1];	/* To save stack */
 	struct s_command *cmd, *cmd2, *stack;
 	struct s_format *fp;
 	char re[_POSIX2_LINE_MAX + 1];
@@ -165,22 +162,22 @@ compile_stream(struct s_command **link)
 
 	stack = NULL;
 	for (;;) {
-		if ((p = cu_fgets(NULL)) == NULL) {
+		if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) {
 			if (stack != NULL)
 				errx(1, "%lu: %s: unexpected EOF (pending }'s)",
 							linenum, fname);
 			return (link);
 		}
 
-semicolon:	EATSPACEN();
-		switch (*p) {
-		case '#': case '\0': case '\n':
-			continue;	/* to next command-unit */
-		case ';':
-			p++;
-			goto semicolon;
+semicolon:	EATSPACE();
+		if (p) {
+			if (*p == '#' || *p == '\0')
+				continue;
+			else if (*p == ';') {
+				p++;
+				goto semicolon;
+			}
 		}
-
 		if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL)
 			err(1, "malloc");
 		link = &cmd->next;
@@ -211,14 +208,14 @@ semicolon:	EATSPACEN();
 			cmd->a1 = cmd->a2 = NULL;
 
 nonsel:		/* Now parse the command */
-		if (*p == '\0' || *p == '\n')
+		if (!*p)
 			errx(1, "%lu: %s: command expected", linenum, fname);
 		cmd->code = *p;
 		for (fp = cmd_fmts; fp->code; fp++)
 			if (fp->code == *p)
 				break;
 		if (!fp->code)
-			errx(1, "%lu: %s: invalid command code %c (%s)", linenum, fname, *p, p);
+			errx(1, "%lu: %s: invalid command code %c", linenum, fname, *p);
 		if (naddr > fp->naddr)
 			errx(1,
 				"%lu: %s: command %c expects up to %d address(es), found %d",
@@ -231,11 +228,11 @@ nonsel:		/* Now parse the command */
 			goto nonsel;
 		case GROUP:			/* { */
 			p++;
-			EATSPACEN();
+			EATSPACE();
 			cmd->next = stack;
 			stack = cmd;
 			link = &cmd->u.c;
-			if (*p != '\0' && *p != '\n')
+			if (*p)
 				goto semicolon;
 			break;
 		case ENDGROUP:
@@ -252,13 +249,13 @@ nonsel:		/* Now parse the command */
 			/*FALLTHROUGH*/
 		case EMPTY:		/* d D g G h H l n N p P q x = \0 */
 			p++;
-			EATSPACEN();
+			EATSPACE();
 			if (*p == ';') {
 				p++;
 				link = &cmd->next;
 				goto semicolon;
 			}
-			if (*p != '\0' && *p != '\n')
+			if (*p)
 				errx(1, "%lu: %s: extra characters at the end of %c command",
 						linenum, fname, cmd->code);
 			break;
@@ -269,12 +266,12 @@ nonsel:		/* Now parse the command */
 				errx(1,
 "%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code);
 			p++;
-			EATSPACEN();
-			if (*p != '\n')
+			EATSPACE();
+			if (*p)
 				errx(1,
-				"%lu: %s: extra characters (%c) after \\ at the end of %c command",
-				linenum, fname, *p, cmd->code);
-			cmd->t = compile_text(&cmd->tlen);
+				"%lu: %s: extra characters after \\ at the end of %c command",
+				linenum, fname, cmd->code);
+			cmd->t = compile_text();
 			break;
 		case COMMENT:			/* \0 # */
 			break;
@@ -283,10 +280,10 @@ nonsel:		/* Now parse the command */
 			EATSPACE();
 			if (*p == '\0')
 				errx(1, "%lu: %s: filename expected", linenum, fname);
-			cmd->t = duptoeol(p, "w command", &cmd->tlen);
+			cmd->t = duptoeol(p, "w command");
 			if (aflag)
 				cmd->u.fd = -1;
-			else if ((cmd->u.fd = open(cmd->t,
+			else if ((cmd->u.fd = open(p,
 			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
 			    DEFFILEMODE)) == -1)
 				err(1, "%s", p);
@@ -297,27 +294,27 @@ nonsel:		/* Now parse the command */
 			if (*p == '\0')
 				errx(1, "%lu: %s: filename expected", linenum, fname);
 			else
-				cmd->t = duptoeol(p, "read command", &cmd->tlen);
+				cmd->t = duptoeol(p, "read command");
 			break;
 		case BRANCH:			/* b t */
 			p++;
-			EATSPACEN();
-			if (*p == '\0' || *p == '\n')
+			EATSPACE();
+			if (*p == '\0')
 				cmd->t = NULL;
 			else
-				cmd->t = duptoeol(p, "branch", &cmd->tlen);
+				cmd->t = duptoeol(p, "branch");
 			break;
 		case LABEL:			/* : */
 			p++;
 			EATSPACE();
-			cmd->t = duptoeol(p, "label", &cmd->tlen);
-			if (cmd->t[0] == '\0')
+			cmd->t = duptoeol(p, "label");
+			if (strlen(p) == 0)
 				errx(1, "%lu: %s: empty label", linenum, fname);
 			enterlabel(cmd);
 			break;
 		case SUBST:			/* s */
 			p++;
-			if (*p == '\0' || *p == '\\' || *p == '\n')
+			if (*p == '\0' || *p == '\\')
 				errx(1,
 "%lu: %s: substitute pattern can not be delimited by newline or backslash",
 					linenum, fname);
@@ -328,15 +325,21 @@ nonsel:		/* Now parse the command */
 				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);
 
-			if (*re != '\0')
+			/* Recompile RE with case sensitivity from "I" flag if any */
+			if (*re == '\0')
+				cmd->u.s->re = NULL;
+			else
 				cmd->u.s->re = compile_re(re, cmd->u.s->icase);
-
 			EATSPACE();
-
 			if (*p == ';') {
 				p++;
 				link = &cmd->next;
@@ -369,8 +372,8 @@ nonsel:		/* Now parse the command */
  * in the case of a non-terminated string.  The character array d is filled
  * with the processed string.
  */
-static const char *
-compile_delimited(const char *p, char *d, int is_tr)
+static char *
+compile_delimited(char *p, char *d, int is_tr)
 {
 	char c;
 
@@ -413,10 +416,10 @@ compile_delimited(const char *p, char *d
 
 /* compile_ccl: expand a POSIX character class */
 static char *
-compile_ccl(const char **sp, char *t)
+compile_ccl(char **sp, char *t)
 {
 	int c, d;
-	const char *s = *sp;
+	char *s = *sp;
 
 	*t++ = *s++;
 	if (*s == '^')
@@ -438,8 +441,8 @@ compile_ccl(const char **sp, char *t)
  * regular expression.
  * Cflags are passed to regcomp.
  */
-static const regex_t *
-compile_re(const char *re, int case_insensitive)
+static regex_t *
+compile_re(char *re, int case_insensitive)
 {
 	regex_t *rep;
 	int eval, flags;
@@ -463,13 +466,14 @@ compile_re(const char *re, int case_inse
  * point to a saved copy of it.  Nsub is the number of parenthesized regular
  * expressions.
  */
-static const char *
-compile_subst(const char *p, struct s_subst *s)
+static char *
+compile_subst(char *p, struct s_subst *s)
 {
+	static char lbuf[_POSIX2_LINE_MAX + 1];
 	int asize, size;
 	u_char ref;
 	char c, *text, *op, *sp;
-	int more = 0, sawesc = 0;
+	int more = 1, sawesc = 0;
 
 	c = *p++;			/* Terminator character */
 	if (c == '\0')
@@ -483,7 +487,7 @@ compile_subst(const char *p, struct s_su
 	size = 0;
 	do {
 		op = sp = text + size;
-		for (; *p != '\0' && *p != '\n'; p++) {
+		for (; *p; p++) {
 			if (*p == '\\' || sawesc) {
 				/*
 				 * If this is a continuation from the last
@@ -505,10 +509,7 @@ compile_subst(const char *p, struct s_su
 					 */
 					sawesc = 1;
 					p--;
-					break;
-				} else if (*p == '\n') {
-					*sp++ = '\n';
-					break;
+					continue;
 				} else if (strchr("123456789", *p) != NULL) {
 					*sp++ = '\\';
 					ref = *p - '0';
@@ -522,11 +523,8 @@ compile_subst(const char *p, struct s_su
 					*sp++ = '\\';
 			} else if (*p == c) {
 				if (*++p == '\0' && more) {
-					const char *nextp;
-
-					nextp = cu_fgets(&more);
-					if (nextp != NULL)
-						p = nextp;
+					if (cu_fgets(lbuf, sizeof(lbuf), &more))
+						p = lbuf;
 				}
 				*sp++ = '\0';
 				size += sp - op;
@@ -546,7 +544,7 @@ compile_subst(const char *p, struct s_su
 			if ((text = realloc(text, asize)) == NULL)
 				err(1, "realloc");
 		}
-	} while ((p = cu_fgets(&more)) != NULL);
+	} while (cu_fgets(p = lbuf, sizeof(lbuf), &more) != NULL);
 	errx(1, "%lu: %s: unterminated substitute in regular expression",
 			linenum, fname);
 	/* NOTREACHED */
@@ -555,12 +553,12 @@ compile_subst(const char *p, struct s_su
 /*
  * Compile the flags of the s command
  */
-static const char *
-compile_flags(const char *p, struct s_subst *s)
+static char *
+compile_flags(char *p, struct s_subst *s)
 {
 	int gn;			/* True if we have seen g or n */
 	unsigned long nval;
-	char *q;
+	char wfile[_POSIX2_LINE_MAX + 1], *q, *eq;
 
 	s->n = 1;				/* Default */
 	s->p = 0;
@@ -568,7 +566,7 @@ compile_flags(const char *p, struct s_su
 	s->wfd = -1;
 	s->icase = 0;
 	for (gn = 0;;) {
-		EATSPACEN();			/* EXTENSION */
+		EATSPACE();			/* EXTENSION */
 		switch (*p) {
 		case 'g':
 			if (gn)
@@ -596,13 +594,13 @@ compile_flags(const char *p, struct s_su
 "%lu: %s: more than one number or 'g' in substitute flags", linenum, fname);
 			gn = 1;
 			errno = 0;
-			nval = strtol(p, &q, 10);
+			nval = strtol(p, &p, 10);
 			if (errno == ERANGE || nval > INT_MAX)
 				errx(1,
 "%lu: %s: overflow in the 'N' substitute flag", linenum, fname);
 			s->n = nval;
-			p = q;
-			continue;
+			p--;
+			break;
 		case 'w':
 			p++;
 #ifdef HISTORIC_PRACTICE
@@ -612,15 +610,27 @@ compile_flags(const char *p, struct s_su
 			}
 #endif
 			EATSPACE();
-			s->wfile = duptoeol(p, "w flag", NULL);
-			if (!aflag && (s->wfd = open(s->wfile,
+			q = wfile;
+			eq = wfile + sizeof(wfile) - 1;
+			while (*p) {
+				if (*p == '\n')
+					break;
+				if (q >= eq)
+					err(1, "wfile too long");
+				*q++ = *p++;
+			}
+			*q = '\0';
+			if (q == wfile)
+				errx(1, "%lu: %s: no wfile specified", linenum, fname);
+			s->wfile = strdup(wfile);
+			if (!aflag && (s->wfd = open(wfile,
 			    O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
 			    DEFFILEMODE)) == -1)
-				err(1, "%s", s->wfile);
+				err(1, "%s", wfile);
 			return (p);
 		default:
-			errx(1, "%lu: %s: bad flag in substitute command: '%c' (%.10s)",
-					linenum, fname, *p, p);
+			errx(1, "%lu: %s: bad flag in substitute command: '%c'",
+					linenum, fname, *p);
 			break;
 		}
 		p++;
@@ -630,8 +640,8 @@ compile_flags(const char *p, struct s_su
 /*
  * Compile a translation set of strings into a lookup table.
  */
-static const char *
-compile_tr(const char *p, struct s_tr **py)
+static char *
+compile_tr(char *p, struct s_tr **py)
 {
 	struct s_tr *y;
 	int i;
@@ -642,7 +652,7 @@ compile_tr(const char *p, struct s_tr **
 	mbstate_t mbs1, mbs2;
 
 	if ((*py = y = malloc(sizeof(*y))) == NULL)
-		err(1, "malloc");
+		err(1, NULL);
 	y->multis = NULL;
 	y->nmultis = 0;
 
@@ -662,11 +672,11 @@ compile_tr(const char *p, struct s_tr **
 	op = old;
 	oldlen = mbsrtowcs(NULL, &op, 0, NULL);
 	if (oldlen == (size_t)-1)
-		err(1, "mbsrtowcs");
+		err(1, NULL);
 	np = new;
 	newlen = mbsrtowcs(NULL, &np, 0, NULL);
 	if (newlen == (size_t)-1)
-		err(1, "mbsrtowcs");
+		err(1, NULL);
 	if (newlen != oldlen)
 		errx(1, "%lu: %s: transform strings are not the same length",
 				linenum, fname);
@@ -705,7 +715,7 @@ compile_tr(const char *p, struct s_tr **
 				y->multis = realloc(y->multis,
 				    (y->nmultis + 1) * sizeof(*y->multis));
 				if (y->multis == NULL)
-					err(1, "realloc");
+					err(1, NULL);
 				i = y->nmultis++;
 				y->multis[i].fromlen = oclen;
 				memcpy(y->multis[i].from, op, oclen);
@@ -723,24 +733,23 @@ compile_tr(const char *p, struct s_tr **
  * Compile the text following an a, c, or i command.
  */
 static char *
-compile_text(size_t *ptlen)
+compile_text(void)
 {
 	int asize, esc_nl, size;
-	char *text, *s;
-	const char *p, *op;
+	char *text, *p, *op, *s;
+	char lbuf[_POSIX2_LINE_MAX + 1];
 
 	asize = 2 * _POSIX2_LINE_MAX + 1;
 	if ((text = malloc(asize)) == NULL)
 		err(1, "malloc");
 	size = 0;
-	while ((p = cu_fgets(NULL)) != NULL) {
+	while (cu_fgets(lbuf, sizeof(lbuf), NULL) != NULL) {
 		op = s = text + size;
+		p = lbuf;
 		for (esc_nl = 0; *p != '\0'; p++) {
 			if (*p == '\\' && p[1] != '\0' && *++p == '\n')
 				esc_nl = 1;
 			*s++ = *p;
-			if (*p == '\n')
-				break;
 		}
 		size += s - op;
 		if (!esc_nl) {
@@ -754,18 +763,17 @@ compile_text(size_t *ptlen)
 		}
 	}
 	text[size] = '\0';
-	if ((text = realloc(text, size + 1)) == NULL)
+	if ((p = realloc(text, size + 1)) == NULL)
 		err(1, "realloc");
-	*ptlen = size;
-	return (text);
+	return (p);
 }
 
 /*
  * Get an address and return a pointer to the first character after
  * it.  Fill the structure pointed to according to the address.
  */
-static const char *
-compile_addr(const char *p, struct s_addr *a)
+static char *
+compile_addr(char *p, struct s_addr *a)
 {
 	char *end, re[_POSIX2_LINE_MAX + 1];
 	int icase;
@@ -819,26 +827,22 @@ compile_addr(const char *p, struct s_add
  *	Return a copy of all the characters up to \n or \0.
  */
 static char *
-duptoeol(const char *s, const char *ctype, size_t *ptlen)
+duptoeol(char *s, const char *ctype)
 {
 	size_t len;
 	int ws;
-	char *p;
-	const char *start;
+	char *p, *start;
 
 	ws = 0;
 	for (start = s; *s != '\0' && *s != '\n'; ++s)
 		ws = isspace((unsigned char)*s);
+	*s = '\0';
 	if (ws)
 		warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
-	len = s - start;
-	if ((p = malloc(len + 1)) == NULL)
+	len = s - start + 1;
+	if ((p = malloc(len)) == NULL)
 		err(1, "malloc");
-	memmove(p, start, len);
-	p[len] = '\0';
-	if (ptlen != NULL)
-		*ptlen = len;
-	return p;
+	return (memmove(p, start, len));
 }
 
 /*
@@ -849,7 +853,7 @@ duptoeol(const char *s, const char *ctyp
  * TODO: Remove } nodes
  */
 static void
-fixuplabel(struct s_command *cp, const struct s_command *end)
+fixuplabel(struct s_command *cp, struct s_command *end)
 {
 
 	for (; cp != end; cp = cp->next)
@@ -866,7 +870,7 @@ fixuplabel(struct s_command *cp, const s
 				break;
 			}
 			if ((cp->u.c = findlabel(cp->t)) == NULL)
-				errx(1, "%lu: %s: %c: undefined label '%s'", linenum, fname, cp->code, cp->t);
+				errx(1, "%lu: %s: undefined label '%s'", linenum, fname, cp->t);
 			free(cp->t);
 			break;
 		case '{':
@@ -906,13 +910,13 @@ enterlabel(struct s_command *cp)
  * list cp.  L is excluded from the search.  Return NULL if not found.
  */
 static struct s_command *
-findlabel(const char *name)
+findlabel(char *name)
 {
 	struct labhash *lh;
-	const u_char *p;
+	u_char *p;
 	u_int h, c;
 
-	for (h = 0, p = (const u_char *)name; (c = *p) != 0; p++)
+	for (h = 0, p = (u_char *)name; (c = *p) != 0; p++)
 		h = (h << 5) + h + c;
 	for (lh = labels[h & LHMASK]; lh != NULL; lh = lh->lh_next) {
 		if (lh->lh_hash == h && strcmp(name, lh->lh_cmd->t) == 0) {

Modified: head/usr.bin/sed/defs.h
==============================================================================
--- head/usr.bin/sed/defs.h	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/defs.h	Tue Aug  2 15:35:53 2016	(r303662)
@@ -51,7 +51,7 @@ struct s_addr {
 	enum e_atype type;			/* Address type */
 	union {
 		u_long l;			/* Line number */
-		const regex_t *r;		/* Regular expression */
+		regex_t *r;			/* Regular expression */
 	} u;
 };
 
@@ -64,7 +64,7 @@ struct s_subst {
 	int icase;				/* True if I flag */
 	char *wfile;				/* NULL if no wfile */
 	int wfd;				/* Cached file descriptor */
-	const regex_t *re;			/* Regular expression */
+	regex_t *re;				/* Regular expression */
 	unsigned int maxbref;			/* Largest backreference. */
 	u_long linenum;				/* Line number. */
 	char *new;				/* Replacement text */
@@ -94,7 +94,6 @@ struct s_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 */
-	size_t tlen;
 	union {
 		struct s_command *c;		/* Command(s) for b t { */
 		struct s_subst *s;		/* Substitute command */

Modified: head/usr.bin/sed/extern.h
==============================================================================
--- head/usr.bin/sed/extern.h	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/extern.h	Tue Aug  2 15:35:53 2016	(r303662)
@@ -45,12 +45,12 @@ extern const char *fname, *outfname;
 extern FILE *infile, *outfile;
 extern int rflags;	/* regex flags to use */
 
-void	 cfclose(struct s_command *, const struct s_command *);
+void	 cfclose(struct s_command *, struct s_command *);
 void	 compile(void);
 void	 cspace(SPACE *, const char *, size_t, enum e_spflag);
-const char *cu_fgets(int *);
+char	*cu_fgets(char *, int, int *);
 int	 mf_fgets(SPACE *, enum e_spflag);
 int	 lastline(void);
 void	 process(void);
 void	 resetstate(void);
-char	*strregerror(int, const regex_t *);
+char	*strregerror(int, regex_t *);

Modified: head/usr.bin/sed/main.c
==============================================================================
--- head/usr.bin/sed/main.c	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/main.c	Tue Aug  2 15:35:53 2016	(r303662)
@@ -72,7 +72,7 @@ static const char sccsid[] = "@(#)main.c
 struct s_compunit {
 	struct s_compunit *next;
 	enum e_cut {CU_FILE, CU_STRING} type;
-	const char *s;			/* Pointer to string or fname */
+	char *s;			/* Pointer to string or fname */
 };
 
 /*
@@ -85,7 +85,7 @@ static struct s_compunit *script, **cu_n
  * Linked list of files to be processed
  */
 struct s_flist {
-	const char *fname;
+	char *fname;
 	struct s_flist *next;
 };
 
@@ -116,15 +116,15 @@ static char tmpfname[PATH_MAX];	/* Tempo
 static const char *inplace;	/* Inplace edit file extension. */
 u_long linenum;
 
-static void add_compunit(enum e_cut, const char *);
-static void add_file(const char *);
+static void add_compunit(enum e_cut, char *);
+static void add_file(char *);
 static void usage(void);
 
 int
 main(int argc, char *argv[])
 {
-	char *temp_arg;
 	int c, fflag;
+	char *temp_arg;
 
 	(void) setlocale(LC_ALL, "");
 
@@ -146,9 +146,10 @@ main(int argc, char *argv[])
 			break;
 		case 'e':
 			eflag = 1;
-			asprintf(&temp_arg, "%s\n", optarg);
-			if (temp_arg == NULL)
-				errx(1, "Couldn't allocate temporary buffer");
+			if ((temp_arg = malloc(strlen(optarg) + 2)) == NULL)
+				err(1, "malloc");
+			strcpy(temp_arg, optarg);
+			strcat(temp_arg, "\n");
 			add_compunit(CU_STRING, temp_arg);
 			break;
 		case 'f':
@@ -212,16 +213,14 @@ usage(void)
  * Like fgets, but go through the chain of compilation units chaining them
  * together.  Empty strings and files are ignored.
  */
-const char *
-cu_fgets(int *more)
+char *
+cu_fgets(char *buf, int n, int *more)
 {
 	static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
 	static FILE *f;		/* Current open file */
-	static const char *s;	/* Current pointer inside string */
-	static char string_ident[30], *lastresult;
-	static size_t lastsize;
+	static char *s;		/* Current pointer inside string */
+	static char string_ident[30];
 	char *p;
-	const char *start;
 
 again:
 	switch (state) {
@@ -251,16 +250,14 @@ again:
 			goto again;
 		}
 	case ST_FILE:
-		p = lastresult;
-		if (getline(&p, &lastsize, f) != -1) {
+		if ((p = fgets(buf, n, f)) != NULL) {
 			linenum++;
-			if (linenum == 1 && p[0] == '#' && p[1] == 'n')
+			if (linenum == 1 && buf[0] == '#' && buf[1] == 'n')
 				nflag = 1;
 			if (more != NULL)
 				*more = !feof(f);
-			return (lastresult = p);
-		} else if (ferror(f))
-			err(1, "%s", script->s);
+			return (p);
+		}
 		script = script->next;
 		(void)fclose(f);
 		state = ST_EOF;
@@ -268,26 +265,39 @@ again:
 	case ST_STRING:
 		if (linenum == 0 && s[0] == '#' && s[1] == 'n')
 			nflag = 1;
-		else if (s[0] == '\0') {
-			state = ST_EOF;
-			script = script->next;
-			goto again;
-		}
-		start = s;
+		p = buf;
 		for (;;) {
+			if (n-- <= 1) {
+				*p = '\0';
+				linenum++;
+				if (more != NULL)
+					*more = 1;
+				return (buf);
+			}
 			switch (*s) {
 			case '\0':
 				state = ST_EOF;
-				script = script->next;
-				/* FALLTHROUGH */
+				if (s == script->s) {
+					script = script->next;
+					goto again;
+				} else {
+					script = script->next;
+					*p = '\0';
+					linenum++;
+					if (more != NULL)
+						*more = 0;
+					return (buf);
+				}
 			case '\n':
+				*p++ = '\n';
+				*p = '\0';
 				s++;
 				linenum++;
 				if (more != NULL)
 					*more = 0;
-				return (start);
+				return (buf);
 			default:
-				s++;
+				*p++ = *s++;
 			}
 		}
 	}
@@ -390,7 +400,7 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
 				    sizeof(oldfname));
 				len = strlcat(oldfname, inplace,
 				    sizeof(oldfname));
-				if ((size_t)len > sizeof(oldfname))
+				if (len > (ssize_t)sizeof(oldfname))
 					errx(1, "%s: name too long", fname);
 			}
 			if ((dirbuf = strdup(fname)) == NULL ||
@@ -401,7 +411,7 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
 			    basename(basebuf));
 			free(dirbuf);
 			free(basebuf);
-			if ((size_t)len >= sizeof(tmpfname))
+			if (len >= (ssize_t)sizeof(tmpfname))
 				errx(1, "%s: name too long", fname);
 			unlink(tmpfname);
 			if (outfile != NULL && outfile != stdout)
@@ -455,7 +465,7 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
  * Add a compilation unit to the linked list
  */
 static void
-add_compunit(enum e_cut type, const char *s)
+add_compunit(enum e_cut type, char *s)
 {
 	struct s_compunit *cu;
 
@@ -472,7 +482,7 @@ add_compunit(enum e_cut type, const char
  * Add a file to the linked list
  */
 static void
-add_file(const char *s)
+add_file(char *s)
 {
 	struct s_flist *fp;
 

Modified: head/usr.bin/sed/misc.c
==============================================================================
--- head/usr.bin/sed/misc.c	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/misc.c	Tue Aug  2 15:35:53 2016	(r303662)
@@ -56,14 +56,16 @@ static const char sccsid[] = "@(#)misc.c
  * the buffer).
  */
 char *
-strregerror(int errcode, const regex_t *preg)
+strregerror(int errcode, regex_t *preg)
 {
 	static char *oe;
 	size_t s;
 
+	if (oe != NULL)
+		free(oe);
 	s = regerror(errcode, preg, NULL, 0);
-	if ((oe = realloc(oe, s)) == NULL)
-		err(1, "realloc");
+	if ((oe = malloc(s)) == NULL)
+		err(1, "malloc");
 	(void)regerror(errcode, preg, oe, s);
 	return (oe);
 }

Modified: head/usr.bin/sed/process.c
==============================================================================
--- head/usr.bin/sed/process.c	Tue Aug  2 15:26:46 2016	(r303661)
+++ head/usr.bin/sed/process.c	Tue Aug  2 15:35:53 2016	(r303662)
@@ -67,14 +67,14 @@ static SPACE HS, PS, SS, YS;
 #define	hs		HS.space
 #define	hsl		HS.len
 
-static inline int	applies(struct s_command *);
-static void		do_tr(const struct s_tr *);
-static void		flush_appends(void);
-static void		lputs(const char *, size_t);
-static int		regexec_e(const regex_t *, const char *, int, int,
-			    size_t, size_t);
-static void		regsub(SPACE *, const char *, const char *);
-static int		substitute(const struct s_command *);
+static inline int	 applies(struct s_command *);
+static void		 do_tr(struct s_tr *);
+static void		 flush_appends(void);
+static void		 lputs(char *, size_t);
+static int		 regexec_e(regex_t *, const char *, int, int, size_t,
+			     size_t);
+static void		 regsub(SPACE *, char *, char *);
+static int		 substitute(struct s_command *);
 
 struct s_appends *appends;	/* Array of pointers to strings to append. */
 static int appendx;		/* Index into appends array. */
@@ -83,7 +83,7 @@ int appendnum;			/* Size of appends arra
 static int lastaddr;		/* Set by applies if last address of a range. */
 static int sdone;		/* If any substitutes since last line input. */
 				/* Iov structure for 'w' commands. */
-static const regex_t *defpreg;
+static regex_t *defpreg;
 size_t maxnsub;
 regmatch_t *match;
 
@@ -377,13 +377,13 @@ resetstate(void)
  *	and then swap them.
  */
 static int
-substitute(const struct s_command *cp)
+substitute(struct s_command *cp)
 {
 	SPACE tspace;
-	const regex_t *re;
+	regex_t *re;
 	regoff_t slen;
 	int lastempty, n;
-	regoff_t le = 0;
+	size_t le = 0;
 	char *s;
 
 	s = ps;
@@ -489,7 +489,7 @@ substitute(const struct s_command *cp)
  *	Perform translation ('y' command) in the pattern space.
  */
 static void
-do_tr(const struct s_tr *y)
+do_tr(struct s_tr *y)
 {
 	SPACE tmp;
 	char c, *p;
@@ -579,7 +579,7 @@ flush_appends(void)
 }
 
 static void
-lputs(const char *s, size_t len)
+lputs(char *s, size_t len)
 {
 	static const char escapes[] = "\\\a\b\f\r\t\v";
 	int c, col, width;
@@ -659,7 +659,7 @@ lputs(const char *s, size_t len)
 }
 
 static int
-regexec_e(const regex_t *preg, const char *string, int eflags, int nomatch,
+regexec_e(regex_t *preg, const char *string, int eflags, int nomatch,
 	size_t start, size_t stop)
 {
 	int eval;
@@ -691,7 +691,7 @@ regexec_e(const regex_t *preg, const cha
  * Based on a routine by Henry Spencer
  */
 static void
-regsub(SPACE *sp, const char *string, const char *src)
+regsub(SPACE *sp, char *string, char *src)
 {
 	int len, no;
 	char c, *dst;
@@ -763,7 +763,7 @@ cspace(SPACE *sp, const char *p, size_t 
  * Close all cached opened files and report any errors
  */
 void
-cfclose(struct s_command *cp, const struct s_command *end)
+cfclose(struct s_command *cp, struct s_command *end)
 {
 
 	for (; cp != end; cp = cp->next)


More information about the svn-src-head mailing list