diff options
author | jkh <jkh@FreeBSD.org> | 1995-08-16 05:56:44 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1995-08-16 05:56:44 +0000 |
commit | 529c9b015ab62caa94981c2f131f9b291428a10b (patch) | |
tree | 698a431f9038d11c62b9e1a96307628f0d4df8f1 /usr.bin/sed | |
parent | 8c03fe0f4db1526151e5a3607d650f1555f4b68f (diff) | |
download | FreeBSD-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.c | 99 | ||||
-rw-r--r-- | usr.bin/sed/defs.h | 1 | ||||
-rw-r--r-- | usr.bin/sed/process.c | 34 |
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; |