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