summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-03-13 20:43:11 +0000
committerjilles <jilles@FreeBSD.org>2010-03-13 20:43:11 +0000
commit38ae12dc0c3b3fd9d5dcc2e6fd681c943127458d (patch)
tree05be89c0727b267974b27b69d328e339c4cb5bde /bin
parent497b0c9195ac00c7946a82ee2fc0145de08b0af4 (diff)
downloadFreeBSD-src-38ae12dc0c3b3fd9d5dcc2e6fd681c943127458d.zip
FreeBSD-src-38ae12dc0c3b3fd9d5dcc2e6fd681c943127458d.tar.gz
sh: Fix longjmp clobber warnings in parser.c.
Make parsebackq a function instead of an emulated nested function. This puts the setjmp usage in a smaller function where it is easier to avoid bad optimizations.
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/parser.c328
1 files changed, 162 insertions, 166 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index d8903c9..e19a04e 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -863,6 +863,164 @@ breakloop:
}
+/*
+ * Called to parse command substitutions.
+ */
+
+STATIC char *
+parsebackq(char *out, struct nodelist **pbqlist,
+ int oldstyle, int dblquote, int quoted)
+{
+ struct nodelist **nlpp;
+ union node *n;
+ char *volatile str;
+ struct jmploc jmploc;
+ struct jmploc *const savehandler = handler;
+ int savelen;
+ int saveprompt;
+ const int bq_startlinno = plinno;
+ char *volatile ostr = NULL;
+ struct parsefile *const savetopfile = getcurrentfile();
+
+ str = NULL;
+ if (setjmp(jmploc.loc)) {
+ popfilesupto(savetopfile);
+ if (str)
+ ckfree(str);
+ if (ostr)
+ ckfree(ostr);
+ handler = savehandler;
+ if (exception == EXERROR) {
+ startlinno = bq_startlinno;
+ synerror("Error in command substitution");
+ }
+ longjmp(handler->loc, 1);
+ }
+ INTOFF;
+ savelen = out - stackblock();
+ if (savelen > 0) {
+ str = ckmalloc(savelen);
+ memcpy(str, stackblock(), savelen);
+ }
+ handler = &jmploc;
+ INTON;
+ if (oldstyle) {
+ /* We must read until the closing backquote, giving special
+ treatment to some slashes, and then push the string and
+ reread it as input, interpreting it normally. */
+ char *oout;
+ int c;
+ int olen;
+
+
+ STARTSTACKSTR(oout);
+ for (;;) {
+ if (needprompt) {
+ setprompt(2);
+ needprompt = 0;
+ }
+ switch (c = pgetc()) {
+ case '`':
+ goto done;
+
+ 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 STPUTC after the
+ * switch).
+ */
+ continue;
+ }
+ if (c != '\\' && c != '`' && c != '$'
+ && (!dblquote || c != '"'))
+ STPUTC('\\', oout);
+ break;
+
+ case '\n':
+ plinno++;
+ needprompt = doprompt;
+ break;
+
+ case PEOF:
+ startlinno = plinno;
+ synerror("EOF in backquote substitution");
+ break;
+
+ default:
+ break;
+ }
+ STPUTC(c, oout);
+ }
+done:
+ STPUTC('\0', oout);
+ olen = oout - stackblock();
+ INTOFF;
+ ostr = ckmalloc(olen);
+ memcpy(ostr, stackblock(), olen);
+ setinputstring(ostr, 1);
+ INTON;
+ }
+ nlpp = pbqlist;
+ while (*nlpp)
+ nlpp = &(*nlpp)->next;
+ *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+ (*nlpp)->next = NULL;
+
+ if (oldstyle) {
+ saveprompt = doprompt;
+ doprompt = 0;
+ }
+
+ n = list(0);
+
+ if (oldstyle)
+ doprompt = saveprompt;
+ else {
+ if (readtoken() != TRP)
+ synexpect(TRP);
+ }
+
+ (*nlpp)->n = n;
+ if (oldstyle) {
+ /*
+ * Start reading from old file again, ignoring any pushed back
+ * tokens left from the backquote parsing
+ */
+ popfile();
+ tokpushback = 0;
+ }
+ while (stackblocksize() <= savelen)
+ growstackblock();
+ STARTSTACKSTR(out);
+ if (str) {
+ memcpy(out, str, savelen);
+ STADJUST(savelen, out);
+ INTOFF;
+ ckfree(str);
+ str = NULL;
+ INTON;
+ }
+ if (ostr) {
+ INTOFF;
+ ckfree(ostr);
+ ostr = NULL;
+ INTON;
+ }
+ handler = savehandler;
+ if (quoted)
+ USTPUTC(CTLBACKQ | CTLQUOTE, out);
+ else
+ USTPUTC(CTLBACKQ, out);
+ return out;
+}
+
/*
* If eofmark is NULL, read a word or a redirection symbol. If eofmark
@@ -879,8 +1037,6 @@ breakloop:
#define CHECKEND() {goto checkend; checkend_return:;}
#define PARSEREDIR() {goto parseredir; parseredir_return:;}
#define PARSESUB() {goto parsesub; parsesub_return:;}
-#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
-#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
#define PARSEARITH() {goto parsearith; parsearith_return:;}
STATIC int
@@ -896,7 +1052,6 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
int varnest; /* levels of variables expansion */
int arinest; /* levels of arithmetic expansion */
int parenlevel; /* levels of parens in arithmetic */
- int oldstyle;
char const *prevsyntax; /* syntax before arithmetic */
int synentry;
@@ -1029,7 +1184,8 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
}
break;
case CBQUOTE: /* '`' */
- PARSEBACKQOLD();
+ out = parsebackq(out, &bqlist, 1, dblquote,
+ arinest || dblquote);
break;
case CEOF:
goto endword; /* exit outer loop */
@@ -1189,7 +1345,8 @@ parsesub: {
PARSEARITH();
} else {
pungetc();
- PARSEBACKQNEW();
+ out = parsebackq(out, &bqlist, 0, dblquote,
+ arinest || dblquote);
}
} else {
USTPUTC(CTLVAR, out);
@@ -1296,167 +1453,6 @@ parsesub: {
/*
- * Called to parse command substitutions. Newstyle is set if the command
- * is enclosed inside $(...); nlpp is a pointer to the head of the linked
- * list of commands (passed by reference), and savelen is the number of
- * characters on the top of the stack which must be preserved.
- */
-
-parsebackq: {
- struct nodelist **nlpp;
- union node *n;
- char *volatile str;
- struct jmploc jmploc;
- struct jmploc *const savehandler = handler;
- int savelen;
- int saveprompt;
- const int bq_startlinno = plinno;
- char *volatile ostr = NULL;
- struct parsefile *const savetopfile = getcurrentfile();
-
- str = NULL;
- if (setjmp(jmploc.loc)) {
- popfilesupto(savetopfile);
- if (str)
- ckfree(str);
- if (ostr)
- ckfree(ostr);
- handler = savehandler;
- if (exception == EXERROR) {
- startlinno = bq_startlinno;
- synerror("Error in command substitution");
- }
- longjmp(handler->loc, 1);
- }
- INTOFF;
- savelen = out - stackblock();
- if (savelen > 0) {
- str = ckmalloc(savelen);
- memcpy(str, stackblock(), savelen);
- }
- handler = &jmploc;
- INTON;
- if (oldstyle) {
- /* We must read until the closing backquote, giving special
- treatment to some slashes, and then push the string and
- reread it as input, interpreting it normally. */
- char *oout;
- int c;
- int olen;
-
-
- STARTSTACKSTR(oout);
- for (;;) {
- if (needprompt) {
- setprompt(2);
- needprompt = 0;
- }
- switch (c = pgetc()) {
- case '`':
- goto done;
-
- 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 STPUTC after the
- * switch).
- */
- continue;
- }
- if (c != '\\' && c != '`' && c != '$'
- && (!dblquote || c != '"'))
- STPUTC('\\', oout);
- break;
-
- case '\n':
- plinno++;
- needprompt = doprompt;
- break;
-
- case PEOF:
- startlinno = plinno;
- synerror("EOF in backquote substitution");
- break;
-
- default:
- break;
- }
- STPUTC(c, oout);
- }
-done:
- STPUTC('\0', oout);
- olen = oout - stackblock();
- INTOFF;
- ostr = ckmalloc(olen);
- memcpy(ostr, stackblock(), olen);
- setinputstring(ostr, 1);
- INTON;
- }
- nlpp = &bqlist;
- while (*nlpp)
- nlpp = &(*nlpp)->next;
- *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
- (*nlpp)->next = NULL;
-
- if (oldstyle) {
- saveprompt = doprompt;
- doprompt = 0;
- }
-
- n = list(0);
-
- if (oldstyle)
- doprompt = saveprompt;
- else {
- if (readtoken() != TRP)
- synexpect(TRP);
- }
-
- (*nlpp)->n = n;
- if (oldstyle) {
- /*
- * Start reading from old file again, ignoring any pushed back
- * tokens left from the backquote parsing
- */
- popfile();
- tokpushback = 0;
- }
- while (stackblocksize() <= savelen)
- growstackblock();
- STARTSTACKSTR(out);
- if (str) {
- memcpy(out, str, savelen);
- STADJUST(savelen, out);
- INTOFF;
- ckfree(str);
- str = NULL;
- INTON;
- }
- if (ostr) {
- INTOFF;
- ckfree(ostr);
- ostr = NULL;
- INTON;
- }
- handler = savehandler;
- if (arinest || dblquote)
- USTPUTC(CTLBACKQ | CTLQUOTE, out);
- else
- USTPUTC(CTLBACKQ, out);
- if (oldstyle)
- goto parsebackq_oldreturn;
- else
- goto parsebackq_newreturn;
-}
-
-/*
* Parse an arithmetic expansion (indicate start of one and set state)
*/
parsearith: {
OpenPOWER on IntegriCloud