Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/bin/sh Deal with \newline line continuations more correctly.
details: https://anonhg.NetBSD.org/src/rev/e63eabe7c21d
branches: trunk
changeset: 823691:e63eabe7c21d
user: kre <kre%NetBSD.org@localhost>
date: Wed May 03 04:51:04 2017 +0000
description:
Deal with \newline line continuations more correctly.
They can occur anywhere (*anywhere*) not only where it
happens to be convenient to the parser...
This fix from FreeBSD (thanks again folks).
To make this work, pushstring()'s signature needed to change to allow a
const char * as its string arg, which meant sprinkling some const other
places for a brighter appearance (and handling fallout).
All this because I wanted to see what number would come from
echo $\
{\
L\
I\
N\
E\
N\
O\
}
and was surprised at the result! That works now...
The bug would also affect stuff like
true &\
& false
and all kinds of other uses where the \newline occurred in the
"wrong" place.
An ATF test for sh syntax is coming... (sometime.)
diffstat:
bin/sh/input.c | 16 +++++++------
bin/sh/input.h | 6 ++--
bin/sh/parser.c | 65 +++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 59 insertions(+), 28 deletions(-)
diffs (285 lines):
diff -r 30d5bb3d548a -r e63eabe7c21d bin/sh/input.c
--- a/bin/sh/input.c Wed May 03 04:13:53 2017 +0000
+++ b/bin/sh/input.c Wed May 03 04:51:04 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: input.c,v 1.54 2017/05/03 04:13:53 kre Exp $ */
+/* $NetBSD: input.c,v 1.55 2017/05/03 04:51:04 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
#else
-__RCSID("$NetBSD: input.c,v 1.54 2017/05/03 04:13:53 kre Exp $");
+__RCSID("$NetBSD: input.c,v 1.55 2017/05/03 04:51:04 kre Exp $");
#endif
#endif /* not lint */
@@ -71,7 +71,7 @@
MKINIT
struct strpush {
struct strpush *prev; /* preceding string on stack */
- char *prevstring;
+ const char *prevstring;
int prevnleft;
int prevlleft;
struct alias *ap; /* if push was associated with an alias */
@@ -89,7 +89,7 @@
int fd; /* file descriptor (or -1 if string) */
int nleft; /* number of chars left in this line */
int lleft; /* number of chars left in this buffer */
- char *nextc; /* next char in buffer */
+ const char *nextc; /* next char in buffer */
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
@@ -99,7 +99,7 @@
int plinno = 1; /* input line number */
int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
-char *parsenextc; /* copy of parsefile->nextc */
+const char *parsenextc; /* copy of parsefile->nextc */
MKINIT struct parsefile basepf; /* top level input file */
MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
struct parsefile *parsefile = &basepf; /* current input file */
@@ -262,7 +262,9 @@
}
}
- q = p = parsenextc;
+ /* p = (not const char *)parsenextc; */
+ p = parsefile->buf + (parsenextc - parsefile->buf);
+ q = p;
/* delete nul characters */
#ifndef SMALL
@@ -341,7 +343,7 @@
* We handle aliases this way.
*/
void
-pushstring(char *s, int len, struct alias *ap)
+pushstring(const char *s, int len, struct alias *ap)
{
struct strpush *sp;
diff -r 30d5bb3d548a -r e63eabe7c21d bin/sh/input.h
--- a/bin/sh/input.h Wed May 03 04:13:53 2017 +0000
+++ b/bin/sh/input.h Wed May 03 04:51:04 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: input.h,v 1.17 2017/05/03 04:13:53 kre Exp $ */
+/* $NetBSD: input.h,v 1.18 2017/05/03 04:51:04 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -43,7 +43,7 @@
*/
extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */
-extern char *parsenextc; /* next character in input buffer */
+extern const char *parsenextc; /* next character in input buffer */
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
struct alias;
@@ -52,7 +52,7 @@
int pgetc(void);
int preadbuffer(void);
void pungetc(void);
-void pushstring(char *, int, struct alias *);
+void pushstring(const char *, int, struct alias *);
void popstring(void);
void setinputfile(const char *, int);
void setinputfd(int, int);
diff -r 30d5bb3d548a -r e63eabe7c21d bin/sh/parser.c
--- a/bin/sh/parser.c Wed May 03 04:13:53 2017 +0000
+++ b/bin/sh/parser.c Wed May 03 04:51:04 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: parser.c,v 1.120 2016/06/01 02:47:05 kre Exp $ */
+/* $NetBSD: parser.c,v 1.121 2017/05/03 04:51:04 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
#else
-__RCSID("$NetBSD: parser.c,v 1.120 2016/06/01 02:47:05 kre Exp $");
+__RCSID("$NetBSD: parser.c,v 1.121 2017/05/03 04:51:04 kre Exp $");
#endif
#endif /* not lint */
@@ -119,6 +119,7 @@
STATIC void synexpect(int, const char *) __dead;
STATIC void synerror(const char *) __dead;
STATIC void setprompt(int);
+STATIC int pgetc_linecont(void);
static const char EOFhere[] = "EOF reading here (<<) document";
@@ -1005,17 +1006,17 @@
RETURN(TEOF);
case '&':
- if (pgetc() == '&')
+ if (pgetc_linecont() == '&')
RETURN(TAND);
pungetc();
RETURN(TBACKGND);
case '|':
- if (pgetc() == '|')
+ if (pgetc_linecont() == '|')
RETURN(TOR);
pungetc();
RETURN(TPIPE);
case ';':
- if (pgetc() == ';')
+ if (pgetc_linecont() == ';')
RETURN(TENDCASE);
pungetc();
RETURN(TSEMI);
@@ -1281,7 +1282,7 @@
setprompt(2);
needprompt = 0;
}
- switch (pc = pgetc()) {
+ switch (pc = pgetc_linecont()) {
case '`':
goto done;
@@ -1405,7 +1406,7 @@
if (c == '>') {
if (fd < 0)
fd = 1;
- c = pgetc();
+ c = pgetc_linecont();
if (c == '>')
np->type = NAPPEND;
else if (c == '|')
@@ -1419,7 +1420,7 @@
} else { /* c == '<' */
if (fd < 0)
fd = 0;
- switch (c = pgetc()) {
+ switch (c = pgetc_linecont()) {
case '<':
if (sizeof (struct nfile) != sizeof (struct nhere)) {
np = stalloc(sizeof(struct nhere));
@@ -1429,7 +1430,7 @@
heredoc = stalloc(sizeof(struct heredoc));
heredoc->here = np;
heredoc->startline = plinno;
- if ((c = pgetc()) == '-') {
+ if ((c = pgetc_linecont()) == '-') {
heredoc->striptabs = 1;
} else {
heredoc->striptabs = 0;
@@ -1623,7 +1624,7 @@
USTPUTC(c, out);
--parenlevel;
} else {
- if (pgetc() == ')') {
+ if (pgetc_linecont() == ')') {
if (--arinest == 0) {
TS_POP();
USTPUTC(CTLENDARI, out);
@@ -1707,12 +1708,12 @@
int i;
int linno;
- c = pgetc();
+ c = pgetc_linecont();
if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
USTPUTC('$', out);
pungetc();
} else if (c == '(') { /* $(command) or $((arith)) */
- if (pgetc() == '(') {
+ if (pgetc_linecont() == '(') {
PARSEARITH();
} else {
pungetc();
@@ -1725,7 +1726,7 @@
subtype = VSNORMAL;
flags = 0;
if (c == OPENBRACE) {
- c = pgetc();
+ c = pgetc_linecont();
if (c == '#') {
if ((c = pgetc()) == CLOSEBRACE)
c = '#';
@@ -1739,7 +1740,7 @@
p = out;
do {
STPUTC(c, out);
- c = pgetc();
+ c = pgetc_linecont();
} while (is_in_name(c));
if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) {
/* Replace the variable name with the
@@ -1756,12 +1757,12 @@
} else if (is_digit(c)) {
do {
USTPUTC(c, out);
- c = pgetc();
+ c = pgetc_linecont();
} while (subtype != VSNORMAL && is_digit(c));
}
else if (is_special(c)) {
USTPUTC(c, out);
- c = pgetc();
+ c = pgetc_linecont();
}
else {
badsub:
@@ -1774,7 +1775,7 @@
switch (c) {
case ':':
flags |= VSNUL;
- c = pgetc();
+ c = pgetc_linecont();
/*FALLTHROUGH*/
default:
p = strchr(types, c);
@@ -1788,7 +1789,7 @@
int cc = c;
subtype = c == '#' ? VSTRIMLEFT :
VSTRIMRIGHT;
- c = pgetc();
+ c = pgetc_linecont();
if (c == cc)
subtype++;
else
@@ -1959,6 +1960,34 @@
}
/*
+ * handle getting the next character, while ignoring \ \n
+ * (which is a little tricky as we only have one char of pushback
+ * and we need that one elsewhere).
+ */
+STATIC int
+pgetc_linecont(void)
+{
+ int c;
+
+ while ((c = pgetc_macro()) == '\\') {
+ c = pgetc();
+ if (c == '\n') {
+ plinno++;
+ if (doprompt)
+ setprompt(2);
+ else
+ setprompt(0);
+ } else {
+ pungetc();
+ /* Allow the backslash to be pushed back. */
+ pushstring("\\", 1, NULL);
+ return (pgetc());
+ }
+ }
+ return (c);
+}
+
+/*
* called by editline -- any expansions to the prompt
* should be added here.
*/
Home |
Main Index |
Thread Index |
Old Index