00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00047 #include "calc.h"
00048 #include <stdarg.h>
00049
00050
00051 static const command commands[] = {
00052 {
00053 "add",
00054 OP_ADD,
00055 "Pop two values and push their sum"
00056 } , {
00057 "sub",
00058 OP_SUB,
00059 "Pop two values and push their subtraction"
00060 } , {
00061 "mul",
00062 OP_MUL,
00063 "Pop two values and push their mul"
00064 } , {
00065 "div",
00066 OP_DIV,
00067 "Divide the two values"
00068 } , {
00069 "mod",
00070 OP_MOD
00071 } , {
00072 "and",
00073 OP_AND,
00074 "Logical and between the two values"
00075 } , {
00076 "or",
00077 OP_OR,
00078 "Logical or between the two values"
00079 } , {
00080 "xor",
00081 OP_XOR
00082 } , {
00083 "not",
00084 OP_NOT
00085 } , {
00086 "neg",
00087 OP_NEG
00088 } , {
00089 "sqrt",
00090 OP_SQRT,
00091 "Square root of the value"
00092 } , {
00093 "quit",
00094 OP_QUIT,
00095 "Quit the calculator"
00096 } , {
00097 "list",
00098 OP_LIST,
00099 "List the stack"
00100 } , {
00101 "help",
00102 OP_HELP,
00103 "This help"
00104 } , {
00105 "dec",
00106 OP_DEC,
00107 "Switch in decimal mode"
00108 } , {
00109 "hex",
00110 OP_HEX,
00111 "Switch in hexadecimal mode"
00112 } , {
00113 0,
00114 0,
00115 0
00116 }
00117 };
00118
00119
00120
00121 int
00122 strcmp (const char* s1, const char* s2)
00123 {
00124 while (*s1 && (*s1 == *s2))
00125 s1++, s2++;
00126
00127 return *s1 - *s2;
00128 }
00129
00130 static char*
00131 hex_convert(char* buf, value_t value)
00132 {
00133 char num[32];
00134 int pos;
00135
00136 *buf++ = '0';
00137 *buf++ = 'x';
00138
00139 pos = 0;
00140 while (value != 0)
00141 {
00142 char c = value & 0x0F;
00143 num[pos++] = "0123456789ABCDEF"[(unsigned) c];
00144 value = (value >> 4) & HEX_CVT_MASK;
00145 }
00146 if (pos == 0)
00147 num[pos++] = '0';
00148
00149 while (--pos >= 0)
00150 *buf++ = num[pos];
00151
00152 *buf = 0;
00153 return buf;
00154 }
00155
00156 static char*
00157 dec_convert(char* buf, value_t value)
00158 {
00159 char num[20];
00160 int pos;
00161
00162 pos = 0;
00163 if (value < 0)
00164 {
00165 *buf++ = '-';
00166 value = -value;
00167 }
00168 while (value != 0)
00169 {
00170 char c = value % 10;
00171 value = value / 10;
00172 num[pos++] = c + '0';
00173 }
00174 if (pos == 0)
00175 num[pos++] = '0';
00176
00177 while (--pos >= 0)
00178 {
00179 *buf = num[pos];
00180 buf++;
00181 }
00182 *buf = 0;
00183 return buf;
00184 }
00185
00186
00187
00188
00189 char*
00190 sprintf(char* buf, const char* pattern, ...)
00191 {
00192 va_list argp;
00193 char* p = buf;
00194 char c;
00195
00196 va_start (argp, pattern);
00197 while ((c = *pattern++) != 0)
00198 {
00199 if (c != '%')
00200 {
00201 *p++ = c;
00202 }
00203 else
00204 {
00205 value_t v;
00206
00207 c = *pattern++;
00208 if (c == 'l')
00209 c = *pattern++;
00210
00211 switch (c)
00212 {
00213 case 'b':
00214 case 'o':
00215 case 'x':
00216 v = va_arg (argp, vavalue_t);
00217 p = hex_convert (p, v);
00218 break;
00219
00220 case 'd':
00221 v = va_arg (argp, vavalue_t);
00222 p = dec_convert (p, v);
00223 break;
00224
00225 default:
00226 *p++ = '%';
00227 *p++ = c;
00228 break;
00229 }
00230 }
00231 }
00232 va_end (argp);
00233 *p++ = 0;
00234 return buf;
00235 }
00236
00237
00238
00239 int
00240 push_value(value_stack_t* stack, value_t v)
00241 {
00242 if (stack->top >= stack->max)
00243 return -1;
00244
00245 stack->values[stack->top++] = v;
00246 return 0;
00247 }
00248
00249
00250 value_t
00251 pop_value(value_stack_t* stack)
00252 {
00253 if (stack->top == 0)
00254 return 0;
00255
00256 return stack->values[--stack->top];
00257 }
00258
00259
00260
00261 int
00262 operation(value_stack_t* stack, enum op_type op)
00263 {
00264 int result;
00265
00266 switch (op)
00267 {
00268 case OP_ADD:
00269 result = push_value (stack, pop_value (stack) + pop_value (stack));
00270 break;
00271
00272 case OP_SUB:
00273 result = push_value (stack, pop_value (stack) - pop_value (stack));
00274 break;
00275
00276 case OP_MUL:
00277 result = push_value (stack, pop_value (stack) * pop_value (stack));
00278 break;
00279
00280 case OP_DIV:
00281 result = push_value (stack, pop_value (stack) / pop_value (stack));
00282 break;
00283
00284 case OP_MOD:
00285 result = push_value (stack, pop_value (stack) % pop_value (stack));
00286 break;
00287
00288 case OP_AND:
00289 result = push_value (stack, pop_value (stack) & pop_value (stack));
00290 break;
00291
00292 case OP_OR:
00293 result = push_value (stack, pop_value (stack) | pop_value (stack));
00294 break;
00295
00296 case OP_XOR:
00297 result = push_value (stack, pop_value (stack) ^ pop_value (stack));
00298 break;
00299
00300 case OP_NOT:
00301 result = push_value (stack, ~pop_value (stack));
00302 break;
00303
00304 case OP_NEG:
00305 result = push_value (stack, -pop_value (stack));
00306 break;
00307
00308 case OP_SQRT:
00309 result = push_value (stack, calc_sqrt (pop_value (stack)));
00310 break;
00311
00312 default:
00313 result = 0;
00314 break;
00315 }
00316 return result;
00317 }
00318
00319 void
00320 print_value(value_stack_t* stack, print_mode mode, int which)
00321 {
00322 char buf[40];
00323 value_t value;
00324
00325 static const char* const print_formats[] = {
00326 " %d\r\n",
00327 " %x\r\n",
00328 " %o\r\n",
00329 " %b\r\n"
00330 };
00331
00332
00333 if (which < 0)
00334 {
00335 which = stack->top - 1;
00336 if (which < 0)
00337 {
00338 print ("Stack is empty\n");
00339 return;
00340 }
00341
00342
00343
00344
00345 sprintf (buf, "Top (%ld) = ", (vavalue_t) stack->top);
00346 print (buf);
00347 }
00348 else
00349 {
00350 sprintf (buf, "[%ld] = ", (vavalue_t) which);
00351 print (buf);
00352 }
00353
00354 if (which >= 0 && which < stack->top)
00355 value = stack->values[which];
00356 else
00357 value = 0;
00358
00359 sprintf (buf, print_formats[mode], value);
00360 print (buf);
00361 }
00362
00363
00364
00365
00366
00367 int
00368 get_value(const char* buf, value_t* v)
00369 {
00370 value_t value = 0;
00371 char c;
00372
00373 if (!(*buf >= '0' && *buf <= '9'))
00374 return -1;
00375
00376
00377 if (*buf == '0' && (buf[1] == 'x' || buf[1] == 'X'))
00378 {
00379 buf += 2;
00380 while ((c = *buf++))
00381 {
00382 if (c >= '0' && c <= '9')
00383 c = c - '0';
00384 else if (c >= 'a' && c <= 'f')
00385 c = c - 'a' + 10;
00386 else if (c >= 'A' && c <= 'F')
00387 c = c - 'A' + 10;
00388 else
00389 return -1;
00390
00391 value = (value << 4) | (value_t) ((unsigned) c);
00392 }
00393 *v = value;
00394 return 0;
00395 }
00396 else
00397 {
00398 int sign = 0;
00399
00400 if (buf[0] == '-')
00401 {
00402 sign = 1;
00403 buf++;
00404 }
00405 while ((c = *buf++) != 0)
00406 {
00407 if (c >= '0' && c <= '9')
00408 c = c - '0';
00409 else
00410 return -1;
00411
00412 value = (value * 10) + (value_t) c;
00413 }
00414 if (sign)
00415 value = -value;
00416 *v = value;
00417 return 0;
00418 }
00419 return -1;
00420 }
00421
00422
00423 op_type
00424 calc_wait_command(value_t* v)
00425 {
00426 char buf[64];
00427 int pos;
00428 char c;
00429
00430 while (1)
00431 {
00432 int i;
00433
00434 pos = 0;
00435 while (1)
00436 {
00437 c = serial_recv ();
00438 if (c == '\r' || c == '\n')
00439 break;
00440
00441 if (c == '\b')
00442 {
00443 print ("\b \b");
00444 pos--;
00445 if (pos < 0)
00446 pos = 0;
00447 }
00448 else
00449 {
00450 buf[pos] = c;
00451 buf[pos+1] = 0;
00452 print (&buf[pos]);
00453 pos++;
00454 }
00455 }
00456
00457 print ("\n");
00458 buf[pos] = 0;
00459
00460 if (get_value (buf, v) == 0)
00461 return OP_NUMBER;
00462
00463 for (i = 0; commands[i].name; i++)
00464 {
00465 if (strcmp (commands[i].name, buf) == 0)
00466 return commands[i].type;
00467 }
00468 print ("\nOperation not recognized.\r\n");
00469 }
00470 }
00471
00472 static void
00473 print_help()
00474 {
00475 int i;
00476
00477 #ifdef VALUE_16
00478 print ("16-bit Integer Calculator\n");
00479 #elif defined(VALUE_32)
00480 print ("32-bit Integer Calculator\n");
00481 #else
00482 print ("64-bit Integer Calculator\n");
00483 #endif
00484
00485 for (i = 0; commands[i].name; i++)
00486 {
00487 if (commands[i].help == 0)
00488 continue;
00489
00490 print (commands[i].name);
00491 print (" \t");
00492 print (commands[i].help);
00493 print ("\n");
00494 }
00495 }
00496
00497 int
00498 calc_loop(value_stack_t* stack)
00499 {
00500 op_type op;
00501 int result;
00502 value_t value;
00503 int i;
00504
00505 print_help ();
00506 while (1)
00507 {
00508 print_value (stack, stack->mode, -1);
00509
00510 op = calc_wait_command (&value);
00511 switch (op)
00512 {
00513 case OP_QUIT:
00514 return 0;
00515
00516 case OP_NUMBER:
00517 result = push_value (stack, value);
00518 if (result != 0)
00519 {
00520 print ("The stack is full.\n");
00521 }
00522 break;
00523
00524 case OP_DEC:
00525 stack->mode = PRINT_DEC;
00526 break;
00527
00528 case OP_HEX:
00529 stack->mode = PRINT_HEX;
00530 break;
00531
00532 case OP_LIST:
00533 for (i = 0; i < stack->top; i++)
00534 print_value (stack, stack->mode, i);
00535 break;
00536
00537 case OP_HELP:
00538 print_help ();
00539 break;
00540
00541 default:
00542 result = operation (stack, op);
00543 break;
00544 }
00545 }
00546 }
00547
00548 int main()
00549 {
00550 value_t val_table[10];
00551 value_stack_t values;
00552
00553 serial_init ();
00554
00555 values.top = 0;
00556 values.values = val_table;
00557 values.max = 10;
00558 values.mode = PRINT_DEC;
00559
00560 print ("Simple Calculator Test Program\n");
00561 calc_loop (&values);
00562 return 0;
00563 }