summaryrefslogtreecommitdiffstats
path: root/usr.bin/sed
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-08-16 05:56:44 +0000
committerjkh <jkh@FreeBSD.org>1995-08-16 05:56:44 +0000
commit529c9b015ab62caa94981c2f131f9b291428a10b (patch)
tree698a431f9038d11c62b9e1a96307628f0d4df8f1 /usr.bin/sed
parent8c03fe0f4db1526151e5a3607d650f1555f4b68f (diff)
downloadFreeBSD-src-529c9b015ab62caa94981c2f131f9b291428a10b.zip
FreeBSD-src-529c9b015ab62caa94981c2f131f9b291428a10b.tar.gz
Merge various fixes from NetBSD. This will allow the WordPerfect for
SCO installation to run all the way through (some POSIX fixes).
Diffstat (limited to 'usr.bin/sed')
-rw-r--r--usr.bin/sed/compile.c99
-rw-r--r--usr.bin/sed/defs.h1
-rw-r--r--usr.bin/sed/process.c34
3 files changed, 87 insertions, 47 deletions
diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c
index 5564f6e..9f13fd7 100644
--- a/usr.bin/sed/compile.c
+++ b/usr.bin/sed/compile.c
@@ -64,6 +64,7 @@ static struct labhash {
} *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 *));
static char *compile_flags __P((char *, struct s_subst *));
static char *compile_re __P((char *, regex_t **));
@@ -71,7 +72,7 @@ static char *compile_subst __P((char *, struct s_subst *));
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 *));
+ **compile_stream __P((struct s_command **));
static char *duptoeol __P((char *, char *));
static void enterlabel __P((struct s_command *));
static struct s_command
@@ -90,6 +91,7 @@ struct s_format {
static struct s_format cmd_fmts[] = {
{'{', 2, GROUP},
+ {'}', 0, ENDGROUP},
{'a', 1, TEXT},
{'b', 2, BRANCH},
{'c', 2, TEXT},
@@ -129,7 +131,7 @@ struct s_command *prog;
void
compile()
{
- *compile_stream(NULL, &prog, NULL) = NULL;
+ *compile_stream(&prog) = NULL;
fixuplabel(prog, NULL);
uselabel();
appends = xmalloc(sizeof(struct s_appends) * appendnum);
@@ -143,21 +145,19 @@ compile()
} while (0)
static struct s_command **
-compile_stream(terminator, link, p)
- char *terminator;
+compile_stream(link)
struct s_command **link;
- register char *p;
{
+ register char *p;
static char lbuf[_POSIX2_LINE_MAX + 1]; /* To save stack */
- struct s_command *cmd, *cmd2;
+ struct s_command *cmd, *cmd2, *stack;
struct s_format *fp;
int naddr; /* Number of addresses */
- if (p != NULL)
- goto semicolon;
+ stack = 0;
for (;;) {
if ((p = cu_fgets(lbuf, sizeof(lbuf))) == NULL) {
- if (terminator != NULL)
+ if (stack != 0)
err(COMPILE, "unexpected EOF (pending }'s)");
return (link);
}
@@ -165,17 +165,11 @@ compile_stream(terminator, link, p)
semicolon: EATSPACE();
if (p && (*p == '#' || *p == '\0'))
continue;
- if (*p == '}') {
- if (terminator == NULL)
- err(COMPILE, "unexpected }");
- return (link);
- }
*link = cmd = xmalloc(sizeof(struct s_command));
link = &cmd->next;
cmd->nonsel = cmd->inrange = 0;
/* First parse the addresses */
naddr = 0;
- cmd->a1 = cmd->a2 = NULL;
/* Valid characters to start an address */
#define addrchar(c) (strchr("0123456789/\\$", (c)))
@@ -185,16 +179,18 @@ semicolon: EATSPACE();
p = compile_addr(p, cmd->a1);
EATSPACE(); /* EXTENSION */
if (*p == ',') {
- naddr++;
p++;
EATSPACE(); /* EXTENSION */
+ naddr++;
cmd->a2 = xmalloc(sizeof(struct s_addr));
p = compile_addr(p, cmd->a2);
- }
- }
+ EATSPACE();
+ } else
+ cmd->a2 = 0;
+ } else
+ cmd->a1 = cmd->a2 = 0;
nonsel: /* Now parse the command */
- EATSPACE();
if (!*p)
err(COMPILE, "command expected");
cmd->code = *p;
@@ -208,22 +204,31 @@ nonsel: /* Now parse the command */
"command %c expects up to %d address(es), found %d", *p, fp->naddr, naddr);
switch (fp->args) {
case NONSEL: /* ! */
- cmd->nonsel = ! cmd->nonsel;
p++;
+ EATSPACE();
+ cmd->nonsel = ! cmd->nonsel;
goto nonsel;
case GROUP: /* { */
p++;
EATSPACE();
- if (!*p)
- p = NULL;
- cmd2 = xmalloc(sizeof(struct s_command));
- cmd2->nonsel = cmd2->inrange = 0;
- cmd2->a1 = cmd2->a2 = NULL;
- cmd2->code = '}';
- *compile_stream("}", &cmd->u.c, p) = cmd2;
- cmd->next = cmd2;
- link = &cmd2->next;
+ cmd->next = stack;
+ stack = cmd;
+ link = &cmd->u.c;
+ if (*p)
+ goto semicolon;
break;
+ case ENDGROUP:
+ /*
+ * Short-circuit command processing, since end of
+ * group is really just a noop.
+ */
+ cmd->nonsel = 1;
+ if (stack == 0)
+ err(COMPILE, "unexpected }");
+ cmd2 = stack;
+ stack = cmd2->next;
+ cmd2->next = cmd;
+ /*FALLTHROUGH*/
case EMPTY: /* d D g G h H l n N p P q x = \0 */
p++;
EATSPACE();
@@ -259,7 +264,7 @@ nonsel: /* Now parse the command */
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(p,
O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
DEFFILEMODE)) == -1)
err(FATAL, "%s: %s\n", p, strerror(errno));
@@ -347,7 +352,13 @@ compile_delimited(p, d)
else if (c == '\n')
err(COMPILE, "newline can not be used as a string delimiter");
while (*p) {
- if (*p == '\\' && p[1] == c)
+ if (*p == '[') {
+ 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') {
*d++ = '\n';
@@ -364,6 +375,32 @@ compile_delimited(p, d)
return (NULL);
}
+
+/* compile_ccl: expand a POSIX character class */
+static char *
+compile_ccl(sp, t)
+ char **sp;
+ char *t;
+{
+ int c, d;
+ char *s = *sp;
+
+ *t++ = *s++;
+ if (*s == '^')
+ *t++ = *s++;
+ if (*s == ']')
+ *t++ = *s++;
+ for (; *s && (*t = *s) != ']'; s++, t++)
+ if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) {
+ *++t = *++s, t++, s++;
+ for (c = *s; (*t = *s) != ']' || c != d; s++, t++)
+ if ((c = *s) == '\0')
+ return NULL;
+ } else if (*s == '\\' && s[1] == 'n')
+ *t = '\n', s++;
+ return (*s == ']') ? *sp = ++s, ++t : NULL;
+}
+
/*
* Get a regular expression. P points to the delimiter of the regular
* expression; repp points to the address of a regexp pointer. Newline
diff --git a/usr.bin/sed/defs.h b/usr.bin/sed/defs.h
index 3cc580f..6e78e91 100644
--- a/usr.bin/sed/defs.h
+++ b/usr.bin/sed/defs.h
@@ -100,6 +100,7 @@ enum e_args {
TEXT, /* a c i */
NONSEL, /* ! */
GROUP, /* { */
+ ENDGROUP, /* } */
COMMENT, /* # */
BRANCH, /* b t */
LABEL, /* : */
diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c
index ca11189..c435e1e 100644
--- a/usr.bin/sed/process.c
+++ b/usr.bin/sed/process.c
@@ -89,11 +89,12 @@ process()
{
struct s_command *cp;
SPACE tspace;
- size_t len;
- char oldc, *p;
+ size_t len, oldpsl;
+ char *p;
for (linenum = 0; mf_fgets(&PS, REPLACE);) {
pd = 0;
+top:
cp = prog;
redirect:
while (cp != NULL) {
@@ -130,13 +131,14 @@ redirect:
case 'D':
if (pd)
goto new;
- if ((p = memchr(ps, '\n', psl)) == NULL)
+ if ((p = memchr(ps, '\n', psl - 1)) == NULL) {
pd = 1;
- else {
- psl -= (p - ps) + 1;
+ goto new;
+ } else {
+ psl -= (p + 1) - ps;
memmove(ps, p + 1, psl);
+ goto top;
}
- goto new;
case 'g':
cspace(&PS, hs, hsl, REPLACE);
break;
@@ -179,13 +181,13 @@ redirect:
case 'P':
if (pd)
break;
- if ((p = memchr(ps, '\n', psl)) != NULL) {
- oldc = *++p;
- *p = '\0';
+ if ((p = memchr(ps, '\n', psl - 1)) != NULL) {
+ oldpsl = psl;
+ psl = (p + 1) - ps;
}
OUT(ps)
if (p != NULL)
- *p = oldc;
+ psl = oldpsl;
break;
case 'q':
if (!nflag && !pd)
@@ -226,7 +228,7 @@ redirect:
break;
case 'x':
if (hs == NULL)
- cspace(&HS, "", 0, REPLACE);
+ cspace(&HS, "\n", 1, REPLACE);
tspace = PS;
PS = HS;
HS = tspace;
@@ -345,18 +347,18 @@ substitute(cp)
regsub(&SS, s, cp->u.s->new);
}
- /* Move past this match. */
+ /* Move past this match. */
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);
+ cspace(&SS, s, match[0].rm_so + 1,
+ APPEND);
else
- cspace(&SS,
- s + match[0].rm_so, 1, APPEND);
+ cspace(&SS, s + match[0].rm_so, 1,
+ APPEND);
s += match[0].rm_so + 1;
slen -= match[0].rm_so + 1;
lastempty = 1;
OpenPOWER on IntegriCloud