diff options
author | Jan Luebbe <jlu@pengutronix.de> | 2012-10-04 15:27:55 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-01-09 10:32:54 +0100 |
commit | 964893b34b829760d81988af79a0cb0766ddc119 (patch) | |
tree | 58b6def4844a4ccbb7491f62bb9bfb9fbb783ddb /include/math.h | |
parent | b46b57f35a27090cfbac4900d1a3d522d7898e53 (diff) | |
download | barebox-964893b34b829760d81988af79a0cb0766ddc119.tar.gz barebox-964893b34b829760d81988af79a0cb0766ddc119.tar.xz |
commands: add let command which supports proper arithmetic
This command works like the corresponding Unix shell command and
is used for adding, multiplying and much more.
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'include/math.h')
-rw-r--r-- | include/math.h | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/include/math.h b/include/math.h new file mode 100644 index 0000000000..5648e3f9c1 --- /dev/null +++ b/include/math.h @@ -0,0 +1,92 @@ +/* math.h - interface to shell math "library" -- this allows shells to share + * the implementation of arithmetic $((...)) expansions. + * + * This aims to be a POSIX shell math library as documented here: + * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04 + * + * See math.c for internal documentation. + */ + +/* The math library has just one function: + * + * arith_t arith(arith_state_t *state, const char *expr); + * + * 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 state argument is a pointer to a struct of hooks for your shell (see below), + * and an error message string (NULL if no error). + * + * 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 + * + * 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 + * + * 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 + * + * 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]* + */ + +#ifndef LIB_MATH_H +#define LIB_MATH_H 1 + +#ifdef ENABLE_SH_MATH_SUPPORT_64 +typedef long long arith_t; +#define ARITH_FMT "%lld" +#define strto_arith_t simple_strtoull +#else +typedef long arith_t; +#define ARITH_FMT "%ld" +#define strto_arith_t simple_strtoul +#endif + +# define is_name(c) (isalpha((unsigned char)(c))) +# define is_in_name(c) ((c) == '_' || (c) == '.' || isalnum((unsigned char)(c))) +const char* arith_endofname(const char *name); + +typedef const char* (*arith_var_lookup_t)(const char *name); +typedef void (*arith_var_set_t)(const char *name, const char *val); +typedef const char* (*arith_var_endofname_t)(const char *name); + +typedef struct arith_state_t { + const char *errmsg; + arith_var_lookup_t lookupvar; + arith_var_set_t setvar; + arith_var_endofname_t endofname; + void *list_of_recursed_names; +} arith_state_t; + +arith_t arith(arith_state_t *state, const char *expr); + +#endif |