Date: Sun, 19 Oct 2014 11:59:15 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273276 - in head/bin/sh: . tests/parser Message-ID: <201410191159.s9JBxFZh077525@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Sun Oct 19 11:59:15 2014 New Revision: 273276 URL: https://svnweb.freebsd.org/changeset/base/273276 Log: sh: Allow backslash-newline continuation in more places: * directly after a $ * directly after ${ * between the characters of a multi-character operator token * within a parameter name Added: head/bin/sh/tests/parser/line-cont10.0 (contents, props changed) head/bin/sh/tests/parser/line-cont11.0 (contents, props changed) head/bin/sh/tests/parser/line-cont4.0 (contents, props changed) head/bin/sh/tests/parser/line-cont5.0 (contents, props changed) head/bin/sh/tests/parser/line-cont6.0 (contents, props changed) head/bin/sh/tests/parser/line-cont7.0 (contents, props changed) head/bin/sh/tests/parser/line-cont8.0 (contents, props changed) head/bin/sh/tests/parser/line-cont9.0 (contents, props changed) Modified: head/bin/sh/parser.c head/bin/sh/tests/parser/Makefile Modified: head/bin/sh/parser.c ============================================================================== --- head/bin/sh/parser.c Sun Oct 19 11:31:23 2014 (r273275) +++ head/bin/sh/parser.c Sun Oct 19 11:59:15 2014 (r273276) @@ -125,6 +125,7 @@ static void consumetoken(int); static void synexpect(int) __dead2; static void synerror(const char *) __dead2; static void setprompt(int); +static int pgetc_linecont(void); static void * @@ -899,17 +900,17 @@ xxreadtoken(void) case PEOF: 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 ';': - c = pgetc(); + c = pgetc_linecont(); if (c == ';') RETURN(TENDCASE); else if (c == '&') @@ -991,7 +992,7 @@ parseredir(char *out, int c) np = (union node *)stalloc(sizeof (struct nfile)); if (c == '>') { np->nfile.fd = 1; - c = pgetc(); + c = pgetc_linecont(); if (c == '>') np->type = NAPPEND; else if (c == '&') @@ -1004,7 +1005,7 @@ parseredir(char *out, int c) } } else { /* c == '<' */ np->nfile.fd = 0; - c = pgetc(); + c = pgetc_linecont(); if (c == '<') { if (sizeof (struct nfile) != sizeof (struct nhere)) { np = (union node *)stalloc(sizeof (struct nhere)); @@ -1013,7 +1014,7 @@ parseredir(char *out, int c) np->type = NHERE; heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); heredoc->here = np; - if ((c = pgetc()) == '-') { + if ((c = pgetc_linecont()) == '-') { heredoc->striptabs = 1; } else { heredoc->striptabs = 0; @@ -1094,25 +1095,12 @@ parsebackq(char *out, struct nodelist ** needprompt = 0; } CHECKSTRSPACE(2, oout); - c = pgetc(); + c = pgetc_linecont(); if (c == '`') break; switch (c) { case '\\': - if ((c = pgetc()) == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - /* - * If eating a newline, avoid putting - * the newline into the new character - * stream (via the USTPUTC after the - * switch). - */ - continue; - } + c = pgetc(); if (c != '\\' && c != '`' && c != '$' && (!dblquote || c != '"')) USTPUTC('\\', oout); @@ -1507,7 +1495,7 @@ readtoken1(int firstc, char const *initi USTPUTC(c, out); --state[level].parenlevel; } else { - if (pgetc() == ')') { + if (pgetc_linecont() == ')') { if (level > 0 && state[level].category == TSTATE_ARITH) { level--; @@ -1593,9 +1581,9 @@ parsesub: { int length; int c1; - c = pgetc(); + c = pgetc_linecont(); if (c == '(') { /* $(command) or $((arith)) */ - if (pgetc() == '(') { + if (pgetc_linecont() == '(') { PARSEARITH(); } else { pungetc(); @@ -1613,7 +1601,7 @@ parsesub: { flags = 0; if (c == '{') { bracketed_name = 1; - c = pgetc(); + c = pgetc_linecont(); subtype = 0; } varname: @@ -1621,7 +1609,7 @@ varname: length = 0; do { STPUTC(c, out); - c = pgetc(); + c = pgetc_linecont(); length++; } while (!is_eof(c) && is_in_name(c)); if (length == 6 && @@ -1640,22 +1628,22 @@ varname: if (bracketed_name) { do { STPUTC(c, out); - c = pgetc(); + c = pgetc_linecont(); } while (is_digit(c)); } else { STPUTC(c, out); - c = pgetc(); + c = pgetc_linecont(); } } else if (is_special(c)) { c1 = c; - c = pgetc(); + c = pgetc_linecont(); if (subtype == 0 && c1 == '#') { subtype = VSLENGTH; if (strchr(types, c) == NULL && c != ':' && c != '#' && c != '%') goto varname; c1 = c; - c = pgetc(); + c = pgetc_linecont(); if (c1 != '}' && c == '}') { pungetc(); c = c1; @@ -1680,7 +1668,7 @@ varname: switch (c) { case ':': flags |= VSNUL; - c = pgetc(); + c = pgetc_linecont(); /*FALLTHROUGH*/ default: p = strchr(types, c); @@ -1700,7 +1688,7 @@ varname: int cc = c; subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; - c = pgetc(); + c = pgetc_linecont(); if (c == cc) subtype++; else @@ -1909,6 +1897,29 @@ setprompt(int which) } } +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. Modified: head/bin/sh/tests/parser/Makefile ============================================================================== --- head/bin/sh/tests/parser/Makefile Sun Oct 19 11:31:23 2014 (r273275) +++ head/bin/sh/tests/parser/Makefile Sun Oct 19 11:59:15 2014 (r273276) @@ -58,6 +58,14 @@ FILES+= heredoc12.0 FILES+= line-cont1.0 FILES+= line-cont2.0 FILES+= line-cont3.0 +FILES+= line-cont4.0 +FILES+= line-cont5.0 +FILES+= line-cont6.0 +FILES+= line-cont7.0 +FILES+= line-cont8.0 +FILES+= line-cont9.0 +FILES+= line-cont10.0 +FILES+= line-cont11.0 FILES+= no-space1.0 FILES+= no-space2.0 FILES+= only-redir1.0 Added: head/bin/sh/tests/parser/line-cont10.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont10.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,18 @@ +# $FreeBSD$ + +v=XaaaXbbbX +[ "${v\ +#\ +*\ +a}.${v\ +#\ +#\ +*\ +a}.${v\ +%\ +b\ +*}.${v\ +%\ +%\ +b\ +*}" = aaXbbbX.XbbbX.XaaaXbb.XaaaX ] Added: head/bin/sh/tests/parser/line-cont11.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont11.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,23 @@ +# $FreeBSD$ + +T=$(mktemp "${TMPDIR:-/tmp}/sh-test.XXXXXXXX") || exit +trap 'rm -f -- "$T"' 0 +w='#A' +# A naive pgetc_linecont() would push back two characters here, which +# fails if a new buffer is read between the two characters. +c='${w#\#}' +c=$c$c$c$c +c=$c$c$c$c +c=$c$c$c$c +c=$c$c$c$c +c=$c$c$c$c +c=$c$c$c$c +printf 'v=%s\n' "$c" >"$T" +. "$T" +if [ "${#v}" != 4096 ]; then + echo "Length is bad (${#v})" + exit 3 +fi +case $v in +*[!A]*) echo "Content is bad"; exit 3 ;; +esac Added: head/bin/sh/tests/parser/line-cont4.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont4.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +v=abcd +[ "$\ +v.$\ +{v}.${\ +v}.${v\ +}" = abcd.abcd.abcd.abcd ] Added: head/bin/sh/tests/parser/line-cont5.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont5.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,14 @@ +# $FreeBSD$ + +bad=1 +case x in +x\ +) ;\ +; *) exit 7 +esac &\ +& bad= &\ +& : >\ +>/dev/null + +false |\ +| [ -z "$bad" ] Added: head/bin/sh/tests/parser/line-cont6.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont6.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,23 @@ +# $FreeBSD$ + +v0\ +=abc + +v=$(cat <\ +<\ +E\ +O\ +F +${v0}d +EOF +) + +w=$(cat <\ +<\ +-\ +EOF + efgh +EOF +) + +[ "$v.$w" = "abcd.efgh" ] Added: head/bin/sh/tests/parser/line-cont7.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont7.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,7 @@ +# $FreeBSD$ + +[ "$(\ +( +1\ ++ 1)\ +)" = 2 ] Added: head/bin/sh/tests/parser/line-cont8.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont8.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +set -- a b c d e f g h i j +[ "${1\ +0\ +}" = j ] Added: head/bin/sh/tests/parser/line-cont9.0 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/bin/sh/tests/parser/line-cont9.0 Sun Oct 19 11:59:15 2014 (r273276) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +[ "${$\ +:\ ++\ +xyz}" = xyz ]
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410191159.s9JBxFZh077525>