shell/math.c: rename arith_eval_hooks to arith_state, put error code into it
No binary (build failed)
—
(log yok)
| @@ -5442,22 +5442,21 @@ redirectsafe(union node *redir, int flags) | |
| 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) |
| + | result = arith(&math_state, s); |
| + | if (math_state.errcode < 0) { |
| + | if (math_state.errcode == -3) |
| ash_msg_and_raise_error("exponent less than 0"); | |
| - | if (errcode == -2) |
| + | if (math_state.errcode == -2) |
| ash_msg_and_raise_error("divide by zero"); | |
| - | if (errcode == -5) |
| + | if (math_state.errcode == -5) |
| ash_msg_and_raise_error("expression recursion loop detected"); | |
| raise_error_syntax(s); | |
| } | |
| @@ -4463,15 +4463,16 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int | |
| #if ENABLE_SH_MATH_SUPPORT | |
| static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) | |
| { | |
| - | arith_eval_hooks_t hooks; |
| + | arith_state_t math_state; |
| arith_t res; | |
| char *exp_str; | |
| - | hooks.lookupvar = get_local_var_value; |
| - | hooks.setvar = set_local_var_from_halves; |
| - | //hooks.endofname = endofname; |
| + | math_state.lookupvar = get_local_var_value; |
| + | math_state.setvar = set_local_var_from_halves; |
| + | //math_state.endofname = endofname; |
| exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | |
| - | res = arith(exp_str ? exp_str : arg, errcode_p, &hooks); |
| + | res = arith(&math_state, exp_str ? exp_str : arg); |
| + | *errcode_p = math_state.errcode; |
| free(exp_str); | |
| return res; | |
| } | |
| @@ -119,10 +119,9 @@ | |
| #include "libbb.h" | |
| #include "math.h" | |
| - | #define a_e_h_t arith_eval_hooks_t |
| - | #define lookupvar (math_hooks->lookupvar) |
| - | #define setvar (math_hooks->setvar ) |
| - | //#define endofname (math_hooks->endofname) |
| + | #define lookupvar (math_state->lookupvar) |
| + | #define setvar (math_state->setvar ) |
| + | //#define endofname (math_state->endofname) |
| typedef unsigned char operator; | |
| @@ -249,13 +248,12 @@ typedef struct chk_var_recursive_looped_t { | |
| static chk_var_recursive_looped_t *prev_chk_var_recursive; | |
| static int | |
| - | arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) |
| + | arith_lookup_val(arith_state_t *math_state, v_n_t *t) |
| { | |
| if (t->var) { | |
| const char *p = lookupvar(t->var); | |
| if (p) { | |
| - | int errcode; |
| chk_var_recursive_looped_t *cur; | |
| chk_var_recursive_looped_t cur_save; | |
| @@ -273,10 +271,10 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) | |
| cur_save.next = cur; | |
| prev_chk_var_recursive = &cur_save; | |
| - | t->val = arith(p, &errcode, math_hooks); |
| + | t->val = arith(math_state, p); |
| /* restore previous ptr after recursion */ | |
| prev_chk_var_recursive = cur; | |
| - | return errcode; |
| + | return math_state->errcode; |
| } | |
| /* allow undefined var as 0 */ | |
| t->val = 0; | |
| @@ -288,13 +286,13 @@ arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) | |
| * stack. For an unary operator it will only change the top element, but a | |
| * binary operator will pop two arguments and push the result */ | |
| static NOINLINE int | |
| - | arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hooks) |
| + | arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) |
| { | |
| #define NUMPTR (*numstackptr) | |
| v_n_t *numptr_m1; | |
| arith_t numptr_val, rez; | |
| - | int ret_arith_lookup_val; |
| + | int err; |
| /* There is no operator that can work without arguments */ | |
| if (NUMPTR == numstack) | |
| @@ -302,9 +300,9 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo | |
| numptr_m1 = NUMPTR - 1; | |
| /* Check operand is var with noninteger value */ | |
| - | ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); |
| - | if (ret_arith_lookup_val) |
| - | return ret_arith_lookup_val; |
| + | err = arith_lookup_val(math_state, numptr_m1); |
| + | if (err) |
| + | return err; |
| rez = numptr_m1->val; | |
| if (op == TOK_UMINUS) | |
| @@ -339,9 +337,9 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo | |
| numptr_m1 = NUMPTR - 1; | |
| if (op != TOK_ASSIGN) { | |
| /* check operand is var with noninteger value for not '=' */ | |
| - | ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); |
| - | if (ret_arith_lookup_val) |
| - | return ret_arith_lookup_val; |
| + | err = arith_lookup_val(math_state, numptr_m1); |
| + | if (err) |
| + | return err; |
| } | |
| if (op == TOK_CONDITIONAL) { | |
| numptr_m1->contidional_second_val = rez; | |
| @@ -490,7 +488,7 @@ endofname(const char *name) | |
| } | |
| arith_t | |
| - | arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) |
| + | arith(arith_state_t *math_state, const char *expr) |
| { | |
| operator lasttok; | |
| int errcode; | |
| @@ -543,7 +541,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |
| } | |
| if (numstack->var) { | |
| /* expression is $((var)) only, lookup now */ | |
| - | errcode = arith_lookup_val(numstack, math_hooks); |
| + | errcode = arith_lookup_val(math_state, numstack); |
| } | |
| goto ret; | |
| } | |
| @@ -658,7 +656,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |
| break; | |
| } | |
| } | |
| - | errcode = arith_apply(prev_op, numstack, &numstackptr, math_hooks); |
| + | errcode = arith_apply(math_state, prev_op, numstack, &numstackptr); |
| if (errcode) | |
| goto ret; | |
| } | |
| @@ -675,7 +673,7 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |
| err: | |
| numstack->val = errcode = -1; | |
| ret: | |
| - | *perrcode = errcode; |
| + | math_state->errcode = errcode; |
| return numstack->val; | |
| } | |
| @@ -9,61 +9,59 @@ | |
| /* The math library has just one function: | |
| * | |
| - | * arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t *hooks); |
| + | * arith_t arith(arith_state_t *states, const char *expr); |
| * | |
| - | * The first argument is the math string to parse. All normal expansions must |
| - | * be done already. i.e. no dollar symbols should be present. |
| + | * The expr argument is the math string to parse. All normal expansions must |
| + | * be done already. i.e. no dollar symbols should be present. |
| * | |
| - | * The second argument is a semi-detailed error description in case something |
| - | * goes wrong in the parsing steps. Currently, those values are (for |
| - | * compatibility, you should assume all negative values are errors): |
| - | * 0 - no errors (yay!) |
| - | * -1 - unspecified problem |
| - | * -2 - divide by zero |
| - | * -3 - exponent less than 0 |
| - | * -5 - expression recursion loop detected |
| + | * The state argument is a pointer to a struct of hooks for your shell (see below), |
| + | * and a semi-detailed error code. Currently, those values are (for |
| + | * compatibility, you should assume all negative values are errors): |
| + | * 0 - no errors (yay!) |
| + | * -1 - unspecified problem |
| + | * -2 - divide by zero |
| + | * -3 - exponent less than 0 |
| + | * -5 - expression recursion loop detected |
| * | |
| - | * The third argument is a struct pointer of hooks for your shell (see below). |
| - | * |
| - | * The function returns the answer to the expression. So if you called it |
| - | * with the expression: |
| - | * "1 + 2 + 3" |
| - | * You would obviously get back 6. |
| + | * The function returns the answer to the expression. So if you called it |
| + | * with the expression: |
| + | * "1 + 2 + 3" |
| + | * you would obviously get back 6. |
| */ | |
| /* To add support to a shell, you need to implement three functions: | |
| * | |
| - | * lookupvar() - look up and return the value of a variable |
| + | * lookupvar() - look up and return the value of a variable |
| * | |
| - | * If the shell does: |
| - | * foo=123 |
| - | * Then the code: |
| - | * const char *val = lookupvar("foo"); |
| - | * Will result in val pointing to "123" |
| + | * If the shell does: |
| + | * foo=123 |
| + | * Then the code: |
| + | * const char *val = lookupvar("foo"); |
| + | * will result in val pointing to "123" |
| * | |
| - | * setvar() - set a variable to some value |
| + | * setvar() - set a variable to some value |
| * | |
| - | * If the arithmetic expansion does something like: |
| - | * $(( i = 1)) |
| - | * Then the math code will make a call like so: |
| - | * setvar("i", "1", 0); |
| - | * The storage for the first two parameters are not allocated, so your |
| - | * shell implementation will most likely need to strdup() them to save. |
| + | * If the arithmetic expansion does something like: |
| + | * $(( i = 1)) |
| + | * then the math code will make a call like so: |
| + | * setvar("i", "1", 0); |
| + | * The storage for the first two parameters are not allocated, so your |
| + | * shell implementation will most likely need to strdup() them to save. |
| * | |
| - | * endofname() - return the end of a variable name from input |
| + | * endofname() - return the end of a variable name from input |
| * | |
| - | * The arithmetic code does not know about variable naming conventions. |
| - | * So when it is given an experession, it knows something is not numeric, |
| - | * but it is up to the shell to dictate what is a valid identifiers. |
| - | * So when it encounters something like: |
| - | * $(( some_var + 123 )) |
| - | * It will make a call like so: |
| - | * end = endofname("some_var + 123"); |
| - | * So the shell needs to scan the input string and return a pointer to the |
| - | * first non-identifier string. In this case, it should return the input |
| - | * pointer with an offset pointing to the first space. The typical |
| - | * implementation will return the offset of first char that does not match |
| - | * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* |
| + | * The arithmetic code does not know about variable naming conventions. |
| + | * So when it is given an experession, it knows something is not numeric, |
| + | * but it is up to the shell to dictate what is a valid identifiers. |
| + | * So when it encounters something like: |
| + | * $(( some_var + 123 )) |
| + | * It will make a call like so: |
| + | * end = endofname("some_var + 123"); |
| + | * So the shell needs to scan the input string and return a pointer to the |
| + | * first non-identifier string. In this case, it should return the input |
| + | * pointer with an offset pointing to the first space. The typical |
| + | * implementation will return the offset of first char that does not match |
| + | * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* |
| */ | |
| /* To make your life easier when dealing with optional 64bit math support, | |
| @@ -96,13 +94,14 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | |
| typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); | |
| //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); | |
| - | typedef struct arith_eval_hooks { |
| + | typedef struct arith_state_t { |
| arith_var_lookup_t lookupvar; | |
| arith_var_set_t setvar; | |
| // arith_var_endofname_t endofname; | |
| - | } arith_eval_hooks_t; |
| + | int errcode; |
| + | } arith_state_t; |
| - | arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t*); |
| + | arith_t arith(arith_state_t *state, const char *expr); |
| POP_SAVED_FUNCTION_VISIBILITY | |