dc: make it use long longs for integer ops

function                                             old     new   delta
print_base                                           176     238     +62
or                                                    91     103     +12
eor                                                   91     103     +12
and                                                   91     103     +12
not                                                   60      64      +4
mod                                                  103     105      +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 104/0)             Total: 104 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-07-29 04:00:27 +02:00
parent 416f0405cb
commit 7a07b0ee6a
2 changed files with 51 additions and 36 deletions

View File

@ -736,28 +736,6 @@ INSERT
"$ date\n" \ "$ date\n" \
"Wed Apr 12 18:52:41 MDT 2000\n" "Wed Apr 12 18:52:41 MDT 2000\n"
#define dc_trivial_usage \
"expression..."
#define dc_full_usage "\n\n" \
"Tiny RPN calculator. Operations:\n" \
"+, add, -, sub, *, mul, /, div, %, mod, **, exp, and, or, not, eor,\n" \
"p - print top of the stack (without altering the stack),\n" \
"f - print entire stack, o - pop the value and set output radix\n" \
"(value must be 10 or 16).\n" \
"Examples: 'dc 2 2 add' -> 4, 'dc 8 8 * 2 2 + /' -> 16\n" \
#define dc_example_usage \
"$ dc 2 2 + p\n" \
"4\n" \
"$ dc 8 8 \\* 2 2 + / p\n" \
"16\n" \
"$ dc 0 1 and p\n" \
"0\n" \
"$ dc 0 1 or p\n" \
"1\n" \
"$ echo 72 9 div 8 mul p | dc\n" \
"64\n"
#define dd_trivial_usage \ #define dd_trivial_usage \
"[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \ "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \
" [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]")

View File

@ -6,7 +6,39 @@
#include "libbb.h" #include "libbb.h"
#include <math.h> #include <math.h>
/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ //usage:#define dc_trivial_usage
//usage: "expression..."
//usage:
//usage:#define dc_full_usage "\n\n"
//usage: "Tiny RPN calculator. Operations:\n"
//usage: "+, add, -, sub, *, mul, /, div, %, mod, **, exp, and, or, not, eor,\n"
//usage: "p - print top of the stack (without popping),\n"
//usage: "f - print entire stack, o - pop the value and set output radix\n"
//usage: "(value must be 10, 16, 8 or 2).\n"
//usage: "Examples: 'dc 2 2 add' -> 4, 'dc 8 8 * 2 2 + /' -> 16\n"
//usage:
//usage:#define dc_example_usage
//usage: "$ dc 2 2 + p\n"
//usage: "4\n"
//usage: "$ dc 8 8 \\* 2 2 + / p\n"
//usage: "16\n"
//usage: "$ dc 0 1 and p\n"
//usage: "0\n"
//usage: "$ dc 0 1 or p\n"
//usage: "1\n"
//usage: "$ echo 72 9 div 8 mul p | dc\n"
//usage: "64\n"
#if 0
typedef unsigned data_t;
#define DATA_FMT ""
#elif 0
typedef unsigned long data_t;
#define DATA_FMT "l"
#else
typedef unsigned long long data_t;
#define DATA_FMT "ll"
#endif
struct globals { struct globals {
@ -73,29 +105,29 @@ static void divide(void)
static void mod(void) static void mod(void)
{ {
unsigned d = pop(); data_t d = pop();
push((unsigned) pop() % d); push((data_t) pop() % d);
} }
static void and(void) static void and(void)
{ {
push((unsigned) pop() & (unsigned) pop()); push((data_t) pop() & (data_t) pop());
} }
static void or(void) static void or(void)
{ {
push((unsigned) pop() | (unsigned) pop()); push((data_t) pop() | (data_t) pop());
} }
static void eor(void) static void eor(void)
{ {
push((unsigned) pop() ^ (unsigned) pop()); push((data_t) pop() ^ (data_t) pop());
} }
static void not(void) static void not(void)
{ {
push(~(unsigned) pop()); push(~(data_t) pop());
} }
static void set_output_base(void) static void set_output_base(void)
@ -112,25 +144,30 @@ static void set_output_base(void)
static void print_base(double print) static void print_base(double print)
{ {
unsigned x, i; data_t x, i;
x = (data_t) print;
if (base == 10) { if (base == 10) {
printf("%g\n", print); if (x == print) /* exactly representable as unsigned integer */
printf("%"DATA_FMT"u\n", x);
else
printf("%g\n", print);
return; return;
} }
x = (unsigned)print;
switch (base) { switch (base) {
case 16: case 16:
printf("%x\n", x); printf("%"DATA_FMT"x\n", x);
break; break;
case 8: case 8:
printf("%o\n", x); printf("%"DATA_FMT"o\n", x);
break; break;
default: /* base 2 */ default: /* base 2 */
i = (unsigned)INT_MAX + 1; i = MAXINT(data_t) - (MAXINT(data_t) >> 1);
/* i is 100000...00000 */
do { do {
if (x & i) break; if (x & i)
break;
i >>= 1; i >>= 1;
} while (i > 1); } while (i > 1);
do { do {