Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/miscutils/dc.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/miscutils/dc.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    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.
    44 */
    55
     
    77#include <math.h>
    88
    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
     33typedef unsigned data_t;
     34#define DATA_FMT ""
     35#elif 0
     36typedef unsigned long data_t;
     37#define DATA_FMT "l"
     38#else
     39typedef unsigned long long data_t;
     40#define DATA_FMT "ll"
     41#endif
     42
     43
     44struct globals {
     45    unsigned pointer;
     46    unsigned base;
     47    double stack[1];
     48} FIX_ALIASING;
     49enum { 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
    1658
    1759static void push(double a)
     
    4688}
    4789
     90#if ENABLE_FEATURE_DC_LIBM
    4891static void power(void)
    4992{
     
    5295    push(pow(pop(), topower));
    5396}
     97#endif
    5498
    5599static void divide(void)
     
    62106static void mod(void)
    63107{
    64     unsigned int d = pop();
    65 
    66     push((unsigned int) pop() % d);
     108    data_t d = pop();
     109
     110    push((data_t) pop() % d);
    67111}
    68112
    69113static void and(void)
    70114{
    71     push((unsigned int) pop() & (unsigned int) pop());
     115    push((data_t) pop() & (data_t) pop());
    72116}
    73117
    74118static void or(void)
    75119{
    76     push((unsigned int) pop() | (unsigned int) pop());
     120    push((data_t) pop() | (data_t) pop());
    77121}
    78122
    79123static void eor(void)
    80124{
    81     push((unsigned int) pop() ^ (unsigned int) pop());
     125    push((data_t) pop() ^ (data_t) pop());
    82126}
    83127
    84128static void not(void)
    85129{
    86     push(~(unsigned int) pop());
     130    push(~(data_t) pop());
    87131}
    88132
    89133static void set_output_base(void)
    90134{
    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);
    94141        base = 10;
    95142    }
     
    98145static void print_base(double print)
    99146{
    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    }
    104179}
    105180
    106181static void print_stack_no_pop(void)
    107182{
    108     unsigned int i = pointer;
     183    unsigned i = pointer;
    109184    while (i)
    110185        print_base(stack[--i]);
     
    130205    {"/",   divide},
    131206    {"div", divide},
     207#if ENABLE_FEATURE_DC_LIBM
    132208    {"**",  power},
    133209    {"exp", power},
    134210    {"pow", power},
     211#endif
    135212    {"%",   mod},
    136213    {"mod", mod},
     
    143220    {"f", print_stack_no_pop},
    144221    {"o", set_output_base},
    145     {"", 0}
     222    { "", NULL }
    146223};
    147224
    148225static void stack_machine(const char *argument)
    149226{
    150     char *endPointer = 0;
     227    char *endPointer;
    151228    double d;
    152229    const struct op *o = operators;
    153230
    154     if (argument == 0)
    155         return;
    156 
    157231    d = strtod(argument, &endPointer);
    158232
    159     if (endPointer != argument) {
     233    if (endPointer != argument && *endPointer == '\0') {
    160234        push(d);
    161235        return;
    162236    }
    163237
    164     while (o->name[0]) {
     238    while (o->function) {
    165239        if (strcmp(o->name, argument) == 0) {
    166240            o->function();
     
    169243        o++;
    170244    }
    171     bb_error_msg_and_die("%s: syntax error", argument);
     245    bb_error_msg_and_die("syntax error at '%s'", argument);
    172246}
    173247
     
    177251static char *get_token(char **buffer)
    178252{
    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
     261int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     262int 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) {
    210273            cursor = line;
    211             len = number_of_tokens(line);
    212             for (i = 0; i < len; i++) {
     274            while (1) {
    213275                token = get_token(&cursor);
    214                 *cursor++ = 0;
     276                if (!token)
     277                    break;
     278                *cursor++ = '\0';
    215279                stack_machine(token);
    216280            }
     
    218282        }
    219283    } 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);
    227290    }
    228291    return EXIT_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.