diff options
Diffstat (limited to 'usr.bin/sed')
-rw-r--r-- | usr.bin/sed/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/sed/POSIX | 11 | ||||
-rw-r--r-- | usr.bin/sed/compile.c | 167 | ||||
-rw-r--r-- | usr.bin/sed/defs.h | 11 | ||||
-rw-r--r-- | usr.bin/sed/extern.h | 11 | ||||
-rw-r--r-- | usr.bin/sed/main.c | 21 | ||||
-rw-r--r-- | usr.bin/sed/misc.c | 7 | ||||
-rw-r--r-- | usr.bin/sed/process.c | 154 |
8 files changed, 235 insertions, 153 deletions
diff --git a/usr.bin/sed/Makefile b/usr.bin/sed/Makefile index 52f0fb5f3e5d..9a6871df40b5 100644 --- a/usr.bin/sed/Makefile +++ b/usr.bin/sed/Makefile @@ -1,7 +1,7 @@ -# @(#)Makefile 5.1 (Berkeley) 8/24/92 +# from: @(#)Makefile 8.1 (Berkeley) 6/6/93 PROG= sed -SRCS= compile.c main.c misc.c process.c -CFLAGS+=-I${.CURDIR} -DHISTORIC_PRACTICE +SRCS= compile.c main.c misc.c process.c +CFLAGS+=-I${.CURDIR} .include <bsd.prog.mk> diff --git a/usr.bin/sed/POSIX b/usr.bin/sed/POSIX index 467b31db3e96..fcd557f72800 100644 --- a/usr.bin/sed/POSIX +++ b/usr.bin/sed/POSIX @@ -97,10 +97,7 @@ All uses of "POSIX" refer to section 4.55, Draft 12 of POSIX 1003.2. did not produce any output. POSIX does not specify this behavior. This implementation follows historic practice. -10. POSIX does not specify that the q command causes all lines that - have been appended to be output and that the pattern space is - printed before exiting. This implementation follows historic - practice. +10. Deleted. 11. Historical implementations do not output the change text of a c command in the case of an address range whose first line number @@ -175,11 +172,7 @@ All uses of "POSIX" refer to section 4.55, Draft 12 of POSIX 1003.2. string1 or string2 of the y command. This is not specified by POSIX. This implementation follows historic practice. -21. POSIX does not specify if the "Nth occurrence" of an RE in a - substitute command is an overlapping or a non-overlapping one, - i.e. what is the result of s/a*/A/2 on the pattern "aaaaa aaaaa". - Historical practice is to drop core or only do non-overlapping - RE's. This implementation only does non-overlapping RE's. +21. Deleted. 22. Historic implementations of sed ignore the RE delimiter characters within character classes. This is not specified in POSIX. This diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c index 526f21c89f7e..72cb93fcd3f4 100644 --- a/usr.bin/sed/compile.c +++ b/usr.bin/sed/compile.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[] = "@(#)compile.c 5.6 (Berkeley) 11/2/92"; +/* from: static char sccsid[] = "@(#)compile.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: compile.c,v 1.5 1994/04/17 09:41:36 alm Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -54,6 +55,15 @@ static char sccsid[] = "@(#)compile.c 5.6 (Berkeley) 11/2/92"; #include "defs.h" #include "extern.h" +#define LHSZ 128 +#define LHMASK (LHSZ - 1) +static struct labhash { + struct labhash *lh_next; + u_int lh_hash; + struct s_command *lh_cmd; + int lh_ref; +} *labels[LHSZ]; + static char *compile_addr __P((char *, struct s_addr *)); static char *compile_ccl __P((char **, char *)); static char *compile_delimited __P((char *, char *)); @@ -64,11 +74,12 @@ static char *compile_text __P((void)); static char *compile_tr __P((char *, char **)); static struct s_command **compile_stream __P((char *, struct s_command **, char *)); -static char *duptoeol __P((char *)); +static char *duptoeol __P((char *, char *)); +static void enterlabel __P((struct s_command *)); static struct s_command - *findlabel __P((struct s_command *, struct s_command *)); -static void fixuplabel __P((struct s_command *, struct s_command *, - struct s_command *)); + *findlabel __P((char *)); +static void fixuplabel __P((struct s_command *, struct s_command *)); +static void uselabel __P((void)); /* * Command specification. This is used to drive the command parser. @@ -121,7 +132,8 @@ void compile() { *compile_stream(NULL, &prog, NULL) = NULL; - fixuplabel(prog, prog, NULL); + fixuplabel(prog, NULL); + uselabel(); appends = xmalloc(sizeof(struct s_appends) * appendnum); match = xmalloc((maxnsub + 1) * sizeof(regmatch_t)); } @@ -208,8 +220,6 @@ nonsel: /* Now parse the command */ p = NULL; cmd2 = xmalloc(sizeof(struct s_command)); cmd2->code = '}'; - cmd2->a1 = cmd2->a2 = NULL; - cmd2->nonsel = 0; *compile_stream("}", &cmd->u.c, p) = cmd2; cmd->next = cmd2; link = &cmd2->next; @@ -246,7 +256,7 @@ nonsel: /* Now parse the command */ EATSPACE(); if (*p == '\0') err(COMPILE, "filename expected"); - cmd->t = duptoeol(p); + cmd->t = duptoeol(p, "w command"); if (aflag) cmd->u.fd = -1; else if ((cmd->u.fd = open(p, @@ -260,7 +270,7 @@ nonsel: /* Now parse the command */ if (*p == '\0') err(COMPILE, "filename expected"); else - cmd->t = duptoeol(p); + cmd->t = duptoeol(p, "read command"); break; case BRANCH: /* b t */ p++; @@ -268,14 +278,15 @@ nonsel: /* Now parse the command */ if (*p == '\0') cmd->t = NULL; else - cmd->t = duptoeol(p); + cmd->t = duptoeol(p, "branch"); break; case LABEL: /* : */ p++; EATSPACE(); - cmd->t = duptoeol(p); + cmd->t = duptoeol(p, "label"); if (strlen(p) == 0) err(COMPILE, "empty label"); + enterlabel(cmd); break; case SUBST: /* s */ p++; @@ -340,6 +351,8 @@ compile_delimited(p, d) if ((d = compile_ccl(&p, d)) == NULL) err(COMPILE, "unbalanced brackets ([])"); continue; + } else if (*p == '\\' && p[1] == '[') { + *d++ = *p++; } else if (*p == '\\' && p[1] == c) p++; else if (*p == '\\' && p[1] == 'n') { @@ -664,77 +677,129 @@ compile_addr(p, a) } /* - * Return a copy of all the characters up to \n or \0 + * duptoeol -- + * Return a copy of all the characters up to \n or \0. */ static char * -duptoeol(s) +duptoeol(s, ctype) register char *s; + char *ctype; { size_t len; + int ws; char *start; - for (start = s; *s != '\0' && *s != '\n'; ++s); + ws = 0; + for (start = s; *s != '\0' && *s != '\n'; ++s) + ws = isspace(*s); *s = '\0'; + if (ws) + err(WARNING, "whitespace after %s", ctype); len = s - start + 1; return (memmove(xmalloc(len), start, len)); } /* - * Find the label contained in the command l in the command linked list cp. - * L is excluded from the search. Return NULL if not found. - */ -static struct s_command * -findlabel(l, cp) - struct s_command *l, *cp; -{ - struct s_command *r; - - for (; cp; cp = cp->next) - if (cp->code == ':' && cp != l && strcmp(l->t, cp->t) == 0) - return (cp); - else if (cp->code == '{' && (r = findlabel(l, cp->u.c))) - return (r); - return (NULL); -} - -/* - * Convert goto label names to addresses. - * Detect duplicate labels. - * Set appendnum to the number of a and r commands in the script. - * Free the memory used by labels in b and t commands (but not by :) - * Root is a pointer to the script linked list; cp points to the - * search start. + * Convert goto label names to addresses, and count a and r commands, in + * the given subset of the script. Free the memory used by labels in b + * and t commands (but not by :). + * * TODO: Remove } nodes */ static void -fixuplabel(root, cp, end) - struct s_command *root, *cp, *end; +fixuplabel(cp, end) + struct s_command *cp, *end; { - struct s_command *cp2; for (; cp != end; cp = cp->next) switch (cp->code) { - case ':': - if (findlabel(cp, root)) - err(COMPILE2, "duplicate label %s", cp->t); - break; case 'a': case 'r': appendnum++; break; case 'b': case 't': + /* Resolve branch target. */ if (cp->t == NULL) { cp->u.c = NULL; break; } - if ((cp2 = findlabel(cp, root)) == NULL) + if ((cp->u.c = findlabel(cp->t)) == NULL) err(COMPILE2, "undefined label '%s'", cp->t); free(cp->t); - cp->u.c = cp2; break; case '{': - fixuplabel(root, cp->u.c, cp->next); + /* Do interior commands. */ + fixuplabel(cp->u.c, cp->next); break; } } + +/* + * Associate the given command label for later lookup. + */ +static void +enterlabel(cp) + struct s_command *cp; +{ + register struct labhash **lhp, *lh; + register u_char *p; + register u_int h, c; + + for (h = 0, p = (u_char *)cp->t; (c = *p) != 0; p++) + h = (h << 5) + h + c; + lhp = &labels[h & LHMASK]; + for (lh = *lhp; lh != NULL; lh = lh->lh_next) + if (lh->lh_hash == h && strcmp(cp->t, lh->lh_cmd->t) == 0) + err(COMPILE2, "duplicate label '%s'", cp->t); + lh = xmalloc(sizeof *lh); + lh->lh_next = *lhp; + lh->lh_hash = h; + lh->lh_cmd = cp; + lh->lh_ref = 0; + *lhp = lh; +} + +/* + * Find the label contained in the command l in the command linked + * list cp. L is excluded from the search. Return NULL if not found. + */ +static struct s_command * +findlabel(name) + char *name; +{ + register struct labhash *lh; + register u_char *p; + register u_int h, c; + + 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) { + lh->lh_ref = 1; + return (lh->lh_cmd); + } + } + return (NULL); +} + +/* + * Warn about any unused labels. As a side effect, release the label hash + * table space. + */ +static void +uselabel() +{ + register struct labhash *lh, *next; + register int i; + + for (i = 0; i < LHSZ; i++) { + for (lh = labels[i]; lh != NULL; lh = next) { + next = lh->lh_next; + if (!lh->lh_ref) + err(WARNING, "unused label '%s'", + lh->lh_cmd->t); + free(lh); + } + } +} diff --git a/usr.bin/sed/defs.h b/usr.bin/sed/defs.h index 948ba4454811..b4d775fda30a 100644 --- a/usr.bin/sed/defs.h +++ b/usr.bin/sed/defs.h @@ -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. @@ -34,7 +34,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)defs.h 5.3 (Berkeley) 8/28/92 + * from: @(#)defs.h 8.1 (Berkeley) 6/6/93 + * $Id: defs.h,v 1.2 1994/04/17 09:41:38 alm Exp $ */ /* @@ -74,7 +75,7 @@ struct s_subst { /* * An internally compiled command. - * Initialy, label references are stored in u.t, on a second pass they + * Initialy, label references are stored in t, on a second pass they * are updated to pointers. */ struct s_command { @@ -115,11 +116,11 @@ enum e_args { struct s_appends { enum {AP_STRING, AP_FILE} type; char *s; + size_t len; }; enum e_spflag { APPEND, /* Append to the contents. */ - APPENDNL, /* Append, with newline. */ REPLACE, /* Replace the contents. */ }; diff --git a/usr.bin/sed/extern.h b/usr.bin/sed/extern.h index 32b68a1ee9bf..ed0c9bd3bb2a 100644 --- a/usr.bin/sed/extern.h +++ b/usr.bin/sed/extern.h @@ -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. @@ -34,7 +34,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)extern.h 5.5 (Berkeley) 8/30/92 + * from: @(#)extern.h 8.1 (Berkeley) 6/6/93 + * $Id: extern.h,v 1.2 1994/04/17 09:41:41 alm Exp $ */ extern struct s_command *prog; @@ -47,7 +48,9 @@ extern int lastline; extern int aflag, eflag, nflag; extern char *fname; +void cfclose __P((struct s_command *, struct s_command *)); void compile __P((void)); +void cspace __P((SPACE *, char *, size_t, enum e_spflag)); char *cu_fgets __P((char *, int)); void err __P((int, const char *, ...)); int mf_fgets __P((SPACE *, enum e_spflag)); @@ -55,5 +58,3 @@ void process __P((void)); char *strregerror __P((int, regex_t *)); void *xmalloc __P((u_int)); void *xrealloc __P((void *, u_int)); -void cfclose __P((struct s_command *, struct s_command *)); -void cspace __P((SPACE *, char *, size_t, enum e_spflag)); diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c index f4fc96f7026a..276ff4c59007 100644 --- a/usr.bin/sed/main.c +++ b/usr.bin/sed/main.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,13 +36,14 @@ */ #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1992 The Regents of the University of California.\n\ - All rights reserved.\n"; +static char copyright[] = +"@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 5.6 (Berkeley) 8/30/92"; +/* from: static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/3/94"; */ +static char *rcsid = "$Id: main.c,v 1.2 1994/04/17 09:41:44 alm Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -286,11 +287,11 @@ mf_fgets(sp, spflag) } /* - * Use fgetline so that we can handle essentially infinite input - * data. Can't use the pointer into the stdio buffer as the process - * space because the ungetc() can cause it to move. + * Use fgetln so that we can handle essentially infinite input data. + * Can't use the pointer into the stdio buffer as the process space + * because the ungetc() can cause it to move. */ - p = fgetline(f, &len); + p = fgetln(f, &len); if (ferror(f)) err(FATAL, "%s: %s", fname, strerror(errno ? errno : EIO)); cspace(sp, p, len, spflag); diff --git a/usr.bin/sed/misc.c b/usr.bin/sed/misc.c index 807821334cee..41e923e82e22 100644 --- a/usr.bin/sed/misc.c +++ b/usr.bin/sed/misc.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[] = "@(#)misc.c 5.3 (Berkeley) 8/26/92"; +/* from: static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; */ +static char *rcsid = "$Id: misc.c,v 1.2 1994/04/17 09:41:49 alm Exp $"; #endif /* not lint */ #include <sys/types.h> 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'; } |