/*- # X-BASED ABACUS # # AbacusC.c # ### # # Copyright (c) 1992 - 2007 David Albert Bagley, bagleyd@tux.org # # All Rights Reserved # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies and # that both that copyright notice and this permission notice appear in # supporting documentation, and that the name of the author not be # used in advertising or publicity pertaining to distribution of the # software without specific, written prior permission. # # This program is distributed in the hope that it will be "useful", # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Taken from a C++ group project where I was a lead contributer # OOP Group4! */ /* Methods string infix calculator file for Abacus */ #include "AbacusP.h" #ifndef WINVER #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_E #define M_E 2.7182818284590452354 extern int signgam; #endif #endif /* proposed, implemented only a small portion Letter Meaning ------ ------- kill program, or turn off calculator [quit] delete last digit [numeric] [ignore] ! factorial " # number of values for statistics $ summation % mod e.g. 7%2=1 [medium] & bitwise and [medium] ' ( ( [equate] ) ) [equate] * multipication [medium] + addition [low] , real imaginary delimitor [numeric] - subtraction (not sign change) [low] . decimal point (or octal pt if in octal, etc.) [numeric] / divide e.g. 1/2=0.5 [medium] 0 0 [numeric] 1 1 [numeric] 2 2 [numeric] 3 3 [numeric] 4 4 [numeric] 5 5 [numeric] 6 6 [numeric] 7 7 [numeric] 8 8 [numeric] 9 9 [numeric] : ; < bitwise shift left [high] = = [equate] > bitwise shift right [high] ? data input for statistics @ average A hexadecimal 10 [numeric] B hexadecimal 11 [numeric] C hexadecimal 12 [numeric] D hexadecimal 13 [numeric] E hexadecimal 14 [numeric] F hexadecimal 15 [numeric] G variance (sigma^2) H hyperbolic I inverse J K L logarithm base 2 M memory recall ('M', ('0'-'9' | 'A'-'F')) N natural logarithm O bitwise xor [high] P permutation [low] Q quit [quit] R "to the root of" e.g. 8R3=2 [high] S sample variance (s^2) T square summation U x^3 V x^2 W convert from MinSec X e^x (unfortunately 'e' & 'E' are used already) Y Z [ \ Pascal's div i.e 28\8=3 [medium] ] ^ "power of" e.g. 2^3=8 [high] _ reset statistics ` a clear almost all [clear] b base mode ('b', (['2'-'9'] | '1',['0'-'6'])) c combination [low] d decimal hot key (also 'b', '1', '0') e used for exponents e.g. 6.02*10^22 = 6.02e22(input) = 6.02 22(output) f g gradient mode h hexadecimal hot key (also 'b', '1', '6') i invert 1/x j k cosine (kosine) l logarithm base 10 m memory ('m', ('0'-'9' | 'A'-'F')) n bitwise negation o degree mode p pi q clear everything (quit all calulations) [clear] r radian mode s sine t tangent u cube root v unary operation square root (v-) UNIX's dc & bc use this also w convert to MinSec x complex mode (base 10 only) y z clear (zero) [clear] { | bitwise or [low] } ~ negate +/- [numeric (and also unary)] */ enum OrderType {notused, low, medium, high, unary, mode, constant, equate}; static const short unsigned int orderASCII[] = { notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, notused, unary, notused, constant, /* Space ! " # */ constant, medium, medium, notused, /* $ % & ' */ equate, equate, medium, low, /* ( ) * + */ notused, low, notused, medium, /* , - . / */ notused, notused, notused, notused, /* 0 1 2 3 */ notused, notused, notused, notused, /* 4 5 6 7 */ notused, notused, notused, notused, /* 8 9 : ; */ high, equate, high, unary, /* < = > ? */ constant, notused, notused, notused, /* @ A B C */ notused, notused, notused, constant, /* D E F G */ mode, mode, notused, notused, /* H I J K */ unary, constant, unary, high, /* L M N O */ low, notused, high, constant, /* P Q R S */ constant, unary, unary, unary, /* T U V W */ unary, notused, notused, notused, /* X Y Z [ */ medium, notused, high, mode, /* \ ] ^ _ */ notused, notused, mode, low, /* ` a b c */ mode, constant, notused, mode, /* d e f g */ mode, unary, notused, unary, /* h i j k */ unary, mode, unary, mode, /* l m n o */ constant, notused, mode, unary, /* p q r s */ unary, unary, unary, unary, /* t u v w */ mode, notused, notused, notused, /* x y z { */ low, notused, unary, notused /* | } ~ Delete */ }; enum OperationType {undefined, ignore, numeric, operation, clear, quit}; static const short unsigned int operationASCII[] = { undefined, undefined, undefined, quit, /* Null SOH STX Interrupt */ undefined, undefined, undefined, undefined, /* EOT ENQ ACK Bell */ numeric, undefined, ignore, undefined, /* Backspace Tab Linefeed VT */ undefined, ignore, undefined, undefined, /* Formfeed Carriagereturn SO SI */ undefined, undefined, undefined, undefined, /* DLE DC1 DC2 DC3 */ undefined, undefined, undefined, undefined, /* DC4 NAK SYN ETB */ undefined, undefined, undefined, undefined, /* CAN EM SUB Escape */ undefined, undefined, undefined, undefined, /* FS GS RS US */ ignore, operation, undefined, operation, /* Space ! " # */ operation, operation, operation, undefined, /* $ % & ' */ operation, operation, operation, operation, /* ( ) * + */ numeric, operation, numeric, operation, /* , - . / */ numeric, numeric, numeric, numeric, /* 0 1 2 3 */ numeric, numeric, numeric, numeric, /* 4 5 6 7 */ numeric, numeric, undefined, undefined, /* 8 9 : ; */ operation, operation, operation, operation, /* < = > ? */ operation, numeric, numeric, numeric, /* @ A B C */ numeric, numeric, numeric, operation, /* D E F G */ operation, operation, undefined, undefined, /* H I J K */ operation, operation, operation, operation, /* L M N O */ operation, quit, operation, operation, /* P Q R S */ operation, operation, operation, operation, /* T U V W */ operation, undefined, undefined, undefined, /* X Y Z [ */ operation, undefined, operation, operation, /* \ ] ^ _ */ undefined, clear, operation, operation, /* ` a b c */ operation, operation, undefined, operation, /* d e f g */ operation, operation, undefined, operation, /* h i j k */ operation, operation, operation, operation, /* l m n o */ operation, clear, operation, operation, /* p q r s */ operation, operation, operation, operation, /* t u v w */ operation, undefined, clear, undefined, /* x y z { */ operation, undefined, numeric, undefined /* | } ~ Delete */ }; #define CHAR_TO_DIGIT(c) ((c >= 'A') ? c - 'A' + 10 : c - '0') #define DIGIT_TO_CHAR(d) ((d >= 10) ? (char) ('A' + d - 10) : (char) ('0' + d)) #define IS_DIGIT(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) /* True for period, +/-, or operator */ #define IS_VALID(v, b) ((IS_DIGIT(v)) ? (CHAR_TO_DIGIT(v) < b) : True) #define MAXVALUELENGTH 64 enum StackUsage {paren, order}; typedef struct _Term { double variable; char operation; Boolean orderUsage; struct _Term *previous; } Term; typedef struct _Expression { /* char *variable; */ char variable[MAXVALUELENGTH]; /* Hard code a limit for now */ char operation; struct _Expression *previous; } Expression; /* struct Stack */ static Term *term; static Expression *expression; #if 0 #define DEBUG #endif #define DEFAULTBASE 10 #define DEFAULTFRACTDIGITS 16 /* Inputter & Parser & Paren Manager */ static Boolean period = False; static Boolean gotFirstDigit = False; /* handles special case of just a '0' */ static Boolean negateNext = False; /* handles unary '-' */ static double left, right; /* sides of a binary operation */ static char pendingOperation; /* operation to be performed on left (& right if not unary) */ static Boolean hub; /* intermediate result? usually a ')' or pi pressed */ static char memoryBuf[64]; static char displayBuf[64]; static int digits = 1; static int currentBase = DEFAULTBASE, fractDigits = DEFAULTFRACTDIGITS; static int nestingLevel = 0; static Expression parseExpression; #if 0 static double cbrt(double x) /* -inf < x < inf */ { return ((x < 0.0) ? -pow(-x, 1.0 / 3.0) : pow(x, 1.0 / 3.0)); } #endif static double powInt(int base, int y) { int i; double z = 1.0; if (y > 0) for (i = 0; i < y; i++) z *= base; else if (y < 0) for (i = 0; i > y; i--) z /= base; else z = 1.0; return z; } /* More exact (int) (log(x) / log(base)) */ static int logInt(double x, int base) { int i = 0; if (x >= base) while (x >= base) { x /= base; i++; } else if (x > 0.0) while (x < 1.0) { x *= base; i--; } return i; } static double rootInt(double x, int y) /* y != 0 && (x >= 0 || (y odd)) */ { if (x < 0.0 && (y / 2.0) != (y / 2)) return -pow (-x, 1.0 / y); else if (x == 0.0) return 0.0; else return pow (x, 1.0 / y); } static double convertToDecimal(int b, char *inputstring) { int k = 0; Boolean negative = False; double number = 0.0; int digit; int length = 0; double factor; /* Convert Integer Part */ k = 0; if (inputstring[k] == '-') { negative = True; k++; } while (IS_DIGIT(inputstring[k + length])) length++; factor = powInt(b, length); for (; length > 0; length--, k++) { digit = CHAR_TO_DIGIT(inputstring[k]); factor /= b; number += digit * factor; } /* Convert Fractional Part */ if (inputstring[k] == '.') { k++; while (IS_DIGIT(inputstring[k])) { digit = CHAR_TO_DIGIT(inputstring[k]); factor /= b; number += digit * factor; k++; } } if (negative) number = -number; negative = False; return number; } static void convertFromDecimal(char *outputString, int b, double x) { char string[MAXVALUELENGTH]; Boolean localPeriod = False; double number = 0.0; int placesBase; int l = 0, i = 0; short unsigned int digit; double factor; int fractdigits = fractDigits; (void) sprintf(string, "%g", x); if (string[i] == '-') { outputString[l++] = '-'; x = -x; } while (string[i] != '\0') { if (string[i] == '.') localPeriod = True; i++; } { /* Chicken and egg problem: rounding might increase placesBase */ placesBase = logInt(x, b); fractdigits -= (placesBase + 1); /* rounder */ x += (pow(b, -fractdigits) / 2.0); number = x; /* Convert Integer Part */ if (number < 1.0) { outputString[l++] = '0'; factor = 1.0 / b; } else { placesBase = logInt(number, b); factor = pow((double) b, (double) placesBase); for (; placesBase >= 0; placesBase--) { digit = (int) (number / factor); outputString[l++] = DIGIT_TO_CHAR(digit); number -= digit * factor; factor /= b; } } /* Convert Fractional Part */ if (localPeriod) { outputString[l++] = '.'; for (placesBase = 1; placesBase <= fractdigits; placesBase++) { digit = (int) (number / factor); outputString[l++] = DIGIT_TO_CHAR(digit); number -= digit * factor; factor /= b; } while (outputString[l - 1] == '0') l--; } } outputString[l] = '\0'; } static double formatFromDisplay(int base, char *string) { char floatString[MAXVALUELENGTH]; Boolean got1Digit = False; short unsigned int periods = 0; int s = 0, k = 0; while (string[s] != '\0') { /* Look at each input character */ if (IS_DIGIT(string[s])) { got1Digit = True; floatString[k++] = string[s]; } else switch (string[s]) { case '-': floatString[k++] = '-'; break; case '.': if (periods == 1) (void) printf("'%c' handler not implemented in Format_From_Display\n", string[s]); periods++; if (!got1Digit) { got1Digit = True; floatString[k++] ='0'; } floatString[k++] = '.'; break; default: (void) printf("'%c' handler not implemented in Format_From_Display\n", string[s]); } s++; } if (!got1Digit) { got1Digit = True; floatString[k++] = '0'; } floatString[k] = '\0'; return convertToDecimal(base, floatString); } static void formatToDisplay (char *string, double z) { int i = 0, j, length; short unsigned int periods = 0; convertFromDecimal(string, currentBase, z); length = strlen(string); while (i <= length) { if (string[i] == '\0' && periods == 0) { j = length; while (j >= i) { string[j + 1] = string[j]; j--; } length++; string[i++] = '.'; periods++; } if (string[i] == '.') periods++; if (string[i] == '+') { j = i; while (j < length) { string[j] = string[j + 1]; j++; } length--; } else i++; } string[length] = '\0'; } static void reset(void) { period = False; gotFirstDigit = False; digits = 1; memoryBuf[0] = '0'; memoryBuf[1] = '\0'; } static void setBase(int base) { currentBase = base; fractDigits = logInt(powInt(DEFAULTBASE, DEFAULTFRACTDIGITS), base); } static int getNestingLevel(void) { return nestingLevel; } static void incNestingLevel(void) { nestingLevel++; } static void decNestingLevel(void) { nestingLevel--; if (nestingLevel < 0) /* Ignore extra right parentheses */ nestingLevel = 0; } static void resetNestingLevel(void) { nestingLevel = 0; } static double evaluateSingle(double arg, char unaryOperation) { switch(unaryOperation) { case 'i': if (arg == 0.0) { return 0.0; } return 1.0 / arg; case '!': #ifdef WINVER if ((double)((int) arg) == arg) { long long i, j; if (arg < 0.0 || arg > 20.0) { return 0.0; } j = 1; for (i = 2; i <= arg; i++) { j = j * i; } return (double) j; } else { return 0.0; } #else if ((arg < 0.0 && ((int) arg) == arg) || arg > 20.0) { /* this does not catch all the errors */ return 0.0; } else { double lg; #ifdef _REENT_ONLY int signgam_r; lg = lgamma_r(arg + 1.0); return signgam_r * exp(lg); #else lg = lgamma(arg + 1.0); return signgam * exp(lg); #endif } #endif case 'v': if (arg <= 0.0) { return 0.0; } return sqrt(arg); case 'u': return cbrt(arg); default: return 0.0; } } static double evaluateDouble(double arg1, char binaryOperation, double arg2) { double comp = 0.0; switch(binaryOperation) { case '+': comp = arg1 + arg2; break; case '-': comp = arg1 - arg2; break; case '*': comp = arg1 * arg2; break; case '/': if (arg2 == 0.0) return 0.0; comp = arg1 / arg2; break; case '^': comp = pow(arg1, arg2); break; default: return 0.0; } return comp; } static Boolean newStack(void) { Term *plate; if (!(plate = (Term *) malloc(sizeof(Term)))) return False; plate->previous = NULL; term = plate->previous; return True; } static Boolean emptyStack(void) { return ((Boolean) (term == NULL)); } static void flushStack(void) { while (!emptyStack()) { Term *plate = term; term = plate->previous; free(plate); } } static void deleteStack(void) { flushStack(); /* free(term); */ } static Boolean pushStack(double z, char c, Boolean u) { Term *plate; if (!(plate = (Term *) malloc(sizeof(Term)))) return False; plate->variable = z; plate->operation = c; plate->orderUsage = u; plate->previous = term; term = plate; return True; } static void popStack(double *z, char *c, Boolean *u) { Term *plate = term; *z = term->variable; *c = term->operation; *u = term->orderUsage; term = plate->previous; free(plate); } static char topOp(void) { return term->operation; } static Boolean topUsage(void) { return term->orderUsage; } static Boolean emptyExpression(void) { return (emptyStack()); } static Boolean previousOrder(void) { return (!emptyExpression() && topUsage() == order); } static Boolean canReduceExpression(char binaryOperation) { return (previousOrder() && orderASCII[(int) topOp()] >= orderASCII[(int) binaryOperation]); } static void resetWholeExpression(void) { flushStack(); } static void getPreviousExpressionPart(double *myLeft, char *binaryOperation) { Boolean dummy; popStack(myLeft, binaryOperation, &dummy); } static Boolean storeExpressionParen(double *myLeft, char *binaryOperation) { if (pushStack(*myLeft, *binaryOperation, paren)) { *myLeft = 0.0; *binaryOperation = '\0'; return True; } return False; } static void evaluateExpressionPart(double *myLeft, char binaryOperation, double myRight) { if (binaryOperation != '\0') *myLeft = evaluateDouble(*myLeft, binaryOperation, myRight); else *myLeft = myRight; } static Boolean evaluateExpressionOrder(double *myLeft, char *binaryOperation, double *myRight, char newOperation) { if (*binaryOperation != '\0') { if (orderASCII[(int) *binaryOperation] >= orderASCII[(int) newOperation]) { *myLeft = evaluateDouble(*myLeft, *binaryOperation, *myRight); while (canReduceExpression(newOperation)) { *myRight = *myLeft; getPreviousExpressionPart (myLeft, binaryOperation); evaluateExpressionPart(myLeft, *binaryOperation, *myRight); } } else { if (pushStack(*myLeft, *binaryOperation, order)) { *myLeft = *myRight; return True; } else { return False; } } } else *myLeft = *myRight; return True; } static void evaluateExpressionParen(double *myLeft, char *binaryOperation) { double myRight; while (!emptyExpression() && topUsage() == order) { myRight = *myLeft; getPreviousExpressionPart(myLeft, binaryOperation); evaluateExpressionPart(myLeft, *binaryOperation, myRight); } } static void evaluateExpression(double *myLeft, char *binaryOperation) { double myRight; while (!emptyExpression()) { myRight = *myLeft; getPreviousExpressionPart(myLeft, binaryOperation); if (binaryOperation != NULL) *myLeft = evaluateDouble(*myLeft, *binaryOperation, myRight); else *myLeft = myRight; } /* ignore uneven "(()" */ *binaryOperation = '\0'; } static void initParser(void) { left = 0.0; right = 0.0; pendingOperation = '\0'; hub = False; /* FIXME expression = Expression(); */ } static void resetRight(void) { right = 0.0; hub = True; } static void resetExpression(void) { right = left = 0.0; pendingOperation = '\0'; hub = False; resetWholeExpression(); } static void parse(double input, Boolean numeral, char newOperation) { if (numeral) { if (negateNext) { negateNext = False; right = -input; pendingOperation = '\0'; } else { right = input; } } else if (hub) { numeral = True; hub = False; } if (orderASCII[(int) newOperation] == equate) { switch (newOperation) { case '(': incNestingLevel(); (void) storeExpressionParen(&left, &pendingOperation); right = left; /* "#(" # is lost forever */ break; case ')': /* Evaluate last term and restore variable and operation. */ decNestingLevel(); if (pendingOperation != '\0' && numeral) /* this stops 4+) = 8 */ left = evaluateDouble(left, pendingOperation, right); if (pendingOperation == '\0' && numeral) left = right; else { evaluateExpressionParen(&left, &pendingOperation); pendingOperation = '\0'; right = left; if (!emptyExpression()) /* ignore uneven "())" */ { getPreviousExpressionPart (&left, &pendingOperation); hub = True; } } break; case '=': /* Evaluate term and restore variable and operation. */ resetNestingLevel(); if (pendingOperation != '\0' && numeral) { /* this stops 4+= = 8 (2+2) */ left = evaluateDouble(left, pendingOperation, right); } if (pendingOperation == '\0' && numeral) { left = right; } else { evaluateExpression(&left, &pendingOperation); right = left; } break; default: resetExpression(); } } else if (orderASCII[(int) newOperation] == constant) { switch (newOperation) { case 'e': /* natural logarithm */ right = M_E; break; case 'p': /* pi */ right = M_PI; break; default: resetExpression(); } hub = True; } else if (orderASCII[(int) newOperation] == unary) { right = evaluateSingle(right, newOperation); if (pendingOperation == '\0') left = right; hub = True; } else if (orderASCII[(int) newOperation] != notused) { /* binary operation */ if (!numeral) { if (previousOrder()) /* this stops 2*+ = 6 (2*2+2) */ { getPreviousExpressionPart(&left, &pendingOperation); (void) evaluateExpressionOrder(&left, &pendingOperation, &right, newOperation); right = left; } else if (pendingOperation != '\0') { resetExpression(); } else if (newOperation == '-') { negateNext = True; } } else { (void) evaluateExpressionOrder(&left, &pendingOperation, &right, newOperation); right = left; } pendingOperation = newOperation; } else { /* not used operation */ resetExpression(); } formatToDisplay(memoryBuf, right); (void) strcpy(displayBuf, memoryBuf); /* update display */ } static void inputOperator(char input) { if (!gotFirstDigit) { parse(0.0, False, input); } else { parse(formatFromDisplay(currentBase, memoryBuf), True, input); } reset(); } static Boolean inputNumeric(char input) { int i = digits - 1, j; if (!IS_VALID(input, currentBase)) { reset(); return False; } if (IS_DIGIT(input)) { gotFirstDigit = True; if (memoryBuf[0] == '0' && memoryBuf[1] == '\0') { memoryBuf[0] = input; } else { memoryBuf[digits] = input; digits++; memoryBuf[digits] = '\0'; } } else switch(input) { case '.': if (period) { reset(); /* Handle multiple '.' */ } period = True; memoryBuf[digits] = input; digits++; memoryBuf[digits] = '\0'; break; case '~': /* Handle +/- */ /* Note: if `memoryBuf == "0"' then "+/-" should act as a unary operation, that is, if no number is entered, it should act on the result. */ if (!gotFirstDigit) { inputOperator ('~'); return False; } if (memoryBuf[0] == '0' && memoryBuf[1] == '\0') return False; while (memoryBuf[i] != ' ' && memoryBuf[i] != '-' && memoryBuf[i] != ',' && i != 0) i--; if (memoryBuf[i] == '-') { /* Take a '-' from front of a negative number */ while (memoryBuf[i] != '\0') { memoryBuf[i] = memoryBuf[i + 1]; i++; } digits--; } else { /* Put the '-' in the front of a positive number */ if (digits == MAXVALUELENGTH - 1) return False; j = digits; while (j >= i) { memoryBuf[j + 1] = memoryBuf[j]; j--; } memoryBuf[i] = '-'; digits++; } break; default: reset(); return False; } return True; } static void convertStringToAbacus(AbacusWidget w, char *string) { int decimal = 0; int num, factor, i, sign = 0, len = strlen(string); ClearRails(w); while (string[decimal] != '\0' && string[decimal] != '.') decimal++; if (string[0] == '-' || string[0] == '+') { sign = 1; } for (i = 0; i < decimal - sign; i++) { /* w->abacus.displayBase == w->abacus.base and all that ... */ num = char2Int(string[decimal - 1 - i]); factor = num / w->abacus.decks[TOP].factor; if (factor > 0) { setAbacusMove(w, ACTION_MOVE, 0, 1, i, factor); num = num - factor * w->abacus.decks[TOP].factor; } factor = num / w->abacus.decks[BOTTOM].factor; if (factor > 0) { setAbacusMove(w, ACTION_MOVE, 0, 0, i, factor); } } if (w->abacus.sign && string[0] == '-') { setAbacusMove(w, ACTION_MOVE, 0, 0, w->abacus.rails - w->abacus.decimalPosition - 1, 1); } for (i = 0; i < len - decimal - 1 && i < w->abacus.decimalPosition; i++) { num = char2Int(string[decimal + i + 1]); factor = num / w->abacus.decks[TOP].factor; if (factor > 0) { setAbacusMove(w, ACTION_MOVE, 0, 1, -i - 1, factor); num = num - factor * w->abacus.decks[TOP].factor; } factor = num / w->abacus.decks[BOTTOM].factor; if (factor > 0) { setAbacusMove(w, ACTION_MOVE, 0, 0, -i - 1, factor); } } } void calculate(AbacusWidget w, char * buffer) { unsigned int i; #ifdef DEBUG (void) printf("buffer =%s\n", buffer); #endif if (w->abacus.displayBase != w->abacus.base) return; currentBase = w->abacus.displayBase; fractDigits = logInt(powInt(DEFAULTBASE, DEFAULTFRACTDIGITS), currentBase); resetExpression(); memoryBuf[0] = '0'; memoryBuf[1] = '\0'; displayBuf[0] = '0'; displayBuf[1] = '\0'; for (i = 0; i < strlen(buffer); i++) { switch (operationASCII[(int) buffer[i]]) { case undefined: #ifdef DEBUG (void) printf("undefined\n"); #endif break; case ignore: #ifdef DEBUG (void) printf("ignore\n"); #endif break; case numeric: #ifdef DEBUG (void) printf("number %c %s\n", buffer[i], memoryBuf); #endif (void) inputNumeric(buffer[i]); break; case operation: #ifdef DEBUG (void) printf("operate %c %s\n", buffer[i], memoryBuf); #endif inputOperator(buffer[i]); break; case clear: #ifdef DEBUG (void) printf("clear\n"); #endif break; default: #ifdef DEBUG (void) printf("QUIT\n"); #endif break; } } inputOperator('='); #ifdef DEBUG (void) printf("displayBuf %s\n", displayBuf); #endif convertStringToAbacus(w, displayBuf); }