diff --git a/.DS_Store b/.DS_Store index 24aa3a7..4dec4da 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 75dd683..0000000 --- a/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.*.swp -*.o -*.r -*.root -abCalc -abCalcNDA diff --git a/abCalc/Makefile b/abCalc/Makefile new file mode 100644 index 0000000..9ffe8b9 --- /dev/null +++ b/abCalc/Makefile @@ -0,0 +1,21 @@ +all: + make -f nda.mk gen + make -f nda.mk build + make -f shell.mk gen + make -f shell.mk build + +gen: + make -f nda.mk gen + make -f shell.mk gen + +build: + make -f nda.mk build + make -f shell.mk build + +clean: + make -f shell.mk clean + make -f nda.mk clean + +execute: + make -f nda.mk execute +# make -f shell.mk execute diff --git a/abCalc/abCError.c b/abCalc/abCError.c new file mode 100644 index 0000000..35b5f21 --- /dev/null +++ b/abCalc/abCError.c @@ -0,0 +1,75 @@ +/* + abCError.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" + + +static char *gErrorStrings[abCalcErrorTypeMax]; + +static abCalcErrorType gCurrErrorType = abCalcNoError; +static char *gCurrErrorOpName = NULL; + +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"; + gErrorStrings[abCalcInfiniteResultError] = "Infinite Result"; + gErrorStrings[abCalcComplexResultError] = "Complex Result"; +} + + +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/abCalc/abCError.h b/abCalc/abCError.h new file mode 100644 index 0000000..bf6fad0 --- /dev/null +++ b/abCalc/abCError.h @@ -0,0 +1,35 @@ +/* + abCError.h + By: Jeremy Rand + */ + + +#ifndef ABCERROR_H +#define ABCERROR_H + + +typedef enum abCalcErrorType { + abCalcErrorTypeMin = 0, + abCalcNoError, + abCalcSyntaxError, + abCalcBadArgTypeError, + abCalcBadArgValueError, + abCalcTooFewArgsError, + abCalcStackFullError, + abCalcInfiniteResultError, + abCalcComplexResultError, + + abCalcErrorTypeMax +} abCalcErrorType; + + +void abCalcErrorInit(void); + +void abCalcRaiseError(abCalcErrorType type, char *opName); + +char *abCalcGetError(void); + +void abCalcClearError(void); + + +#endif diff --git a/abCalc/abCMode.c b/abCalc/abCMode.c new file mode 100644 index 0000000..987875d --- /dev/null +++ b/abCalc/abCMode.c @@ -0,0 +1,47 @@ +/* + abCMode.c + By: Jeremy Rand + */ + + +#include "abCMode.h" + + + +static abCalcModeIntBase gBase = abCalcModeDecBase; +static int gIntWidth = AB_CALC_EXPR_MAX_INT_WIDTH; + + +void abCalcModeInit(void) +{ +} + + +abCalcModeIntBase abCalcModeGetBase(void) +{ + return gBase; +} + + +void abCalcModeSetBase(abCalcModeIntBase base) +{ + if ((base >= abCalcModeIntBaseMin) && + (base < abCalcModeIntBaseMax)) { + gBase = base; + } +} + + +int abCalcModeGetIntWidth(void) +{ + return gIntWidth; +} + + +void abCalcModeSetIntWidth(int width) +{ + if ((width > 0) && + (width <= AB_CALC_EXPR_MAX_INT_WIDTH)) { + gIntWidth = width; + } +} diff --git a/abCalc/abCMode.h b/abCalc/abCMode.h new file mode 100644 index 0000000..31aa46e --- /dev/null +++ b/abCalc/abCMode.h @@ -0,0 +1,37 @@ +/* + abCMode.h + By: Jeremy Rand + */ + + +#ifndef ABCMODE_H +#define ABCMODE_H + + +#include "expr/abCExpr.h" + + +typedef enum abCalcModeIntBase +{ + abCalcModeIntBaseMin = 0, + abCalcModeBinBase = 0, + abCalcModeOctBase, + abCalcModeDecBase, + abCalcModeHexBase, + + abCalcModeIntBaseMax +} abCalcModeIntBase; + + +void abCalcModeInit(void); + +abCalcModeIntBase abCalcModeGetBase(void); + +void abCalcModeSetBase(abCalcModeIntBase base); + +int abCalcModeGetIntWidth(void); + +void abCalcModeSetIntWidth(int width); + + +#endif diff --git a/abCalc/abCStack.c b/abCalc/abCStack.c new file mode 100644 index 0000000..dc806b7 --- /dev/null +++ b/abCalc/abCStack.c @@ -0,0 +1,103 @@ +/* + abCStack.c + By: Jeremy Rand + */ + + +#include +#include +#include + +#include "abCStack.h" +#include "abCError.h" + + +abCalcExpr gStack[AB_CALC_STACK_DEPTH]; +static int gStackNumItems = 0; + + +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]); + memcpy(result, expr, sizeof(*expr)); + gStackNumItems++; + } + return result; +} + + +abCalcExpr *abCalcStackExprPop(abCalcExpr *expr) +{ + abCalcExpr *result = NULL; + + if (gStackNumItems < 1) + return NULL; + + gStackNumItems--; + + if (expr != NULL) { + result = expr; + memcpy(expr, &(gStack[gStackNumItems]), sizeof(*expr)); + } + + return result; +} + + +int abCalcStackNumItems(void) +{ + return gStackNumItems; +} + + +abCalcExpr *abCalcStackExprAt(int depth) +{ + abCalcExpr *result = NULL; + if (depth < gStackNumItems) { + result = &(gStack[gStackNumItems - 1 - depth]); + } + + return result; +} + + +char *abCalcStackExprStringAt(int depth, char *buffer, int addPrefix) +{ + static char tmpBuffer[AB_CALC_EXPR_STRING_MAX]; + + if (buffer == NULL) + return NULL; + + if (addPrefix) { + sprintf(buffer, "%3d: ", depth + 1); + } else { + buffer[0] = '\0'; + } + if (depth < gStackNumItems) { + if (abCalcFormatExpr(&(gStack[gStackNumItems - 1 - depth]), tmpBuffer) != NULL) { + strcat(buffer, tmpBuffer); + } + } + + return buffer; +} + + +void abCalcStackClear(void) +{ + gStackNumItems = 0; +} diff --git a/abCalc/abCStack.h b/abCalc/abCStack.h new file mode 100644 index 0000000..c62bc2c --- /dev/null +++ b/abCalc/abCStack.h @@ -0,0 +1,32 @@ +/* + abCStack.h + By: Jeremy Rand + */ + + +#ifndef ABCSTACK_H +#define ABCSTACK_H + + +#include "expr/abCExpr.h" + + +#define AB_CALC_STACK_DEPTH 128 + + +void abCalcStackInit(void); + +abCalcExpr *abCalcStackExprPush(abCalcExpr *expr); + +abCalcExpr *abCalcStackExprPop(abCalcExpr *expr); + +abCalcExpr *abCalcStackExprAt(int depth); + +char *abCalcStackExprStringAt(int depth, char *buffer, int addPrefix); + +int abCalcStackNumItems(void); + +void abCalcStackClear(void); + + +#endif diff --git a/abCalc/abCalc.c b/abCalc/abCalc.c new file mode 100644 index 0000000..6083b42 --- /dev/null +++ b/abCalc/abCalc.c @@ -0,0 +1,32 @@ +/* + abCalc.c + By: Jeremy Rand + */ + + +#include "abCMode.h" +#include "abCStack.h" +#include "abCError.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" + + +void abCalcInit(void) +{ + abCalcExprInit(); + abCalcExprRealInit(); + abCalcExprIntInit(); + + abCalcModeInit(); + abCalcStackInit(); + + abCalcOpInit(); + + abCalcErrorInit(); +} + + diff --git a/abCalc/abCalc.h b/abCalc/abCalc.h new file mode 100644 index 0000000..11f7f3c --- /dev/null +++ b/abCalc/abCalc.h @@ -0,0 +1,14 @@ +/* + abCalc.h + By: Jeremy Rand + */ + + +#ifndef ABCALC_H +#define ABCALC_H + + +void abCalcInit(void); + + +#endif diff --git a/abCalc/copydir/abCalcHelp b/abCalc/copydir/abCalcHelp new file mode 100644 index 0000000..1b9a5cb --- /dev/null +++ b/abCalc/copydir/abCalcHelp @@ -0,0 +1 @@ +Ass-Backwards Calculator Help: This document is split into the following sections: 1. Installation 2. UI Overview 3. Shell UI 4. A Bit About RPN 5. Number Formats 6. Operations 1. Installation: To install abCalc, drag the file abCalcNDA to the Desk.Accs folder in your System folder on your boot drive. After rebooting, you should find "abCalc" in the Apple menu in any GUI application on your Apple //GS. Alternatively, if you have the IR Finder extra installed, you can just double click abCalcNDA from the Finder whenever you want to launch it. If you reboot, you will have to double click it again to add it because it won't be loaded automatically on boot up. 2. UI Overview: The abCalc UI is split into the following major components: 1. The list at the top is the "stack" where the numbers you are working with will be displayed. The stack always displays at least four items, even if there are not four things on the stack. Each item on the stack is prefixed with a number which is its depth on the stack where "1:" is the label for the item at the top of the stack and "2:" is the number just below the top of the stack, etc. The number at the top of the stack is displayed at the bottom of the list (did I mention that the NDA is called the "Ass-Backwards Calculator"). Any non-empty row on the stack can be selected and you can do a copy operation on the row. The number on that row will be copied to the clipboard. 2. On the left side, directly below the stack is the entry box. This is where you can type in new numbers which go on the stack. You can actually do everything with abCalc with the keyboard. You can type in numbers or operations which manipulate the numbers on your stack. If you are typing in operations, you can type them in upper-case, lower-case or any mixture. abCalc does a case insensitive match for the operation. You can select text in the entry box and do the usual cut, copy and paste operations your selection. 3. On the right side, directly below the stack is a long list of the operations available in abCalc. The operations are sorted into an order which groups them into the following types: arithmetic, stack, trigonomety, exponentials and logical. You can scroll through the operations but be careful. Just clicking on an operation in the list will result in that operation being executed. So, items in the list operate both as a cheat sheet of the operations available and as a way to execute those operations. 4. Below the entry box is a series of buttons which make abCalc look just a bit like a classic calculator. You can use these buttons by clicking on them using your mouse or you can just type into the entry box directly. Whichever way you want to work. Note that the "+", "-", "x", "/" and "^" buttons do the same thing as their counterparts listed in the operation list. So you can add numbers in three ways: you can click the "+" button, you can click the "+" item in the operation list or you can type + followed by enter on your keyboard. The numbers 1 to 9 and letters A to F are there to allow you to enter numbers in both decimal and hexidecimal (hex numbers consist of numbers 1-9 and letters A-F). When you click them, the number or letter is inserted into the entry box. Similarly the period and # buttons insert those characters into the entry box. See number formats for the meaning the the # character. 3. Shell UI: Included with abCalcNDA is a shell EXE called abCalc which you can use from GNO/ME if you have that installed on your Apple //GS. It has all the functionality of the NDA. When you launch the command from the shell, you will see the stack printed and a prompt where you can enter your numbers and operations. You enter numbers the same way you would using the NDA. All of the operations are supported from the shell version as are supported from the NDA. So, to calculate "4 x 2", you would type 4 2 * . When you are done and want to leave abCalc, just type Ctrl-D. 4. A Bit About RPN: Let's talk about some more backward-ness. RPN stands for "Reverse Polish Notation" and it is a different way to write arithmetic expressions. People are used to things like "1 + 2" but in RPN, that would be "1 2 +". The way to think about this is "Put the number 1 on the stack, then put the number 2 on the stack, then execute the + operation which takes the last two numbers from the stack, adds them and puts the result back on the stack". So, if you wanted to calculate "1+2" on abCalc, you would type or click the following: "1 2 +". NOTE, you can actually avoid pressing the second if you click the + button or the + operation from the operation list. When you click a button which executes an operation or select an operation from the operation list, anything in the entry box is first pushed onto the stack. Then, it executes the operation you selected. This is just a small shortcut you can use. In my examples in this section, I will always include the unnecessary . You can do more complex calculations by combining operations together. Imagine you wanted to calculate "(1+2)*3". In abCalc, you would type or click the following: "1 2 + 3 *". But, what if you wanted "1+(2*3)". That is easy also: "1 2 3 * +". In general, abCalc has two fundamental types of operations: unary operations and binary operations. Addition and multiplication is a binary operation because it takes two items from the stack (two - thus binary) and pushes a single result back onto the stack. A unary operation takes a single number from the stack and pushes a single result back onto the stack. An example of a unary operation is SIN which calculates the sine of a number in radians. So, to calculate "sine(4)", you would type or click the follwing: "4 ". To calcuate "3*(sin(4-2))", you would type or click the following: "3 4 2 <-> <*>". Remember, you can click SIN from the operation list or you can type "sin" into the entry box to execute the sine operation. Operations use case insensitive matching so you can enter "Sin", "sin", "SIN" or even "SiN". Whatever you like. There are operations which are neither unary nor binary (like DROP, CLEAR and RCWS) and those are documented later. RPN may seem unnatural and "ass-backwards" but with practice, it can start to become second nature to the point where you may dread using a standard calculator. 5. Number Formats: abCalc operates on two types of numbers: real numbers and integer numbers. Real numbers are standard decimal numbers which may or may not have a fractional part. They may be expressed as an exponential number, like 6.283E15 which means "6.283 times 10 to the power of 15". The exponential can be negative for a very small number, like 4.712E-13 which means "4.712 times 10 to the power of minus 13". abCalc will automatically display very large or very small real numbers in exponential format. Entering negative real numbers and negative exponentials causes a minor problem in the calculator. The "-" character normally executes the subtract operation. There are some exceptions though. If the entry box is empty, pressing the "-" character will insert a minus character into the entry box. The calculator is assuming you want to enter a negative number. If you actually wanted the subtract operation, just press "" and the calculator will perform a subtract. If you have a positive or negative real number in the entry box followed by "E" or "e", then the calculator assumes you are entering an exponential number. If you then type "-" or hit the "-" button, it will insert a minus character after the "E". This allows you to enter negative exponents. If you have a number on the stack which you want to make negative, you probably want the CHS (change sign) operation. Integer numbers start with a "#" character. But before entering an integer, you need to know what base you are in and the bit width. By default, the calculator is in decimal mode and expects base 10 numbers. You can switch between bases by using the BIN (binary), OCT (octal), DEC (decimal) and HEX (hexadecimal) operations. The integer number you enter is interpreted using that base so if you are not sure, you may want to execute the specific base you intend to use. After the "#" character comes a series of 0's and 1's when entering a binary number. Or numbers from 0 to 7 for an octal number. In decimal mode, you would enter digits from 0 to 9. And in hexadecimal, the digits are the numbers from 0 to 9 and letters A through F. The letters can be entered in lower or uppercase when entering a hexadecimal number. An integer on the stack has the "#" prefix but also has a suffix to tell you the current base. The suffix is "b" for binary, "o" for octal, "d" for decimal and "h" for hexadecimal. This entry and display format is often used in HP RPN calculators which abCalc somewhat mimics. Other than the base, the other thing to be aware of with integer numbers is the current word size. By default, the calculator manipulates 32 bit integers. That means you can enter an integer from #00000000h to $FFFFFFFFh. But you can use the STWS operation to specify a different word size for your integers. If you want to work with 16 bit integers, push the real number "16" onto the stack and execute STWS. You can set the word size to any value from 1 to 32. All operations which manipulate integers respect that word size. So, if you rotate the bits in your integer to the left, then the high bit according to the current word size is rotated into the low bit. This way, if you want to do 8 bit math, 16 bit math or even 5 bit math, it is just a matter of setting your word size. There are two shortcuts when entering integers. Regardless of the current base, you can always enter a hex number by prefixing it with a "$" character. So, you can enter the hex number 42 by entering "$42" even if you happen to be in decimal mode. Also, you can use C like syntax and enter the hex number as "0x42". Note that C syntax for octal numbers does not work. The octal number 42 in C would be represented as "042" but that cannot be distinguished from the real number 42 with a leading zero. So, these shortcuts only work for hex numbers. Note that you can use the R2B and B2R operations to convert real numbers to integers and integer numbers to real numbers respectively. 6. Operations: All of these operations can be entered directly into the entry box or selected from the operation list on the right side of the UI. The descriptions below are grouped into a series of related operations. Arithmetic Operations: +: The add operation takes two numbers from the stack and pushes the sum of those two numbers. The operation works with two real numbers and pushes a real number result. It also works with two integer numbers and pushes ain integer result. And you can add a real number and an integer number. When you add a real and integer number, the real number is converted to an integer in the current word size and then those two numbers are added. The result is an integer number. -: The subtract operation takes two numbers from the stack and pushes the difference of those two numbers. To calculate "4 - 2", you would push 4, then 2 and then do the subtract. The operation works with two real numbers and pushes a real number result. It also works with two integer numbers and pushes an integer result. And you can subtract a real number and an integer number. When you subtract a real and integer number, the real number is converted to an integer in the current word size and then those two numbers are subtracted. The result is an integer number. *: The multiply operation takes two numbers from the stack and pushes the product of those two numbers. To calculate "4 x 2", you would push 4, then 2 and then do the multiply. The operation works with two real numbers and pushes a real number result. It also works with two integer numbers and pushes an integer result. And you can multiple a real number and an integer number. When you multiply a real and integer number, the real number is converted to an integer in the current word size and then those two numbers are multiplied. The result is an integer number. /: The divide operation takes two numbers from the stack and pushes the ratio of those two numbers. To calculate "4 / 2", you would push 4, then 2 and then do the divide. The operation works with two real numbers and pushes a real number result. It also works with two integer numbers and pushes an integer result. And you can divide a real number and an integer number. When you divide a real and integer number, the real number is converted to an integer in the current word size and then those two numbers are divided. The result is an integer number. CHS: The CHS operation stands for "CHange Sign". It takes a single real number from the stack and returns a real number with the opposite sign. Effectively it multiplies its argument by minus one. This operation does not work with integer numbers. INV: The INV operation is short for "INVerse". It takes a single real number from the stack and returns a real number which is the reciprocal of that number. Effectively it calculates "1 / x" where "x" is the number it pulls from the stack. This operation does not work with integer numbers. SQ: The SQ operation is short for "SQuare". It takes a single real number from the stack and returns a real number which is the square of that number. Effectively, it calculates "x * x" where "x" is the number it pulls from the stack. This operation does not work with integer numbers. SQRT: The SQRT operation is short for "SQuare RooT". It takes a single real number from the stack and returns a real number which is the square root of that number. Effectively, it calculates "x ^ 0.5" where "x" is the number it pulls from the stack. This operation does not work with integer numbers. ^: The power operation takes two numbers from the stack and pushes the result. To calculate "4 ^ 2", you would push 4, then 2 and then do the power operation. The operation works with two real numbers and pushes a real number result. This operation does not work with integer numbers. Stack Operations: DROP: This operation just pops the item off the top of the stack. It does not matter if the value is a real number or integer number. SWAP: This operation pops the two items off the tops of the stack and pushes them back onto the stack in reverse order. CLEAR: This operation removes all items from the stack. Trigonometry Operations: PI: This operation pushes the value of pi onto the stack as a real number. SIN: This operation takes a real number from the top of the stack and calculates the sine of that number as an angle in radians and pushes the result back onto the stack as a real number. This operation does not work with integer numbers. COS: This operation takes a real number from the top of the stack and calculates the cosine of that number as an angle in radians and pushes the result back onto the stack as a real number. This operation does not work with integer numbers. TAN: This operation takes a real number from the top of the stack and calculates the tangent of that number as an angle in radians and pushes the result back onto the stack as a real number. This operation does not work with integer numbers. ASIN: This operation takes a real number from the top of the stack and calculates the inverse sine of that number and pushes the result back onto the stack as an angle in radians. This operation does not work with integer numbers. ACOS: This operation takes a real number from the top of the stack and calculates the inverse cosine of that number and pushes the result back onto the stack as an angle in radians. This operation does not work with integer numbers. ATAN: This operation takes a real number from the top of the stack and calculates the inverse tangent of that number and pushes the result back onto the stack as an angle in radians. This operation does not work with integer numbers. Exponential Operations: LOG: This operation takes a real number from the top of the stack and calculates the base ten logarithm of that number and pushes the result back onto the stack. This operation does not work with integer numbers. ALOG: This operation takes a real number from the top of the stack and calculates ten to the power of that number and pushes the result back onto the stack. This operation is the inverse of the LOG operation. This operation does not work with integer numbers. LN: This operation takes a real number from the top of the stack and calculates the base e logarithm of that number and pushes that result back onto the stack. This operation does not work with integer numbers. EXP: This operation takes a real number from the top of the stack and calculates e to the power of that number and pushes that result back onto the stack. This operation is the inverse of the LN operation. This operation does not work with integer numbers. SINH: This operation takes a real number from the top of the stack and calculates the hyperbolic sine of that number and pushes that result back onto the stack. This operation does not work with integer numbers. COSH: This operation takes a real number from the top of the stack and calculates the hyperbolic cosine of that number and pushes that result back onto the stack. This operation does not work with integer numbers. TANH: This operation takes a real number from the top of the stack and calculates the hyperbolic tangent of that number and pushes that result back onto the stack. This operation does not work with integer numbers. Logical Operations: R2B: This operation takes a real number from the stack and converts it to an integer given the current word size. The converted number is pushed onto the stack. B2R: This operation takes a integer number from the stack and converts it to a real number. The converted number is pushed onto the stack. AND: This operation takes two integer numbers from the top of the stack and pushes the logical and of those two numbers back onto the stack as an integer number. This operation does not work with real numbers. OR: This operation takes two integer numbers from the top of the stack and pushes the logical or of those two numbers back onto the stack as an integer number. This operation does not work with real numbers. XOR: This operation takes two integer numbers from the top of the stack and pushes the logical exclusive or of those two numbers back onto the stack as an integer number. This operation does not work with real numbers. NOT: This operation takes a single integer number from the top of the stack and pushes an integer result with each bit inverted (0 to 1, 1 to 0). This operation does not work with real numbers. SL: This operation takes a single integer number from the top of the stack and shifts each bit one position to the left, inserting a 0 bit at the low bit position. The high bit (as determined by the word size) is lost. This operation is basically like multiplying by two. This operation does not work with real numbers. RL: This operation takes a single integer number from the top of the stack and rotates each bit one position to the left and pushes the result back onto the stack. The high bit (as determined by the word size) becomes the bit at the low bit position. This operation does not work with real numbers. SR: This operation takes a single integer number from the top of the stack and shifts each bit one position to the right, inserting a 0 bit at the high bit position (as determined by the word size). The bit at the low bit position is lost. This operation is basically like dividing by two. This operation does not work with real numbers. RR: This operation takes a single integer number from the top of the stack and rotates each bit one position to the right and pushes the result back onto the stack. This low bit becomes the bit at the high bit position (as determined by the word size). This operation does not work with real numbers. ASR: This operation takes a single integer number from the top of the stack and shifts each bit one position to the right. However, the high bit (as determined by the word size) is preserved so if it was a 1, it remains a 1. This operation is basically like dividing by two where the high bit represents a sign bit. This operation does not work with real numbers. BIN: This operation takes no values from the stack and pushes nothing onto the stack. It sets the default integer base size to binary. Any integers on the stack will be displayed in binary format after executing this operation. When entering an integer, the calculator will expect a binary number. OCT: This operation takes no values from the stack and pushes nothing onto the stack. It sets the default integer base size to octal. Any integers on the stack will be displayed in octal format after executing this operation. When entering an integer, the calculator will expect an octal number. DEC: This operation takes no values from the stack and pushes nothing onto the stack. It sets the default integer base size to decimal. Any integers on the stack will be displayed in decimal format after executing this operation. When entering an integer, the calculator will expect a decimal number. HEX: This operation takes no values from the stack and pushes nothing onto the stack. It sets the default integer base size to hexadecimal. Any integers on the stack will be displayed in hexadecimal format after executing this operation. When entering an integer, the calculator will expect a hexadecimal number. STWS: This operation takes a single real number from the stack and pushes nothing onto the stack. The real number should be between 1 and 32 and have no fractional part. The value becomes the new word size used for integers. So, if you want to do 16 bit integer math, you would push 16 onto the stack and then execute the STWS operation. RCWS: This operation takes no values from the stack and pushes a single real number onto the stack. The real number is between 1 and 32 and is the current word size used for integers. Use the STWS operation to change the word size. \ No newline at end of file diff --git a/abCalc/expr/abCExpReal.c b/abCalc/expr/abCExpReal.c new file mode 100644 index 0000000..77d9bc5 --- /dev/null +++ b/abCalc/expr/abCExpReal.c @@ -0,0 +1,217 @@ +/* + abCExpReal.c + By: Jeremy Rand + */ + + +#include +#include +#include +#include + +#include "expr/abCExpr.h" + + +static abCalcExpr *abCalcExprRealParse(abCalcExpr *expr, char *buffer); +static char *abCalcExprRealFormat(abCalcExpr *expr, char *buffer); + + +static abCalcExprCallbacks gRealCallbacks = { + abCalcExprRealParse, + abCalcExprRealFormat +}; + + +void abCalcExprRealInit(void) +{ + abCalcRegisterExprType(abCalcExprTypeReal, &gRealCallbacks); +} + + +abCalcExpr *abCalcExprRealParse(abCalcExpr *expr, char *buffer) +{ + int offset; + int expOffset = -1; + int periodOffset = -1; + int len; + int numOffset = -1; + + /* First validate */ + if (buffer == NULL) + return NULL; + + if (expr == NULL) + return NULL; + + len = strlen(buffer); + + for (offset = 0; offset < len; offset++) { + switch (buffer[offset]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + numOffset = offset; + break; + + case '.': + if (periodOffset != -1) + return NULL; + if (expOffset != -1) + return NULL; + periodOffset = offset; + break; + + case '-': + if (offset == 0) + break; + /* Fallthrough */ + case '+': + if ((expOffset == -1) || + ((expOffset + 1) != offset)) + return NULL; + break; + + case 'e': + case 'E': + if (expOffset != -1) + return NULL; + expOffset = offset; + numOffset = -1; + break; + + default: + return NULL; + } + } + + if (numOffset == -1) + return NULL; + + expr->type = abCalcExprTypeReal; + expr->u.real = atof(buffer); + return expr; +} + + +char *abCalcExprRealFormat(abCalcExpr *expr, char *buffer) +{ + abCalcRealType exp; + abCalcRealType value; + static char format[16]; + int numDecDigits; + int periodPos = -1; + int zerosStart = -1; + int spaceStart = -1; + int expPos = -1; + int len; + int i; + + if (expr == NULL) + return NULL; + + if (buffer == NULL) + return NULL; + + if (expr->type != abCalcExprTypeReal) + return NULL; + + value = expr->u.real; + + if (value == 0.0) { + exp = 0.0; + } else { + exp = floor(log10(fabs(value))); + } + + if (exp >= 0) + exp++; + + if ((exp > 12) || + (exp < -12)) { + strcpy(format, "%-25.11E"); + } else if (exp <= -2) { + double shiftedValue = value * 1.0e12; + if (shiftedValue == floor(shiftedValue)) { + strcpy(format, "%-18.12f"); + } else { + strcpy(format, "%-25.11E"); + } + } else { + int numDecDigits = (int)(12 - exp); + if (numDecDigits > 12) { + numDecDigits = 12; + } + sprintf(format, "%%-28.%df", numDecDigits); + } + + sprintf(buffer, format, value); + len = strlen(buffer); + + for (i = 0; i < len; i++) { + switch (buffer[i]) { + case '.': + periodPos = i; + break; + + case '0': + if (expPos != -1) { + break; + } + if ((periodPos != -1) && + (zerosStart == -1)) { + if (periodPos == i - 1) { + zerosStart = periodPos; + } else { + zerosStart = i; + } + } + break; + case 'E': + expPos = i; + break; + case ' ': + spaceStart = i; + break; + default: + if (expPos == -1) + zerosStart = -1; + break; + } + if (spaceStart != -1) + break; + } + + if (spaceStart != -1) { + buffer[spaceStart] = '\0'; + len = spaceStart; + } + + if (zerosStart != -1) { + if (expPos != -1) { + memmove(&buffer[zerosStart], &buffer[expPos], len - expPos + 1); + len = expPos - zerosStart; + } + else { + buffer[zerosStart] = '\0'; + } + } + + return buffer; +} + + +void abCalcExprRealSet(abCalcExpr *expr, abCalcRealType value) +{ + if (expr == NULL) + return; + + expr->type = abCalcExprTypeReal; + expr->u.real = value; +} diff --git a/abCalc/expr/abCExpReal.h b/abCalc/expr/abCExpReal.h new file mode 100644 index 0000000..8bf5888 --- /dev/null +++ b/abCalc/expr/abCExpReal.h @@ -0,0 +1,17 @@ +/* + abCExpReal.h + By: Jeremy Rand + */ + + +#ifndef ABCEXPREAL_H +#define ABCEXPREAL_H + + +struct abCalcExpr; + +void abCalcExprRealInit(void); + +void abCalcExprRealSet(struct abCalcExpr *expr, abCalcRealType value); + +#endif diff --git a/abCalc/expr/abCExpr.c b/abCalc/expr/abCExpr.c new file mode 100644 index 0000000..495951b --- /dev/null +++ b/abCalc/expr/abCExpr.c @@ -0,0 +1,61 @@ +/* + abCExpr.c + By: Jeremy Rand + */ + + +#include + +#include "expr/abCExpr.h" + + +static abCalcExprCallbacks *gCallbacks[abCalcExprTypeMax]; + + +#define AB_CALC_EXPR_TYPE_INVALID(type) (((type) < abCalcExprTypeMin) || ((type) >= abCalcExprTypeMax)) + +void abCalcExprInit(void) +{ + abCalcExprType type; + + for (type = abCalcExprTypeMin; type < abCalcExprTypeMax; type++) { + gCallbacks[type] = NULL; + } +} + + +void abCalcRegisterExprType(abCalcExprType type, abCalcExprCallbacks *callbacks) +{ + if (AB_CALC_EXPR_TYPE_INVALID(type)) + return; + + gCallbacks[type] = callbacks; +} + + +abCalcExpr *abCalcParseExpr(abCalcExpr *expr, char *buffer) +{ + abCalcExpr *result = NULL; + abCalcExprType type; + + for (type = abCalcExprTypeMin; type < abCalcExprTypeMax; type++) { + if (gCallbacks[type] != NULL) { + result = (gCallbacks[type]->parseExpr)(expr, buffer); + if (result != NULL) + return result; + } + } + return result; +} + + +char *abCalcFormatExpr(abCalcExpr *expr, char *buffer) +{ + if (AB_CALC_EXPR_TYPE_INVALID(expr->type)) + return NULL; + + if (gCallbacks[expr->type] == NULL) + return NULL; + + return (gCallbacks[expr->type]->formatExpr(expr, buffer)); +} diff --git a/abCalc/expr/abCExpr.h b/abCalc/expr/abCExpr.h new file mode 100644 index 0000000..029298c --- /dev/null +++ b/abCalc/expr/abCExpr.h @@ -0,0 +1,51 @@ +/* + abCExpr.h + By: Jeremy Rand + */ + + +#ifndef ABCEXPR_H +#define ABCEXPR_H + + +typedef enum abCalcExprType { + abCalcExprTypeMin = 0, + abCalcExprTypeReal = 0, + abCalcExprTypeInt, + + abCalcExprTypeMax +} abCalcExprType; + + +typedef double abCalcRealType; +typedef unsigned long abCalcIntType; + + +#define AB_CALC_EXPR_MAX_INT_WIDTH ((sizeof(abCalcIntType) * 8)) + +#define AB_CALC_EXPR_STRING_MAX (AB_CALC_EXPR_MAX_INT_WIDTH + 8) + + +typedef struct abCalcExpr { + abCalcExprType type; + union { + abCalcRealType real; + abCalcIntType integer; + } u; +} abCalcExpr; + + +typedef struct abCalcExprCallbacks { + abCalcExpr * (*parseExpr)(abCalcExpr *expr, char *buffer); + char * (*formatExpr)(abCalcExpr *expr, char *buffer); +} abCalcExprCallbacks; + + +void abCalcExprInit(void); +void abCalcRegisterExprType(abCalcExprType type, abCalcExprCallbacks *callbacks); + +abCalcExpr *abCalcParseExpr(abCalcExpr *expr, char *buffer); +char *abCalcFormatExpr(abCalcExpr *expr, char *buffer); + + +#endif diff --git a/abCalc/expr/abCExprInt.c b/abCalc/expr/abCExprInt.c new file mode 100644 index 0000000..48aa390 --- /dev/null +++ b/abCalc/expr/abCExprInt.c @@ -0,0 +1,272 @@ +/* + abCExprInt.c + By: Jeremy Rand + */ + + +#include +#include +#include + +#include "abCMode.h" + +#include "expr/abCExpr.h" + + +static abCalcExpr *abCalcExprIntParse(abCalcExpr *expr, char *buffer); +static char *abCalcExprIntFormat(abCalcExpr *expr, char *buffer); + + +static abCalcExprCallbacks gIntCallbacks = { + abCalcExprIntParse, + abCalcExprIntFormat +}; + + +void abCalcExprIntInit(void) +{ + abCalcRegisterExprType(abCalcExprTypeInt, &gIntCallbacks); +} + + +abCalcExpr *abCalcExprIntParse(abCalcExpr *expr, char *buffer) +{ + abCalcModeIntBase base = abCalcModeGetBase(); + abCalcIntType value = 0; + int len; + int offset = 1; + + if (buffer == NULL) + return NULL; + + if (expr == NULL) + return NULL; + + len = strlen(buffer); + if (len < 2) + return NULL; + + if (buffer[0] == '$') { + base = abCalcModeHexBase; + } else if ((buffer[0] == '0') && + (buffer[1] == 'x')) { + base = abCalcModeHexBase; + offset = 2; + } else if (buffer[0] != '#') + return NULL; + + switch (base) { + case abCalcModeBinBase: + for ( ; offset < len; offset++) { + value <<= 1; + switch (buffer[offset]) { + case '1': + value++; + break; + + case '0': + break; + + default: + return NULL; + } + } + break; + + case abCalcModeOctBase: + for ( ; offset < len; offset++) { + value <<= 3; + switch (buffer[offset]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + value += (buffer[offset] - '0');; + break; + + default: + return NULL; + } + } + break; + + case abCalcModeDecBase: + for ( ; offset < len; offset++) { + value *= 10; + switch (buffer[offset]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + value += (buffer[offset] - '0');; + break; + + default: + return NULL; + } + } + break; + + case abCalcModeHexBase: + for ( ; offset < len; offset++) { + value <<= 4; + switch (buffer[offset]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + value += (buffer[offset] - '0');; + break; + + case 'a': + case 'A': + value += 10; + break; + + case 'b': + case 'B': + value += 11; + break; + + case 'c': + case 'C': + value += 12; + break; + + case 'd': + case 'D': + value += 13; + break; + + case 'e': + case 'E': + value += 14; + break; + + case 'f': + case 'F': + value += 15; + break; + + default: + return NULL; + } + } + break; + + default: + return NULL; + } + + expr->type = abCalcExprTypeInt; + expr->u.integer = value; + return expr; +} + + +char *abCalcExprIntFormat(abCalcExpr *expr, char *buffer) +{ + abCalcModeIntBase base = abCalcModeGetBase(); + int width = abCalcModeGetIntWidth(); + abCalcIntType value; + char *ptr; + int gotFirstOne; + int i; + + if (expr == NULL) + return NULL; + + if (buffer == NULL) + return NULL; + + if (expr->type != abCalcExprTypeInt) + return NULL; + + value = expr->u.integer; + + if (width < AB_CALC_EXPR_MAX_INT_WIDTH) { + value &= ((1l << width) - 1); + } + + switch (base) { + case abCalcModeBinBase: + gotFirstOne = 0; + ptr = buffer; + *ptr = '#'; + ptr++; + + for (i = width - 1; i >= 0; i--) { + if ((value >> i) & 1) { + *ptr = '1'; + ptr++; + gotFirstOne = 1; + } else { + if (gotFirstOne) { + *ptr = '0'; + ptr++; + } + } + } + if (!gotFirstOne) { + *ptr = '0'; + ptr++; + } + *ptr = ' '; + ptr++; + *ptr = 'b'; + ptr++; + *ptr = '\0'; + break; + + case abCalcModeOctBase: + sprintf(buffer, "#%lo o", value); + break; + + case abCalcModeDecBase: + sprintf(buffer, "#%lu d", value); + break; + + case abCalcModeHexBase: + sprintf(buffer, "#%lX h", value); + break; + + default: + return NULL; + } + + return buffer; +} + + +void abCalcExprIntSet(abCalcExpr *expr, abCalcIntType value) +{ + int width; + + if (expr == NULL) + return; + + width = abCalcModeGetIntWidth(); + + expr->type = abCalcExprTypeInt; + expr->u.integer = value; + + if (width < AB_CALC_EXPR_MAX_INT_WIDTH) { + expr->u.integer &= ((1l << width) - 1); + } +} diff --git a/abCalc/expr/abCExprInt.h b/abCalc/expr/abCExprInt.h new file mode 100644 index 0000000..7d08525 --- /dev/null +++ b/abCalc/expr/abCExprInt.h @@ -0,0 +1,19 @@ +/* + abCExprInt.h + By: Jeremy Rand + */ + + +#ifndef ABCEXPRINT_H +#define ABCEXPRINT_H + + +struct abCalcExpr; + + +void abCalcExprIntInit(void); + +void abCalcExprIntSet(struct abCalcExpr *expr, abCalcIntType value); + + +#endif diff --git a/abCalc/make/config.txt b/abCalc/make/config.txt new file mode 100644 index 0000000..143956e --- /dev/null +++ b/abCalc/make/config.txt @@ -0,0 +1,46 @@ +# GSplus configuration file version 0.13 + +s5d1 = +s5d2 = + +s6d1 = +s6d2 = + +s7d1 = ../abCalcNDA.2mg + +g_limit_speed = 0 + + +bram1[00] = 00 00 00 01 00 00 0d 06 02 01 01 00 01 00 00 00 +bram1[10] = 00 00 07 06 02 01 01 00 00 00 0f 06 06 00 05 06 +bram1[20] = 01 00 00 00 00 00 00 01 00 00 00 00 03 02 02 02 +bram1[30] = 00 00 00 00 00 00 00 00 08 00 01 02 03 04 05 06 +bram1[40] = 07 0a 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d +bram1[50] = 0e 0f ff ff ff ff ff ff ff 00 ff ff ff ff ff 81 +bram1[60] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[70] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[80] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[90] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[a0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[b0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[c0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[d0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[e0] = ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +bram1[f0] = ff ff ff ff ff ff ff ff ff ff ff ff 52 06 f8 ac + +bram3[00] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[10] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[20] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[30] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[40] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[50] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[60] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[70] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[80] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[90] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[a0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[b0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[c0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[d0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[e0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +bram3[f0] = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/abCalc/make/createDiskImage b/abCalc/make/createDiskImage new file mode 100755 index 0000000..8808c32 --- /dev/null +++ b/abCalc/make/createDiskImage @@ -0,0 +1,109 @@ +#!/bin/sh + +set -x + +MOUNTDIR=/tmp/a2gs_mount.$$ +TMPDISKIMAGE=/tmp/a2gs_diskimage_$$.2mg +TEMPLATEDISKIMAGE=make/system601.2mg + +if [ $# -lt 3 ] +then + echo USAGE: $0 diskimage file directory + exit 1 +fi + +DISKIMAGE="$1" +shift + +FILE="$1" +shift + +DISKIMAGEDEST="$1" +shift +DEST="${MOUNTDIR}/${DISKIMAGEDEST}" + +COPYDIRS=$* + +cleanupAndExit() +{ + umount "$MOUNTDIR" 2> /dev/null + rm -f "$TMPDISKIMAGE" 2> /dev/null + rm -f "$DISKIMAGE" 2> /dev/null + rmdir "$MOUNTDIR" 2> /dev/null + exit 1 +} + +if [ ! -f "$TEMPLATEDISKIMAGE" ] +then + echo Unable to find the template disk image, $TEMPLATEDISKIMAGE + cleanupAndExit +fi + +cp "$TEMPLATEDISKIMAGE" "$TMPDISKIMAGE" +if [ $? != 0 ] +then + echo Unable to copy template disk image. + cleanupAndExit +fi + +mkdir "$MOUNTDIR" +if [ $? != 0 ] +then + echo Unable to create the mount directory. + cleanupAndExit +fi + +profuse -orw "$TMPDISKIMAGE" "$MOUNTDIR" +if [ $? != 0 ] +then + echo Unable to mount the disk image. + cleanupAndExit +fi + +cp "$FILE" "$DEST" +if [ $? != 0 ] +then + echo Unable to copy the file to the disk image. + cleanupAndExit +fi + +OLDDIR=`pwd` +for COPYDIR in $COPYDIRS +do + cd "$COPYDIR" + if [ $? != 0 ] + then + echo Unable to find $COPYDIR + cleanupAndExit + fi + + find . -print | while read FILEORDIR + do + if [ -d "$FILEORDIR" ] + then + mkdir -p "${MOUNTDIR}/$FILEORDIR" + elif [ -f "$FILEORDIR" ] + then + cp "$FILEORDIR" "${MOUNTDIR}/$FILEORDIR" + fi + done + cd "$OLDDIR" +done + +umount "$MOUNTDIR" +if [ $? != 0 ] +then + echo Unable to unmount the disk image. + cleanupAndExit +fi + +cp "$TMPDISKIMAGE" "$DISKIMAGE" +if [ $? != 0 ] +then + echo Unable to copy the disk image to the destination. + cleanupAndExit +fi + +rm -f "$TMPDISKIMAGE" +rmdir "$MOUNTDIR" +exit 0 diff --git a/abCalc/make/head.mk b/abCalc/make/head.mk new file mode 100644 index 0000000..189ae91 --- /dev/null +++ b/abCalc/make/head.mk @@ -0,0 +1,52 @@ +# +# head.mk +# + +ORCA_HOME := $(HOME)/orca + +ORCA_BINDIR = /usr/local/bin + +export ORCA=$(ORCA_BINDIR)/orca + +AC=make/AppleCommander.jar + +TARGETTYPE=shell + +SRCDIRS=. + +COMPILE=make/orca-cc +CFLAGS= -P -I +ROOTCFILE=main.c +DEFINES= +INCLUDE_PATHS= + +REZ=make/orca-rez +REZFLAGS= + +MACGEN=make/orca-macgen +MACGENFLAGS=-P +MACGENMACROS=13/ORCAInclude/m= + +ASSEMBLE=make/orca-asm +ASMFLAGS=-P + +LINK=$(ORCA) link +LDFLAGS=-P + +CHTYP=$(ORCA) chtyp + +RM=rm -f +CP=cp + +GSPLUS=/Applications/GSplus.app/Contents/MacOS/gsplus +GSPORT=/Applications/GSport/GSport.app/Contents/MacOS/GSport + +export GSPLUS +export GSPORT + + +.PHONY: all gen genclean + +all: + @make gen + @make build diff --git a/abCalc/make/launchEmulator b/abCalc/make/launchEmulator new file mode 100755 index 0000000..49f7ff5 --- /dev/null +++ b/abCalc/make/launchEmulator @@ -0,0 +1,29 @@ +#!/bin/sh + +if [ ! -z "$GSPLUS" ] && [ -x "$GSPLUS" ] +then + EMULATORPATH="$GSPLUS" +elif [ ! -z "$GSPORT" ] && [ -x "$GSPORT" ] +then + EMULATORPATH="$GSPORT" +fi + +if [ -z "$EMULATORPATH" ] +then + echo Unable to find GSplus or GSport at these locations. + echo " GSPLUS=$GSPLUS" + echo " GSPORT=$GSPORT" + exit 1 +fi + +cd make + +# This magic ensure that clicking stop in Xcode results in the emulator terminating. + +$EMULATORPATH & +PID=$! + +trap 'kill $PID' SIGTERM SIGINT SIGHUP EXIT +wait + +exit 0 diff --git a/abCalc/make/orca-asm b/abCalc/make/orca-asm new file mode 100755 index 0000000..cb73ce9 --- /dev/null +++ b/abCalc/make/orca-asm @@ -0,0 +1,18 @@ +#!/bin/bash + +FILENAME="$1" +shift + +if echo $FILENAME | grep -v '\.s$' > /dev/null +then + echo Expected first argument to be a *.s file but got $FILENAME + exit 1 +fi + +DIRNAME=`dirname $FILENAME` +BASENAME=`basename $FILENAME .s` + +cd "$DIRNAME" +$ORCA assemble $* keep="${BASENAME}" "${BASENAME}.s" +RESULT=$? +exit $RESULT diff --git a/abCalc/make/orca-cc b/abCalc/make/orca-cc new file mode 100755 index 0000000..6e7df1e --- /dev/null +++ b/abCalc/make/orca-cc @@ -0,0 +1,66 @@ +#!/bin/bash + +TMPFILE=/tmp/orca-cc.$$ + +FILENAME="$1" +shift + +if echo $FILENAME | grep -v '\.c$' > /dev/null +then + echo Expected first argument to be a *.c file but got $FILENAME + exit 1 +fi + +CCARGS="" +COMPILEARGS="" +for ARG in $* +do + if echo $ARG | grep '^-[id]' > /dev/null + then + CCARGS="$CCARGS cc=$ARG" + else + COMPILEARGS="$COMPILEARGS $ARG" + fi +done + +BASENAME=`echo $FILENAME | sed 's/\.c$//'` +DEPSNAME="${BASENAME}.d" +OBJSNAME="${BASENAME}.a" +ROOTNAME="${BASENAME}.root" + +$ORCA --trace-gsos compile $COMPILEARGS "$FILENAME" keep="${BASENAME}" $CCARGS 2> $TMPFILE +RESULT=$? + +sed '/^[A-Za-z][A-Za-z]*(.*)$/d' $TMPFILE >&2 + +if [ "$RESULT" -ne 0 ] +then + rm -f $TMPFILE + rm -f $OBJSNAME + rm -f $ROOTNAME + exit $RESULT +fi + +DEPS=`awk ' + /^FastFileLoad/ { + sub(/^FastFileLoad\(/, ""); + sub(/\)$/, ""); + print}' $TMPFILE | sort -u | while read FILE + do + if [ -f "$FILE" ] + then + echo $FILE + fi + done | tr '\012' ' '` + +rm -f $TMPFILE + +# We add a dependency for both the .o and the .root file. If this is the +# main.c file being compiled, we need the dependency on the .root file. +cat > $DEPSNAME << EOF +$OBJSNAME: $DEPS + +$ROOTNAME: $DEPS +EOF + +exit 0 diff --git a/abCalc/make/orca-macgen b/abCalc/make/orca-macgen new file mode 100755 index 0000000..6afcdc8 --- /dev/null +++ b/abCalc/make/orca-macgen @@ -0,0 +1,50 @@ +#!/bin/bash + +TMPFILE=/tmp/orca-macgen.$$ + +MACGENFLAGS="$1" +FILENAME="$2" +shift +shift + +if echo $FILENAME | grep -v '\.s$' > /dev/null +then + echo Expected second argument to be a *.s file but got $FILENAME + exit 1 +fi + +BASENAME=`echo $FILENAME | sed 's/\.s$//'` +MACROSNAME="${BASENAME}.macros" +DEPSNAME="${MACROSNAME}.d" + +$ORCA --trace-gsos macgen $MACGENFLAGS "$FILENAME" $* < /dev/null 2> $TMPFILE +RESULT=$? + +sed '/^[A-Za-z][A-Za-z]*(.*)$/d' $TMPFILE >&2 + +if [ "$RESULT" -ne 0 ] +then + rm -f $TMPFILE + rm -f $MACROSNAME + exit $RESULT +fi + +DEPS=`awk ' + /^FastFileLoad/ { + sub(/^FastFileLoad\(/, ""); + sub(/\)$/, ""); + print}' $TMPFILE | sort -u | while read FILE + do + if [ -f "$FILE" ] + then + echo $FILE + fi + done | tr '\012' ' '` + +rm -f $TMPFILE + +cat > $DEPSNAME << EOF +$MACROSNAME: $DEPS +EOF + +exit 0 diff --git a/abCalc/make/orca-rez b/abCalc/make/orca-rez new file mode 100755 index 0000000..da6c137 --- /dev/null +++ b/abCalc/make/orca-rez @@ -0,0 +1,45 @@ +#!/bin/bash + +TMPFILE=/tmp/orca-rez.$$ + +FILENAME="$1" +shift + +if echo $FILENAME | grep -v '\.rez$' > /dev/null +then + echo Expected first argument to be a *.rez file but got $FILENAME + exit 1 +fi + +BASENAME=`echo $FILENAME | sed 's/\.rez$//'` +DEPSNAME="${BASENAME}.rez.d" +OBJSNAME="${BASENAME}.r" + +$ORCA --trace-gsos compile $* keep="${OBJSNAME}" "$FILENAME" 2> $TMPFILE +RESULT=$? + +sed '/^[A-Za-z][A-Za-z]*(.*)$/d' $TMPFILE >&2 + +if [ "$RESULT" -ne 0 ] +then + rm -f $TMPFILE + rm -f $OBJSNAME + exit $RESULT +fi + +DEPS=`awk ' + /^FastFileLoad/ { + sub(/^FastFileLoad\(/, ""); + sub(/\)$/, ""); + print}' $TMPFILE | sort -u | while read FILE + do + if [ -f "$FILE" ] + then + echo $FILE + fi + done` + +echo $OBJSNAME: $DEPS > $DEPSNAME +rm -f $TMPFILE + +exit 0 diff --git a/abCalc/make/system601.2mg b/abCalc/make/system601.2mg new file mode 100644 index 0000000..394d3a2 Binary files /dev/null and b/abCalc/make/system601.2mg differ diff --git a/abCalc/make/tail.mk b/abCalc/make/tail.mk new file mode 100644 index 0000000..c7be210 --- /dev/null +++ b/abCalc/make/tail.mk @@ -0,0 +1,155 @@ +# +# tail.mk +# + +export PATH := $(PATH):$(ORCA_BIN) + +CWD=$(shell pwd) + +DISKIMAGE=$(PGM).2mg +BUILDTARGET=$(DISKIMAGE) +EXECTARGET=executeGUI +DISKIMAGEDEST=. + +ifeq ($(TARGETTYPE),shell) + FILETYPE=exe + EXECTARGET=executeShell + BUILDTARGET=$(PGM) +else ifeq ($(TARGETTYPE),desktop) + FILETYPE=s16 +else ifeq ($(TARGETTYPE),cda) + FILETYPE=cda + DISKIMAGEDEST=System/Desk.Accs +else ifeq ($(TARGETTYPE),cdev) + BINTARGET=$(PGM).bin + FILETYPE=199 + DISKIMAGEDEST=System/CDevs +else ifeq ($(TARGETTYPE),nba) + FILETYPE=exe + BUILDTARGET=$(PGM) +else ifeq ($(TARGETTYPE),nda) + FILETYPE=nda + DISKIMAGEDEST=System/Desk.Accs +else ifeq ($(TARGETTYPE),xcmd) + FILETYPE=exe + BUILDTARGET=$(PGM) +endif + +ifeq ($(wildcard $(ROOTCFILE)),) + ROOTCFILE= +endif + +C_ROOTS=$(ROOTCFILE:.c=.root) +C_SRCS+=$(filter-out $(ROOTCFILE), $(patsubst ./%, %, $(wildcard $(addsuffix /*.c, $(SRCDIRS))))) +C_OBJS=$(C_SRCS:.c=.a) +C_DEPS=$(ROOTCFILE:.c=.d) $(C_SRCS:.c=.d) + +ASM_SRCS=$(patsubst ./%, %, $(wildcard $(addsuffix /*.s, $(SRCDIRS)))) +ASM_MACROS=$(ASM_SRCS:.s=.macros) +ASM_DEPS=$(ASM_SRCS:.s=.macros.d) +ASM_ROOTS=$(ASM_SRCS:.s=.ROOT) +ASM_OBJS=$(ASM_SRCS:.s=.a) + +REZ_SRCS=$(patsubst ./%, %, $(wildcard $(addsuffix /*.rez, $(SRCDIRS)))) +REZ_DEPS=$(REZ_SRCS:.rez=.rez.d) +REZ_OBJS=$(REZ_SRCS:.rez=.r) + +ifneq ($(firstword $(REZ_SRCS)), $(lastword $(REZ_SRCS))) + $(error Only a single resource file supported, found $(REZ_SRCS)) +endif + +BUILD_OBJS=$(C_ROOTS) $(C_OBJS) $(ASM_ROOTS) +ifeq ($(BINTARGET),) + BUILD_OBJS+=$(REZ_OBJS) +endif +BUILD_OBJS_NOSUFFIX=$(C_ROOTS:.root=) $(C_OBJS:.a=) $(ASM_ROOTS:.ROOT=) + +ALL_OBJS=$(C_ROOTS:.root=.a) $(C_OBJS) $(ASM_OBJS) $(REZ_OBJS) +ALL_ROOTS=$(C_ROOTS) $(C_OBJS:.a=.root) $(ASM_ROOTS) +ALL_DEPS=$(C_DEPS) $(ASM_DEPS) $(REZ_DEPS) + +EXECCMD= + +.PHONY: build execute executeShell executeGUI clean + +.PRECIOUS: $(ASM_MACROS) + +build: $(BUILDTARGET) + +clean: genclean + $(RM) "$(PGM)" $(BINTARGET) + $(RM) $(ALL_OBJS) + $(RM) $(ALL_ROOTS) + $(RM) $(ALL_DEPS) + $(RM) $(ASM_MACROS) + $(RM) "$(DISKIMAGE)" + +createPackage: + pkg/createPackage + +cleanMacCruft: + rm -rf pkg + + +ifeq ($(BINTARGET),) + +# This is a standard build where we generate the resources if any and then link +# the binary over that same file creating the resource fork first and the data +# fork second. +$(PGM): $(BUILD_OBJS) +ifneq ($(REZ_OBJS),) + $(RM) $(PGM) + $(CP) $(REZ_OBJS) $(PGM) +endif + $(LINK) $(LDFLAGS) $(BUILD_OBJS_NOSUFFIX) --keep=$(PGM) + $(CHTYP) -t $(FILETYPE) $(PGM) + +else + +# This is a special build for CDevs (maybe others also?) where we build the binary +# into a $(PGM).bin file and then build the resources into the $(PGM) target. The +# resource compile will read the $(PGM).bin binary and load it into the resources +# also. +$(BINTARGET): $(BUILD_OBJS) + $(LINK) $(LDFLAGS) $(BUILD_OBJS_NOSUFFIX) --keep=$(BINTARGET) + +$(REZ_OBJS): $(BINTARGET) + +$(PGM): $(REZ_OBJS) + $(RM) $(PGM) + $(CP) $(REZ_OBJS) $(PGM) + $(CHTYP) -t $(FILETYPE) $(PGM) + +endif + +$(DISKIMAGE): $(PGM) + make/createDiskImage "$(DISKIMAGE)" "$(PGM)" "$(DISKIMAGEDEST)" $(COPYDIRS) + +execute: $(EXECTARGET) + +executeGUI: all + make/launchEmulator -doit + +executeShell: all + $(ORCA) ./$(PGM) + +%.a: %.c + $(COMPILE) $< $(CFLAGS) --noroot + +%.root: %.c + $(COMPILE) $< $(CFLAGS) + +%.macros: %.s + $(MACGEN) "$(MACGENFLAGS)" $< $@ $(MACGENMACROS) + +%.ROOT: %.macros + $(ASSEMBLE) $(<:.macros=.s) $(ASMFLAGS) + +%.r: %.rez + $(REZ) $< $(REZFLAGS) + +$(OBJS): Makefile + +# Include the C and rez dependencies which were generated from the last build +# so we recompile correctly on .h file changes. +-include $(ALL_DEPS) diff --git a/abCalc/nda.mk b/abCalc/nda.mk new file mode 100644 index 0000000..c5d71eb --- /dev/null +++ b/abCalc/nda.mk @@ -0,0 +1,99 @@ +# +# Makefile +# Apple //GS Build Engine for ORCA +# + +include make/head.mk + +# Customize this file to control what kind of project you are working on, +# where to find files, etc. + +# The name of your system or binary file to build goes here: +PGM=abCalcNDA + +# Set the target type you would like to build. The options are: +# shell - A shell command for ORCA, GNO or other GS shell +# desktop - A full desktop application +# cda - A classic desk accessory +# cdev - A control panel device +# nba - A HyperStudio new button action +# nda - A new desk accessory +# xcmd - A HyperCard XCMD or XCFN +# +# TARGETTYPE=shell +# TARGETTYPE=desktop +# TARGETTYPE=cda +# TARGETTYPE=cdev +# TARGETTYPE=nba +TARGETTYPE=nda +# TARGETTYPE=xcmd + +# Add any other directories where you are putting C or assembly source +# files to this list: +# SRCDIRS+= +SRCDIRS+=nda expr ops + +# If you put your main entry point for your project in a file called main.c +# Then you don't need to change this value. If you want to call your entry +# point something other than main.c, set this variable to point to this file. +ROOTCFILE=nda/abCalcNDA.c + +# Add any arguments you want passed to the C compiler to this variable: +CFLAGS+=-dABCALC_GSOS + +# Add any arguments you want passed to the resource compiler to this variable: +REZFLAGS+= + +# Add any arguments you want passed to the macro generator to this variable: +MACGENFLAGS+= + +# Add any other macro libraries to include in this variable: +MACGENMACROS+= + +# Add any arguments you want passed to the assembler to this variable: +ASMFLAGS+= + +# Add any arguments you want passed to the linker to this variable: +LDFLAGS+= + +# Uncomment the following line if you want to build against the GNO libraries +# export ORCA=$(ORCA_BINDIR)/gno + +# If you want to copy one or more files or directories to the target disk +# image, add the root directory to this variable. Any directories under +# the source directory which don't exist in the target disk image will be +# created. All files will be copied from the source to the target using +# the same path from the source. +# +# For example, if you set COPYDIRS to dir and in your project you have +# the following files: +# dir/System/mySystemFile +# dir/newDir/anotherFile +# Then, during the copy phase, mySystemFile will be copied into the System +# folder and a folder newDir will be created and anotherFile will be copied +# into there. +COPYDIRS=copydir + +# By default, the build expects that you have GSplus in the path: +# /Applications/GSplus.app/Contents/MacOS/gsplus +# If you have it in a different location, specify that here. +# GSPLUS=/Applications/GSplus.app/Contents/MacOS/gsplus + +# By default, the build expects that you have GSport in the path: +# /Applications/GSport/GSport.app/Contents/MacOS/GSport +# If you have it in a different location, specify that here. +# GSPORT=/Applications/GSport/GSport.app/Contents/MacOS/GSport + +# Add any rules you want to execute before any compiles or assembly +# commands are called here, if any. You can generate .c, .s or .h +# files for example. You can generate data files. Whatever you +# might need. +gen: + +# For any files you generated in the gen target above, you should +# add rules in genclean to remove those generated files when you +# clean your build. +genclean: + +# Do not change anything else below here... +include make/tail.mk diff --git a/abCalc/nda/abCalcNDA.c b/abCalc/nda/abCalcNDA.c new file mode 100644 index 0000000..815bb8e --- /dev/null +++ b/abCalc/nda/abCalcNDA.c @@ -0,0 +1,764 @@ +/* + abCalcNDA.c + By: Jeremy Rand + */ + + +#pragma nda NDAOpen NDAClose NDAAction NDAInit -1 0xFFFF " abCalc\\H**" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nda/abCalcNDA.h" +#include "abCalc.h" +#include "abCStack.h" +#include "abCError.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" + + +#define MIN_STACK_ITEMS 4 + +void UpdateStack(void); + + +typedef struct listElement { + char *memPtr; + Byte memFlag; +} listElement; + + +static BOOLEAN gListStarted = FALSE; +static Handle gSANEDirectPage = NULL; + +static BOOLEAN gCalcActive = FALSE; +static GrafPortPtr gCalcWinPtr = NULL; +static unsigned int gUserId; +static unsigned int gResourceId; +listElement *gOpList = NULL; +listElement gStackList[AB_CALC_STACK_DEPTH]; +abCalcExpr gNDAExpr; + +static Str255 gStrBuf; +static int gSelectedStackItem = -1; + +char *gBuffer = NULL; + + +void NDAClose(void) +{ + int i; + + if (gCalcActive) { + CloseWindow(gCalcWinPtr); + gCalcWinPtr = NULL; + gCalcActive = FALSE; + } + + if (gBuffer != NULL) { + free(gBuffer); + gBuffer = NULL; + } + + if (gOpList != NULL) { + free(gOpList); + gOpList = NULL; + } + + for (i = 0; i < AB_CALC_STACK_DEPTH; i++) { + if (gStackList[i].memPtr != NULL) { + free(gStackList[i].memPtr); + gStackList[i].memPtr = NULL; + } + } + + CloseResourceFile(gResourceId); + ResourceShutDown(); +} + + +void NDAInit(int code) +{ + int i; + + if (code) { + gCalcActive = FALSE; + gUserId = MMStartUp(); + + if (!ListStatus()) { + LoadOneTool(0x1c, 0); + ListStartUp(); + gListStarted = TRUE; + } + + if (!SANEStatus()) { + LoadOneTool(0x0a, 0); + gSANEDirectPage = NewHandle(256, gUserId, + attrBank | attrFixed | attrLocked | attrPage, NULL); + SANEStartUp((Word) *gSANEDirectPage); + } + + abCalcInit(); + + for (i = 0; i < AB_CALC_STACK_DEPTH; i++) { + gStackList[i].memPtr = NULL; + } + } else { + if (gSANEDirectPage) { + SANEShutDown(); + DisposeHandle(gSANEDirectPage); + UnloadOneTool(0x0a); + gSANEDirectPage = NULL; + } + + if (gListStarted) { + ListShutDown(); + UnloadOneTool(0x1c); + gListStarted = FALSE; + } + } +} + + +#pragma databank 1 +void DrawContents(void) +{ + PenNormal(); + DrawControls(GetPort()); +} +#pragma databank 0 + + +GrafPortPtr NDAOpen(void) +{ + Pointer pathToSelf; + unsigned int oldResourceApp; + LevelRecGS levelDCB; + unsigned int oldLevel; + SysPrefsRecGS prefsDCB; + unsigned int oldPrefs; + int numOps; + int i; + Handle opListCtl; + + if (gCalcActive) + return NULL; + + oldResourceApp = GetCurResourceApp(); + ResourceStartUp(gUserId); + pathToSelf = LGetPathname2(gUserId, 1); + + levelDCB.pCount = 2; + GetLevelGS(&levelDCB); + oldLevel = levelDCB.level; + levelDCB.level = 0; + SetLevelGS(&levelDCB); + + prefsDCB.pCount = 1; + GetSysPrefsGS(&prefsDCB); + oldPrefs = prefsDCB.preferences; + prefsDCB.preferences = (prefsDCB.preferences & 0x1fff) | 0x8000; + SetSysPrefsGS(&prefsDCB); + + gResourceId = OpenResourceFile(readEnable, NULL, pathToSelf); + + gCalcWinPtr = NewWindow2("\p abCalc ", 0, DrawContents, NULL, refIsResource, + abCalcWinNum, rWindParam1); + + SetSysWindow(gCalcWinPtr); + ShowWindow(gCalcWinPtr); + SelectWindow(gCalcWinPtr); + SetPort(gCalcWinPtr); + + if (gOpList == NULL) { + numOps = abCalcOpNumOps(); + gOpList = malloc(sizeof(*gOpList) * numOps); + for (i = 0; i < numOps; i++) { + gOpList[i].memPtr = abCalcOpNth(i)->name; + gOpList[i].memFlag = 0; + } + } + + opListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcOpList); + NewList2(NULL, 1, (Ref)gOpList, 0, numOps, opListCtl); + + UpdateStack(); + + gCalcActive = TRUE; + + prefsDCB.preferences = oldPrefs; + SetSysPrefsGS(&prefsDCB); + + levelDCB.level = oldLevel; + SetLevelGS(&levelDCB); + + SetCurResourceApp(oldResourceApp); + + return gCalcWinPtr; +} + + +void UpdateStack(void) +{ + Handle stackListCtl; + int i; + int numToDisplay = abCalcStackNumItems(); + + if (numToDisplay < MIN_STACK_ITEMS) { + numToDisplay = MIN_STACK_ITEMS; + } + + stackListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcStackList); + + for (i = numToDisplay - 1; i >= 0; i--) { + if (gStackList[i].memPtr == NULL) { + gStackList[i].memPtr = malloc(AB_CALC_EXPR_STRING_MAX + 8); + } + abCalcStackExprStringAt(numToDisplay - i - 1, gStackList[i].memPtr, + TRUE); + gStackList[i].memFlag = 0; + } + + NewList2(NULL, numToDisplay - 3, (Ref)gStackList, 0, numToDisplay, stackListCtl); + gSelectedStackItem = -1; +} + + +BOOLEAN ErrorRaised(void) +{ + char *errorString = abCalcGetError(); + if (errorString == NULL) { + return FALSE; + } + + AlertWindow(awCString+awResource, (Pointer)&errorString, abCalcErrorAlert); + + abCalcClearError(); + return TRUE; +} + + +void PushCalcEntry(CtlRecHndl entryBox) +{ + abCalcOp *op; + + GetLETextByID(gCalcWinPtr, abCalcEntryBox, &gStrBuf); + + if (gStrBuf.textLength > 0) { + gStrBuf.text[gStrBuf.textLength] = '\0'; + + op = abCalcOpLookup(gStrBuf.text); + + if (op != NULL) { + op->execute(); + } else if (abCalcParseExpr(&gNDAExpr, gStrBuf.text) != NULL) { + abCalcStackExprPush(&gNDAExpr); + } else { + LERecHndl leHandle; + + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LESetSelect(0, gStrBuf.textLength, leHandle); + abCalcRaiseError(abCalcSyntaxError, NULL); + return; + } + + gStrBuf.textLength = 0; + SetLETextByID(gCalcWinPtr, abCalcEntryBox, &gStrBuf); + } +} + + +void ExecCalcCmd(char *cmd) +{ + abCalcOp *op = abCalcOpLookup(cmd); + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + + PushCalcEntry(entryBox); + + if ((!ErrorRaised()) && + (op != NULL)) { + op->execute(); + } + + ErrorRaised(); + + UpdateStack(); +} + + +void InsertChar(CtlRecHndl entryBox, char ch) +{ + LERecHndl leHandle; + + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LEDelete(leHandle); + LEInsert(&ch, 1, leHandle); +} + + +void ExecMinusButton(void) +{ + int i; + char aChar; + BOOLEAN doCmd = FALSE; + BOOLEAN dotSeen = FALSE; + + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + GetLETextByID(gCalcWinPtr, abCalcEntryBox, &gStrBuf); + + if (gStrBuf.textLength > 0) { + doCmd = TRUE; + + gStrBuf.text[gStrBuf.textLength] = '\0'; + + aChar = gStrBuf.text[gStrBuf.textLength - 1]; + if (((aChar == 'e') || + (aChar == 'E')) && + (gStrBuf.textLength > 1)) { + doCmd = FALSE; + for (i = 0; i < gStrBuf.textLength - 1; i++) { + switch (gStrBuf.text[i]) { + case '-': + if (i != 0) { + doCmd = TRUE; + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + + case '.': + if (dotSeen) { + doCmd = TRUE; + } else { + dotSeen = TRUE; + } + break; + + default: + doCmd = TRUE; + break; + } + if (doCmd) + break; + } + } + } + + if (doCmd) { + ExecCalcCmd("-"); + } else { + InsertChar(entryBox, '-'); + } + + return; +} + + +void HandleEntryBox(void) +{ + Handle stackListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcStackList); + if (gSelectedStackItem != -1) { + ResetMember2(stackListCtl); + DrawMember2(gSelectedStackItem, stackListCtl); + gSelectedStackItem = -1; + } +} + + +void HandleStackClick(void) +{ + Handle stackListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcStackList); + int nthOp; + int numStackItems = abCalcStackNumItems(); + int numDisplayed = numStackItems; + int selectedStackItem = -1; + + nthOp = NextMember2(0, stackListCtl); + if (nthOp == gSelectedStackItem) { + ResetMember2(stackListCtl); + DrawMember2(gSelectedStackItem, stackListCtl); + gSelectedStackItem = -1; + nthOp = NextMember2(0, stackListCtl); + } + if (nthOp == 0) + return; + + if (numDisplayed < MIN_STACK_ITEMS) + numDisplayed = MIN_STACK_ITEMS; + + selectedStackItem = numDisplayed + 1 - nthOp; + + if (selectedStackItem > numStackItems) { + ResetMember2(stackListCtl); + DrawMember2(nthOp, stackListCtl); + gSelectedStackItem = -1; + } else { + gSelectedStackItem = nthOp; + } +} + + +void HandleOpClick(void) +{ + Handle opListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcOpList); + int nthOp = ResetMember2(opListCtl); + abCalcOp *op; + + if (nthOp > 0) { + nthOp--; + + op = abCalcOpNth(nthOp); + if (op != NULL) { + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + PushCalcEntry(entryBox); + + if (!ErrorRaised()) { + op->execute(); + } + + ErrorRaised(); + + UpdateStack(); + } + + DrawMember2(nthOp + 1, opListCtl); + } +} + + +void HandleControl(EventRecord *event) +{ + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + SetPort(gCalcWinPtr); + + switch (event->wmTaskData4) { + case abCalcBtn0: + InsertChar(entryBox, '0'); + break; + + case abCalcBtn1: + InsertChar(entryBox, '1'); + break; + + case abCalcBtn2: + InsertChar(entryBox, '2'); + break; + + case abCalcBtn3: + InsertChar(entryBox, '3'); + break; + + case abCalcBtn4: + InsertChar(entryBox, '4'); + break; + + case abCalcBtn5: + InsertChar(entryBox, '5'); + break; + + case abCalcBtn6: + InsertChar(entryBox, '6'); + break; + + case abCalcBtn7: + InsertChar(entryBox, '7'); + break; + + case abCalcBtn8: + InsertChar(entryBox, '8'); + break; + + case abCalcBtn9: + InsertChar(entryBox, '9'); + break; + + case abCalcBtnEnter: + PushCalcEntry(entryBox); + ErrorRaised(); + UpdateStack(); + break; + + case abCalcBtnDot: + InsertChar(entryBox, '.'); + break; + + case abCalcBtnNum: + InsertChar(entryBox, '#'); + break; + + case abCalcBtnAdd: + ExecCalcCmd("+"); + break; + + case abCalcBtnSub: + ExecMinusButton(); + break; + + case abCalcBtnMult: + ExecCalcCmd("*"); + break; + + case abCalcBtnDiv: + ExecCalcCmd("/"); + break; + + case abCalcBtnPow: + ExecCalcCmd("^"); + break; + + case abCalcBtnA: + InsertChar(entryBox, 'A'); + break; + + case abCalcBtnB: + InsertChar(entryBox, 'B'); + break; + + case abCalcBtnC: + InsertChar(entryBox, 'C'); + break; + + case abCalcBtnD: + InsertChar(entryBox, 'D'); + break; + + case abCalcBtnE: + InsertChar(entryBox, 'E'); + break; + + case abCalcBtnF: + InsertChar(entryBox, 'F'); + break; + + case abCalcEntryBox: + HandleEntryBox(); + break; + + case abCalcStackList: + HandleStackClick(); + break; + + case abCalcOpList: + HandleOpClick(); + break; + } +} + + +void DoCut(void) +{ + LERecHndl leHandle; + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LECut(leHandle); + LEToScrap(); +} + + +void DoCopy(void) +{ + Handle stackListCtl = (Handle)GetCtlHandleFromID(gCalcWinPtr, abCalcStackList); + LERecHndl leHandle; + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + + int numStackItems = abCalcStackNumItems(); + int numDisplayed = numStackItems; + int selectedStackItem; + + if (gSelectedStackItem == -1) { + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LECopy(leHandle); + LEToScrap(); + return; + } + + if (numDisplayed < MIN_STACK_ITEMS) + numDisplayed = MIN_STACK_ITEMS; + + selectedStackItem = numDisplayed - gSelectedStackItem; + + if (gBuffer == NULL) { + gBuffer = malloc(AB_CALC_EXPR_STRING_MAX); + } + + if ((selectedStackItem >= 0) && + (selectedStackItem < numStackItems) && + (abCalcStackExprStringAt(selectedStackItem, gBuffer, FALSE) != NULL)) { + ZeroScrap(); + PutScrap(strlen(gBuffer), textScrap, gBuffer); + } + + SetPort(gCalcWinPtr); + ResetMember2(stackListCtl); + DrawMember2(gSelectedStackItem, stackListCtl); + gSelectedStackItem = -1; +} + + +void DoPaste(void) +{ + LERecHndl leHandle; + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LEFromScrap(); + LEPaste(leHandle); +} + + +void DoClear(void) +{ + LERecHndl leHandle; + CtlRecHndl entryBox = GetCtlHandleFromID(gCalcWinPtr, abCalcEntryBox); + + HLock((Handle)entryBox); + leHandle = (LERecHndl)(*entryBox)->ctlData; + HUnlock((Handle)entryBox); + + LEDelete(leHandle); +} + + +void HandleMenu(int menuItem) +{ + SetPort(gCalcWinPtr); + + switch (menuItem) { + case cutAction: + DoCut(); + break; + + case copyAction: + DoCopy(); + break; + + case pasteAction: + DoPaste(); + break; + + case clearAction: + DoClear(); + break; + + default: + break; + } +} + + +void HandleKey(EventRecord *event) +{ + BOOLEAN appleKeyPressed = ((event->modifiers & appleKey) != 0); + char key = (event->message & 0xff); + + if (!appleKeyPressed) + return; + + switch (key) { + case 'C': + case 'c': + DoCopy(); + break; + + case 'X': + case 'x': + DoCut(); + break; + + case 'V': + case 'v': + DoPaste(); + break; + } +} + + +BOOLEAN NDAAction(EventRecord *sysEvent, int code) +{ + int event; + static EventRecord localEvent; + unsigned int eventCode; + BOOLEAN result = FALSE; + + switch (code) { + case runAction: + return result; + + case eventAction: + BlockMove((Pointer)sysEvent, (Pointer)&localEvent, 16); + localEvent.wmTaskMask = 0x001FFFFF; + eventCode = TaskMasterDA(0, &localEvent); + switch(eventCode) { + case updateEvt: + BeginUpdate(gCalcWinPtr); + DrawContents(); + EndUpdate(gCalcWinPtr); + break; + + case wInControl: + HandleControl(&localEvent); + break; + + case keyDownEvt: + case autoKeyEvt: + HandleKey(&localEvent); + break; + } + break; + + case cutAction: + case copyAction: + case pasteAction: + case clearAction: + result = TRUE; + HandleMenu(code); + break; + } + + return result; +} diff --git a/abCalc/nda/abCalcNDA.h b/abCalc/nda/abCalcNDA.h new file mode 100644 index 0000000..b383cc6 --- /dev/null +++ b/abCalc/nda/abCalcNDA.h @@ -0,0 +1,115 @@ +/* */ +/* abCalcNDA.defs */ +/* By: Jeremy Rand */ +/* */ + +#define abCalcWinNum 1001 +#define abCalcLinedColors 1002 + +#define abCalcControlList 1003 + + +#define abCalcBtn0 2001 +#define abCalcBtn0Str 2002 + +#define abCalcBtn1 2003 +#define abCalcBtn1Str 2004 + +#define abCalcBtn2 2005 +#define abCalcBtn2Str 2006 + +#define abCalcBtn3 2007 +#define abCalcBtn3Str 2008 + +#define abCalcBtn4 2009 +#define abCalcBtn4Str 2010 + +#define abCalcBtn5 2011 +#define abCalcBtn5Str 2012 + +#define abCalcBtn6 2013 +#define abCalcBtn6Str 2014 + +#define abCalcBtn7 2015 +#define abCalcBtn7Str 2016 + +#define abCalcBtn8 2017 +#define abCalcBtn8Str 2018 + +#define abCalcBtn9 2019 +#define abCalcBtn9Str 2020 + +#define abCalcBtnEnter 2021 +#define abCalcBtnEnterStr 2022 + +#define abCalcBtnDot 2023 +#define abCalcBtnDotStr 2024 + +#define abCalcBtnNum 2025 +#define abCalcBtnNumStr 2026 + +#define abCalcBtnAdd 2027 +#define abCalcBtnAddStr 2028 + +#define abCalcBtnSub 2029 +#define abCalcBtnSubStr 2030 + +#define abCalcBtnMult 2031 +#define abCalcBtnMultStr 2032 + +#define abCalcBtnDiv 2033 +#define abCalcBtnDivStr 2034 + +#define abCalcBtnA 2035 +#define abCalcBtnAStr 2036 + +#define abCalcBtnB 2037 +#define abCalcBtnBStr 2038 + +#define abCalcBtnC 2039 +#define abCalcBtnCStr 2040 + +#define abCalcBtnD 2041 +#define abCalcBtnDStr 2042 + +#define abCalcBtnE 2043 +#define abCalcBtnEStr 2044 + +#define abCalcBtnF 2045 +#define abCalcBtnFStr 2046 + +#define abCalcBtnPow 2047 +#define abCalcBtnPowStr 2048 + +#define abCalcEntryBox 3001 +#define abCalcStackList 3002 +#define abCalcOpList 3003 + +#define abCalcErrorAlert 4001 + + +#define abCalcWinX 10 +#define abCalcWinY 25 +#define abCalcWinWidth 300 +#define abCalcWinHeight 170 + +#define abCalcBtnSpaceX 5 +#define abCalcBtnSpaceY 2 +#define abCalcBtnWidth 39 +#define abCalcBtnHeight 14 + +#define abCalcBtnRow0 abCalcWinHeight-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow1 abCalcBtnRow0-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow2 abCalcBtnRow1-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow3 abCalcBtnRow2-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow4 abCalcBtnRow3-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow5 abCalcBtnRow4-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow6 abCalcBtnRow5-abCalcBtnSpaceY-abCalcBtnHeight +#define abCalcBtnRow7 abCalcBtnRow6-abCalcBtnSpaceY-abCalcBtnHeight + +#define abCalcBtnCol0 abCalcBtnSpaceX +#define abCalcBtnCol1 abCalcBtnCol0+abCalcBtnSpaceX+abCalcBtnWidth +#define abCalcBtnCol2 abCalcBtnCol1+abCalcBtnSpaceX+abCalcBtnWidth +#define abCalcBtnCol3 abCalcBtnCol2+abCalcBtnSpaceX+abCalcBtnWidth + +#define abCalcOpCol abCalcBtnCol3+abCalcBtnSpaceX+abCalcBtnWidth diff --git a/abCalc/nda/abCalcNDA.rez b/abCalc/nda/abCalcNDA.rez new file mode 100644 index 0000000..84d1598 --- /dev/null +++ b/abCalc/nda/abCalcNDA.rez @@ -0,0 +1,462 @@ +/* */ +/* abCalcNDA.h */ +/* By: Jeremy Rand */ +/* */ + + +#include "types.rez" +#include "nda/abCalcNda.h" + + +resource rWindParam1 (abCalcWinNum) { + $C0A5, /* wFrameBits */ + nil, /* wTitle */ + 0, /* wRefCon */ + {0,0,0,0}, /* ZoomRect */ + abCalcLinedColors, /* wColor ID */ + {0,0}, /* Origin */ + {0,0}, /* data size */ + {0,0}, /* max height-width */ + {0,0}, /* scroll ver hors */ + {0,0}, /* page ver horiz */ + 0, /* winfoRefcon */ + 0, /* wInfoHeight */ + {abCalcWinY,abCalcWinX,abCalcWinY+abCalcWinHeight,abCalcWinX+abCalcWinWidth}, /* wposition */ + infront, /* wPlane */ + abCalcControlList, /* wStorage */ + $0809 /* wInVerb */ +}; + + +resource rWindColor (abCalcLinedColors) { + 0x0000, /* frameColor */ + 0x0F00, /* titleColor */ + 0x020F, /* tbarColor */ + 0xF0F0, /* growColor */ + 0x00F0, /* infoColor */ +}; + + +resource rControlList (abCalcControlList) { + { + abCalcBtn0, + abCalcBtn1, + abCalcBtn2, + abCalcBtn3, + abCalcBtn4, + abCalcBtn5, + abCalcBtn6, + abCalcBtn7, + abCalcBtn8, + abCalcBtn9, + abCalcBtnEnter, + abCalcBtnDot, + abCalcBtnNum, + abCalcBtnAdd, + abCalcBtnSub, + abCalcBtnMult, + abCalcBtnDiv, + abCalcBtnPow, + abCalcBtnA, + abCalcBtnB, + abCalcBtnC, + abCalcBtnD, + abCalcBtnE, + abCalcBtnF, + abCalcEntryBox, + abCalcStackList, + abCalcOpList + } +}; + + +resource rControlTemplate (abCalcBtn0) { + abCalcBtn0, + {abCalcBtnRow0, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn0Str, + 0, + {"0","",0,0} + }}; +}; +resource rPString (abCalcBtn0Str, noCrossBank) { "0" }; + +resource rControlTemplate (abCalcBtnDot) { + abCalcBtnDot, + {abCalcBtnRow0, abCalcBtnCol1, abCalcBtnRow0+abCalcBtnHeight, abCalcBtnCol1+abCalcBtnWidth}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnDotStr, + 0, + {".","",0,0} + }}; +}; +resource rPString (abCalcBtnDotStr, noCrossBank) { "." }; + +resource rControlTemplate (abCalcBtnNum) { + abCalcBtnNum, + {abCalcBtnRow0, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnNumStr, + 0, + {"#","",0,0} + }}; +}; +resource rPString (abCalcBtnNumStr, noCrossBank) { "#" }; + +resource rControlTemplate (abCalcBtn1) { + abCalcBtn1, + {abCalcBtnRow1, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn1Str, + 0, + {"1","",0,0} + }}; +}; +resource rPString (abCalcBtn1Str, noCrossBank) { "1" }; + +resource rControlTemplate (abCalcBtn2) { + abCalcBtn2, + {abCalcBtnRow1, abCalcBtnCol1, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn2Str, + 0, + {"2","",0,0} + }}; +}; +resource rPString (abCalcBtn2Str, noCrossBank) { "2" }; + +resource rControlTemplate (abCalcBtn3) { + abCalcBtn3, + {abCalcBtnRow1, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn3Str, + 0, + {"3","",0,0} + }}; +}; +resource rPString (abCalcBtn3Str, noCrossBank) { "3" }; + +resource rControlTemplate (abCalcBtn4) { + abCalcBtn4, + {abCalcBtnRow2, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn4Str, + 0, + {"4","",0,0} + }}; +}; +resource rPString (abCalcBtn4Str, noCrossBank) { "4" }; + +resource rControlTemplate (abCalcBtn5) { + abCalcBtn5, + {abCalcBtnRow2, abCalcBtnCol1, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn5Str, + 0, + {"5","",0,0} + }}; +}; +resource rPString (abCalcBtn5Str, noCrossBank) { "5" }; + +resource rControlTemplate (abCalcBtn6) { + abCalcBtn6, + {abCalcBtnRow2, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn6Str, + 0, + {"6","",0,0} + }}; +}; +resource rPString (abCalcBtn6Str, noCrossBank) { "6" }; + +resource rControlTemplate (abCalcBtn7) { + abCalcBtn7, + {abCalcBtnRow3, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn7Str, + 0, + {"7","",0,0} + }}; +}; +resource rPString (abCalcBtn7Str, noCrossBank) { "7" }; + +resource rControlTemplate (abCalcBtn8) { + abCalcBtn8, + {abCalcBtnRow3, abCalcBtnCol1, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn8Str, + 0, + {"8","",0,0} + }}; +}; +resource rPString (abCalcBtn8Str, noCrossBank) { "8" }; + +resource rControlTemplate (abCalcBtn9) { + abCalcBtn9, + {abCalcBtnRow3, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtn9Str, + 0, + {"9","",0,0} + }}; +}; +resource rPString (abCalcBtn9Str, noCrossBank) { "9" }; + +resource rControlTemplate (abCalcBtnEnter) { + abCalcBtnEnter, + {abCalcBtnRow4, abCalcBtnCol0, abCalcBtnRow4+abCalcBtnHeight, abCalcBtnCol2+abCalcBtnWidth}, + SimpleButtonControl {{ + $0003, + $3002, + 0, + abCalcBtnEnterStr, + 0, + {"\n","",0,0} + }}; +}; +resource rPString (abCalcBtnEnterStr, noCrossBank) { "Enter" }; + +resource rControlTemplate (abCalcBtnPow) { + abCalcBtnPow, + {abCalcBtnRow4, abCalcBtnCol3, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnPowStr, + 0, + {"^","",0,0} + }}; +}; +resource rPString (abCalcBtnPowStr, noCrossBank) { "^" }; + +resource rControlTemplate (abCalcBtnAdd) { + abCalcBtnAdd, + {abCalcBtnRow0, abCalcBtnCol3, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnAddStr, + 0, + {"+","",0,0} + }}; +}; +resource rPString (abCalcBtnAddStr, noCrossBank) { "+" }; + +resource rControlTemplate (abCalcBtnSub) { + abCalcBtnSub, + {abCalcBtnRow1, abCalcBtnCol3, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnSubStr, + 0, + {"-","",0,0} + }}; +}; +resource rPString (abCalcBtnSubStr, noCrossBank) { "-" }; + +resource rControlTemplate (abCalcBtnMult) { + abCalcBtnMult, + {abCalcBtnRow2, abCalcBtnCol3, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnMultStr, + 0, + {"*","",0,0} + }}; +}; +resource rPString (abCalcBtnMultStr, noCrossBank) { "x" }; + +resource rControlTemplate (abCalcBtnDiv) { + abCalcBtnDiv, + {abCalcBtnRow3, abCalcBtnCol3, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnDivStr, + 0, + {"/","",0,0} + }}; +}; +resource rPString (abCalcBtnDivStr, noCrossBank) { "/" }; + +resource rControlTemplate (abCalcBtnA) { + abCalcBtnA, + {abCalcBtnRow5, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnAStr, + 0, + {"A","",0,0} + }}; +}; +resource rPString (abCalcBtnAStr, noCrossBank) { "A" }; + +resource rControlTemplate (abCalcBtnB) { + abCalcBtnB, + {abCalcBtnRow5, abCalcBtnCol1, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnBStr, + 0, + {"B","",0,0} + }}; +}; +resource rPString (abCalcBtnBStr, noCrossBank) { "B" }; + +resource rControlTemplate (abCalcBtnC) { + abCalcBtnC, + {abCalcBtnRow5, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnCStr, + 0, + {"C","",0,0} + }}; +}; +resource rPString (abCalcBtnCStr, noCrossBank) { "C" }; + +resource rControlTemplate (abCalcBtnD) { + abCalcBtnD, + {abCalcBtnRow6, abCalcBtnCol0, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnDStr, + 0, + {"D","",0,0} + }}; +}; +resource rPString (abCalcBtnDStr, noCrossBank) { "D" }; + +resource rControlTemplate (abCalcBtnE) { + abCalcBtnE, + {abCalcBtnRow6, abCalcBtnCol1, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnEStr, + 0, + {"E","",0,0} + }}; +}; +resource rPString (abCalcBtnEStr, noCrossBank) { "E" }; + +resource rControlTemplate (abCalcBtnF) { + abCalcBtnF, + {abCalcBtnRow6, abCalcBtnCol2, 0, 0}, + SimpleButtonControl {{ + $0002, + $3002, + 0, + abCalcBtnFStr, + 0, + {"F","",0,0} + }}; +}; +resource rPString (abCalcBtnFStr, noCrossBank) { "F" }; + +resource rControlTemplate (abCalcStackList) { + abCalcStackList, /* control ID */ + {1, abCalcBtnSpaceX, 41, abCalcWinWidth-abCalcBtnSpaceX}, /* control rect */ + ListControl {{ + $0000, /* flags */ + $1400, /* more flags */ + 0, /* refcon */ + 0, /* list size */ + 4, /* List View */ + $0007, /* List Type */ + 0, /* List Start */ + 10, /* ListMemHeight */ + 5, /* List Mem Size */ + 0, /* List Ref */ + 0 /* Color Ref */ + }}; + }; + +resource rControlTemplate (abCalcOpList) { + abCalcOpList, /* control ID */ + {abCalcBtnRow7, abCalcOpCol, abCalcWinHeight-(3*abCalcBtnSpaceY), abCalcWinWidth-abCalcBtnSpaceX}, /* control rect */ + ListControl {{ + $0000, /* flags */ + $1400, /* more flags */ + 0, /* refcon */ + 0, /* list size */ + 12, /* List View */ + $0007, /* List Type */ + 0, /* List Start */ + 10, /* ListMemHeight */ + 5, /* List Mem Size */ + 0, /* List Ref */ + 0 /* Color Ref */ + }}; + }; + +resource rControlTemplate (abCalcEntryBox) { + abCalcEntryBox, /* control ID */ + {abCalcBtnRow7, abCalcBtnCol0, abCalcBtnRow7+abCalcBtnHeight, abCalcBtnCol3+abCalcBtnWidth}, /* control rect */ + editLineControl {{ + $0000, /* flags */ + $7000, /* more flags */ + 0, /* refcon */ + 34, /* Max size */ + 0 /* text Ref */ + }}; + }; + +resource rAlertString (abCalcErrorAlert) { + "23/" + "*0" + "/^#0\$00" +}; + diff --git a/abCalc/ops/abCOp.c b/abCalc/ops/abCOp.c new file mode 100644 index 0000000..aeee3e2 --- /dev/null +++ b/abCalc/ops/abCOp.c @@ -0,0 +1,177 @@ +/* + abCOp.c + By: Jeremy Rand + */ + + +#include +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" + +#include "ops/abCOpAdd.h" +#include "ops/abCOpSubtr.h" +#include "ops/abCOpMult.h" +#include "ops/abCOpDiv.h" +#include "ops/abCOpChs.h" +#include "ops/abCOpInv.h" +#include "ops/abCOpSq.h" +#include "ops/abCOpSqrt.h" +#include "ops/abCOpPower.h" + +#include "ops/abCOpDrop.h" +#include "ops/abCOpSwap.h" +#include "ops/abCOpClear.h" + +#include "ops/abCOpPi.h" +#include "ops/abCOpSin.h" +#include "ops/abCOpCos.h" +#include "ops/abCOpTan.h" +#include "ops/abCOpAsin.h" +#include "ops/abCOpAcos.h" +#include "ops/abCOpAtan.h" + +#include "ops/abCOpLog.h" +#include "ops/abCOpAlog.h" +#include "ops/abCOpLn.h" +#include "ops/abCOpExp.h" +#include "ops/abCOpSinh.h" +#include "ops/abCOpCosh.h" +#include "ops/abCOpTanh.h" + +#include "ops/abCOpR2B.h" +#include "ops/abCOpB2R.h" + +#include "ops/abCOpAnd.h" +#include "ops/abCOpOr.h" +#include "ops/abCOpXor.h" +#include "ops/abCOpNot.h" +#include "ops/abCOpSl.h" +#include "ops/abCOpRl.h" +#include "ops/abCOpSr.h" +#include "ops/abCOpRr.h" +#include "ops/abCOpAsr.h" + +#include "ops/abCOpBin.h" +#include "ops/abCOpOct.h" +#include "ops/abCOpDec.h" +#include "ops/abCOpHex.h" +#include "ops/abCOpStws.h" +#include "ops/abCOpRcws.h" + + +#define AB_CALC_MAX_OPS 128 + + +abCalcOp gOps[AB_CALC_MAX_OPS]; +static int gNumOps = 0; + + +void abCalcOpInit(void) +{ + gNumOps = 0; + memset(gOps, 0, sizeof(gOps)); + + abCalcOpAddInit(); + abCalcOpSubtrInit(); + abCalcOpMultInit(); + abCalcOpDivInit(); + abCalcOpChsInit(); + abCalcOpInvInit(); + abCalcOpSqInit(); + abCalcOpSqrtInit(); + abCalcOpPowerInit(); + + abCalcOpDropInit(); + abCalcOpSwapInit(); + abCalcOpClearInit(); + + abCalcOpPiInit(); + abCalcOpSinInit(); + abCalcOpCosInit(); + abCalcOpTanInit(); + abCalcOpAsinInit(); + abCalcOpAcosInit(); + abCalcOpAtanInit(); + + abCalcOpLogInit(); + abCalcOpAlogInit(); + abCalcOpLnInit(); + abCalcOpExpInit(); + abCalcOpSinhInit(); + abCalcOpCoshInit(); + abCalcOpTanhInit(); + + abCalcOpR2BInit(); + abCalcOpB2RInit(); + + abCalcOpAndInit(); + abCalcOpOrInit(); + abCalcOpXorInit(); + abCalcOpNotInit(); + abCalcOpSlInit(); + abCalcOpRlInit(); + abCalcOpSrInit(); + abCalcOpRrInit(); + abCalcOpAsrInit(); + + abCalcOpBinInit(); + abCalcOpOctInit(); + abCalcOpDecInit(); + abCalcOpHexInit(); + abCalcOpStwsInit(); + abCalcOpRcwsInit(); +} + + +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++) { +#ifdef ABCALC_GSOS + if (stricmp(gOps[i].name, name) == 0) { +#else + if (strcasecmp(gOps[i].name, name) == 0) { +#endif + return &gOps[i]; + } + } + + return NULL; +} + + +abCalcOp *abCalcOpNth(int n) +{ + if ((n < 0) || + (n >= gNumOps)) + return NULL; + + return &gOps[n]; +} + + +int abCalcOpNumOps(void) +{ + return gNumOps; +} diff --git a/abCalc/ops/abCOp.h b/abCalc/ops/abCOp.h new file mode 100644 index 0000000..e970000 --- /dev/null +++ b/abCalc/ops/abCOp.h @@ -0,0 +1,44 @@ +/* + abCOp.h + By: Jeremy Rand + */ + + +#ifndef ABCOP_H +#define ABCOP_H + + +#define AB_CALC_OP_ONE_ARG(opName) \ + abCalcExpr *expr; \ + if (abCalcStackNumItems() < 1) { \ + abCalcRaiseError(abCalcTooFewArgsError, opName); \ + return; \ + } \ + expr = abCalcStackExprAt(0); + +#define AB_CALC_OP_TWO_ARGS(opName) \ + abCalcExpr *expr1, *expr2; \ + if (abCalcStackNumItems() < 2) { \ + abCalcRaiseError(abCalcTooFewArgsError, opName); \ + return; \ + } \ + expr1 = abCalcStackExprAt(0); \ + expr2 = abCalcStackExprAt(1); + +typedef struct abCalcOp { + char *name; + void (*execute)(void); +} abCalcOp; + + +void abCalcOpInit(void); + +void abCalcOpRegister(char *name, void (*execute)(void)); + +abCalcOp *abCalcOpLookup(char *name); + +abCalcOp *abCalcOpNth(int n); + +int abCalcOpNumOps(void); + +#endif diff --git a/abCalc/ops/abCOpAcos.c b/abCalc/ops/abCOpAcos.c new file mode 100644 index 0000000..55deec5 --- /dev/null +++ b/abCalc/ops/abCOpAcos.c @@ -0,0 +1,52 @@ +/* + abCOpAcos.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAcos.h" + + +#define ACOS_NAME "ACOS" + + +static void acosExecute(void); + + +void abCalcOpAcosInit(void) +{ + abCalcOpRegister(ACOS_NAME, acosExecute); +} + + +void acosExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(ACOS_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, ACOS_NAME); + return; + } + + if ((expr->u.real < -1.0) || + (expr->u.real > 1.0)) { + abCalcRaiseError(abCalcComplexResultError, ACOS_NAME); + return; + } + + abCalcExprRealSet(&result, acos(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAcos.h b/abCalc/ops/abCOpAcos.h new file mode 100644 index 0000000..157c75a --- /dev/null +++ b/abCalc/ops/abCOpAcos.h @@ -0,0 +1,14 @@ +/* + abCOpAcos.h + By: Jeremy Rand + */ + + +#ifndef ABCOPACOS_H +#define ABCOPACOS_H + + +void abCalcOpAcosInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAdd.c b/abCalc/ops/abCOpAdd.c new file mode 100644 index 0000000..30469cd --- /dev/null +++ b/abCalc/ops/abCOpAdd.c @@ -0,0 +1,69 @@ +/* + abCOpAdd.c + By: Jeremy Rand + */ + + +#include + + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAdd.h" + + +#define ADD_NAME "+" + + +static void addExecute(void); + + +void abCalcOpAddInit(void) +{ + abCalcOpRegister(ADD_NAME, addExecute); +} + + +void addExecute(void) +{ + abCalcExpr result; + char expr1Real = 0; + char expr2Real = 0; + AB_CALC_OP_TWO_ARGS(ADD_NAME); + + if (expr1->type == abCalcExprTypeReal) { + expr1Real = 1; + } else if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, ADD_NAME); + return; + } + + if (expr2->type == abCalcExprTypeReal) { + expr2Real = 1; + } else if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, ADD_NAME); + return; + } + + if ((expr1Real) && (expr2Real)) { + abCalcExprRealSet(&result, expr2->u.real + expr1->u.real); + } else { + if (expr1Real) { + abCalcExprIntSet(&result, expr2->u.integer + (abCalcIntType)expr1->u.real); + } else if (expr2Real) { + abCalcExprIntSet(&result, (abCalcIntType)expr2->u.real + expr1->u.integer); + } else { + abCalcExprIntSet(&result, expr2->u.integer + expr1->u.integer); + } + } + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAdd.h b/abCalc/ops/abCOpAdd.h new file mode 100644 index 0000000..cc3319d --- /dev/null +++ b/abCalc/ops/abCOpAdd.h @@ -0,0 +1,14 @@ +/* + abCOpAdd.h + By: Jeremy Rand + */ + + +#ifndef ABCOPADD_H +#define ABCOPADD_H + + +void abCalcOpAddInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAlog.c b/abCalc/ops/abCOpAlog.c new file mode 100644 index 0000000..dd13648 --- /dev/null +++ b/abCalc/ops/abCOpAlog.c @@ -0,0 +1,46 @@ +/* + abCOpAlog.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAlog.h" + + +#define ALOG_NAME "ALOG" + + +static void alogExecute(void); + + +void abCalcOpAlogInit(void) +{ + abCalcOpRegister(ALOG_NAME, alogExecute); +} + + +void alogExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(ALOG_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, ALOG_NAME); + return; + } + + abCalcExprRealSet(&result, pow(10.0, expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAlog.h b/abCalc/ops/abCOpAlog.h new file mode 100644 index 0000000..fd49111 --- /dev/null +++ b/abCalc/ops/abCOpAlog.h @@ -0,0 +1,14 @@ +/* + abCOpAlog.h + By: Jeremy Rand + */ + + +#ifndef ABCOPALOG_H +#define ABCOPALOG_H + + +void abCalcOpAlogInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAnd.c b/abCalc/ops/abCOpAnd.c new file mode 100644 index 0000000..c4a92c0 --- /dev/null +++ b/abCalc/ops/abCOpAnd.c @@ -0,0 +1,51 @@ +/* + abCOpAnd.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAnd.h" + + +#define AND_NAME "AND" + + +static void andExecute(void); + + +void abCalcOpAndInit(void) +{ + abCalcOpRegister(AND_NAME, andExecute); +} + + +void andExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_TWO_ARGS(AND_NAME); + + if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, AND_NAME); + return; + } + + if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, AND_NAME); + return; + } + + abCalcExprIntSet(&result, expr2->u.integer & expr1->u.integer); + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAnd.h b/abCalc/ops/abCOpAnd.h new file mode 100644 index 0000000..27a0610 --- /dev/null +++ b/abCalc/ops/abCOpAnd.h @@ -0,0 +1,14 @@ +/* + abCOpAnd.h + By: Jeremy Rand + */ + + +#ifndef ABCOPAND_H +#define ABCOPAND_H + + +void abCalcOpAndInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAsin.c b/abCalc/ops/abCOpAsin.c new file mode 100644 index 0000000..e1d1627 --- /dev/null +++ b/abCalc/ops/abCOpAsin.c @@ -0,0 +1,52 @@ +/* + abCOpAsin.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAsin.h" + + +#define ASIN_NAME "ASIN" + + +static void asinExecute(void); + + +void abCalcOpAsinInit(void) +{ + abCalcOpRegister(ASIN_NAME, asinExecute); +} + + +void asinExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(ASIN_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, ASIN_NAME); + return; + } + + if ((expr->u.real < -1.0) || + (expr->u.real > 1.0)) { + abCalcRaiseError(abCalcComplexResultError, ASIN_NAME); + return; + } + + abCalcExprRealSet(&result, asin(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAsin.h b/abCalc/ops/abCOpAsin.h new file mode 100644 index 0000000..f6d88cf --- /dev/null +++ b/abCalc/ops/abCOpAsin.h @@ -0,0 +1,14 @@ +/* + abCOpAsin.h + By: Jeremy Rand + */ + + +#ifndef ABCOPASIN_H +#define ABCOPASIN_H + + +void abCalcOpAsinInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAsr.c b/abCalc/ops/abCOpAsr.c new file mode 100644 index 0000000..7e961ab --- /dev/null +++ b/abCalc/ops/abCOpAsr.c @@ -0,0 +1,51 @@ +/* + abCOpAsr.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCMode.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAsr.h" + + +#define ASR_NAME "ASR" + + +static void asrExecute(void); + + +void abCalcOpAsrInit(void) +{ + abCalcOpRegister(ASR_NAME, asrExecute); +} + + +void asrExecute(void) +{ + abCalcExpr result; + int width; + abCalcIntType upperBit; + AB_CALC_OP_ONE_ARG(ASR_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, ASR_NAME); + return; + } + + width = abCalcModeGetIntWidth(); + upperBit = (expr->u.integer & (1 << (width - 1))); + + abCalcExprIntSet(&result, ((expr->u.integer >> 1) | upperBit)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAsr.h b/abCalc/ops/abCOpAsr.h new file mode 100644 index 0000000..a796c1a --- /dev/null +++ b/abCalc/ops/abCOpAsr.h @@ -0,0 +1,14 @@ +/* + abCOpAsr.h + By: Jeremy Rand + */ + + +#ifndef ABCOPASR_H +#define ABCOPASR_H + + +void abCalcOpAsrInit(void); + + +#endif diff --git a/abCalc/ops/abCOpAtan.c b/abCalc/ops/abCOpAtan.c new file mode 100644 index 0000000..2ceaf9c --- /dev/null +++ b/abCalc/ops/abCOpAtan.c @@ -0,0 +1,46 @@ +/* + abCOpAtan.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpAtan.h" + + +#define ATAN_NAME "ATAN" + + +static void atanExecute(void); + + +void abCalcOpAtanInit(void) +{ + abCalcOpRegister(ATAN_NAME, atanExecute); +} + + +void atanExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(ATAN_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, ATAN_NAME); + return; + } + + abCalcExprRealSet(&result, atan(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpAtan.h b/abCalc/ops/abCOpAtan.h new file mode 100644 index 0000000..fb38491 --- /dev/null +++ b/abCalc/ops/abCOpAtan.h @@ -0,0 +1,14 @@ +/* + abCOpAtan.h + By: Jeremy Rand + */ + + +#ifndef ABCOPATAN_H +#define ABCOPATAN_H + + +void abCalcOpAtanInit(void); + + +#endif diff --git a/abCalc/ops/abCOpB2R.c b/abCalc/ops/abCOpB2R.c new file mode 100644 index 0000000..99a6700 --- /dev/null +++ b/abCalc/ops/abCOpB2R.c @@ -0,0 +1,48 @@ +/* + abCOpB2R.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpB2R.h" + + +#define B2R_NAME "B2R" + + +static void b2rExecute(void); + + +void abCalcOpB2RInit(void) +{ + abCalcOpRegister(B2R_NAME, b2rExecute); +} + + +void b2rExecute(void) +{ + abCalcExpr result; + int width; + int topBit; + AB_CALC_OP_ONE_ARG(B2R_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, B2R_NAME); + return; + } + + abCalcExprRealSet(&result, (abCalcRealType)expr->u.integer); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpB2R.h b/abCalc/ops/abCOpB2R.h new file mode 100644 index 0000000..1029e1c --- /dev/null +++ b/abCalc/ops/abCOpB2R.h @@ -0,0 +1,14 @@ +/* + abCOpB2R.h + By: Jeremy Rand + */ + + +#ifndef ABCOPB2R_H +#define ABCOPB2R_H + + +void abCalcOpB2RInit(void); + + +#endif diff --git a/abCalc/ops/abCOpBin.c b/abCalc/ops/abCOpBin.c new file mode 100644 index 0000000..073d2b2 --- /dev/null +++ b/abCalc/ops/abCOpBin.c @@ -0,0 +1,30 @@ +/* + abCOpBin.c + By: Jeremy Rand + */ + + +#include + +#include "abCMode.h" + +#include "ops/abCOp.h" +#include "ops/abCOpBin.h" + + +#define BIN_NAME "BIN" + + +static void binExecute(void); + + +void abCalcOpBinInit(void) +{ + abCalcOpRegister(BIN_NAME, binExecute); +} + + +void binExecute(void) +{ + abCalcModeSetBase(abCalcModeBinBase); +} diff --git a/abCalc/ops/abCOpBin.h b/abCalc/ops/abCOpBin.h new file mode 100644 index 0000000..15126a2 --- /dev/null +++ b/abCalc/ops/abCOpBin.h @@ -0,0 +1,14 @@ +/* + abCOpBin.h + By: Jeremy Rand + */ + + +#ifndef ABCOPBIN_H +#define ABCOPBIN_H + + +void abCalcOpBinInit(void); + + +#endif diff --git a/abCalc/ops/abCOpChs.c b/abCalc/ops/abCOpChs.c new file mode 100644 index 0000000..b9ebd11 --- /dev/null +++ b/abCalc/ops/abCOpChs.c @@ -0,0 +1,46 @@ +/* + abCOpChs.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpChs.h" + + +#define CHS_NAME "CHS" + + +static void chsExecute(void); + + +void abCalcOpChsInit(void) +{ + abCalcOpRegister(CHS_NAME, chsExecute); +} + + +void chsExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(CHS_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, CHS_NAME); + return; + } + + abCalcExprRealSet(&result, -1.0 * expr->u.real); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpChs.h b/abCalc/ops/abCOpChs.h new file mode 100644 index 0000000..af58822 --- /dev/null +++ b/abCalc/ops/abCOpChs.h @@ -0,0 +1,14 @@ +/* + abCOpChs.h + By: Jeremy Rand + */ + + +#ifndef ABCOPCHS_H +#define ABCOPCHS_H + + +void abCalcOpChsInit(void); + + +#endif diff --git a/abCalc/ops/abCOpClear.c b/abCalc/ops/abCOpClear.c new file mode 100644 index 0000000..98cf922 --- /dev/null +++ b/abCalc/ops/abCOpClear.c @@ -0,0 +1,31 @@ +/* + abCOpClear.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCStack.h" + +#include "ops/abCOp.h" +#include "ops/abCOpClear.h" + + +#define CLEAR_NAME "CLEAR" + + +static void clearExecute(void); + + +void abCalcOpClearInit(void) +{ + abCalcOpRegister(CLEAR_NAME, clearExecute); +} + + +void clearExecute(void) +{ + abCalcStackClear(); +} diff --git a/abCalc/ops/abCOpClear.h b/abCalc/ops/abCOpClear.h new file mode 100644 index 0000000..c7b45f6 --- /dev/null +++ b/abCalc/ops/abCOpClear.h @@ -0,0 +1,14 @@ +/* + abCOpClean.h + By: Jeremy Rand + */ + + +#ifndef ABCOPCLEAR_H +#define ABCOPCLEAR_H + + +void abCalcOpClearInit(void); + + +#endif diff --git a/abCalc/ops/abCOpCos.c b/abCalc/ops/abCOpCos.c new file mode 100644 index 0000000..44a00a5 --- /dev/null +++ b/abCalc/ops/abCOpCos.c @@ -0,0 +1,46 @@ +/* + abCOpCos.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpCos.h" + + +#define COS_NAME "COS" + + +static void cosExecute(void); + + +void abCalcOpCosInit(void) +{ + abCalcOpRegister(COS_NAME, cosExecute); +} + + +void cosExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(COS_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, COS_NAME); + return; + } + + abCalcExprRealSet(&result, cos(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpCos.h b/abCalc/ops/abCOpCos.h new file mode 100644 index 0000000..57edc5b --- /dev/null +++ b/abCalc/ops/abCOpCos.h @@ -0,0 +1,14 @@ +/* + abCOpCos.h + By: Jeremy Rand + */ + + +#ifndef ABCOPCOS_H +#define ABCOPCOS_H + + +void abCalcOpCosInit(void); + + +#endif diff --git a/abCalc/ops/abCOpCosh.c b/abCalc/ops/abCOpCosh.c new file mode 100644 index 0000000..f34a929 --- /dev/null +++ b/abCalc/ops/abCOpCosh.c @@ -0,0 +1,46 @@ +/* + abCOpCosh.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpCosh.h" + + +#define COSH_NAME "COSH" + + +static void coshExecute(void); + + +void abCalcOpCoshInit(void) +{ + abCalcOpRegister(COSH_NAME, coshExecute); +} + + +void coshExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(COSH_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, COSH_NAME); + return; + } + + abCalcExprRealSet(&result, cosh(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpCosh.h b/abCalc/ops/abCOpCosh.h new file mode 100644 index 0000000..5e1b4bf --- /dev/null +++ b/abCalc/ops/abCOpCosh.h @@ -0,0 +1,14 @@ +/* + abCOpCosh.h + By: Jeremy Rand + */ + + +#ifndef ABCOPCOSH_H +#define ABCOPCOSH_H + + +void abCalcOpCoshInit(void); + + +#endif diff --git a/abCalc/ops/abCOpDec.c b/abCalc/ops/abCOpDec.c new file mode 100644 index 0000000..809e86c --- /dev/null +++ b/abCalc/ops/abCOpDec.c @@ -0,0 +1,30 @@ +/* + abCOpDec.c + By: Jeremy Rand + */ + + +#include + +#include "abCMode.h" + +#include "ops/abCOp.h" +#include "ops/abCOpDec.h" + + +#define DEC_NAME "DEC" + + +static void decExecute(void); + + +void abCalcOpDecInit(void) +{ + abCalcOpRegister(DEC_NAME, decExecute); +} + + +void decExecute(void) +{ + abCalcModeSetBase(abCalcModeDecBase); +} diff --git a/abCalc/ops/abCOpDec.h b/abCalc/ops/abCOpDec.h new file mode 100644 index 0000000..f47057a --- /dev/null +++ b/abCalc/ops/abCOpDec.h @@ -0,0 +1,14 @@ +/* + abCOpDec.h + By: Jeremy Rand + */ + + +#ifndef ABCOPDEC_H +#define ABCOPDEC_H + + +void abCalcOpDecInit(void); + + +#endif diff --git a/abCalc/ops/abCOpDiv.c b/abCalc/ops/abCOpDiv.c new file mode 100644 index 0000000..df04601 --- /dev/null +++ b/abCalc/ops/abCOpDiv.c @@ -0,0 +1,77 @@ +/* + abCOpDiv.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpDiv.h" + + +#define DIV_NAME "/" + + +static void divExecute(void); + + +void abCalcOpDivInit(void) +{ + abCalcOpRegister(DIV_NAME, divExecute); +} + + +void divExecute(void) +{ + abCalcExpr result; + char expr1Real = 0; + char expr2Real = 0; + AB_CALC_OP_TWO_ARGS(DIV_NAME); + + if (expr1->type == abCalcExprTypeReal) { + expr1Real = 1; + if (expr1->u.real == 0.0) { + abCalcRaiseError(abCalcInfiniteResultError, DIV_NAME); + return; + } + } else if (expr1->type == abCalcExprTypeInt) { + if (expr1->u.integer == 0l) { + abCalcRaiseError(abCalcInfiniteResultError, DIV_NAME); + return; + } + } else { + abCalcRaiseError(abCalcBadArgTypeError, DIV_NAME); + return; + } + + if (expr2->type == abCalcExprTypeReal) { + expr2Real = 1; + } else if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, DIV_NAME); + return; + } + + if ((expr1Real) && (expr2Real)) { + abCalcExprRealSet(&result, expr2->u.real / expr1->u.real); + } else { + if (expr1Real) { + abCalcExprIntSet(&result, expr2->u.integer / (abCalcIntType)expr1->u.real); + } else if (expr2Real) { + abCalcExprIntSet(&result, (abCalcIntType)expr2->u.real / expr1->u.integer); + } else { + abCalcExprIntSet(&result, expr2->u.integer / expr1->u.integer); + } + } + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpDiv.h b/abCalc/ops/abCOpDiv.h new file mode 100644 index 0000000..24f10dd --- /dev/null +++ b/abCalc/ops/abCOpDiv.h @@ -0,0 +1,14 @@ +/* + abCOpDiv.h + By: Jeremy Rand + */ + + +#ifndef ABCOPDIV_H +#define ABCOPDIV_H + + +void abCalcOpDivInit(void); + + +#endif diff --git a/abCalc/ops/abCOpDrop.c b/abCalc/ops/abCOpDrop.c new file mode 100644 index 0000000..3eb44fa --- /dev/null +++ b/abCalc/ops/abCOpDrop.c @@ -0,0 +1,36 @@ +/* + abCOpDrop.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" +#include "ops/abCOpDrop.h" + + +#define DROP_NAME "DROP" + + +static void dropExecute(void); + + +void abCalcOpDropInit(void) +{ + abCalcOpRegister(DROP_NAME, dropExecute); +} + + +void dropExecute(void) +{ + AB_CALC_OP_ONE_ARG(DROP_NAME); + + abCalcStackExprPop(NULL); +} diff --git a/abCalc/ops/abCOpDrop.h b/abCalc/ops/abCOpDrop.h new file mode 100644 index 0000000..b0927c0 --- /dev/null +++ b/abCalc/ops/abCOpDrop.h @@ -0,0 +1,14 @@ +/* + abCOpDrop.h + By: Jeremy Rand + */ + + +#ifndef ABCOPDROP_H +#define ABCOPDROP_H + + +void abCalcOpDropInit(void); + + +#endif diff --git a/abCalc/ops/abCOpExp.c b/abCalc/ops/abCOpExp.c new file mode 100644 index 0000000..74cb743 --- /dev/null +++ b/abCalc/ops/abCOpExp.c @@ -0,0 +1,46 @@ +/* + abCOpExp.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpExp.h" + + +#define EXP_NAME "EXP" + + +static void expExecute(void); + + +void abCalcOpExpInit(void) +{ + abCalcOpRegister(EXP_NAME, expExecute); +} + + +void expExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(EXP_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, EXP_NAME); + return; + } + + abCalcExprRealSet(&result, exp(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpExp.h b/abCalc/ops/abCOpExp.h new file mode 100644 index 0000000..4c8492a --- /dev/null +++ b/abCalc/ops/abCOpExp.h @@ -0,0 +1,14 @@ +/* + abCOpExp.h + By: Jeremy Rand + */ + + +#ifndef ABCOPEXP_H +#define ABCOPEXP_H + + +void abCalcOpExpInit(void); + + +#endif diff --git a/abCalc/ops/abCOpHex.c b/abCalc/ops/abCOpHex.c new file mode 100644 index 0000000..12973b0 --- /dev/null +++ b/abCalc/ops/abCOpHex.c @@ -0,0 +1,30 @@ +/* + abCOpHex.c + By: Jeremy Rand + */ + + +#include + +#include "abCMode.h" + +#include "ops/abCOp.h" +#include "ops/abCOpHex.h" + + +#define HEX_NAME "HEX" + + +static void hexExecute(void); + + +void abCalcOpHexInit(void) +{ + abCalcOpRegister(HEX_NAME, hexExecute); +} + + +void hexExecute(void) +{ + abCalcModeSetBase(abCalcModeHexBase); +} diff --git a/abCalc/ops/abCOpHex.h b/abCalc/ops/abCOpHex.h new file mode 100644 index 0000000..8471eb0 --- /dev/null +++ b/abCalc/ops/abCOpHex.h @@ -0,0 +1,14 @@ +/* + abCOpHex.h + By: Jeremy Rand + */ + + +#ifndef ABCOPHEX_H +#define ABCOPHEX_H + + +void abCalcOpHexInit(void); + + +#endif diff --git a/abCalc/ops/abCOpInv.c b/abCalc/ops/abCOpInv.c new file mode 100644 index 0000000..771fd53 --- /dev/null +++ b/abCalc/ops/abCOpInv.c @@ -0,0 +1,51 @@ +/* + abCOpInv.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpInv.h" + + +#define INV_NAME "INV" + + +static void invExecute(void); + + +void abCalcOpInvInit(void) +{ + abCalcOpRegister(INV_NAME, invExecute); +} + + +void invExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(INV_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, INV_NAME); + return; + } + + if (expr->u.real == 0.0) { + abCalcRaiseError(abCalcInfiniteResultError, INV_NAME); + return; + } + + abCalcExprRealSet(&result, 1.0 / expr->u.real); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpInv.h b/abCalc/ops/abCOpInv.h new file mode 100644 index 0000000..eab8c87 --- /dev/null +++ b/abCalc/ops/abCOpInv.h @@ -0,0 +1,14 @@ +/* + abCOpInv.h + By: Jeremy Rand + */ + + +#ifndef ABCOPINV_H +#define ABCOPINV_H + + +void abCalcOpInvInit(void); + + +#endif diff --git a/abCalc/ops/abCOpLn.c b/abCalc/ops/abCOpLn.c new file mode 100644 index 0000000..c1593b6 --- /dev/null +++ b/abCalc/ops/abCOpLn.c @@ -0,0 +1,55 @@ +/* + abCOpLn.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpLn.h" + + +#define LN_NAME "LN" + + +static void lnExecute(void); + + +void abCalcOpLnInit(void) +{ + abCalcOpRegister(LN_NAME, lnExecute); +} + + +void lnExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(LN_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, LN_NAME); + return; + } + + if (expr->u.real == 0.0) { + abCalcRaiseError(abCalcInfiniteResultError, LN_NAME); + return; + } + if (expr->u.real < 0.0) { + abCalcRaiseError(abCalcComplexResultError, LN_NAME); + return; + } + + abCalcExprRealSet(&result, log(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpLn.h b/abCalc/ops/abCOpLn.h new file mode 100644 index 0000000..adb0752 --- /dev/null +++ b/abCalc/ops/abCOpLn.h @@ -0,0 +1,14 @@ +/* + abCOpLn.h + By: Jeremy Rand + */ + + +#ifndef ABCOPLN_H +#define ABCOPLN_H + + +void abCalcOpLnInit(void); + + +#endif diff --git a/abCalc/ops/abCOpLog.c b/abCalc/ops/abCOpLog.c new file mode 100644 index 0000000..0523ae3 --- /dev/null +++ b/abCalc/ops/abCOpLog.c @@ -0,0 +1,55 @@ +/* + abCOpLog.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpLog.h" + + +#define LOG_NAME "LOG" + + +static void logExecute(void); + + +void abCalcOpLogInit(void) +{ + abCalcOpRegister(LOG_NAME, logExecute); +} + + +void logExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(LOG_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, LOG_NAME); + return; + } + + if (expr->u.real == 0.0) { + abCalcRaiseError(abCalcInfiniteResultError, LOG_NAME); + return; + } + if (expr->u.real < 0.0) { + abCalcRaiseError(abCalcComplexResultError, LOG_NAME); + return; + } + + abCalcExprRealSet(&result, log10(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpLog.h b/abCalc/ops/abCOpLog.h new file mode 100644 index 0000000..b05ca20 --- /dev/null +++ b/abCalc/ops/abCOpLog.h @@ -0,0 +1,14 @@ +/* + abCOpLog.h + By: Jeremy Rand + */ + + +#ifndef ABCOPLOG_H +#define ABCOPLOG_H + + +void abCalcOpLogInit(void); + + +#endif diff --git a/abCalc/ops/abCOpMult.c b/abCalc/ops/abCOpMult.c new file mode 100644 index 0000000..b097188 --- /dev/null +++ b/abCalc/ops/abCOpMult.c @@ -0,0 +1,68 @@ +/* + abCOpMult.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpMult.h" + + +#define MUL_NAME "*" + + +static void multExecute(void); + + +void abCalcOpMultInit(void) +{ + abCalcOpRegister(MUL_NAME, multExecute); +} + + +void multExecute(void) +{ + abCalcExpr result; + char expr1Real = 0; + char expr2Real = 0; + AB_CALC_OP_TWO_ARGS(MUL_NAME); + + if (expr1->type == abCalcExprTypeReal) { + expr1Real = 1; + } else if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, MUL_NAME); + return; + } + + if (expr2->type == abCalcExprTypeReal) { + expr2Real = 1; + } else if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, MUL_NAME); + return; + } + + if ((expr1Real) && (expr2Real)) { + abCalcExprRealSet(&result, expr2->u.real * expr1->u.real); + } else { + if (expr1Real) { + abCalcExprIntSet(&result, expr2->u.integer * (abCalcIntType)expr1->u.real); + } else if (expr2Real) { + abCalcExprIntSet(&result, (abCalcIntType)expr2->u.real * expr1->u.integer); + } else { + abCalcExprIntSet(&result, expr2->u.integer * expr1->u.integer); + } + } + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpMult.h b/abCalc/ops/abCOpMult.h new file mode 100644 index 0000000..b32db73 --- /dev/null +++ b/abCalc/ops/abCOpMult.h @@ -0,0 +1,14 @@ +/* + abCOpMult.h + By: Jeremy Rand + */ + + +#ifndef ABCOPMULT_H +#define ABCOPMULT_H + + +void abCalcOpMultInit(void); + + +#endif diff --git a/abCalc/ops/abCOpNot.c b/abCalc/ops/abCOpNot.c new file mode 100644 index 0000000..e321fc8 --- /dev/null +++ b/abCalc/ops/abCOpNot.c @@ -0,0 +1,45 @@ +/* + abCOpNot.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpNot.h" + + +#define NOT_NAME "NOT" + + +static void notExecute(void); + + +void abCalcOpNotInit(void) +{ + abCalcOpRegister(NOT_NAME, notExecute); +} + + +void notExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(NOT_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, NOT_NAME); + return; + } + + abCalcExprIntSet(&result, ~(expr->u.integer)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpNot.h b/abCalc/ops/abCOpNot.h new file mode 100644 index 0000000..f7c90b0 --- /dev/null +++ b/abCalc/ops/abCOpNot.h @@ -0,0 +1,14 @@ +/* + abCOpNot.h + By: Jeremy Rand + */ + + +#ifndef ABCOPNOT_H +#define ABCOPNOT_H + + +void abCalcOpNotInit(void); + + +#endif diff --git a/abCalc/ops/abCOpOct.c b/abCalc/ops/abCOpOct.c new file mode 100644 index 0000000..1a50f72 --- /dev/null +++ b/abCalc/ops/abCOpOct.c @@ -0,0 +1,30 @@ +/* + abCOpOct.c + By: Jeremy Rand + */ + + +#include + +#include "abCMode.h" + +#include "ops/abCOp.h" +#include "ops/abCOpOct.h" + + +#define OCT_NAME "OCT" + + +static void octExecute(void); + + +void abCalcOpOctInit(void) +{ + abCalcOpRegister(OCT_NAME, octExecute); +} + + +void octExecute(void) +{ + abCalcModeSetBase(abCalcModeOctBase); +} diff --git a/abCalc/ops/abCOpOct.h b/abCalc/ops/abCOpOct.h new file mode 100644 index 0000000..6fac438 --- /dev/null +++ b/abCalc/ops/abCOpOct.h @@ -0,0 +1,14 @@ +/* + abCOpOct.h + By: Jeremy Rand + */ + + +#ifndef ABCOPOCT_H +#define ABCOPOCT_H + + +void abCalcOpOctInit(void); + + +#endif diff --git a/abCalc/ops/abCOpOr.c b/abCalc/ops/abCOpOr.c new file mode 100644 index 0000000..ac2316e --- /dev/null +++ b/abCalc/ops/abCOpOr.c @@ -0,0 +1,51 @@ +/* + abCOpOr.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpOr.h" + + +#define OR_NAME "OR" + + +static void orExecute(void); + + +void abCalcOpOrInit(void) +{ + abCalcOpRegister(OR_NAME, orExecute); +} + + +void orExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_TWO_ARGS(OR_NAME); + + if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, OR_NAME); + return; + } + + if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, OR_NAME); + return; + } + + abCalcExprIntSet(&result, expr2->u.integer | expr1->u.integer); + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpOr.h b/abCalc/ops/abCOpOr.h new file mode 100644 index 0000000..525968e --- /dev/null +++ b/abCalc/ops/abCOpOr.h @@ -0,0 +1,14 @@ +/* + abCOpOr.h + By: Jeremy Rand + */ + + +#ifndef ABCOPOR_H +#define ABCOPOR_H + + +void abCalcOpOrInit(void); + + +#endif diff --git a/abCalc/ops/abCOpPi.c b/abCalc/ops/abCOpPi.c new file mode 100644 index 0000000..859fac7 --- /dev/null +++ b/abCalc/ops/abCOpPi.c @@ -0,0 +1,42 @@ +/* + abCOpPi.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpPi.h" + + +#define PI_NAME "PI" + + +static void piExecute(void); + + +void abCalcOpPiInit(void) +{ + abCalcOpRegister(PI_NAME, piExecute); +} + + +void piExecute(void) +{ + abCalcExpr result; + +#ifdef ABCALC_GSOS + abCalcExprRealSet(&result, 2.0 * asin(1.0)); +#else + abCalcExprRealSet(&result, M_PI); +#endif + + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpPi.h b/abCalc/ops/abCOpPi.h new file mode 100644 index 0000000..5cde26c --- /dev/null +++ b/abCalc/ops/abCOpPi.h @@ -0,0 +1,14 @@ +/* + abCOpPi.h + By: Jeremy Rand + */ + + +#ifndef ABCOPPI_H +#define ABCOPPI_H + + +void abCalcOpPiInit(void); + + +#endif diff --git a/abCalc/ops/abCOpPower.c b/abCalc/ops/abCOpPower.c new file mode 100644 index 0000000..69f76f8 --- /dev/null +++ b/abCalc/ops/abCOpPower.c @@ -0,0 +1,73 @@ +/* + abCOpPower.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpPower.h" + + +#define POWER_NAME "^" + + +static void powerExecute(void); + + +void abCalcOpPowerInit(void) +{ + abCalcOpRegister(POWER_NAME, powerExecute); +} + + +void powerExecute(void) +{ + abCalcExpr result; + double integral; + AB_CALC_OP_TWO_ARGS(POWER_NAME); + + if (expr1->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, POWER_NAME); + return; + } + + if (expr2->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, POWER_NAME); + return; + } + + if (expr2->u.real == 0.0) { + if (expr1->u.real < 0.0) { + abCalcRaiseError(abCalcInfiniteResultError, POWER_NAME); + return; + } + if (expr1->u.real == 0.0) { + abCalcExprRealSet(&result, 1.0); + } else { + abCalcExprRealSet(&result, 0.0); + } + } else { + if (expr2->u.real < 0.0) { + modf(expr1->u.real, &integral); + if (expr1->u.real != integral) { + abCalcRaiseError(abCalcComplexResultError, POWER_NAME); + return; + } + } + + abCalcExprRealSet(&result, pow(expr2->u.real, expr1->u.real)); + } + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpPower.h b/abCalc/ops/abCOpPower.h new file mode 100644 index 0000000..df058fc --- /dev/null +++ b/abCalc/ops/abCOpPower.h @@ -0,0 +1,14 @@ +/* + abCOpPower.h + By: Jeremy Rand + */ + + +#ifndef ABCOPPOWER_H +#define ABCOPPOWER_H + + +void abCalcOpPowerInit(void); + + +#endif diff --git a/abCalc/ops/abCOpR2B.c b/abCalc/ops/abCOpR2B.c new file mode 100644 index 0000000..5b18989 --- /dev/null +++ b/abCalc/ops/abCOpR2B.c @@ -0,0 +1,48 @@ +/* + abCOpR2B.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpR2B.h" + + +#define R2B_NAME "R2B" + + +static void r2bExecute(void); + + +void abCalcOpR2BInit(void) +{ + abCalcOpRegister(R2B_NAME, r2bExecute); +} + + +void r2bExecute(void) +{ + abCalcExpr result; + int width; + int topBit; + AB_CALC_OP_ONE_ARG(R2B_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, R2B_NAME); + return; + } + + abCalcExprIntSet(&result, (abCalcIntType)expr->u.real); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpR2B.h b/abCalc/ops/abCOpR2B.h new file mode 100644 index 0000000..4b8c87e --- /dev/null +++ b/abCalc/ops/abCOpR2B.h @@ -0,0 +1,14 @@ +/* + abCOpR2B.h + By: Jeremy Rand + */ + + +#ifndef ABCOPR2B_H +#define ABCOPR2B_H + + +void abCalcOpR2BInit(void); + + +#endif diff --git a/abCalc/ops/abCOpRcws.c b/abCalc/ops/abCOpRcws.c new file mode 100644 index 0000000..222d9d4 --- /dev/null +++ b/abCalc/ops/abCOpRcws.c @@ -0,0 +1,38 @@ +/* + abCOpRcws.c + By: Jeremy Rand + */ + + +#include + +#include "abCStack.h" +#include "abCMode.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpRcws.h" + + +#define RCWS_NAME "RCWS" + + +static void rcwsExecute(void); + + +void abCalcOpRcwsInit(void) +{ + abCalcOpRegister(RCWS_NAME, rcwsExecute); +} + + +void rcwsExecute(void) +{ + abCalcExpr result; + + abCalcExprRealSet(&result, (abCalcRealType)abCalcModeGetIntWidth()); + + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpRcws.h b/abCalc/ops/abCOpRcws.h new file mode 100644 index 0000000..b6f1ad3 --- /dev/null +++ b/abCalc/ops/abCOpRcws.h @@ -0,0 +1,14 @@ +/* + abCOpRcws.h + By: Jeremy Rand + */ + + +#ifndef ABCOPRCWS_H +#define ABCOPRCWS_H + + +void abCalcOpRcwsInit(void); + + +#endif diff --git a/abCalc/ops/abCOpRl.c b/abCalc/ops/abCOpRl.c new file mode 100644 index 0000000..a7670b8 --- /dev/null +++ b/abCalc/ops/abCOpRl.c @@ -0,0 +1,51 @@ +/* + abCOpRl.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCMode.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpRl.h" + + +#define RL_NAME "RL" + + +static void rlExecute(void); + + +void abCalcOpRlInit(void) +{ + abCalcOpRegister(RL_NAME, rlExecute); +} + + +void rlExecute(void) +{ + abCalcExpr result; + int width; + int topBit; + AB_CALC_OP_ONE_ARG(RL_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, RL_NAME); + return; + } + + width = abCalcModeGetIntWidth(); + topBit = ((expr->u.integer >> (width - 1)) & 1); + + abCalcExprIntSet(&result, ((expr->u.integer << 1) | topBit)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpRl.h b/abCalc/ops/abCOpRl.h new file mode 100644 index 0000000..463f867 --- /dev/null +++ b/abCalc/ops/abCOpRl.h @@ -0,0 +1,14 @@ +/* + abCOpRl.h + By: Jeremy Rand + */ + + +#ifndef ABCOPRL_H +#define ABCOPRL_H + + +void abCalcOpRlInit(void); + + +#endif diff --git a/abCalc/ops/abCOpRr.c b/abCalc/ops/abCOpRr.c new file mode 100644 index 0000000..41cd173 --- /dev/null +++ b/abCalc/ops/abCOpRr.c @@ -0,0 +1,51 @@ +/* + abCOpRr.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCMode.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpRr.h" + + +#define RR_NAME "RR" + + +static void rrExecute(void); + + +void abCalcOpRrInit(void) +{ + abCalcOpRegister(RR_NAME, rrExecute); +} + + +void rrExecute(void) +{ + abCalcExpr result; + int width; + abCalcIntType bottomBit; + AB_CALC_OP_ONE_ARG(RR_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, RR_NAME); + return; + } + + width = abCalcModeGetIntWidth(); + bottomBit = (expr->u.integer & 1); + + abCalcExprIntSet(&result, ((expr->u.integer >> 1) | (bottomBit << (width - 1)))); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpRr.h b/abCalc/ops/abCOpRr.h new file mode 100644 index 0000000..6184ae9 --- /dev/null +++ b/abCalc/ops/abCOpRr.h @@ -0,0 +1,14 @@ +/* + abCOpRr.h + By: Jeremy Rand + */ + + +#ifndef ABCOPRR_H +#define ABCOPRR_H + + +void abCalcOpRrInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSin.c b/abCalc/ops/abCOpSin.c new file mode 100644 index 0000000..efe3cf2 --- /dev/null +++ b/abCalc/ops/abCOpSin.c @@ -0,0 +1,46 @@ +/* + abCOpSin.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSin.h" + + +#define SIN_NAME "SIN" + + +static void sinExecute(void); + + +void abCalcOpSinInit(void) +{ + abCalcOpRegister(SIN_NAME, sinExecute); +} + + +void sinExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SIN_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, SIN_NAME); + return; + } + + abCalcExprRealSet(&result, sin(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSin.h b/abCalc/ops/abCOpSin.h new file mode 100644 index 0000000..e6ae3e2 --- /dev/null +++ b/abCalc/ops/abCOpSin.h @@ -0,0 +1,14 @@ +/* + abCOpSin.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSIN_H +#define ABCOPSIN_H + + +void abCalcOpSinInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSinh.c b/abCalc/ops/abCOpSinh.c new file mode 100644 index 0000000..42ee78a --- /dev/null +++ b/abCalc/ops/abCOpSinh.c @@ -0,0 +1,46 @@ +/* + abCOpSinh.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSinh.h" + + +#define SINH_NAME "SINH" + + +static void sinhExecute(void); + + +void abCalcOpSinhInit(void) +{ + abCalcOpRegister(SINH_NAME, sinhExecute); +} + + +void sinhExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SINH_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, SINH_NAME); + return; + } + + abCalcExprRealSet(&result, sinh(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSinh.h b/abCalc/ops/abCOpSinh.h new file mode 100644 index 0000000..dab0958 --- /dev/null +++ b/abCalc/ops/abCOpSinh.h @@ -0,0 +1,14 @@ +/* + abCOpSinh.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSINH_H +#define ABCOPSINH_H + + +void abCalcOpSinhInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSl.c b/abCalc/ops/abCOpSl.c new file mode 100644 index 0000000..0834e09 --- /dev/null +++ b/abCalc/ops/abCOpSl.c @@ -0,0 +1,45 @@ +/* + abCOpSl.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSl.h" + + +#define SL_NAME "SL" + + +static void slExecute(void); + + +void abCalcOpSlInit(void) +{ + abCalcOpRegister(SL_NAME, slExecute); +} + + +void slExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SL_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, SL_NAME); + return; + } + + abCalcExprIntSet(&result, (expr->u.integer << 1)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSl.h b/abCalc/ops/abCOpSl.h new file mode 100644 index 0000000..e539b78 --- /dev/null +++ b/abCalc/ops/abCOpSl.h @@ -0,0 +1,14 @@ +/* + abCOpSl.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSL_H +#define ABCOPSL_H + + +void abCalcOpSlInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSq.c b/abCalc/ops/abCOpSq.c new file mode 100644 index 0000000..4b4e7f0 --- /dev/null +++ b/abCalc/ops/abCOpSq.c @@ -0,0 +1,46 @@ +/* + abCOpSq.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSq.h" + + +#define SQ_NAME "SQ" + + +static void sqExecute(void); + + +void abCalcOpSqInit(void) +{ + abCalcOpRegister(SQ_NAME, sqExecute); +} + + +void sqExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SQ_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, SQ_NAME); + return; + } + + abCalcExprRealSet(&result, expr->u.real * expr->u.real); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSq.h b/abCalc/ops/abCOpSq.h new file mode 100644 index 0000000..41ff873 --- /dev/null +++ b/abCalc/ops/abCOpSq.h @@ -0,0 +1,14 @@ +/* + abCOpSq.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSQ_H +#define ABCOPSQ_H + + +void abCalcOpSqInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSqrt.c b/abCalc/ops/abCOpSqrt.c new file mode 100644 index 0000000..02e70c0 --- /dev/null +++ b/abCalc/ops/abCOpSqrt.c @@ -0,0 +1,51 @@ +/* + abCOpSqrt.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSqrt.h" + + +#define SQRT_NAME "SQRT" + + +static void sqrtExecute(void); + + +void abCalcOpSqrtInit(void) +{ + abCalcOpRegister(SQRT_NAME, sqrtExecute); +} + + +void sqrtExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SQRT_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, SQRT_NAME); + return; + } + + if (expr->u.real < 0.0) { + abCalcRaiseError(abCalcComplexResultError, SQRT_NAME); + return; + } + + abCalcExprRealSet(&result, sqrt(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSqrt.h b/abCalc/ops/abCOpSqrt.h new file mode 100644 index 0000000..9b518b5 --- /dev/null +++ b/abCalc/ops/abCOpSqrt.h @@ -0,0 +1,14 @@ +/* + abCOpSqrt.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSQRT_H +#define ABCOPSQRT_H + + +void abCalcOpSqrtInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSr.c b/abCalc/ops/abCOpSr.c new file mode 100644 index 0000000..b58cfbd --- /dev/null +++ b/abCalc/ops/abCOpSr.c @@ -0,0 +1,45 @@ +/* + abCOpSr.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSr.h" + + +#define SR_NAME "SR" + + +static void srExecute(void); + + +void abCalcOpSrInit(void) +{ + abCalcOpRegister(SR_NAME, srExecute); +} + + +void srExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(SR_NAME); + + if (expr->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, SR_NAME); + return; + } + + abCalcExprIntSet(&result, (expr->u.integer >> 1)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSr.h b/abCalc/ops/abCOpSr.h new file mode 100644 index 0000000..fe41bd5 --- /dev/null +++ b/abCalc/ops/abCOpSr.h @@ -0,0 +1,14 @@ +/* + abCOpSr.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSR_H +#define ABCOPSR_H + + +void abCalcOpSrInit(void); + + +#endif diff --git a/abCalc/ops/abCOpStws.c b/abCalc/ops/abCOpStws.c new file mode 100644 index 0000000..040f068 --- /dev/null +++ b/abCalc/ops/abCOpStws.c @@ -0,0 +1,50 @@ +/* + abCOpStws.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" +#include "abCMode.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" +#include "ops/abCOpStws.h" + + +#define STWS_NAME "STWS" + + +static void stwsExecute(void); + + +void abCalcOpStwsInit(void) +{ + abCalcOpRegister(STWS_NAME, stwsExecute); +} + + +void stwsExecute(void) +{ + int newWidth; + AB_CALC_OP_ONE_ARG(STWS_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, STWS_NAME); + return; + } + + newWidth = (int)expr->u.real; + if ((newWidth < 1) || + (newWidth > AB_CALC_EXPR_MAX_INT_WIDTH)) { + abCalcRaiseError(abCalcBadArgValueError, STWS_NAME); + return; + } + + abCalcModeSetIntWidth(newWidth); + abCalcStackExprPop(NULL); +} diff --git a/abCalc/ops/abCOpStws.h b/abCalc/ops/abCOpStws.h new file mode 100644 index 0000000..52e2120 --- /dev/null +++ b/abCalc/ops/abCOpStws.h @@ -0,0 +1,14 @@ +/* + abCOpStws.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSTWS_H +#define ABCOPSTWS_H + + +void abCalcOpStwsInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSubtr.c b/abCalc/ops/abCOpSubtr.c new file mode 100644 index 0000000..3d4dc01 --- /dev/null +++ b/abCalc/ops/abCOpSubtr.c @@ -0,0 +1,68 @@ +/* + abCOpSubtr.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSubtr.h" + + +#define SUB_NAME "-" + + +static void subtrExecute(void); + + +void abCalcOpSubtrInit(void) +{ + abCalcOpRegister(SUB_NAME, subtrExecute); +} + + +void subtrExecute(void) +{ + abCalcExpr result; + char expr1Real = 0; + char expr2Real = 0; + AB_CALC_OP_TWO_ARGS(SUB_NAME); + + if (expr1->type == abCalcExprTypeReal) { + expr1Real = 1; + } else if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, SUB_NAME); + return; + } + + if (expr2->type == abCalcExprTypeReal) { + expr2Real = 1; + } else if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, SUB_NAME); + return; + } + + if ((expr1Real) && (expr2Real)) { + abCalcExprRealSet(&result, expr2->u.real - expr1->u.real); + } else { + if (expr1Real) { + abCalcExprIntSet(&result, expr2->u.integer - (abCalcIntType)expr1->u.real); + } else if (expr2Real) { + abCalcExprIntSet(&result, (abCalcIntType)expr2->u.real - expr1->u.integer); + } else { + abCalcExprIntSet(&result, expr2->u.integer - expr1->u.integer); + } + } + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpSubtr.h b/abCalc/ops/abCOpSubtr.h new file mode 100644 index 0000000..e2edefa --- /dev/null +++ b/abCalc/ops/abCOpSubtr.h @@ -0,0 +1,14 @@ +/* + abCOpSubtr.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSUBTR_H +#define ABCOPSUBTR_H + + +void abCalcOpSubtrInit(void); + + +#endif diff --git a/abCalc/ops/abCOpSwap.c b/abCalc/ops/abCOpSwap.c new file mode 100644 index 0000000..8c1cee9 --- /dev/null +++ b/abCalc/ops/abCOpSwap.c @@ -0,0 +1,45 @@ +/* + abCOpSwap.c + By: Jeremy Rand + */ + + +#include +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" +#include "ops/abCOpSwap.h" + + +#define SWAP_NAME "SWAP" + + +static void swapExecute(void); + + +void abCalcOpSwapInit(void) +{ + abCalcOpRegister(SWAP_NAME, swapExecute); +} + + +void swapExecute(void) +{ + abCalcExpr result1; + abCalcExpr result2; + AB_CALC_OP_TWO_ARGS(SWAP_NAME); + + memcpy(&result2, expr2, sizeof(result2)); + memcpy(&result1, expr1, sizeof(result1)); + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result1); + abCalcStackExprPush(&result2); +} diff --git a/abCalc/ops/abCOpSwap.h b/abCalc/ops/abCOpSwap.h new file mode 100644 index 0000000..1edff5f --- /dev/null +++ b/abCalc/ops/abCOpSwap.h @@ -0,0 +1,14 @@ +/* + abCOpSwap.h + By: Jeremy Rand + */ + + +#ifndef ABCOPSWAP_H +#define ABCOPSWAP_H + + +void abCalcOpSwapInit(void); + + +#endif diff --git a/abCalc/ops/abCOpTan.c b/abCalc/ops/abCOpTan.c new file mode 100644 index 0000000..a8f0f76 --- /dev/null +++ b/abCalc/ops/abCOpTan.c @@ -0,0 +1,46 @@ +/* + abCOpTan.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpTan.h" + + +#define TAN_NAME "TAN" + + +static void tanExecute(void); + + +void abCalcOpTanInit(void) +{ + abCalcOpRegister(TAN_NAME, tanExecute); +} + + +void tanExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(TAN_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, TAN_NAME); + return; + } + + abCalcExprRealSet(&result, tan(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpTan.h b/abCalc/ops/abCOpTan.h new file mode 100644 index 0000000..78d5e3f --- /dev/null +++ b/abCalc/ops/abCOpTan.h @@ -0,0 +1,14 @@ +/* + abCOpTan.h + By: Jeremy Rand + */ + + +#ifndef ABCOPTAN_H +#define ABCOPTAN_H + + +void abCalcOpTanInit(void); + + +#endif diff --git a/abCalc/ops/abCOpTanh.c b/abCalc/ops/abCOpTanh.c new file mode 100644 index 0000000..d9c0224 --- /dev/null +++ b/abCalc/ops/abCOpTanh.c @@ -0,0 +1,46 @@ +/* + abCOpTanh.c + By: Jeremy Rand + */ + + +#include +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExpReal.h" + +#include "ops/abCOp.h" +#include "ops/abCOpTanh.h" + + +#define TANH_NAME "TANH" + + +static void tanhExecute(void); + + +void abCalcOpTanhInit(void) +{ + abCalcOpRegister(TANH_NAME, tanhExecute); +} + + +void tanhExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_ONE_ARG(TANH_NAME); + + if (expr->type != abCalcExprTypeReal) { + abCalcRaiseError(abCalcBadArgTypeError, TANH_NAME); + return; + } + + abCalcExprRealSet(&result, tanh(expr->u.real)); + + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpTanh.h b/abCalc/ops/abCOpTanh.h new file mode 100644 index 0000000..47046e9 --- /dev/null +++ b/abCalc/ops/abCOpTanh.h @@ -0,0 +1,14 @@ +/* + abCOpTanh.h + By: Jeremy Rand + */ + + +#ifndef ABCOPTANH_H +#define ABCOPTANH_H + + +void abCalcOpTanhInit(void); + + +#endif diff --git a/abCalc/ops/abCOpXor.c b/abCalc/ops/abCOpXor.c new file mode 100644 index 0000000..412dd26 --- /dev/null +++ b/abCalc/ops/abCOpXor.c @@ -0,0 +1,51 @@ +/* + abCOpXor.c + By: Jeremy Rand + */ + + +#include + +#include "abCError.h" +#include "abCStack.h" + +#include "expr/abCExpr.h" +#include "expr/abCExprInt.h" + +#include "ops/abCOp.h" +#include "ops/abCOpXor.h" + + +#define XOR_NAME "XOR" + + +static void xorExecute(void); + + +void abCalcOpXorInit(void) +{ + abCalcOpRegister(XOR_NAME, xorExecute); +} + + +void xorExecute(void) +{ + abCalcExpr result; + AB_CALC_OP_TWO_ARGS(XOR_NAME); + + if (expr1->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, XOR_NAME); + return; + } + + if (expr2->type != abCalcExprTypeInt) { + abCalcRaiseError(abCalcBadArgTypeError, XOR_NAME); + return; + } + + abCalcExprIntSet(&result, expr2->u.integer ^ expr1->u.integer); + + abCalcStackExprPop(NULL); + abCalcStackExprPop(NULL); + abCalcStackExprPush(&result); +} diff --git a/abCalc/ops/abCOpXor.h b/abCalc/ops/abCOpXor.h new file mode 100644 index 0000000..9b9b136 --- /dev/null +++ b/abCalc/ops/abCOpXor.h @@ -0,0 +1,14 @@ +/* + abCOpXor.h + By: Jeremy Rand + */ + + +#ifndef ABCOPXOR_H +#define ABCOPXOR_H + + +void abCalcOpXorInit(void); + + +#endif diff --git a/abCalc/screenshots/abCalc.png b/abCalc/screenshots/abCalc.png new file mode 100644 index 0000000..5d8b548 Binary files /dev/null and b/abCalc/screenshots/abCalc.png differ diff --git a/abCalc/screenshots/abCalcNDA.png b/abCalc/screenshots/abCalcNDA.png new file mode 100644 index 0000000..b8c7ac7 Binary files /dev/null and b/abCalc/screenshots/abCalcNDA.png differ diff --git a/abCalc/shell.mk b/abCalc/shell.mk new file mode 100644 index 0000000..6206f12 --- /dev/null +++ b/abCalc/shell.mk @@ -0,0 +1,99 @@ +# +# Makefile +# Apple //GS Build Engine for ORCA +# + +include make/head.mk + +# Customize this file to control what kind of project you are working on, +# where to find files, etc. + +# The name of your system or binary file to build goes here: +PGM=abCalcNDA + +# Set the target type you would like to build. The options are: +# shell - A shell command for ORCA, GNO or other GS shell +# desktop - A full desktop application +# cda - A classic desk accessory +# cdev - A control panel device +# nba - A HyperStudio new button action +# nda - A new desk accessory +# xcmd - A HyperCard XCMD or XCFN +# +TARGETTYPE=shell +# TARGETTYPE=desktop +# TARGETTYPE=cda +# TARGETTYPE=cdev +# TARGETTYPE=nba +# TARGETTYPE=nda +# TARGETTYPE=xcmd + +# Add any other directories where you are putting C or assembly source +# files to this list: +# SRCDIRS+= +SRCDIRS+=shell expr ops + +# If you put your main entry point for your project in a file called main.c +# Then you don't need to change this value. If you want to call your entry +# point something other than main.c, set this variable to point to this file. +ROOTCFILE=shell/abCMain.c + +# Add any arguments you want passed to the C compiler to this variable: +CFLAGS+=-dABCALC_GSOS + +# Add any arguments you want passed to the resource compiler to this variable: +REZFLAGS+= + +# Add any arguments you want passed to the macro generator to this variable: +MACGENFLAGS+= + +# Add any other macro libraries to include in this variable: +MACGENMACROS+= + +# Add any arguments you want passed to the assembler to this variable: +ASMFLAGS+= + +# Add any arguments you want passed to the linker to this variable: +LDFLAGS+= + +# Uncomment the following line if you want to build against the GNO libraries +# export ORCA=$(ORCA_BINDIR)/gno + +# If you want to copy one or more files or directories to the target disk +# image, add the root directory to this variable. Any directories under +# the source directory which don't exist in the target disk image will be +# created. All files will be copied from the source to the target using +# the same path from the source. +# +# For example, if you set COPYDIRS to dir and in your project you have +# the following files: +# dir/System/mySystemFile +# dir/newDir/anotherFile +# Then, during the copy phase, mySystemFile will be copied into the System +# folder and a folder newDir will be created and anotherFile will be copied +# into there. +COPYDIRS= + +# By default, the build expects that you have GSplus in the path: +# /Applications/GSplus.app/Contents/MacOS/gsplus +# If you have it in a different location, specify that here. +# GSPLUS=/Applications/GSplus.app/Contents/MacOS/gsplus + +# By default, the build expects that you have GSport in the path: +# /Applications/GSport/GSport.app/Contents/MacOS/GSport +# If you have it in a different location, specify that here. +# GSPORT=/Applications/GSport/GSport.app/Contents/MacOS/GSport + +# Add any rules you want to execute before any compiles or assembly +# commands are called here, if any. You can generate .c, .s or .h +# files for example. You can generate data files. Whatever you +# might need. +gen: + +# For any files you generated in the gen target above, you should +# add rules in genclean to remove those generated files when you +# clean your build. +genclean: + +# Do not change anything else below here... +include make/tail.mk diff --git a/abCalc/shell/abCMain.c b/abCalc/shell/abCMain.c new file mode 100644 index 0000000..6d74347 --- /dev/null +++ b/abCalc/shell/abCMain.c @@ -0,0 +1,77 @@ +/* + abCMain.c + By: Jeremy Rand + */ + + +#include +#include +#include + +#include "abCalc.h" +#include "abCStack.h" +#include "abCError.h" + +#include "expr/abCExpr.h" + +#include "ops/abCOp.h" + + +char gBuffer[AB_CALC_EXPR_STRING_MAX]; +abCalcExpr gExpr; + + +int main(void) +{ + int timeToQuit = 0; + int depth; + int item; + int len; + abCalcOp *op; + char *errorString; + + abCalcInit(); + + while (!timeToQuit) { + printf("\n---------------------------\nStack:\n"); + depth = abCalcStackNumItems(); + + if (depth == 0) { + printf(" Empty!\n"); + } else { + for(item = depth - 1; item >= 0; item--) { + abCalcFormatExpr(abCalcStackExprAt(item), gBuffer); + printf(" %3d: %s\n", item + 1, gBuffer); + } + } + + errorString = abCalcGetError(); + if (errorString != NULL) { + printf("\n === %s ===\n", errorString); + abCalcClearError(); + } + + printf("> "); + if (fgets(gBuffer, sizeof(gBuffer), stdin) != NULL) { + len = strlen(gBuffer); + if ((gBuffer[len - 1] == '\r') || + (gBuffer[len - 1] == '\n')) { + gBuffer[len - 1] = '\0'; + } + + op = abCalcOpLookup(gBuffer); + + if (op != NULL) { + op->execute(); + } else if (abCalcParseExpr(&gExpr, gBuffer) != NULL) { + abCalcStackExprPush(&gExpr); + } else { + abCalcRaiseError(abCalcSyntaxError, NULL); + } + } else { + timeToQuit = 1; + } + } + + exit(0); +}