* HUSH_DEBUG >= 2 prints line number in this file where it was detected.
*/
#if HUSH_DEBUG < 2
-# define die_if_script(lineno, fmt, msg) die_if_script(fmt, msg)
-# define syntax_error(lineno, msg) syntax_error(msg)
-# define syntax_error_at(lineno, msg) syntax_error_at(msg)
-# define syntax_error_unterminated(lineno, ch) syntax_error_unterminated(ch)
+# define die_if_script(lineno, fmt...) die_if_script(fmt)
+# define syntax_error(lineno, msg) syntax_error(msg)
+# define syntax_error_at(lineno, msg) syntax_error_at(msg)
+# define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch)
+# define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s)
#endif
-static void die_if_script(unsigned lineno, const char *fmt, const char *msg)
+static void die_if_script(unsigned lineno, const char *fmt, ...)
{
- void FAST_FUNC (*fp)(const char *s, ...) = bb_error_msg_and_die;
-#if ENABLE_HUSH_INTERACTIVE
- if (G_interactive_fd)
- fp = bb_error_msg;
-#endif
+ va_list p;
+
#if HUSH_DEBUG >= 2
bb_error_msg("hush.c:%u", lineno);
#endif
- fp(fmt, msg);
+ va_start(p, fmt);
+ bb_verror_msg(fmt, p, NULL);
+ va_end(p);
+ if (!G_interactive_fd)
+ xfunc_die();
}
static void syntax_error(unsigned lineno, const char *msg)
die_if_script(lineno, "syntax error at '%s'", msg);
}
-static void syntax_error_unterminated(unsigned lineno, char ch)
+static void syntax_error_unterm_ch(unsigned lineno, char ch)
{
char msg[2];
msg[0] = ch;
die_if_script(lineno, "syntax error: unterminated %s", msg);
}
+static void syntax_error_unterm_str(unsigned lineno, const char *s)
+{
+ die_if_script(lineno, "syntax error: unterminated %s", s);
+}
+
#if HUSH_DEBUG < 2
# undef die_if_script
# undef syntax_error
# undef syntax_error_at
-# undef syntax_error_unterminated
+# undef syntax_error_unterm_ch
+# undef syntax_error_unterm_str
#else
-# define die_if_script(fmt, msg) die_if_script(__LINE__, fmt, msg)
-# define syntax_error(msg) syntax_error(__LINE__, msg)
-# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
-# define syntax_error_unterminated(ch) syntax_error_unterminated(__LINE__, ch)
+# define die_if_script(fmt...) die_if_script(__LINE__, fmt)
+# define syntax_error(msg) syntax_error(__LINE__, msg)
+# define syntax_error_at(msg) syntax_error_at(__LINE__, msg)
+# define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch)
+# define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s)
#endif
msg = "expression recursion loop detected";
break;
}
- die_if_script(msg, NULL);
+ die_if_script(msg);
}
debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res);
sprintf(arith_buf, arith_t_fmt, res);
debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
exp_null ? "true" : "false", exp_test);
if (exp_test) {
- if (exp_op == '?')
-//TODO: what does interactive bash
+ if (exp_op == '?') {
+//TODO: how interactive bash aborts expansion mid-command?
/* ${var?[error_msg_if_unset]} */
/* ${var:?[error_msg_if_unset_or_null]} */
/* mimic bash message */
- if (*exp_word) {
- char *msg = xasprintf("%s: %s", var, exp_word);
- die_if_script("%s", msg);
- free(msg);
- } else {
- die_if_script("%s: parameter null or not set", var);
- }
- else
+ die_if_script("%s: %s",
+ var,
+ exp_word[0] ? exp_word : "parameter null or not set"
+ );
+ } else {
val = exp_word;
+ }
if (exp_op == '=') {
/* ${var=[word]} or ${var:=[word]} */
while (1) {
int ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated('\'');
+ syntax_error_unterm_ch('\'');
return 1;
}
if (ch == '\'')
while (1) {
int ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated('"');
+ syntax_error_unterm_ch('"');
return 1;
}
if (ch == '"')
while (1) {
int ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated('`');
+ syntax_error_unterm_ch('`');
return 1;
}
if (ch == '`')
/* \x. Copy both chars unless it is \` */
int ch2 = i_getch(input);
if (ch2 == EOF) {
- syntax_error_unterminated('`');
+ syntax_error_unterm_ch('`');
return 1;
}
if (ch2 != '`' && ch2 != '$' && ch2 != '\\')
while (1) {
int ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated(')');
+ syntax_error_unterm_ch(')');
return 1;
}
if (ch == '(')
/* \x. Copy verbatim. Important for \(, \) */
ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated(')');
+ syntax_error_unterm_ch(')');
return 1;
}
o_addchr(dest, ch);
break;
default:
case_default:
- syntax_error("unterminated ${name}");
+ syntax_error_unterm_str("${name}");
debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
return 1;
}
}
/* note: can't move it above ch == dquote_end check! */
if (ch == EOF) {
- syntax_error_unterminated('"');
+ syntax_error_unterm_ch('"');
debug_printf_parse("parse_stream_dquoted return 1: unterminated \"\n");
return 1;
}
struct pipe *pi;
if (heredoc_cnt) {
- syntax_error("unterminated here document");
+ syntax_error_unterm_str("here document");
goto parse_error;
}
if (done_word(&dest, &ctx)) {
* We require heredoc to be in enclosing {}/(),
* if any.
*/
- syntax_error("unterminated here document");
+ syntax_error_unterm_str("here document");
goto parse_error;
}
if (done_word(&dest, &ctx)) {
while (1) {
ch = i_getch(input);
if (ch == EOF) {
- syntax_error_unterminated('\'');
+ syntax_error_unterm_ch('\'');
goto parse_error;
}
nommu_addchr(&ctx.as_string, ch);