Merge various fixes from NetBSD. This will allow the WordPerfect for
SCO installation to run all the way through (some POSIX fixes).
This commit is contained in:
parent
f4df6549b2
commit
ce19262d8c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=10075
@ -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 @@ semicolon: EATSPACE();
|
||||
"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 @@ semicolon: EATSPACE();
|
||||
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
|
||||
|
@ -100,6 +100,7 @@ enum e_args {
|
||||
TEXT, /* a c i */
|
||||
NONSEL, /* ! */
|
||||
GROUP, /* { */
|
||||
ENDGROUP, /* } */
|
||||
COMMENT, /* # */
|
||||
BRANCH, /* b t */
|
||||
LABEL, /* : */
|
||||
|
@ -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 @@ process()
|
||||
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 @@ process()
|
||||
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 @@ process()
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user