#include <sys/times.h>
#include "shell_common.h"
-#include "math.h"
+#if ENABLE_SH_MATH_SUPPORT
+# include "math.h"
+#endif
#if ENABLE_ASH_RANDOM_SUPPORT
# include "random.h"
#else
#endif
static void
-setprompt(int whichprompt)
+setprompt_if(smallint do_set, int whichprompt)
{
const char *prompt;
-#if ENABLE_ASH_EXPAND_PRMT
- struct stackmark smark;
-#endif
+ IF_ASH_EXPAND_PRMT(struct stackmark smark;)
+
+ if (!do_set)
+ return;
needprompt = 0;
static arith_t
ash_arith(const char *s)
{
- arith_eval_hooks_t math_hooks;
+ arith_state_t math_state;
arith_t result;
- int errcode = 0;
- math_hooks.lookupvar = lookupvar;
- math_hooks.setvar = setvar2;
- //math_hooks.endofname = endofname;
+ math_state.lookupvar = lookupvar;
+ math_state.setvar = setvar2;
+ //math_state.endofname = endofname;
INT_OFF;
- result = arith(s, &errcode, &math_hooks);
- if (errcode < 0) {
- if (errcode == -3)
- ash_msg_and_raise_error("exponent less than 0");
- if (errcode == -2)
- ash_msg_and_raise_error("divide by zero");
- if (errcode == -5)
- ash_msg_and_raise_error("expression recursion loop detected");
- raise_error_syntax(s);
- }
+ result = arith(&math_state, s);
+ if (math_state.errmsg)
+ ash_msg_and_raise_error(math_state.errmsg);
INT_ON;
return result;
/*
* Our own itoa().
*/
+#if !ENABLE_SH_MATH_SUPPORT
+/* cvtnum() is used even if math support is off (to prepare $? values and such) */
+typedef long arith_t;
+# define ARITH_FMT "%ld"
+#endif
static int
cvtnum(arith_t num)
{
int len;
expdest = makestrspace(32, expdest);
- len = fmtstr(expdest, 32, arith_t_fmt, num);
+ len = fmtstr(expdest, 32, ARITH_FMT, num);
STADJUST(len, expdest);
return len;
}
c = p[length];
if (c) {
if (!(c & 0x80)
-#if ENABLE_SH_MATH_SUPPORT
- || c == CTLENDARI
-#endif
+ IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
) {
/* c == '=' || c == ':' || c == CTLENDARI */
length++;
#endif
}
}
- breakloop:
- ;
+ breakloop: ;
}
static char *
for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
if (cmdp->cmdtype == CMDNORMAL
|| (cmdp->cmdtype == CMDBUILTIN
- && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
+ && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
&& builtinloc > 0)
) {
cmdp->rehash = 1;
/* Called to execute a trap.
* Single callsite - at the end of evaltree().
- * If we return non-zero, exaltree raises EXEXIT exception.
+ * If we return non-zero, evaltree raises EXEXIT exception.
*
* Perhaps we should avoid entering new trap handlers
* while we are executing a trap handler. [is it a TODO?]
out:
exception_handler = savehandler;
+
out1:
+ /* Order of checks below is important:
+ * signal handlers trigger before exit caused by "set -e".
+ */
+ if (pending_sig && dotrap())
+ goto exexit;
if (checkexit & exitstatus)
evalskip |= SKIPEVAL;
- else if (pending_sig && dotrap())
- goto exexit;
if (flags & EV_EXIT) {
exexit:
while ((lvp = localvars) != NULL) {
localvars = lvp->next;
vp = lvp->vp;
- TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
+ TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
if (vp == NULL) { /* $- saved */
memcpy(optlist, lvp->text, sizeof(optlist));
free((char*)lvp->text);
STARTSTACKSTR(out);
loop:
/* For each line, until end of word */
- {
- CHECKEND(); /* set c to PEOF if at end of here document */
- for (;;) { /* until end of line or end of word */
- CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
- switch (SIT(c, syntax)) {
- case CNL: /* '\n' */
- if (syntax == BASESYNTAX)
- goto endword; /* exit outer loop */
- USTPUTC(c, out);
- g_parsefile->linno++;
- if (doprompt)
- setprompt(2);
- c = pgetc();
- goto loop; /* continue outer loop */
- case CWORD:
- USTPUTC(c, out);
- break;
- case CCTL:
- if (eofmark == NULL || dblquote)
- USTPUTC(CTLESC, out);
+ CHECKEND(); /* set c to PEOF if at end of here document */
+ for (;;) { /* until end of line or end of word */
+ CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
+ switch (SIT(c, syntax)) {
+ case CNL: /* '\n' */
+ if (syntax == BASESYNTAX)
+ goto endword; /* exit outer loop */
+ USTPUTC(c, out);
+ g_parsefile->linno++;
+ setprompt_if(doprompt, 2);
+ c = pgetc();
+ goto loop; /* continue outer loop */
+ case CWORD:
+ USTPUTC(c, out);
+ break;
+ case CCTL:
+ if (eofmark == NULL || dblquote)
+ USTPUTC(CTLESC, out);
#if ENABLE_ASH_BASH_COMPAT
- if (c == '\\' && bash_dollar_squote) {
- c = decode_dollar_squote();
- if (c & 0x100) {
- USTPUTC('\\', out);
- c = (unsigned char)c;
- }
+ if (c == '\\' && bash_dollar_squote) {
+ c = decode_dollar_squote();
+ if (c & 0x100) {
+ USTPUTC('\\', out);
+ c = (unsigned char)c;
}
+ }
#endif
- USTPUTC(c, out);
- break;
- case CBACK: /* backslash */
- c = pgetc_without_PEOA();
- if (c == PEOF) {
+ USTPUTC(c, out);
+ break;
+ case CBACK: /* backslash */
+ c = pgetc_without_PEOA();
+ if (c == PEOF) {
+ USTPUTC(CTLESC, out);
+ USTPUTC('\\', out);
+ pungetc();
+ } else if (c == '\n') {
+ setprompt_if(doprompt, 2);
+ } else {
+#if ENABLE_ASH_EXPAND_PRMT
+ if (c == '$' && pssyntax) {
USTPUTC(CTLESC, out);
USTPUTC('\\', out);
- pungetc();
- } else if (c == '\n') {
- if (doprompt)
- setprompt(2);
- } else {
-#if ENABLE_ASH_EXPAND_PRMT
- if (c == '$' && pssyntax) {
- USTPUTC(CTLESC, out);
- USTPUTC('\\', out);
- }
+ }
#endif
- /* Backslash is retained if we are in "str" and next char isn't special */
- if (dblquote
- && c != '\\'
- && c != '`'
- && c != '$'
- && (c != '"' || eofmark != NULL)
- ) {
- USTPUTC(CTLESC, out);
- USTPUTC('\\', out);
- }
- if (SIT(c, SQSYNTAX) == CCTL)
- USTPUTC(CTLESC, out);
- USTPUTC(c, out);
- quotef = 1;
+ /* Backslash is retained if we are in "str" and next char isn't special */
+ if (dblquote
+ && c != '\\'
+ && c != '`'
+ && c != '$'
+ && (c != '"' || eofmark != NULL)
+ ) {
+ USTPUTC(CTLESC, out);
+ USTPUTC('\\', out);
}
- break;
- case CSQUOTE:
- syntax = SQSYNTAX;
+ if (SIT(c, SQSYNTAX) == CCTL)
+ USTPUTC(CTLESC, out);
+ USTPUTC(c, out);
+ quotef = 1;
+ }
+ break;
+ case CSQUOTE:
+ syntax = SQSYNTAX;
quotemark:
- if (eofmark == NULL) {
- USTPUTC(CTLQUOTEMARK, out);
+ if (eofmark == NULL) {
+ USTPUTC(CTLQUOTEMARK, out);
+ }
+ break;
+ case CDQUOTE:
+ syntax = DQSYNTAX;
+ dblquote = 1;
+ goto quotemark;
+ case CENDQUOTE:
+ IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
+ if (eofmark != NULL && arinest == 0
+ && varnest == 0
+ ) {
+ USTPUTC(c, out);
+ } else {
+ if (dqvarnest == 0) {
+ syntax = BASESYNTAX;
+ dblquote = 0;
}
- break;
- case CDQUOTE:
- syntax = DQSYNTAX;
- dblquote = 1;
+ quotef = 1;
goto quotemark;
- case CENDQUOTE:
- IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
- if (eofmark != NULL && arinest == 0
- && varnest == 0
- ) {
- USTPUTC(c, out);
- } else {
- if (dqvarnest == 0) {
- syntax = BASESYNTAX;
- dblquote = 0;
- }
- quotef = 1;
- goto quotemark;
- }
- break;
- case CVAR: /* '$' */
- PARSESUB(); /* parse substitution */
- break;
- case CENDVAR: /* '}' */
- if (varnest > 0) {
- varnest--;
- if (dqvarnest > 0) {
- dqvarnest--;
- }
- c = CTLENDVAR;
+ }
+ break;
+ case CVAR: /* '$' */
+ PARSESUB(); /* parse substitution */
+ break;
+ case CENDVAR: /* '}' */
+ if (varnest > 0) {
+ varnest--;
+ if (dqvarnest > 0) {
+ dqvarnest--;
}
- USTPUTC(c, out);
- break;
+ c = CTLENDVAR;
+ }
+ USTPUTC(c, out);
+ break;
#if ENABLE_SH_MATH_SUPPORT
- case CLP: /* '(' in arithmetic */
- parenlevel++;
- USTPUTC(c, out);
- break;
- case CRP: /* ')' in arithmetic */
- if (parenlevel > 0) {
- parenlevel--;
- } else {
- if (pgetc() == ')') {
- if (--arinest == 0) {
- syntax = prevsyntax;
- dblquote = (syntax == DQSYNTAX);
- c = CTLENDARI;
- }
- } else {
- /*
- * unbalanced parens
- * (don't 2nd guess - no error)
- */
- pungetc();
+ case CLP: /* '(' in arithmetic */
+ parenlevel++;
+ USTPUTC(c, out);
+ break;
+ case CRP: /* ')' in arithmetic */
+ if (parenlevel > 0) {
+ parenlevel--;
+ } else {
+ if (pgetc() == ')') {
+ if (--arinest == 0) {
+ syntax = prevsyntax;
+ dblquote = (syntax == DQSYNTAX);
+ c = CTLENDARI;
}
+ } else {
+ /*
+ * unbalanced parens
+ * (don't 2nd guess - no error)
+ */
+ pungetc();
}
- USTPUTC(c, out);
- break;
+ }
+ USTPUTC(c, out);
+ break;
#endif
- case CBQUOTE: /* '`' */
- PARSEBACKQOLD();
- break;
- case CENDFILE:
- goto endword; /* exit outer loop */
- case CIGN:
- break;
- default:
- if (varnest == 0) {
+ case CBQUOTE: /* '`' */
+ PARSEBACKQOLD();
+ break;
+ case CENDFILE:
+ goto endword; /* exit outer loop */
+ case CIGN:
+ break;
+ default:
+ if (varnest == 0) {
#if ENABLE_ASH_BASH_COMPAT
- if (c == '&') {
- if (pgetc() == '>')
- c = 0x100 + '>'; /* flag &> */
- pungetc();
- }
-#endif
- goto endword; /* exit outer loop */
+ if (c == '&') {
+ if (pgetc() == '>')
+ c = 0x100 + '>'; /* flag &> */
+ pungetc();
}
- IF_ASH_ALIAS(if (c != PEOA))
- USTPUTC(c, out);
+#endif
+ goto endword; /* exit outer loop */
}
- c = pgetc_fast();
- } /* for (;;) */
- }
+ IF_ASH_ALIAS(if (c != PEOA))
+ USTPUTC(c, out);
+ }
+ c = pgetc_fast();
+ } /* for (;;) */
endword:
+
#if ENABLE_SH_MATH_SUPPORT
if (syntax == ARISYNTAX)
raise_error_syntax("missing '))'");
treatment to some slashes, and then push the string and
reread it as input, interpreting it normally. */
char *pout;
- int pc;
size_t psavelen;
char *pstr;
-
STARTSTACKSTR(pout);
for (;;) {
- if (needprompt) {
- setprompt(2);
- }
+ int pc;
+
+ setprompt_if(needprompt, 2);
pc = pgetc();
switch (pc) {
case '`':
pc = pgetc();
if (pc == '\n') {
g_parsefile->linno++;
- if (doprompt)
- setprompt(2);
+ setprompt_if(doprompt, 2);
/*
* If eating a newline, avoid putting
* the newline into the new character
tokpushback = 0;
return lasttoken;
}
- if (needprompt) {
- setprompt(2);
- }
+ setprompt_if(needprompt, 2);
startlinno = g_parsefile->linno;
for (;;) { /* until token or start of word found */
c = pgetc_fast();
break; /* return readtoken1(...) */
}
startlinno = ++g_parsefile->linno;
- if (doprompt)
- setprompt(2);
+ setprompt_if(doprompt, 2);
} else {
const char *p;
tokpushback = 0;
return lasttoken;
}
- if (needprompt) {
- setprompt(2);
- }
+ setprompt_if(needprompt, 2);
startlinno = g_parsefile->linno;
for (;;) { /* until token or start of word found */
c = pgetc_fast();
case '\\':
if (pgetc() == '\n') {
startlinno = ++g_parsefile->linno;
- if (doprompt)
- setprompt(2);
+ setprompt_if(doprompt, 2);
continue;
}
pungetc();
tokpushback = 0;
doprompt = interact;
- if (doprompt)
- setprompt(doprompt);
+ setprompt_if(doprompt, doprompt);
needprompt = 0;
t = readtoken();
if (t == TEOF)
heredoclist = NULL;
while (here) {
- if (needprompt) {
- setprompt(2);
- }
- readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+ setprompt_if(needprompt, 2);
+ readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
here->eofmark, here->striptabs);
n = stzalloc(sizeof(struct narg));
n->narg.type = NARG;
}
if ((act & DO_NOFUNC)
|| !prefix(pathopt, "func")
- ) { /* ignore unimplemented options */
+ ) { /* ignore unimplemented options */
continue;
}
}
/* bash re-enables SIGHUP which is SIG_IGNed on entry.
* Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
*/
- signal(SIGHUP, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
/* from var.c: */
{
if (e == EXERROR)
exitstatus = 2;
s = state;
- if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+ if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
exitshell();
- if (e == EXINT)
+ }
+ if (e == EXINT) {
outcslow('\n', stderr);
+ }
popstackmark(&smark);
FORCE_INT_ON; /* enable interrupts */
_mcleanup();
}
#endif
+ TRACE(("End of main reached\n"));
exitshell();
/* NOTREACHED */
}