Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/miscutils/dc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 3  Line 3 
3   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4   */   */
5    
6  #include "busybox.h"  #include "libbb.h"
 #include <ctype.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <unistd.h>  
7  #include <math.h>  #include <math.h>
8    
9  /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */  /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
10    
11  static double stack[100];  
12  static unsigned int pointer;  struct globals {
13  static unsigned char base;   unsigned pointer;
14     unsigned base;
15     double stack[1];
16    };
17    enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(double) };
18    #define G (*(struct globals*)&bb_common_bufsiz1)
19    #define pointer   (G.pointer   )
20    #define base      (G.base      )
21    #define stack     (G.stack     )
22    #define INIT_G() do { \
23     base = 10; \
24    } while (0)
25    
26    
27  static void push(double a)  static void push(double a)
28  {  {
29   if (pointer >= (sizeof(stack) / sizeof(*stack)))   if (pointer >= STACK_SIZE)
30   bb_error_msg_and_die("stack overflow");   bb_error_msg_and_die("stack overflow");
31   stack[pointer++] = a;   stack[pointer++] = a;
32  }  }
# Line 48  static void mul(void) Line 55  static void mul(void)
55   push(pop() * pop());   push(pop() * pop());
56  }  }
57    
58    #if ENABLE_FEATURE_DC_LIBM
59  static void power(void)  static void power(void)
60  {  {
61   double topower = pop();   double topower = pop();
62    
63   push(pow(pop(), topower));   push(pow(pop(), topower));
64  }  }
65    #endif
66    
67  static void divide(void)  static void divide(void)
68  {  {
# Line 64  static void divide(void) Line 73  static void divide(void)
73    
74  static void mod(void)  static void mod(void)
75  {  {
76   unsigned int d = pop();   unsigned d = pop();
77    
78   push((unsigned int) pop() % d);   push((unsigned) pop() % d);
79  }  }
80    
81  static void and(void)  static void and(void)
82  {  {
83   push((unsigned int) pop() & (unsigned int) pop());   push((unsigned) pop() & (unsigned) pop());
84  }  }
85    
86  static void or(void)  static void or(void)
87  {  {
88   push((unsigned int) pop() | (unsigned int) pop());   push((unsigned) pop() | (unsigned) pop());
89  }  }
90    
91  static void eor(void)  static void eor(void)
92  {  {
93   push((unsigned int) pop() ^ (unsigned int) pop());   push((unsigned) pop() ^ (unsigned) pop());
94  }  }
95    
96  static void not(void)  static void not(void)
97  {  {
98   push(~(unsigned int) pop());   push(~(unsigned) pop());
99  }  }
100    
101  static void set_output_base(void)  static void set_output_base(void)
102  {  {
103   base=(unsigned char)pop();   static const char bases[] ALIGN1 = { 2, 8, 10, 16, 0 };
104   if ((base != 10) && (base != 16)) {   unsigned b = (unsigned)pop();
105   fprintf(stderr, "Error: base = %d is not supported.\n", base);  
106   base=10;   base = *strchrnul(bases, b);
107     if (base == 0) {
108     bb_error_msg("error, base %u is not supported", b);
109     base = 10;
110   }   }
111  }  }
112    
113  static void print_base(double print)  static void print_base(double print)
114  {  {
115   if (base == 16)   unsigned x, i;
116   printf("%x\n", (unsigned int)print);  
117   else   if (base == 10) {
118   printf("%g\n", print);   printf("%g\n", print);
119     return;
120     }
121    
122     x = (unsigned)print;
123     switch (base) {
124     case 16:
125     printf("%x\n", x);
126     break;
127     case 8:
128     printf("%o\n", x);
129     break;
130     default: /* base 2 */
131     i = (unsigned)INT_MAX + 1;
132     do {
133     if (x & i) break;
134     i >>= 1;
135     } while (i > 1);
136     do {
137     bb_putchar('1' - !(x & i));
138     i >>= 1;
139     } while (i);
140     bb_putchar('\n');
141     }
142  }  }
143    
144  static void print_stack_no_pop(void)  static void print_stack_no_pop(void)
145  {  {
146   unsigned int i=pointer;   unsigned i = pointer;
147   while (i)   while (i)
148   print_base(stack[--i]);   print_base(stack[--i]);
149  }  }
# Line 119  static void print_no_pop(void) Line 154  static void print_no_pop(void)
154  }  }
155    
156  struct op {  struct op {
157   const char *name;   const char name[4];
158   void (*function) (void);   void (*function) (void);
159  };  };
160    
# Line 132  static const struct op operators[] = { Line 167  static const struct op operators[] = {
167   {"mul", mul},   {"mul", mul},
168   {"/",   divide},   {"/",   divide},
169   {"div", divide},   {"div", divide},
170    #if ENABLE_FEATURE_DC_LIBM
171   {"**",  power},   {"**",  power},
172   {"exp", power},   {"exp", power},
173   {"pow", power},   {"pow", power},
174    #endif
175   {"%",   mod},   {"%",   mod},
176   {"mod", mod},   {"mod", mod},
177   {"and", and},   {"and", and},
# Line 145  static const struct op operators[] = { Line 182  static const struct op operators[] = {
182   {"p", print_no_pop},   {"p", print_no_pop},
183   {"f", print_stack_no_pop},   {"f", print_stack_no_pop},
184   {"o", set_output_base},   {"o", set_output_base},
185   {0,     0}   { /* zero filled */ }
186  };  };
187    
188  static void stack_machine(const char *argument)  static void stack_machine(const char *argument)
189  {  {
190   char *endPointer = 0;   char *endPointer;
191   double d;   double d;
192   const struct op *o = operators;   const struct op *o = operators;
193    
# Line 164  static void stack_machine(const char *ar Line 201  static void stack_machine(const char *ar
201   return;   return;
202   }   }
203    
204   while (o->name != 0) {   while (o->name[0]) {
205   if (strcmp(o->name, argument) == 0) {   if (strcmp(o->name, argument) == 0) {
206   (*(o->function)) ();   o->function();
207   return;   return;
208   }   }
209   o++;   o++;
# Line 179  static void stack_machine(const char *ar Line 216  static void stack_machine(const char *ar
216   */   */
217  static char *get_token(char **buffer)  static char *get_token(char **buffer)
218  {  {
219   char *start = NULL;   char *current = skip_whitespace(*buffer);
220   char *current;   if (*current != '\0') {
221     *buffer = skip_non_whitespace(current);
222   current = skip_whitespace(*buffer);   return current;
  if (*current != 0) {  
  start = current;  
  while (!isspace(*current) && *current != 0) { current++; }  
  *buffer = current;  
223   }   }
224   return start;   return NULL;
225  }  }
226    
227  /* In Perl one might say, scalar m|\s*(\S+)\s*|g */  int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
228  static int number_of_tokens(char *buffer)  int dc_main(int argc UNUSED_PARAM, char **argv)
229  {  {
230   int   i = 0;   INIT_G();
  char *b = buffer;  
  while (get_token(&b)) { i++; }  
  return i;  
 }  
231    
232  int dc_main(int argc, char **argv)   argv++;
233  {   if (!argv[0]) {
234   /* take stuff from stdin if no args are given */   /* take stuff from stdin if no args are given */
235   if (argc <= 1) {   char *line;
236   int i, len;   char *cursor;
237   char *line   = NULL;   char *token;
238   char *cursor = NULL;   while ((line = xmalloc_fgetline(stdin)) != NULL) {
  char *token  = NULL;  
  while ((line = xmalloc_getline(stdin))) {  
239   cursor = line;   cursor = line;
240   len = number_of_tokens(line);   while (1) {
  for (i = 0; i < len; i++) {  
241   token = get_token(&cursor);   token = get_token(&cursor);
242   *cursor++ = 0;   if (!token) break;
243     *cursor++ = '\0';
244   stack_machine(token);   stack_machine(token);
245   }   }
246   free(line);   free(line);
247   }   }
248   } else {   } else {
249   if (*argv[1]=='-')   if (argv[0][0] == '-')
250   bb_show_usage();   bb_show_usage();
251   while (argc >= 2) {   do {
252   stack_machine(argv[1]);   stack_machine(*argv);
253   argv++;   } while (*++argv);
  argc--;  
  }  
254   }   }
255   return EXIT_SUCCESS;   return EXIT_SUCCESS;
256  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.816