From 0021679b0dc5767e0c023b28b36eeb1476dc2364 Mon Sep 17 00:00:00 2001 From: John Beppu Date: Wed, 21 Jun 2000 19:06:16 +0000 Subject: + added dc (aka the function formerly known as math) + did all the housekeeping that this change requires. --- Changelog | 2 + applets/busybox.c | 3 + busybox.c | 3 + busybox.def.h | 2 +- dc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ docs/busybox.pod | 51 +++++++------- internal.h | 1 + math.c | 194 ------------------------------------------------------ miscutils/dc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 425 insertions(+), 219 deletions(-) create mode 100644 dc.c delete mode 100644 math.c create mode 100644 miscutils/dc.c diff --git a/Changelog b/Changelog index 07fd30d50..8e8de9523 100644 --- a/Changelog +++ b/Changelog @@ -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 diff --git a/busybox.c b/busybox.c index 191dee13f..221ef2a65 100644 --- a/busybox.c +++ b/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 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 diff --git a/dc.c b/dc.c new file mode 100644 index 000000000..37c7731d2 --- /dev/null +++ b/dc.c @@ -0,0 +1,194 @@ +/* vi: set sw=4 ts=4: */ +#include "internal.h" +#include +#include +#include +#include +#include + +/* 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); +} 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 =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/math.c b/math.c deleted file mode 100644 index 15a826ce4..000000000 --- a/math.c +++ /dev/null @@ -1,194 +0,0 @@ -/* vi: set sw=4 ts=4: */ -#include "internal.h" -#include -#include -#include -#include -#include - -/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ - -static const char math_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 math_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(math_usage); - while (argc >= 2) { - stack_machine(argv[1]); - argv++; - argc--; - } - } - stack_machine(0); - return( TRUE); -} 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 +#include +#include +#include +#include + +/* 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); +} -- cgit v1.2.3