diff options
-rw-r--r-- | Changelog | 2 | ||||
-rw-r--r-- | applets/busybox.c | 3 | ||||
-rw-r--r-- | busybox.c | 3 | ||||
-rw-r--r-- | busybox.def.h | 2 | ||||
-rw-r--r-- | dc.c (renamed from math.c) | 6 | ||||
-rw-r--r-- | docs/busybox.pod | 51 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | miscutils/dc.c | 194 |
8 files changed, 234 insertions, 28 deletions
@@ -86,6 +86,8 @@ * Fixed grep "Line too long" problem -- John Beppu * Fixed 'grep -q -i B some_file' so it works * math takes input from stdin if no args are given. -- John Beppu + * math was renamed to dc. Although it deviates from dc's behaviour, + this will probably be remedied in the future. -- John Beppu -Erik Andersen diff --git a/applets/busybox.c b/applets/busybox.c index 191dee13f..221ef2a65 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -72,6 +72,9 @@ const struct BB_applet applets[] = { #ifdef BB_DATE {"date", date_main, _BB_DIR_BIN}, #endif +#ifdef BB_DC + {"dc", dc_main, _BB_DIR_USR_BIN}, +#endif #ifdef BB_DD {"dd", dd_main, _BB_DIR_BIN}, #endif @@ -72,6 +72,9 @@ const struct BB_applet applets[] = { #ifdef BB_DATE {"date", date_main, _BB_DIR_BIN}, #endif +#ifdef BB_DC + {"dc", dc_main, _BB_DIR_USR_BIN}, +#endif #ifdef BB_DD {"dd", dd_main, _BB_DIR_BIN}, #endif diff --git a/busybox.def.h b/busybox.def.h index d7756a498..89172ea98 100644 --- a/busybox.def.h +++ b/busybox.def.h @@ -17,6 +17,7 @@ #define BB_CP_MV #define BB_CUT #define BB_DATE +#define BB_DC #define BB_DD #define BB_DEALLOCVT #define BB_DF @@ -54,7 +55,6 @@ #define BB_LS #define BB_LSMOD #define BB_MAKEDEVS -#define BB_MATH //#define BB_MD5SUM #define BB_MKDIR #define BB_MKFIFO @@ -8,7 +8,7 @@ /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ -static const char math_usage[] = "math expression ...\n" +static const char dc_usage[] = "math expression ...\n" #ifndef BB_FEATURE_TRIVIAL_HELP "\nThis is a Tiny RPN calculator that understands the\n" "following operations: +, -, /, *, and, or, not, eor.\n" @@ -162,7 +162,7 @@ static int number_of_tokens(char *buffer) return i; } -int math_main(int argc, char **argv) +int dc_main(int argc, char **argv) { /* take stuff from stdin if no args are given */ if (argc <= 1) { @@ -182,7 +182,7 @@ int math_main(int argc, char **argv) } } else { if (*argv[1]=='-') - usage(math_usage); + usage(dc_usage); while (argc >= 2) { stack_machine(argv[1]); argv++; diff --git a/docs/busybox.pod b/docs/busybox.pod index 8b1b7155f..75763d33f 100644 --- a/docs/busybox.pod +++ b/docs/busybox.pod @@ -313,6 +313,32 @@ Example: ------------------------------- +=item dc + +Usage: dc expression ... + +This is a Tiny RPN calculator that understands the +following operations: +, -, /, *, and, or, not, eor. +If no arguments are given, dc will process input from STDIN. + +The behaviour of BusyBox/dc deviates (just a little ;-) from +GNU/dc, but this will be remedied in the future. + +Example: + + $ dc 2 2 + + 4 + $ dc 8 8 \* 2 2 + / + 16 + $ dc 0 1 and + 0 + $ dc 0 1 or + 1 + $ echo 72 9 div 8 mul | dc + 64 + +------------------------------- + =item dd Usage: dd [if=name] [of=name] [bs=n] [count=n] [skip=n] [seek=n] @@ -1012,29 +1038,6 @@ Example: ------------------------------- -=item math - -Usage: math expression ... - -This is a Tiny RPN calculator that understands the -following operations: +, -, /, *, and, or, not, eor. -If no arguments are given, math will process input from STDIN. - -Example: - - $ math 2 2 + - 4 - $ math 8 8 \* 2 2 + / - 16 - $ math 0 1 and - 0 - $ math 0 1 or - 1 - $ echo 72 9 / | math - 8 - -------------------------------- - =item md5sum Usage: md5sum [OPTION] [file ...] @@ -2021,4 +2024,4 @@ Enrique Zanardi <ezanardi@ull.es> =cut -# $Id: busybox.pod,v 1.43 2000/06/20 00:11:07 proski Exp $ +# $Id: busybox.pod,v 1.44 2000/06/21 19:06:16 beppu Exp $ diff --git a/internal.h b/internal.h index 50bb17a10..58f68f59b 100644 --- a/internal.h +++ b/internal.h @@ -113,6 +113,7 @@ extern int clear_main(int argc, char** argv); extern int cp_mv_main(int argc, char** argv); extern int cut_main(int argc, char** argv); extern int date_main(int argc, char** argv); +extern int dc_main(int argc, char** argv); extern int dd_main(int argc, char** argv); extern int dirname_main(int argc, char** argv); extern int deallocvt_main(int argc, char** argv); diff --git a/miscutils/dc.c b/miscutils/dc.c new file mode 100644 index 000000000..37c7731d2 --- /dev/null +++ b/miscutils/dc.c @@ -0,0 +1,194 @@ +/* vi: set sw=4 ts=4: */ +#include "internal.h" +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <math.h> + +/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ + +static const char dc_usage[] = "math expression ...\n" +#ifndef BB_FEATURE_TRIVIAL_HELP + "\nThis is a Tiny RPN calculator that understands the\n" + "following operations: +, -, /, *, and, or, not, eor.\n" + "i.e. 'math 2 2 add' -> 4, and 'math 8 8 \\* 2 2 + /' -> 16\n" +#endif + ; + +static double stack[100]; +static unsigned int pointer; + +static void push(double a) +{ + if (pointer >= (sizeof(stack) / sizeof(*stack))) { + fprintf(stderr, "math: stack overflow\n"); + exit(-1); + } else + stack[pointer++] = a; +} + +static double pop() +{ + if (pointer == 0) { + fprintf(stderr, "math: stack underflow\n"); + exit(-1); + } + return stack[--pointer]; +} + +static void add() +{ + push(pop() + pop()); +} + +static void sub() +{ + double subtrahend = pop(); + + push(pop() - subtrahend); +} + +static void mul() +{ + push(pop() * pop()); +} + +static void divide() +{ + double divisor = pop(); + + push(pop() / divisor); +} + +static void and() +{ + push((unsigned int) pop() & (unsigned int) pop()); +} + +static void or() +{ + push((unsigned int) pop() | (unsigned int) pop()); +} + +static void eor() +{ + push((unsigned int) pop() ^ (unsigned int) pop()); +} + +static void not() +{ + push(~(unsigned int) pop()); +} + +static void print() +{ + printf("%g\n", pop()); +} + +struct op { + const char *name; + void (*function) (); +}; + +static const struct op operators[] = { + {"+", add}, + {"add", add}, + {"-", sub}, + {"sub", sub}, + {"*", mul}, + {"mul", mul}, + {"/", divide}, + {"div", divide}, + {"and", and}, + {"or", or}, + {"not", not}, + {"eor", eor}, + {0, 0} +}; + +static void stack_machine(const char *argument) +{ + char *endPointer = 0; + double d; + const struct op *o = operators; + + if (argument == 0) { + print(); + return; + } + + d = strtod(argument, &endPointer); + + if (endPointer != argument) { + push(d); + return; + } + + while (o->name != 0) { + if (strcmp(o->name, argument) == 0) { + (*(o->function)) (); + return; + } + o++; + } + fprintf(stderr, "math: %s: syntax error.\n", argument); + exit(-1); +} + +/* return pointer to next token in buffer and set *buffer to one char + * past the end of the above mentioned token + */ +static char *get_token(char **buffer) +{ + char *start = NULL; + char *current = *buffer; + + while (isspace(*current)) { current++; } + if (*current != 0) { + start = current; + while (!isspace(*current) && current != 0) { current++; } + *buffer = current; + } + return start; +} + +/* In Perl one might say, scalar m|\s*(\S+)\s*|g */ +static int number_of_tokens(char *buffer) +{ + int i = 0; + char *b = buffer; + while (get_token(&b)) { i++; } + return i; +} + +int dc_main(int argc, char **argv) +{ + /* take stuff from stdin if no args are given */ + if (argc <= 1) { + int i, len; + char *line = NULL; + char *cursor = NULL; + char *token = NULL; + while ((line = cstring_lineFromFile(stdin))) { + cursor = line; + len = number_of_tokens(line); + for (i = 0; i < len; i++) { + token = get_token(&cursor); + *cursor++ = 0; + stack_machine(token); + } + free(line); + } + } else { + if (*argv[1]=='-') + usage(dc_usage); + while (argc >= 2) { + stack_machine(argv[1]); + argv++; + argc--; + } + } + stack_machine(0); + return( TRUE); +} |