home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include "defs.h"
- #include "externs.h"
-
- int push_val(int *ip);
- char check_keyword(void);
- int push_op(char op);
- int op_pri(char op);
- int do_op(void);
-
- char *keyword[4] = { "\4HIGH", "\3LOW", "\4PAGE", "\4BANK"};
- unsigned char op_stack[64] = { '' };
- unsigned long val_stack[64];
- struct t_symbol *vlablptr;
- int op_idx, val_idx;
- int vcount;
- int vflag;
-
- /* evaluate expression */
-
- evaluate(int *ip, char flag)
- {
- int end, level;
- unsigned char c;
-
- end = 0;
- vflag = 0;
- level = 0;
- undef = 0;
- op_idx = 0;
- val_idx = 0;
- value = 0;
- val_stack[0] = 0;
-
- while (!end) {
- c = prlnbuf[*ip];
- if (isalnum(c) || c == '_' || c == '.') {
- if (vflag == 1)
- goto error;
- if (!push_val(ip))
- return (0);
- }
- else {
- switch (c) {
- case '$':
- case '\'':
- if (vflag == 1)
- goto error;
- if (!push_val(ip))
- return (0);
- break;
- case '(':
- if (vflag == 1)
- goto error;
- if (!push_op('('))
- return (0);
- level++;
- (*ip)++;
- break;
- case ')':
- if (vflag == 0)
- goto error;
- if (level == 0)
- goto error;
- while (op_stack[op_idx] != '(') {
- if (!do_op())
- return (0);
- }
- op_idx--;
- level--;
- (*ip)++;
- break;
- case '>':
- case '<':
- if (vflag == 0)
- goto error;
- if (prlnbuf[++(*ip)] != c)
- goto error;
- if (!push_op(c))
- return (0);
- (*ip)++;
- break;
- case '~':
- if (vflag == 1)
- goto error;
- if (!push_op(c))
- return (0);
- (*ip)++;
- break;
- case '-':
- if (vflag == 0)
- c = '_';
- if (!push_op(c))
- return (0);
- (*ip)++;
- break;
- case '%':
- case '*':
- case '&':
- if (vflag == 0) {
- if (!push_val(ip))
- return (0);
- break;
- }
- case '+':
- case '/':
- case '^':
- case '|':
- if (vflag == 0)
- goto error;
- if (!push_op(c))
- return (0);
- (*ip)++;
- break;
- case ' ':
- case '\t':
- (*ip)++;
- break;
- case ';':
- case '\0':
- end = 1;
- break;
- case ',':
- end = 2;
- break;
- default:
- end = 3;
- break;
- }
- }
- }
- if (vflag == 0)
- goto error;
- if (level != 0)
- goto error;
- while (op_stack[op_idx] != '') {
- if (!do_op())
- return (0);
- }
- value = val_stack[val_idx];
- if (undef != 0) {
- if (pass == LAST_PASS) {
- error("Undefined symbol in operand field!");
- /* return (0); */
- }
- value = 0;
- }
- switch (flag) {
- case ';':
- if (end != 1)
- goto error;
- (*ip)++;
- break;
- case ',':
- if (end != 2)
- goto error;
- (*ip)++;
- break;
- }
- return (1);
-
- error:
- error("Syntax error in expression!");
- return(0);
- }
-
- /* get a number and push it on the value stack */
-
- push_val(int *ip)
- {
- int mul;
- int val;
- char c;
-
- val = 0;
- c = prlnbuf[*ip];
- if (c == '*') {
- val = (loccnt + (page << 13));
- (*ip)++;
- }
- else if (c == '\'') {
- (*ip)++;
- val = prlnbuf[(*ip)++];
- if ((prlnbuf[(*ip)++] != c) || (val == 0)) {
- error("Syntax Error!");
- return (0);
- }
- }
- else if (isalpha(c) || c == '_' || c == '.') {
- colsym(ip);
- if (c = check_keyword()) {
- if (!push_op(c))
- return (0);
- else
- return (1);
- }
- if ((vlablptr = stlook()) == NULL)
- undef = 1;
- else if (vlablptr->type == UNDEF)
- undef = 1;
- else
- val = vlablptr->value;
- vcount++;
- }
- else {
- if (c == '$')
- mul = 16;
- else if (c == '&')
- mul = 8;
- else if (c == '%')
- mul = 2;
- else if (c >= '0' && c <= '9') {
- mul = 10;
- val = c - '0';
- }
- for (;;) {
- c = prlnbuf[++(*ip)];
-
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c)) {
- c = tolower(c);
- if (c >= 'a' && c <= 'f') {
- c -= 'a';
- c += 10;
- }
- else
- break;
- }
- else if (c == '_' && mul == 2)
- continue;
- else
- break;
- if (c >= mul)
- break;
- val = (val * mul) + c;
- }
- }
- if (val_idx == 63) {
- error("Expression too complex!");
- return (0);
- }
- val_idx++;
- val_stack[val_idx] = val;
- vflag = 1;
- return(1);
- }
-
- /* verify a keyword */
-
- char check_keyword(void)
- {
- char c = 0;
-
- if (!strnicmp(symbol, keyword[0], 5))
- c = 'h';
- else if (!strnicmp(symbol, keyword[1], 4))
- c = 'l';
- else if (!strnicmp(symbol, keyword[2], 5))
- c = 'p';
- else if (!strnicmp(symbol, keyword[3], 5))
- c = 'b';
-
- if (c == 'p' || c == 'b') {
- vlablptr = NULL;
- vcount = 0;
- }
- return (c);
- }
-
- /* push an operator on the stack */
-
- push_op(char op)
- {
- if (op != '(') {
- while (op_pri(op_stack[op_idx]) >= op_pri(op)) {
- if (!do_op())
- return (0);
- }
- }
- if (op_idx == 63) {
- error("Expression too complex!");
- return (0);
- }
- op_idx++;
- op_stack[op_idx] = op;
- vflag = 0;
- return (1);
- }
-
- /* return the priority of an operator */
-
- op_pri(char op)
- {
- int pri = 0;
-
- switch (op) {
- case 'b':
- case 'h':
- case 'l':
- case 'p':
- case '_':
- case '~':
- pri++;
- pri++;
- case '*':
- case '/':
- case '%':
- pri++;
- case '+':
- case '-':
- pri++;
- case '<':
- case '>':
- pri++;
- pri++;
- pri++;
- case '&':
- pri++;
- case '^':
- pri++;
- case '|':
- pri++;
- case '':
- case '(':
- break;
- }
- return (pri);
- }
-
- /* apply an operator to the value stack */
-
- do_op(void)
- {
- unsigned long val[2];
- char op;
-
- op = op_stack[op_idx--];
- val[0] = val_stack[val_idx];
- if (op_pri(op) < 10)
- val[1] = val_stack[--val_idx];
- switch (op) {
- case 'p':
- if (vcount != 1) {
- if (vcount == 0)
- error("No symbol in function PAGE!");
- else
- error("Too many symbols in function PAGE!");
- return (0);
- }
- if (vlablptr)
- val[0] = vlablptr->page;
- break;
- case 'b':
- if (vcount != 1) {
- if (vcount == 0)
- error("No symbol in function BANK!");
- else
- error("Too many symbols in function BANK!");
- return (0);
- }
- if (vlablptr)
- val[0] = vlablptr->bank;
- break;
- case 'h':
- val[0] = (val[0] & 0xFF00) >> 8;
- break;
- case 'l':
- val[0] = val[0] & 0xFF;
- break;
- case '+':
- val[0] = val[1] + val[0];
- break;
- case '-':
- val[0] = val[1] - val[0];
- break;
- case '*':
- val[0] = val[1] * val[0];
- break;
- case '/':
- if (val[0] == 0) {
- error("Divide by zero!");
- return (0);
- }
- val[0] = val[1] / val[0];
- break;
- case '%':
- if (val[0] == 0) {
- error("Divide by zero!");
- return (0);
- }
- val[0] = val[1] % val[0];
- break;
- case '_':
- val[0] = -val[0];
- break;
- case '<':
- val[0] = val[1] << (val[0] & 0x1F);
- break;
- case '>':
- val[0] = val[1] >> (val[0] & 0x1f);
- break;
- case '|':
- val[0] = val[1] | val[0];
- break;
- case '^':
- val[0] = val[1] ^ val[0];
- break;
- case '&':
- val[0] = val[1] & val[0];
- break;
- case '~':
- val[0] = ~val[0];
- break;
- default:
- error("Invalid operator in expression!");
- return (0);
- }
-
- val_stack[val_idx] = val[0];
- return (1);
- }
-
-