Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/miscutils/dc.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/miscutils/dc.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 5 … … 7 7 #include <math.h> 8 8 9 /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ 10 11 enum { STACK_SIZE = COMMON_BUFSIZE / sizeof(double) }; 12 13 #define stack ((double*)&bb_common_bufsiz1) 14 static unsigned int pointer; 15 static unsigned char base; 9 //usage:#define dc_trivial_usage 10 //usage: "EXPRESSION..." 11 //usage: 12 //usage:#define dc_full_usage "\n\n" 13 //usage: "Tiny RPN calculator. Operations:\n" 14 //usage: "+, add, -, sub, *, mul, /, div, %, mod, **, exp, and, or, not, eor,\n" 15 //usage: "p - print top of the stack (without popping),\n" 16 //usage: "f - print entire stack,\n" 17 //usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" 18 //usage: "Examples: 'dc 2 2 add' -> 4, 'dc 8 8 * 2 2 + /' -> 16" 19 //usage: 20 //usage:#define dc_example_usage 21 //usage: "$ dc 2 2 + p\n" 22 //usage: "4\n" 23 //usage: "$ dc 8 8 \\* 2 2 + / p\n" 24 //usage: "16\n" 25 //usage: "$ dc 0 1 and p\n" 26 //usage: "0\n" 27 //usage: "$ dc 0 1 or p\n" 28 //usage: "1\n" 29 //usage: "$ echo 72 9 div 8 mul p | dc\n" 30 //usage: "64\n" 31 32 #if 0 33 typedef unsigned data_t; 34 #define DATA_FMT "" 35 #elif 0 36 typedef unsigned long data_t; 37 #define DATA_FMT "l" 38 #else 39 typedef unsigned long long data_t; 40 #define DATA_FMT "ll" 41 #endif 42 43 44 struct globals { 45 unsigned pointer; 46 unsigned base; 47 double stack[1]; 48 } FIX_ALIASING; 49 enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) }; 50 #define G (*(struct globals*)&bb_common_bufsiz1) 51 #define pointer (G.pointer ) 52 #define base (G.base ) 53 #define stack (G.stack ) 54 #define INIT_G() do { \ 55 base = 10; \ 56 } while (0) 57 16 58 17 59 static void push(double a) … … 46 88 } 47 89 90 #if ENABLE_FEATURE_DC_LIBM 48 91 static void power(void) 49 92 { … … 52 95 push(pow(pop(), topower)); 53 96 } 97 #endif 54 98 55 99 static void divide(void) … … 62 106 static void mod(void) 63 107 { 64 unsigned int d = pop();65 66 push(( unsigned int) pop() % d);108 data_t d = pop(); 109 110 push((data_t) pop() % d); 67 111 } 68 112 69 113 static void and(void) 70 114 { 71 push(( unsigned int) pop() & (unsigned int) pop());115 push((data_t) pop() & (data_t) pop()); 72 116 } 73 117 74 118 static void or(void) 75 119 { 76 push(( unsigned int) pop() | (unsigned int) pop());120 push((data_t) pop() | (data_t) pop()); 77 121 } 78 122 79 123 static void eor(void) 80 124 { 81 push(( unsigned int) pop() ^ (unsigned int) pop());125 push((data_t) pop() ^ (data_t) pop()); 82 126 } 83 127 84 128 static void not(void) 85 129 { 86 push(~( unsigned int) pop());130 push(~(data_t) pop()); 87 131 } 88 132 89 133 static void set_output_base(void) 90 134 { 91 base = (unsigned char)pop(); 92 if ((base != 10) && (base != 16)) { 93 bb_error_msg("error, base %d is not supported", base); 135 static const char bases[] ALIGN1 = { 2, 8, 10, 16, 0 }; 136 unsigned b = (unsigned)pop(); 137 138 base = *strchrnul(bases, b); 139 if (base == 0) { 140 bb_error_msg("error, base %u is not supported", b); 94 141 base = 10; 95 142 } … … 98 145 static void print_base(double print) 99 146 { 100 if (base == 16) 101 printf("%x\n", (unsigned int)print); 102 else 103 printf("%g\n", print); 147 data_t x, i; 148 149 x = (data_t) print; 150 if (base == 10) { 151 if (x == print) /* exactly representable as unsigned integer */ 152 printf("%"DATA_FMT"u\n", x); 153 else 154 printf("%g\n", print); 155 return; 156 } 157 158 switch (base) { 159 case 16: 160 printf("%"DATA_FMT"x\n", x); 161 break; 162 case 8: 163 printf("%"DATA_FMT"o\n", x); 164 break; 165 default: /* base 2 */ 166 i = MAXINT(data_t) - (MAXINT(data_t) >> 1); 167 /* i is 100000...00000 */ 168 do { 169 if (x & i) 170 break; 171 i >>= 1; 172 } while (i > 1); 173 do { 174 bb_putchar('1' - !(x & i)); 175 i >>= 1; 176 } while (i); 177 bb_putchar('\n'); 178 } 104 179 } 105 180 106 181 static void print_stack_no_pop(void) 107 182 { 108 unsigned i nt i= pointer;183 unsigned i = pointer; 109 184 while (i) 110 185 print_base(stack[--i]); … … 130 205 {"/", divide}, 131 206 {"div", divide}, 207 #if ENABLE_FEATURE_DC_LIBM 132 208 {"**", power}, 133 209 {"exp", power}, 134 210 {"pow", power}, 211 #endif 135 212 {"%", mod}, 136 213 {"mod", mod}, … … 143 220 {"f", print_stack_no_pop}, 144 221 {"o", set_output_base}, 145 { "", 0}222 { "", NULL } 146 223 }; 147 224 148 225 static void stack_machine(const char *argument) 149 226 { 150 char *endPointer = 0;227 char *endPointer; 151 228 double d; 152 229 const struct op *o = operators; 153 230 154 if (argument == 0)155 return;156 157 231 d = strtod(argument, &endPointer); 158 232 159 if (endPointer != argument ) {233 if (endPointer != argument && *endPointer == '\0') { 160 234 push(d); 161 235 return; 162 236 } 163 237 164 while (o-> name[0]) {238 while (o->function) { 165 239 if (strcmp(o->name, argument) == 0) { 166 240 o->function(); … … 169 243 o++; 170 244 } 171 bb_error_msg_and_die(" %s: syntax error", argument);245 bb_error_msg_and_die("syntax error at '%s'", argument); 172 246 } 173 247 … … 177 251 static char *get_token(char **buffer) 178 252 { 179 char *start = NULL; 180 char *current; 181 182 current = skip_whitespace(*buffer); 183 if (*current != 0) { 184 start = current; 185 current = skip_non_whitespace(current); 186 *buffer = current; 187 } 188 return start; 189 } 190 191 /* In Perl one might say, scalar m|\s*(\S+)\s*|g */ 192 static int number_of_tokens(char *buffer) 193 { 194 int i = 0; 195 char *b = buffer; 196 while (get_token(&b)) { i++; } 197 return i; 198 } 199 200 int dc_main(int argc, char **argv); 201 int dc_main(int argc, char **argv) 202 { 203 /* take stuff from stdin if no args are given */ 204 if (argc <= 1) { 205 int i, len; 206 char *line = NULL; 207 char *cursor = NULL; 208 char *token = NULL; 209 while ((line = xmalloc_getline(stdin))) { 253 char *current = skip_whitespace(*buffer); 254 if (*current != '\0') { 255 *buffer = skip_non_whitespace(current); 256 return current; 257 } 258 return NULL; 259 } 260 261 int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 262 int dc_main(int argc UNUSED_PARAM, char **argv) 263 { 264 INIT_G(); 265 266 argv++; 267 if (!argv[0]) { 268 /* take stuff from stdin if no args are given */ 269 char *line; 270 char *cursor; 271 char *token; 272 while ((line = xmalloc_fgetline(stdin)) != NULL) { 210 273 cursor = line; 211 len = number_of_tokens(line); 212 for (i = 0; i < len; i++) { 274 while (1) { 213 275 token = get_token(&cursor); 214 *cursor++ = 0; 276 if (!token) 277 break; 278 *cursor++ = '\0'; 215 279 stack_machine(token); 216 280 } … … 218 282 } 219 283 } else { 220 if (*argv[1] == '-') 221 bb_show_usage(); 222 while (argc >= 2) { 223 stack_machine(argv[1]); 224 argv++; 225 argc--; 226 } 284 // why? it breaks "dc -2 2 * p" 285 //if (argv[0][0] == '-') 286 // bb_show_usage(); 287 do { 288 stack_machine(*argv); 289 } while (*++argv); 227 290 } 228 291 return EXIT_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.