diff --git a/Makefile b/Makefile index 9572506..4c2b83a 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,21 @@ -OBJS=abCalc.o abCalcExpr.o abCalcExprReal.o abCalcExprInt.o abCalcStack.o abCalcMode.o abCalcMain.o +OBJS=abCalc.o abCalcExpr.o abCalcExprReal.o abCalcExprInt.o abCalcStack.o \ + abCalcMode.o abCalcMain.o abCalcOp.o abCalcOpAdd.o abCalcError.o + NAME=abCalc all: $(NAME) abCalcExpr.o: abCalcExpr.h abCalcExprReal.o: abCalcExpr.h abCalcExprReal.h -abCalcStack.o: abCalcExpr.h abCalcStack.h +abCalcStack.o: abCalcExpr.h abCalcStack.h abCalcError.h abCalcMode.o: abCalcMode.h abCalcExpr.h abCalcExprInt.o: abCalcExpr.h abCalcMode.h abCalcExprInt.h -abCalc.o: abCalc.h abCalcExpr.h abCalcMode.h abCalcExprReal.h abCalcExprInt.h abCalcStack.h -abCalcMain.o: abCalc.h abCalcStack.h abCalcExpr.h +abCalc.o: abCalc.h abCalcExpr.h abCalcMode.h abCalcExprReal.h abCalcExprInt.h \ + abCalcStack.h abCalcOp.h abCalcError.h +abCalcMain.o: abCalc.h abCalcStack.h abCalcExpr.h abCalcOp.h abCalcError.h +abCalcOp.o: abCalcOp.h abCalcOpAdd.h +abCalcOpAdd.o: abCalcOp.h abCalcOpAdd.h +abCalcError.o: abCalcError.h CFLAGS=-g diff --git a/abCalc.c b/abCalc.c index 4569a33..682389f 100644 --- a/abCalc.c +++ b/abCalc.c @@ -9,6 +9,8 @@ #include "abCalcExprReal.h" #include "abCalcMode.h" #include "abCalcStack.h" +#include "abCalcOp.h" +#include "abCalcError.h" void abCalcInit(void) @@ -19,6 +21,10 @@ void abCalcInit(void) abCalcModeInit(); abCalcStackInit(); + + abCalcOpInit(); + + abCalcErrorInit(); } diff --git a/abCalcError.c b/abCalcError.c new file mode 100644 index 0000000..360c64e --- /dev/null +++ b/abCalcError.c @@ -0,0 +1,73 @@ +/* + abCalcError.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCalcError.h" + + +static char *gErrorStrings[abCalcErrorTypeMax]; + +static abCalcErrorType gCurrErrorType = abCalcNoError; +static char *gCurrErrorOpName = NULL; + +static char gErrorBuffer[128]; + + +void abCalcErrorInit(void) +{ + gErrorStrings[abCalcNoError] = NULL; + gErrorStrings[abCalcSyntaxError] = "Syntax Error"; + gErrorStrings[abCalcBadArgTypeError] = "Bad Argument Type"; + gErrorStrings[abCalcBadArgValueError] = "Bad Argument Value"; + gErrorStrings[abCalcTooFewArgsError] = "Too Few Arguments"; + gErrorStrings[abCalcStackFullError] = "Stack Full"; +} + + +void abCalcRaiseError(abCalcErrorType type, char *opName) +{ + if ((type < abCalcErrorTypeMin) || + (type >= abCalcErrorTypeMax)) + return; + + if (gCurrErrorType == abCalcNoError) { + gCurrErrorType = type; + gCurrErrorOpName = opName; + } +} + + +char *abCalcGetError(void) +{ + char *errorString; + + if ((gCurrErrorType < abCalcErrorTypeMin) || + (gCurrErrorType >= abCalcErrorTypeMax)) + return NULL; + + errorString = gErrorStrings[gCurrErrorType]; + + if (errorString == NULL) + return NULL; + + if (gCurrErrorOpName != NULL) { + sprintf(gErrorBuffer, "%s Error: %s", gCurrErrorOpName, gErrorStrings[gCurrErrorType]); + } else { + sprintf(gErrorBuffer, "Error: %s", gErrorStrings[gCurrErrorType]); + } + + return gErrorBuffer; +} + + +void abCalcClearError(void) +{ + gCurrErrorType = abCalcNoError; + gCurrErrorOpName = NULL; +} + diff --git a/abCalcError.h b/abCalcError.h new file mode 100644 index 0000000..f191b09 --- /dev/null +++ b/abCalcError.h @@ -0,0 +1,33 @@ +/* + abCalcError.h + By: Jeremy Rand + */ + + +#ifndef ABCALCERROR_H +#define ABCALCERROR_H + + +typedef enum abCalcErrorType { + abCalcErrorTypeMin = 0, + abCalcNoError, + abCalcSyntaxError, + abCalcBadArgTypeError, + abCalcBadArgValueError, + abCalcTooFewArgsError, + abCalcStackFullError, + + abCalcErrorTypeMax +} abCalcErrorType; + + +void abCalcErrorInit(void); + +void abCalcRaiseError(abCalcErrorType type, char *opName); + +char *abCalcGetError(void); + +void abCalcClearError(void); + + +#endif diff --git a/abCalcMain.c b/abCalcMain.c index 7ba3c91..d6c1c49 100644 --- a/abCalcMain.c +++ b/abCalcMain.c @@ -11,6 +11,8 @@ #include "abCalc.h" #include "abCalcExpr.h" #include "abCalcStack.h" +#include "abCalcOp.h" +#include "abCalcError.h" char gBuffer[AB_CALC_EXPR_STRING_MAX]; @@ -23,6 +25,8 @@ int main(void) int depth; int item; int len; + abCalcOp *op; + char *errorString; abCalcInit(); @@ -39,6 +43,12 @@ int main(void) } } + errorString = abCalcGetError(); + if (errorString != NULL) { + printf("\n %s\n", errorString); + abCalcClearError(); + } + timeToQuit = 1; if (fgets(gBuffer, sizeof(gBuffer), stdin) != NULL) { len = strlen(gBuffer); @@ -47,9 +57,14 @@ int main(void) gBuffer[len - 1] = '\0'; } - if ((abCalcParseExpr(&gExpr, gBuffer) != NULL) && - (abCalcStackExprPush(&gExpr) != NULL)) { - timeToQuit = 0; + op = abCalcOpLookup(gBuffer); + + if (op != NULL) { + op->execute(); + } else if (abCalcParseExpr(&gExpr, gBuffer) != NULL) { + abCalcStackExprPush(&gExpr); + } else { + abCalcRaiseError(abCalcSyntaxError, NULL); } } } diff --git a/abCalcOp.c b/abCalcOp.c new file mode 100644 index 0000000..b5766af --- /dev/null +++ b/abCalcOp.c @@ -0,0 +1,54 @@ +/* + abCalcOp.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCalcOp.h" + +#include "abCalcOpAdd.h" + + +#define AB_CALC_MAX_OPS 128 + + +static abCalcOp gOps[AB_CALC_MAX_OPS]; +static int gNumOps = 0; + + +void abCalcOpInit(void) +{ + memset(gOps, 0, sizeof(gOps)); + + abCalcOpAddInit(); +} + + +void abCalcOpRegister(char *name, void (*execute)(void)) +{ + if (gNumOps >= AB_CALC_MAX_OPS) { + fprintf(stderr, "Operation registration overflow"); + return; + } + + gOps[gNumOps].name = name; + gOps[gNumOps].execute = execute; + gNumOps++; +} + + +abCalcOp *abCalcOpLookup(char *name) +{ + int i; + + for (i = 0; i < gNumOps; i++) { + if (strcmp(gOps[i].name, name) == 0) { + return &gOps[i]; + } + } + + return NULL; +} diff --git a/abCalcOp.h b/abCalcOp.h new file mode 100644 index 0000000..513812d --- /dev/null +++ b/abCalcOp.h @@ -0,0 +1,24 @@ +/* + abCalcOp.h + By: Jeremy Rand + */ + + +#ifndef ABCALCOP_H +#define ABCALCOP_H + + +typedef struct abCalcOp { + char *name; + void (*execute)(void); +} abCalcOp; + + +void abCalcOpInit(void); + +void abCalcOpRegister(char *name, void (*execute)(void)); + +abCalcOp *abCalcOpLookup(char *name); + + +#endif diff --git a/abCalcOpAdd.c b/abCalcOpAdd.c new file mode 100644 index 0000000..82d3907 --- /dev/null +++ b/abCalcOpAdd.c @@ -0,0 +1,28 @@ +/* + abCalcOpAdd.c + By: Jeremy Rand + */ + + +#include + +#include "abCalcOpAdd.h" +#include "abCalcOp.h" + + +#define OP_NAME "+" + + +static void addExecute(void); + + +void abCalcOpAddInit(void) +{ + abCalcOpRegister(OP_NAME, addExecute); +} + + +void addExecute(void) +{ + printf("In add!\n"); +} diff --git a/abCalcOpAdd.h b/abCalcOpAdd.h new file mode 100644 index 0000000..e7dd11b --- /dev/null +++ b/abCalcOpAdd.h @@ -0,0 +1,14 @@ +/* + abCalcOpAdd.h + By: Jeremy Rand + */ + + +#ifndef ABCALCOPADD_H +#define ABCALCOPADD_H + + +void abCalcOpAddInit(void); + + +#endif diff --git a/abCalcStack.c b/abCalcStack.c index 07fc886..ad857de 100644 --- a/abCalcStack.c +++ b/abCalcStack.c @@ -8,6 +8,7 @@ #include #include "abCalcStack.h" +#include "abCalcError.h" #define AB_CALC_STACK_DEPTH 128 @@ -25,6 +26,12 @@ void abCalcStackInit(void) abCalcExpr *abCalcStackExprPush(abCalcExpr *expr) { abCalcExpr *result = NULL; + + if (gStackNumItems >= AB_CALC_STACK_DEPTH) { + abCalcRaiseError(abCalcStackFullError, NULL); + return NULL; + } + if ((gStackNumItems < AB_CALC_STACK_DEPTH) && (expr != NULL)) { result = &(gStack[gStackNumItems]);