summaryrefslogtreecommitdiff
path: root/usr.bin/sed/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/sed/process.c')
-rw-r--r--usr.bin/sed/process.c154
1 files changed, 87 insertions, 67 deletions
diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c
index f1a4e9e9f2c2..ef6bc71b6d26 100644
--- a/usr.bin/sed/process.c
+++ b/usr.bin/sed/process.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 1992 Diomidis Spinellis.
- * Copyright (c) 1992 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Diomidis Spinellis of Imperial College, University of London.
@@ -36,7 +36,8 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)process.c 5.10 (Berkeley) 12/2/92";
+/* from: static char sccsid[] = "@(#)process.c 8.1 (Berkeley) 6/6/93"; */
+static char *rcsid = "$Id: process.c,v 1.5 1994/04/17 09:41:52 alm Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -57,7 +58,7 @@ static char sccsid[] = "@(#)process.c 5.10 (Berkeley) 12/2/92";
#include "defs.h"
#include "extern.h"
-static SPACE HS = {""}, PS, SS;
+static SPACE HS, PS, SS;
#define pd PS.deleted
#define ps PS.space
#define psl PS.len
@@ -67,7 +68,7 @@ static SPACE HS = {""}, PS, SS;
static inline int applies __P((struct s_command *));
static void flush_appends __P((void));
static void lputs __P((char *));
-static inline int regexec_e __P((regex_t *, const char *, int, int));
+static inline int regexec_e __P((regex_t *, const char *, int, int, size_t));
static void regsub __P((SPACE *, char *, char *));
static int substitute __P((struct s_command *));
@@ -78,12 +79,12 @@ int appendnum; /* Size of appends array. */
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 struct iovec iov[2] = { NULL, 0, "\n", 1 };
-
static regex_t *defpreg;
size_t maxnsub;
regmatch_t *match;
+#define OUT(s) { fwrite(s, sizeof(u_char), psl, stdout); }
+
void
process()
{
@@ -113,6 +114,7 @@ redirect:
(appendnum *= 2));
appends[appendx].type = AP_STRING;
appends[appendx].s = cp->t;
+ appends[appendx].len = strlen(cp->t);
appendx++;
break;
case 'b':
@@ -130,10 +132,10 @@ redirect:
case 'D':
if (pd)
goto new;
- if ((p = strchr(ps, '\n')) == NULL)
+ if ((p = memchr(ps, '\n', psl)) == NULL)
pd = 1;
else {
- psl -= (p - ps) - 1;
+ psl -= (p + 1) - ps;
memmove(ps, p + 1, psl);
}
goto new;
@@ -141,13 +143,13 @@ redirect:
cspace(&PS, hs, hsl, REPLACE);
break;
case 'G':
- cspace(&PS, hs, hsl, APPENDNL);
+ cspace(&PS, hs, hsl, 0);
break;
case 'h':
cspace(&HS, ps, psl, REPLACE);
break;
case 'H':
- cspace(&HS, ps, psl, APPENDNL);
+ cspace(&HS, ps, psl, 0);
break;
case 'i':
(void)printf("%s", cp->t);
@@ -157,10 +159,10 @@ redirect:
break;
case 'n':
if (!nflag && !pd)
- (void)printf("%s\n", ps);
+ OUT(ps)
flush_appends();
r = mf_fgets(&PS, REPLACE);
-#ifdef HISTORIC_PRACTICE
+#ifndef NONHISTORIC_PRACTICE
if (!r)
exit(0);
#endif
@@ -168,31 +170,31 @@ redirect:
break;
case 'N':
flush_appends();
- if (!mf_fgets(&PS, APPENDNL)) {
+ if (!mf_fgets(&PS, 0)) {
if (!nflag && !pd)
- (void)printf("%s\n", ps);
+ OUT(ps)
exit(0);
}
break;
case 'p':
if (pd)
break;
- (void)printf("%s\n", ps);
+ OUT(ps)
break;
case 'P':
if (pd)
break;
- if ((p = strchr(ps, '\n')) != NULL) {
+ if ((p = memchr(ps, '\n', psl)) != NULL) {
oldc = *p;
*p = '\0';
}
- (void)printf("%s\n", ps);
+ OUT(ps)
if (p != NULL)
*p = oldc;
break;
case 'q':
if (!nflag && !pd)
- (void)printf("%s\n", ps);
+ OUT(ps)
flush_appends();
exit(0);
case 'r':
@@ -202,6 +204,7 @@ redirect:
(appendnum *= 2));
appends[appendx].type = AP_FILE;
appends[appendx].s = cp->t;
+ appends[appendx].len = strlen(cp->t);
appendx++;
break;
case 's':
@@ -222,13 +225,13 @@ redirect:
DEFFILEMODE)) == -1)
err(FATAL, "%s: %s\n",
cp->t, strerror(errno));
- iov[0].iov_base = ps;
- iov[0].iov_len = psl;
- if (writev(cp->u.fd, iov, 2) != psl + 1)
+ if (write(cp->u.fd, ps, psl) != psl)
err(FATAL, "%s: %s\n",
cp->t, strerror(errno));
break;
case 'x':
+ if (hs == NULL)
+ cspace(&HS, "", 0, REPLACE);
tspace = PS;
PS = HS;
HS = tspace;
@@ -236,7 +239,7 @@ redirect:
case 'y':
if (pd)
break;
- for (p = ps, len = psl; len--; ++p)
+ for (p = ps, len = psl; --len; ++p)
*p = cp->u.y[*p];
break;
case ':':
@@ -249,7 +252,7 @@ redirect:
} /* for all cp */
new: if (!nflag && !pd)
- (void)printf("%s\n", ps);
+ OUT(ps)
flush_appends();
} /* for all lines */
}
@@ -258,8 +261,8 @@ new: if (!nflag && !pd)
* TRUE if the address passed matches the current program state
* (lastline, linenumber, ps).
*/
-#define MATCH(a) \
- (a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1) : \
+#define MATCH(a) \
+ (a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1, psl) : \
(a)->type == AT_LINE ? linenum == (a)->u.l : lastline
/*
@@ -314,14 +317,11 @@ substitute(cp)
{
SPACE tspace;
regex_t *re;
- size_t re_off;
- size_t re_eoff;
- int n;
+ size_t re_off, slen;
+ int n, lastempty;
char *s;
- char *eos;
s = ps;
- eos = s + strlen(s);
re = cp->u.s->re;
if (re == NULL) {
if (defpreg != NULL && cp->u.s->maxbref > defpreg->re_nsub) {
@@ -330,33 +330,52 @@ substitute(cp)
cp->u.s->maxbref);
}
}
- if (!regexec_e(re, s, 0, 0))
+ if (!regexec_e(re, s, 0, 0, psl))
return (0);
SS.len = 0; /* Clean substitute space. */
+ slen = psl;
n = cp->u.s->n;
+ lastempty = 1;
+
switch (n) {
case 0: /* Global */
do {
- /* Locate start of replaced string. */
- re_off = match[0].rm_so;
- re_eoff = match[0].rm_eo;
- /* Copy leading retained string. */
- cspace(&SS, s, re_off, APPEND);
- /* Add in regular expression. */
- regsub(&SS, s, cp->u.s->new);
+ if (lastempty || match[0].rm_so != match[0].rm_eo) {
+ /* Locate start of replaced string. */
+ re_off = match[0].rm_so;
+ /* Copy leading retained string. */
+ cspace(&SS, s, re_off, APPEND);
+ /* Add in regular expression. */
+ regsub(&SS, s, cp->u.s->new);
+ }
+
/* Move past this match. */
- s += match[0].rm_eo;
- } while(*s && re_eoff && regexec_e(re, s, REG_NOTBOL, 0));
- if (eos - s > 0 && !re_eoff)
- err(FATAL, "infinite substitution loop");
+ if (match[0].rm_so != match[0].rm_eo) {
+ s += match[0].rm_eo;
+ slen -= match[0].rm_eo;
+ lastempty = 0;
+ } else {
+ if (match[0].rm_so == 0)
+ cspace(&SS, s, match[0].rm_so + 1,
+ APPEND);
+ else
+ cspace(&SS, s + match[0].rm_so, 1,
+ APPEND);
+ s += match[0].rm_so + 1;
+ slen -= match[0].rm_so + 1;
+ lastempty = 1;
+ }
+ } while (slen > 0 && regexec_e(re, s, REG_NOTBOL, 0, slen));
/* Copy trailing retained string. */
- cspace(&SS, s, strlen(s), APPEND);
+ if (slen > 0)
+ cspace(&SS, s, slen, APPEND);
break;
default: /* Nth occurrence */
while (--n) {
s += match[0].rm_eo;
- if (!regexec_e(re, s, REG_NOTBOL, 0))
+ slen -= match[0].rm_eo;
+ if (!regexec_e(re, s, REG_NOTBOL, 0, slen))
return (0);
}
/* FALLTHROUGH */
@@ -369,7 +388,8 @@ substitute(cp)
regsub(&SS, s, cp->u.s->new);
/* Copy trailing retained string. */
s += match[0].rm_eo;
- cspace(&SS, s, strlen(s), APPEND);
+ slen -= match[0].rm_eo;
+ cspace(&SS, s, slen, APPEND);
break;
}
@@ -384,16 +404,14 @@ substitute(cp)
/* Handle the 'p' flag. */
if (cp->u.s->p)
- (void)printf("%s\n", ps);
+ OUT(ps)
/* Handle the 'w' flag. */
if (cp->u.s->wfile && !pd) {
if (cp->u.s->wfd == -1 && (cp->u.s->wfd = open(cp->u.s->wfile,
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, DEFFILEMODE)) == -1)
err(FATAL, "%s: %s\n", cp->u.s->wfile, strerror(errno));
- iov[0].iov_base = ps;
- iov[0].iov_len = psl;
- if (writev(cp->u.s->wfd, iov, 2) != psl + 1)
+ if (write(cp->u.s->wfd, ps, psl) != psl)
err(FATAL, "%s: %s\n", cp->u.s->wfile, strerror(errno));
}
return (1);
@@ -413,7 +431,8 @@ flush_appends()
for (i = 0; i < appendx; i++)
switch (appends[i].type) {
case AP_STRING:
- (void)printf("%s", appends[i].s);
+ fwrite(appends[i].s, sizeof(char), appends[i].len,
+ stdout);
break;
case AP_FILE:
/*
@@ -426,8 +445,8 @@ flush_appends()
*/
if ((f = fopen(appends[i].s, "r")) == NULL)
break;
- while (count = fread(buf, 1, sizeof(buf), f))
- (void)fwrite(buf, 1, count, stdout);
+ while (count = fread(buf, sizeof(char), sizeof(buf), f))
+ (void)fwrite(buf, sizeof(char), count, stdout);
(void)fclose(f);
break;
}
@@ -469,7 +488,7 @@ lputs(s)
(void)putchar("\\abfnrtv"[p - escapes]);
count += 2;
} else {
- (void)printf("%03o", (u_char)*s);
+ (void)printf("%03o", *(u_char *)s);
count += 4;
}
}
@@ -481,21 +500,28 @@ lputs(s)
}
static inline int
-regexec_e(preg, string, eflags, nomatch)
+regexec_e(preg, string, eflags, nomatch, slen)
regex_t *preg;
const char *string;
int eflags, nomatch;
+ size_t slen;
{
int eval;
-
+
if (preg == NULL) {
if (defpreg == NULL)
err(FATAL, "first RE may not be empty");
} else
defpreg = preg;
+ /* Set anchors, discounting trailing newline (if any). */
+ if (slen > 0 && string[slen - 1] == '\n')
+ slen--;
+ match[0].rm_so = 0;
+ match[0].rm_eo = slen;
+
eval = regexec(defpreg, string,
- nomatch ? 0 : maxnsub + 1, match, eflags);
+ nomatch ? 0 : maxnsub + 1, match, eflags | REG_STARTEND);
switch(eval) {
case 0:
return (1);
@@ -565,24 +591,18 @@ cspace(sp, p, len, spflag)
{
size_t tlen;
- /*
- * Make sure SPACE has enough memory and ramp up quickly. Appends
- * need two extra bytes, one for the newline, one for a terminating
- * NULL.
- */
-/* tlen = sp->len + len + spflag == APPENDNL ? 2 : 1; */
- tlen = sp->len + len + (spflag == APPENDNL ? 2 : 1); /* XXX */
+ /* Make sure SPACE has enough memory and ramp up quickly. */
+ tlen = sp->len + len + 1;
if (tlen > sp->blen) {
sp->blen = tlen + 1024;
sp->space = sp->back = xrealloc(sp->back, sp->blen);
}
- if (spflag == APPENDNL)
- sp->space[sp->len++] = '\n';
- else if (spflag == REPLACE)
+ if (spflag == REPLACE)
sp->len = 0;
memmove(sp->space + sp->len, p, len);
+
sp->space[sp->len += len] = '\0';
}