home *** CD-ROM | disk | FTP | other *** search
- /*
- | CALC command for Epsilon
- |
- | (C)CopyRight Yuval Rakavy 1986 All Rights reserved.
- |
- | Version 1.1 - Character constants added
- |
- | This file contains a pocket calculator package for Epsilon
- |
- | Full C expression are supported execpt for assigment as an operator,
- | and the ? : construct.
- |
- | The following commands are defined:
- |
- | calc Evaluate the value of an expression
- | calc prompts you for an expression having the following syntax:
- | A) <variable-name> = <C-expression>
- | or
- | B) <C-expression>
- |
- | Where <C-expression> is a valid C language expression. You may assign
- | values to variables by using syntax A:. Variables are defined when thay
- | are first used. A newly defined variable has the value 0.
- | The result is displayed in decimal and hex in the echo area, and also
- | assigned to the variable '_'.
- |
- | set-result-format Define the format used by the insert-result command
- | set-result-format prompts you for a 'printf' like format to be used
- | when inserting the result obtained by the last calc command into the
- | current buffer.
- |
- | insert-result Insert last result obtained from calc into the buffer
- | insert-result inserts the result calculated by the last invokation of the
- | calc command into the buffer. The format of the inserted text is
- | controlled by the set-result-format command.
- |
- | dump-variables Display the names and values of all calc variables
- | dump-variables displayes a list of all the CALC variables defined.
- | for each variable defined, dump-variables displayed the name of
- | the variable and its current value in both hex and decimal.
- |
- | set-iter-from-calc Set interation count value to the last 'calc' result.
- */
-
- #define NULL 0
-
- #define TOKEN_NUMBER 0x80
- #define TOKEN_NAME 0x81
- #define TOKEN_LSHIFT 0x82
- #define TOKEN_RSHIFT 0x83
- #define TOKEN_EQ 0x84
- #define TOKEN_NOTEQ 0x85
- #define TOKEN_LAND 0x86
- #define TOKEN_LOR 0x87
- #define TOKEN_LEQ 0x88
- #define TOKEN_GEQ 0x89
- #define TOKEN_BASE 'B'
- #define TOKEN_INC 0x8a
- #define TOKEN_DEC 0x8b
- #define TOKEN_VARIABLE 0x8c
-
- struct CalcName {
- char *Name; /* Variable name */
- int Value; /* Variable value */
- int *NextVar; /* BUG in EEL prevent the correct type which is:
- | struct CalcName *NextVar
- */
- };
-
- struct {
- char First;
- char Second;
- int Token;
- } CalcDoubleCharToken[] = {
- '>', '>', TOKEN_RSHIFT,
- '<', '<', TOKEN_LSHIFT,
- '=', '=', TOKEN_EQ,
- '!', '=', TOKEN_NOTEQ,
- '&', '&', TOKEN_LAND,
- '|', '|', TOKEN_LOR,
- '<', '=', TOKEN_LEQ,
- '>', '=', TOKEN_GEQ,
- '+', '+', TOKEN_INC,
- '-', '-', TOKEN_DEC,
- 0, 0, 0
- };
-
- int CalcResult;
-
- char CalcSyntaxError;
- char *CalcNext;
- char CalcDigits[] = "0123456789ABCDEF";
- char CalcPushBackToken = 0;
- char CalcFormat[20] = "%d";
- int CalcParanLevel;
- struct CalcName *CalcVariables = NULL;
- struct CalcName *CalcFindVar();
-
- union {
- int Numeric;
- struct CalcName *Variable;
- } CalcLLval;
-
- struct CalcPrior {
- char Token;
- char Priority;
- } CalcPrior[] = {
- 0, 0,
- TOKEN_BASE, 1,
- ')', 1,
- TOKEN_LOR, 2,
- TOKEN_LAND, 3,
- '|', 4,
- '^', 5,
- '&', 6,
- TOKEN_EQ, 7,
- TOKEN_NOTEQ, 7,
- '<', 8,
- '>', 8,
- TOKEN_LEQ, 8,
- TOKEN_GEQ, 8,
- TOKEN_RSHIFT, 9,
- TOKEN_LSHIFT, 9,
- '+', 10,
- '-', 10,
- '*', 11,
- '/', 11,
- '%', 11,
- 0xff, 0
- };
-
- struct CalcName *CalcLastResult = NULL;
-
- command calc() {
- char Expr[80];
- int TmpCalcResult;
-
- get_string(Expr, "Expression: ");
- CalcSyntaxError = 0;
- CalcParanLevel = 0;
-
- TmpCalcResult = CalcEval(Expr);
-
- if(CalcParanLevel != 0) {
- if(CalcParanLevel < 0)
- error("Too many )");
- else
- error("Missing )");
- }
- else if(!CalcSyntaxError) {
- CalcResult = TmpCalcResult;
- say("Result: %d %xH", CalcResult, CalcResult);
- if(CalcLastResult == NULL)
- CalcLastResult = CalcFindVar("_");
- CalcLastResult->Value = CalcResult;
- }
- }
-
- command set_result_format() {
- char Buf[30];
-
- sprintf(Buf, "Calc format [%s]: ", CalcFormat);
- get_string(Buf, Buf);
- if(Buf[0] != '\0')
- strcpy(CalcFormat, Buf);
- }
-
- command insert_result() {
- bprintf(CalcFormat, CalcResult);
- }
-
- command dump_variables() {
- char *OldBuf = bufname;
- struct CalcName *p;
- char *temp_buf();
-
- bufname = temp_buf();
- bprintf("Calc variables dump:\n\n");
- bprintf("Name: Value\n");
- for(p = CalcVariables; p; p = (struct CalcName *)p->NextVar)
- bprintf("%-12s %5d %5x\n", p->Name, p->Value, p->Value);
- view_buffer(bufname);
- bufname = OldBuf;
- }
-
- command set_iter_from_calc() {
-
- iter = CalcResult;
-
- getkey();
- has_arg = 1;
- say("");
-
- do_topkey();
- has_arg = 0;
- iter = 1;
- }
-
- CalcSkip() {
- while(*CalcNext == ' ')
- CalcNext++;
- }
-
- IsNumberCharacter(c) {
- return ('0' <= c && c <= '9') || isalpha(c);
- }
-
- IsSymbolCharacter(c) {
- c = tolower(c);
- return ('a' <= c && c <= 'z') || c == '_' || IsNumberCharacter(c);
- }
-
- /*
- | Subroutines used by the calc routines
- */
- struct CalcName *CalcFindVar(Name)
- char *Name;
- {
- struct CalcName *p;
-
- for(p = CalcVariables; p; p = (struct CalcName *)p->NextVar)
- if(!strcmp(p->Name, Name))
- return p;
-
- p = (struct CalcName *)malloc(sizeof(struct CalcName));
- p->Name = (char *)strsave(Name);
- p->NextVar = (int *)CalcVariables;
- p->Value = 0;
- CalcVariables = p;
-
- return p;
- }
-
- CalcToken() {
- char c, *p;
- char Buf[20];
- int Radix, Index;
-
- if(CalcPushBackToken) {
- Index = CalcPushBackToken;
- CalcPushBackToken = 0;
- return Index;
- }
-
- CalcSkip();
-
- if('0' <= *CalcNext && *CalcNext <= '9') {
-
- /*
- | Number, collect all alpha-numeric characters into buffer
- | then try to figure out the base
- */
- Radix = -1;
- if(*CalcNext == '0' && toupper(CalcNext[1]) == 'X') {
- Radix = 16; /* C Style hex number '0xa' */
- CalcNext += 2;
- }
-
- for(Index = 0; Index< 10 && *CalcNext && IsNumberCharacter(*CalcNext);
- Index++)
- Buf[Index] = *CalcNext++;
-
- Buf[Index] = '\0';
-
- if(Radix == -1) {
- /* Figure out the radix based on the last character */
- Radix = 10;
- switch(toupper(Buf[Index-1])) {
-
- case 'H': Radix = 16; break;
- case 'O':
- case 'Q': Radix = 8; break;
- case 'B': Radix = 2; break;
- }
- if(Radix != 10)
- Buf[Index-1] = '\0';
- else if(Buf[0] == '0')
- Radix = 8; /* C like octal numbers */
- }
-
- CalcLLval.Numeric = 0;
- for(Index = 0; Buf[Index]; Index++) {
- if(!(p = index(CalcDigits, toupper(Buf[Index])))) {
- error("Invalid digit");
- return 0;
- }
- if((p - CalcDigits) >= Radix) {
- error("Invalid digit %c for radix %d", Buf[Index], Radix);
- return 0;
- }
- else
- CalcLLval.Numeric = CalcLLval.Numeric*Radix + (p-CalcDigits);
- }
- return TOKEN_NUMBER;
- }
- else if(*CalcNext == '\'') {
- CalcLLval.Numeric = *++CalcNext;
- if(*++CalcNext == '\'')
- CalcNext++; /* Skip on optional closeing ' */
- return TOKEN_NUMBER;
- }
- else if(('a' <= tolower(*CalcNext) && tolower(*CalcNext) <= 'z') ||
- *CalcNext == '_') {
- /* We have a name */
- for(p = Buf; IsSymbolCharacter(*CalcNext); p++)
- *p = *CalcNext++;
- *p = '\0';
- CalcLLval.Variable = CalcFindVar(Buf);
- return TOKEN_VARIABLE;
- }
- else {
- if(*CalcNext == '\0')
- return 0;
-
- /*
- | Check if we have a double character token
- */
- for(Index = 0; CalcDoubleCharToken[Index].First != 0; Index++)
- if(*CalcNext == CalcDoubleCharToken[Index].First &&
- CalcNext[1] == CalcDoubleCharToken[Index].Second) {
- CalcNext += 2;
- return CalcDoubleCharToken[Index].Token;
- }
-
- if(*CalcNext)
- return *CalcNext++;
- else
- return 0;
- }
- }
-
- CalcFindPrior(Operator) {
- int i;
-
- for(i = 0; CalcPrior[i].Token != 0xff; i++)
- if(CalcPrior[i].Token == Operator)
- return CalcPrior[i].Priority;
-
- CalcSyntaxError = 1;
- error("Unkown operator in expression (%x)", Operator);
- return 0;
- }
-
- CalcUnaryExp() {
- int Token;
- int Value;
-
- Token = CalcToken();
-
- if(Token == TOKEN_NUMBER)
- return CalcLLval.Numeric;
- else if(Token == TOKEN_VARIABLE) {
- Token = CalcToken();
- if(Token == TOKEN_INC || Token == TOKEN_DEC) {
- Value = CalcLLval.Variable->Value;
- if(Token == TOKEN_INC)
- CalcLLval.Variable->Value++;
- else
- CalcLLval.Variable->Value--;
- return Value;
- }
- else
- CalcPushBackToken = Token;
-
- return CalcLLval.Variable->Value;
- }
- else if(Token == '-')
- return -CalcUnaryExp();
- else if(Token == '~')
- return ~CalcUnaryExp();
- else if(Token == '(') {
- CalcParanLevel++;
- CalcPushBackToken = TOKEN_BASE;
- return CalcDoEval(0);
- }
- else if(Token == '!')
- return !CalcUnaryExp();
- else if(Token == TOKEN_INC || Token == TOKEN_DEC) {
- if(CalcToken() != TOKEN_VARIABLE) {
- CalcSyntaxError = 1;
- error("Variable expected after ++ or --");
- CalcLLval.Numeric = 0;
- return TOKEN_NUMBER;
- }
- if(Token == TOKEN_INC)
- CalcLLval.Variable->Value++;
- else
- CalcLLval.Variable->Value--;
- return CalcLLval.Variable->Value;
- }
-
- if(!CalcSyntaxError) {
- CalcSyntaxError = 1;
- error("Number expected %d", Token);
- }
- CalcLLval.Numeric = 0;
- return TOKEN_NUMBER;
- }
-
- CalcDoEval(Left) {
- int Oper1;
- int Pri1;
- int Oper2, Pri2;
- int Right;
-
- while((Oper1 = CalcToken()) != 0 && Oper1 != ')') {
-
- Pri1 = CalcFindPrior(Oper1);
- if(*CalcNext) {
- Right = CalcUnaryExp();
- Oper2 = CalcToken();
- Pri2 = CalcFindPrior(Oper2);
- CalcPushBackToken = Oper2;
- }
-
- if(Pri1 < Pri2)
- Right = CalcDoEval(Right);
-
- switch(Oper1) {
-
- case '+': Left += Right; break;
- case '-': Left -= Right; break;
- case '*': Left *= Right; break;
- case '/': Left /= Right; break;
- case '%': Left %= Right; break;
- case TOKEN_LOR: Left = Left || Right; break;
- case TOKEN_LAND: Left = Left && Right; break;
- case '|': Left |= Right; break;
- case '&': Left &= Right; break;
- case '^': Left ^= Right; break;
- case TOKEN_EQ: Left = Left == Right; break;
- case TOKEN_NOTEQ: Left = Left != Right; break;
- case '<': Left = Left < Right; break;
- case '>': Left = Left > Right; break;
- case TOKEN_LEQ: Left = Left <= Right; break;
- case TOKEN_GEQ: Left = Left >= Right; break;
- case TOKEN_LSHIFT: Left <<= Right; break;
- case TOKEN_RSHIFT: Left >>= Right; break;
- case TOKEN_BASE: Left = Right; break;
- }
-
- if(Pri2 < Pri1)
- return Left;
- }
-
- if(Oper1 == ')')
- CalcParanLevel--;
-
- return Left;
- }
-
- CalcEval(Expr)
- char *Expr;
- {
- int Token;
- struct CalcName *p;
-
- /*
- | Test for special case of assignment statement
- */
-
- CalcNext = Expr;
- CalcParanLevel = 0;
- CalcPushBackToken = 0;
-
- if(CalcToken() == TOKEN_VARIABLE) {
- if(CalcToken() == '=') {
- /* Assignment statment */
- p = CalcLLval.Variable;
- CalcPushBackToken = TOKEN_BASE;
- p->Value = CalcDoEval(0);
- return p->Value;
- }
- }
-
- CalcPushBackToken = TOKEN_BASE;
- CalcNext = Expr;
- return CalcDoEval(0);
- }
-