hush: fix \<newline> handling
[oweals/busybox.git] / shell / ash.c
index 4aaea2803d86cf4d6275acf0100b69a485c49ffb..b27b2777ea5975e0c2ddd4ba26c9e21f0e4e5ca5 100644 (file)
 /* STANDALONE does not make sense, and won't compile */
 #undef CONFIG_FEATURE_SH_STANDALONE
 #undef ENABLE_FEATURE_SH_STANDALONE
-#undef USE_FEATURE_SH_STANDALONE
-#undef SKIP_FEATURE_SH_STANDALONE(...)
+#undef IF_FEATURE_SH_STANDALONE
+#undef IF_NOT_FEATURE_SH_STANDALONE(...)
 #define ENABLE_FEATURE_SH_STANDALONE 0
-#define USE_FEATURE_SH_STANDALONE(...)
-#define SKIP_FEATURE_SH_STANDALONE(...) __VA_ARGS__
+#define IF_FEATURE_SH_STANDALONE(...)
+#define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
 #endif
 
 #ifndef PIPE_BUF
@@ -185,10 +185,6 @@ struct globals_misc {
 #define debug optlist[15]
 #endif
 
-#if ENABLE_SH_MATH_SUPPORT
-       arith_eval_hooks_t math_hooks;
-#endif
-
        /* trap handler commands */
        /*
         * Sigmode records the current value of the signal handlers for the various
@@ -238,7 +234,6 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
 #define random_LCG         (G_misc.random_LCG        )
 #define backgndpid  (G_misc.backgndpid )
 #define job_warning (G_misc.job_warning)
-#define math_hooks  (G_misc.math_hooks )
 #define INIT_G_misc() do { \
        (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
        barrier(); \
@@ -354,7 +349,7 @@ raise_interrupt(void)
 } while (0)
 #endif
 
-static USE_ASH_OPTIMIZE_FOR_SIZE(inline) void
+static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 int_on(void)
 {
        xbarrier();
@@ -363,7 +358,7 @@ int_on(void)
        }
 }
 #define INT_ON int_on()
-static USE_ASH_OPTIMIZE_FOR_SIZE(inline) void
+static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 force_int_on(void)
 {
        xbarrier();
@@ -1103,6 +1098,14 @@ ash_msg_and_raise_error(const char *msg, ...)
        va_end(ap);
 }
 
+static void raise_error_syntax(const char *) NORETURN;
+static void
+raise_error_syntax(const char *msg)
+{
+       ash_msg_and_raise_error("syntax error: %s", msg);
+       /* NOTREACHED */
+}
+
 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
 static void
 ash_msg_and_raise(int cond, const char *msg, ...)
@@ -4216,7 +4219,7 @@ cmdputs(const char *s)
        static const char vstype[VSTYPE + 1][3] = {
                "", "}", "-", "+", "?", "=",
                "%", "%%", "#", "##"
-               USE_ASH_BASH_COMPAT(, ":", "/", "//")
+               IF_ASH_BASH_COMPAT(, ":", "/", "//")
        };
 
        const char *p, *str;
@@ -5241,7 +5244,32 @@ redirectsafe(union node *redir, int flags)
  */
 
 #if ENABLE_SH_MATH_SUPPORT
-static arith_t dash_arith(const char *);
+static arith_t
+ash_arith(const char *s)
+{
+       arith_eval_hooks_t math_hooks;
+       arith_t result;
+       int errcode = 0;
+
+       math_hooks.lookupvar = lookupvar;
+       math_hooks.setvar = setvar;
+       math_hooks.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);
+       }
+       INT_ON;
+
+       return result;
+}
 #endif
 
 /*
@@ -5720,7 +5748,7 @@ expari(int quotes)
        if (quotes)
                rmescapes(p + 2);
 
-       len = cvtnum(dash_arith(p + 2));
+       len = cvtnum(ash_arith(p + 2));
 
        if (flag != '"')
                recordregion(begoff, begoff + len, 0);
@@ -6041,9 +6069,9 @@ subevalvar(char *p, char *str, int strloc, int subtype,
        char *startp;
        char *loc;
        char *rmesc, *rmescend;
-       USE_ASH_BASH_COMPAT(char *repl = NULL;)
-       USE_ASH_BASH_COMPAT(char null = '\0';)
-       USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
+       IF_ASH_BASH_COMPAT(char *repl = NULL;)
+       IF_ASH_BASH_COMPAT(char null = '\0';)
+       IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
        int saveherefd = herefd;
        int amount, workloc, resetloc;
        int zero;
@@ -6129,7 +6157,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
         * stack will need rebasing, and we'll need to remove our work
         * areas each time
         */
USE_ASH_BASH_COMPAT(restart:)
IF_ASH_BASH_COMPAT(restart:)
 
        amount = expdest - ((char *)stackblock() + resetloc);
        STADJUST(-amount, expdest);
@@ -7055,7 +7083,7 @@ static int builtinloc = -1;     /* index in path of %builtin, or -1 */
 
 
 static void
-tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
+tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
 {
        int repeated = 0;
 
@@ -7127,13 +7155,13 @@ shellexec(char **argv, const char *path, int idx)
         || (applet_no = find_applet_by_name(argv[0])) >= 0
 #endif
        ) {
-               tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
+               tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
                e = errno;
        } else {
                e = ENOENT;
                while ((cmdname = padvance(&path, argv[0])) != NULL) {
                        if (--idx < 0 && pathopt == NULL) {
-                               tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
+                               tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
                                if (errno != ENOENT && errno != ENOTDIR)
                                        e = errno;
                        }
@@ -10127,14 +10155,6 @@ static struct heredoc *heredoc;
  */
 #define NEOF ((union node *)&tokpushback)
 
-static void raise_error_syntax(const char *) NORETURN;
-static void
-raise_error_syntax(const char *msg)
-{
-       ash_msg_and_raise_error("syntax error: %s", msg);
-       /* NOTREACHED */
-}
-
 /*
  * Called when an unexpected token is read during the parse.  The argument
  * is the token that is expected, or -1 if more than one type of token can
@@ -10769,7 +10789,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
        int parenlevel;      /* levels of parens in arithmetic */
        int dqvarnest;       /* levels of variables expansion within double quotes */
 
-       USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
+       IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
 
 #if __GNUC__
        /* Avoid longjmp clobbering */
@@ -10875,7 +10895,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
                                dblquote = 1;
                                goto quotemark;
                        case CENDQUOTE:
-                               USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
+                               IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
                                if (eofmark != NULL && arinest == 0
                                 && varnest == 0
                                ) {
@@ -10974,7 +10994,7 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
        len = out - (char *)stackblock();
        out = stackblock();
        if (eofmark == NULL) {
-               if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
+               if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
                 && quotef == 0
                ) {
                        if (isdigit_str9(out)) {
@@ -11468,7 +11488,7 @@ xxreadtoken(void)
        startlinno = g_parsefile->linno;
        for (;;) {                      /* until token or start of word found */
                c = pgetc_fast();
-               if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
+               if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
                        continue;
 
                if (c == '#') {
@@ -11828,7 +11848,9 @@ cmdloop(int top)
 #endif
                }
                n = parsecmd(inter);
-               /* showtree(n); DEBUG */
+#if DEBUG
+               showtree(n);
+#endif
                if (n == NEOF) {
                        if (!top || numeof >= 50)
                                break;
@@ -12210,7 +12232,9 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
        unsigned col;
        unsigned i;
 
-       out1fmt("\nBuilt-in commands:\n-------------------\n");
+       out1fmt("\n"
+               "Built-in commands:\n"
+               "------------------\n");
        for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
                col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
                                        builtintab[i].name + 1);
@@ -12353,33 +12377,11 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 }
 
 #if ENABLE_SH_MATH_SUPPORT
-static arith_t
-dash_arith(const char *s)
-{
-       arith_t result;
-       int errcode = 0;
-
-       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);
-       }
-       INT_ON;
-
-       return result;
-}
-
 /*
- *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
- *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+ * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
+ * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
  *
- *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
+ * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
  */
 static int
 letcmd(int argc UNUSED_PARAM, char **argv)
@@ -12390,7 +12392,7 @@ letcmd(int argc UNUSED_PARAM, char **argv)
        if (!*argv)
                ash_msg_and_raise_error("expression expected");
        do {
-               i = dash_arith(*argv);
+               i = ash_arith(*argv);
        } while (*++argv);
 
        return !i;
@@ -12452,8 +12454,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
        rflag = 0;
        prompt = NULL;
        while ((i = nextopt("p:u:r"
-               USE_ASH_READ_TIMEOUT("t:")
-               USE_ASH_READ_NCHARS("n:s")
+               IF_ASH_READ_TIMEOUT("t:")
+               IF_ASH_READ_NCHARS("n:s")
        )) != '\0') {
                switch (i) {
                case 'p':
@@ -12644,6 +12646,8 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
                S_IROTH, S_IWOTH, S_IXOTH
        };
 
+       /* TODO: use bb_parse_mode() instead */
+
        char *ap;
        mode_t mask;
        int i;
@@ -12710,7 +12714,6 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
  *
  * Public domain.
  */
-
 struct limits {
        uint8_t cmd;          /* RLIMIT_xxx fit into it */
        uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
@@ -13119,11 +13122,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
        INIT_G_alias();
 #endif
        INIT_G_cmdtable();
-#if ENABLE_SH_MATH_SUPPORT
-       math_hooks.lookupvar = lookupvar;
-       math_hooks.setvar = setvar;
-       math_hooks.endofname = endofname;
-#endif
 
 #if PROFILE
        monitor(4, etext, profile_buf, sizeof(profile_buf), 50);