aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-04-02 10:02:37 +0000
committerMike Frysinger <vapier@gentoo.org>2009-04-02 10:02:37 +0000
commit98c52645c02dacebccae7d68d6c2627f9318fcf7 (patch)
treee0c64b5b24206f95e72fd060336f74cb459f2109 /shell/hush.c
parent551ffdccea39a9223ad451954db40fd7a6e20e79 (diff)
downloadbusybox-w32-98c52645c02dacebccae7d68d6c2627f9318fcf7.tar.gz
busybox-w32-98c52645c02dacebccae7d68d6c2627f9318fcf7.tar.bz2
busybox-w32-98c52645c02dacebccae7d68d6c2627f9318fcf7.zip
split math code out of ash and into a standalone library so we can use it in any shell (like hush!)
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c102
1 files changed, 91 insertions, 11 deletions
diff --git a/shell/hush.c b/shell/hush.c
index af6763517..e93e5a9a0 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -76,6 +76,8 @@
76#include <fnmatch.h> 76#include <fnmatch.h>
77#endif 77#endif
78 78
79#include "math.h"
80
79#define HUSH_VER_STR "0.92" 81#define HUSH_VER_STR "0.92"
80 82
81#if defined SINGLE_APPLET_MAIN 83#if defined SINGLE_APPLET_MAIN
@@ -452,6 +454,9 @@ struct globals {
452#if ENABLE_FEATURE_EDITING 454#if ENABLE_FEATURE_EDITING
453 line_input_t *line_input_state; 455 line_input_t *line_input_state;
454#endif 456#endif
457#if ENABLE_SH_MATH_SUPPORT
458 arith_eval_hooks_t hooks;
459#endif
455 pid_t root_pid; 460 pid_t root_pid;
456 pid_t last_bg_pid; 461 pid_t last_bg_pid;
457#if ENABLE_HUSH_JOB 462#if ENABLE_HUSH_JOB
@@ -1164,6 +1169,31 @@ static int unset_local_var(const char *name)
1164 return EXIT_SUCCESS; 1169 return EXIT_SUCCESS;
1165} 1170}
1166 1171
1172#if ENABLE_SH_MATH_SUPPORT
1173#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1174#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1175static char *endofname(const char *name)
1176{
1177 char *p;
1178
1179 p = (char *) name;
1180 if (!is_name(*p))
1181 return p;
1182 while (*++p) {
1183 if (!is_in_name(*p))
1184 break;
1185 }
1186 return p;
1187}
1188
1189static void arith_set_local_var(const char *name, const char *val, int flags)
1190{
1191 /* arith code doesnt malloc space, so do it for it */
1192 char *var = xmalloc(strlen(name) + 1 + strlen(val) + 1);
1193 sprintf(var, "%s=%s", name, val);
1194 set_local_var(var, flags);
1195}
1196#endif
1167 1197
1168/* 1198/*
1169 * in_str support 1199 * in_str support
@@ -1374,6 +1404,11 @@ static void o_addstr(o_string *o, const char *str, int len)
1374 o->data[o->length] = '\0'; 1404 o->data[o->length] = '\0';
1375} 1405}
1376 1406
1407static void o_addstrauto(o_string *o, const char *str)
1408{
1409 o_addstr(o, str, strlen(str) + 1);
1410}
1411
1377static void o_addstr_duplicate_backslash(o_string *o, const char *str, int len) 1412static void o_addstr_duplicate_backslash(o_string *o, const char *str, int len)
1378{ 1413{
1379 while (len) { 1414 while (len) {
@@ -1564,7 +1599,7 @@ static int o_glob(o_string *o, int n)
1564 char **argv = globdata.gl_pathv; 1599 char **argv = globdata.gl_pathv;
1565 o->length = pattern - o->data; /* "forget" pattern */ 1600 o->length = pattern - o->data; /* "forget" pattern */
1566 while (1) { 1601 while (1) {
1567 o_addstr(o, *argv, strlen(*argv) + 1); 1602 o_addstrauto(o, *argv);
1568 n = o_save_ptr_helper(o, n); 1603 n = o_save_ptr_helper(o, n);
1569 argv++; 1604 argv++;
1570 if (!*argv) 1605 if (!*argv)
@@ -1770,6 +1805,28 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
1770 goto store_val; 1805 goto store_val;
1771 } 1806 }
1772#endif 1807#endif
1808#if ENABLE_SH_MATH_SUPPORT
1809 case '+': { /* <SPECIAL_VAR_SYMBOL>(cmd<SPECIAL_VAR_SYMBOL> */
1810 arith_t res;
1811 char buf[30];
1812 int errcode;
1813 *p = '\0';
1814 ++arg;
1815 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
1816 res = arith(arg, &errcode, &G.hooks);
1817 if (errcode < 0)
1818 switch (errcode) {
1819 case -3: maybe_die("arith", "exponent less than 0"); break;
1820 case -2: maybe_die("arith", "divide by zero"); break;
1821 case -5: maybe_die("arith", "expression recursion loop detected"); break;
1822 default: maybe_die("arith", "syntax error");
1823 }
1824 sprintf(buf, arith_t_fmt, res);
1825 o_addstrauto(output, buf);
1826 debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res);
1827 break;
1828 }
1829#endif
1773 default: /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */ 1830 default: /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */
1774 case_default: { 1831 case_default: {
1775 bool exp_len = false, exp_null = false; 1832 bool exp_len = false, exp_null = false;
@@ -1877,7 +1934,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
1877 debug_print_list("expand_vars_to_list[a]", output, n); 1934 debug_print_list("expand_vars_to_list[a]", output, n);
1878 /* this part is literal, and it was already pre-quoted 1935 /* this part is literal, and it was already pre-quoted
1879 * if needed (much earlier), do not use o_addQstr here! */ 1936 * if needed (much earlier), do not use o_addQstr here! */
1880 o_addstr(output, arg, strlen(arg) + 1); 1937 o_addstrauto(output, arg);
1881 debug_print_list("expand_vars_to_list[b]", output, n); 1938 debug_print_list("expand_vars_to_list[b]", output, n);
1882 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ 1939 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
1883 && !(ored_ch & 0x80) /* and all vars were not quoted. */ 1940 && !(ored_ch & 0x80) /* and all vars were not quoted. */
@@ -3754,7 +3811,7 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
3754 /* command remains "open", available for possible redirects */ 3811 /* command remains "open", available for possible redirects */
3755} 3812}
3756 3813
3757#if ENABLE_HUSH_TICK 3814#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT
3758/* Subroutines for copying $(...) and `...` things */ 3815/* Subroutines for copying $(...) and `...` things */
3759static void add_till_backquote(o_string *dest, struct in_str *input); 3816static void add_till_backquote(o_string *dest, struct in_str *input);
3760/* '...' */ 3817/* '...' */
@@ -3834,7 +3891,7 @@ static void add_till_backquote(o_string *dest, struct in_str *input)
3834 * echo $(echo 'TEST)' BEST) TEST) BEST 3891 * echo $(echo 'TEST)' BEST) TEST) BEST
3835 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST 3892 * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
3836 */ 3893 */
3837static void add_till_closing_curly_brace(o_string *dest, struct in_str *input) 3894static void add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl)
3838{ 3895{
3839 int count = 0; 3896 int count = 0;
3840 while (1) { 3897 while (1) {
@@ -3844,8 +3901,14 @@ static void add_till_closing_curly_brace(o_string *dest, struct in_str *input)
3844 if (ch == '(') 3901 if (ch == '(')
3845 count++; 3902 count++;
3846 if (ch == ')') 3903 if (ch == ')')
3847 if (--count < 0) 3904 if (--count < 0) {
3848 break; 3905 if (!dbl)
3906 break;
3907 if (i_peek(input) == ')') {
3908 i_getch(input);
3909 break;
3910 }
3911 }
3849 o_addchr(dest, ch); 3912 o_addchr(dest, ch);
3850 if (ch == '\'') { 3913 if (ch == '\'') {
3851 add_till_single_quote(dest, input); 3914 add_till_single_quote(dest, input);
@@ -3866,7 +3929,7 @@ static void add_till_closing_curly_brace(o_string *dest, struct in_str *input)
3866 } 3929 }
3867 } 3930 }
3868} 3931}
3869#endif /* ENABLE_HUSH_TICK */ 3932#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT */
3870 3933
3871/* Return code: 0 for OK, 1 for syntax error */ 3934/* Return code: 0 for OK, 1 for syntax error */
3872static int handle_dollar(o_string *dest, struct in_str *input) 3935static int handle_dollar(o_string *dest, struct in_str *input)
@@ -3983,18 +4046,30 @@ static int handle_dollar(o_string *dest, struct in_str *input)
3983 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4046 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3984 break; 4047 break;
3985 } 4048 }
3986#if ENABLE_HUSH_TICK
3987 case '(': { 4049 case '(': {
3988 //int pos = dest->length;
3989 i_getch(input); 4050 i_getch(input);
4051
4052#if ENABLE_SH_MATH_SUPPORT
4053 if (i_peek(input) == '(') {
4054 i_getch(input);
4055 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4056 o_addchr(dest, quote_mask | '+');
4057 add_till_closing_paren(dest, input, true);
4058 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4059 break;
4060 }
4061#endif
4062
4063#if ENABLE_HUSH_TICK
4064 //int pos = dest->length;
3990 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4065 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3991 o_addchr(dest, quote_mask | '`'); 4066 o_addchr(dest, quote_mask | '`');
3992 add_till_closing_curly_brace(dest, input); 4067 add_till_closing_paren(dest, input, false);
3993 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); 4068 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
3994 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4069 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4070#endif
3995 break; 4071 break;
3996 } 4072 }
3997#endif
3998 case '_': 4073 case '_':
3999 i_getch(input); 4074 i_getch(input);
4000 ch = i_peek(input); 4075 ch = i_peek(input);
@@ -4526,6 +4601,11 @@ int hush_main(int argc, char **argv)
4526#if ENABLE_FEATURE_EDITING 4601#if ENABLE_FEATURE_EDITING
4527 G.line_input_state = new_line_input_t(FOR_SHELL); 4602 G.line_input_state = new_line_input_t(FOR_SHELL);
4528#endif 4603#endif
4604#if ENABLE_SH_MATH_SUPPORT
4605 G.hooks.lookupvar = lookup_param;
4606 G.hooks.setvar = arith_set_local_var;
4607 G.hooks.endofname = endofname;
4608#endif
4529 /* XXX what should these be while sourcing /etc/profile? */ 4609 /* XXX what should these be while sourcing /etc/profile? */
4530 G.global_argc = argc; 4610 G.global_argc = argc;
4531 G.global_argv = argv; 4611 G.global_argv = argv;