diff --git a/src/cali.c b/src/cali.c index 260b4c8..9ba096e 100644 --- a/src/cali.c +++ b/src/cali.c @@ -18,11 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * - * 0.00 97/11/27 初版 - * 0.01 97/12/06 計算式の評価順序がおかしかった - * @version 0.01-01 97/12/06 メッセージから日本語を削除 - * */ /* $Id: cali.c,v 1.16 2002/12/31 04:11:19 chikama Exp $ */ @@ -34,19 +29,25 @@ #include "nact.h" #include "xsystem35.h" -#define CALI_TRUE (1) /* comparison is ture */ -#define CALI_FALSE (0) /* comparison is false */ -#define CALI_MAX_VAL (65535) /* maxinum of value */ -#define CALI_MIN_VAL (0) /* mininum of value */ -#define CALI_NaN (CALI_MIN_VAL) /* devied by 0 */ -#define CALI_OF (CALI_MAX_VAL) /* calculate over flow */ -#define CALI_SubNG (CALI_MIN_VAL) /* nagative result */ -#define CALI_TERMINATER (0x7f) /* terminater */ +#define OP_AND 0x74 +#define OP_OR 0x75 +#define OP_XOR 0x76 +#define OP_MUL 0x77 +#define OP_DIV 0x78 +#define OP_ADD 0x79 +#define OP_SUB 0x7a +#define OP_EQUAL 0x7b +#define OP_LT 0x7c +#define OP_GT 0x7d +#define OP_NEQUAL 0x7e +#define OP_END 0x7f -#define CALI_DEPTH_MAX (256) +#define OP_C0_INDEX 1 +#define OP_C0_MOD 2 +#define OP_C0_LE 3 +#define OP_C0_GE 4 -static int buf[CALI_DEPTH_MAX]; /* 計算式バッファ */ -static int *cali = buf; /* インデックス */ +#define CALI_DEPTH_MAX 256 static int *getVar(int c0, struct VarRef *ref) { int addr = sl_getIndex(); @@ -55,9 +56,9 @@ static int *getVar(int c0, struct VarRef *ref) { var = c0 & 0x3f; // 0 - 0x3f } else { int c1 = sl_getc(); - if (c0 != 0xc0) + if (c0 != 0xc0) { var = (c0 & 0x3f) * 256 + c1; // 0x100 - 0x3fff - else if (c1 == 1) { + } else if (c1 == 1) { c0 = sl_getc(); c1 = sl_getc(); var = c0 << 8 | c1; @@ -79,178 +80,140 @@ static int *getVar(int c0, struct VarRef *ref) { return store; } -/* 変数番号が返る */ +// Returns a pointer to the variable int *getCaliVariable(void) { int *c0 = getVar(sl_getc(), NULL); - if (sl_getc() != 0x7f) { - SYSERROR("Something is Wrong @ %03d:%05x", sl_getPage(), sl_getIndex()); + if (sl_getc() != OP_END) { + SYSERROR("Invalid variable expression at %03d:%05x", sl_getPage(), sl_getIndex()); } return c0; } bool getCaliArray(struct VarRef *ref) { bool ok = getVar(sl_getc(), ref) != NULL; - if (sl_getc() != 0x7f) { - SYSERROR("Something is Wrong @ %03d:%05x", sl_getPage(), sl_getIndex()); + if (sl_getc() != OP_END) { + SYSERROR("Invalid variable expression at %03d:%05x", sl_getPage(), sl_getIndex()); } return ok; } -/* 変数代入コマンド用 */ +// For variable assignment commands int *getVariable(void) { return getVar(sl_getc(), NULL); } -/* 計算式の評価後の値が返る */ +// Returns the result of the calculation int getCaliValue(void) { - register int ingVal,edVal,rstVal; + uint16_t stack[CALI_DEPTH_MAX]; + uint16_t *sp = stack; + int rhs, lhs, result; int c0,c1; - int *bufc = cali; - - while((c0 = sl_getc()) != CALI_TERMINATER) { - if ((c0 & 0x80) != 0) { /* variable */ + + while ((c0 = sl_getc()) != OP_END) { + if (c0 & 0x80) { // variable int c1 = sl_getcAt(sl_getIndex()); int *t; if (c0 == 0xc0) { - if (c1 == 1 || c1 >= 0x34) goto l_var; + if (c1 == OP_C0_INDEX || c1 >= 0x34) goto l_var; c1 = sl_getc(); - if (c1 == 2) { /* % */ - ingVal = *--cali; - edVal = *--cali; - if (ingVal == 0) { - *cali = CALI_NaN; - } else { - rstVal = edVal % ingVal; - *cali = rstVal; - } - cali++; + if (c1 == OP_C0_MOD) { + rhs = *--sp; + lhs = *--sp; + *sp++ = rhs ? lhs % rhs : 0; continue; - } else if (c1 == 3) { /* <= */ - ingVal = *--cali; - edVal = *--cali; - if (edVal <= ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + } else if (c1 == OP_C0_LE) { + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs <= rhs); continue; - } else if (c1 == 4) { /* >= */ - ingVal = *--cali; - edVal = *--cali; - if (edVal >= ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + } else if (c1 == OP_C0_GE) { + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs >= rhs); continue; } else if (c1 < 0x34) { - SYSERROR("Unknow Parameter @ %03d:%05x", sl_getPage(), sl_getIndex()); + SYSERROR("Unknown operator at %03d:%05x", sl_getPage(), sl_getIndex()); } } l_var: t = getVar(c0, NULL); - *cali++ = t ? *t : 0; + *sp++ = t ? *t : 0; } else { switch(c0) { - case 0x7e: /* != */ - ingVal = *--cali; - edVal = *--cali; - if (edVal != ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + case OP_NEQUAL: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs != rhs); break; - case 0x7d: /* > */ - ingVal = *--cali; - edVal = *--cali; - if (edVal > ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + case OP_GT: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs > rhs); break; - case 0x7c: /* < */ - ingVal = *--cali; - edVal = *--cali; - if (edVal < ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + case OP_LT: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs < rhs); break; - case 0x7b: /* == */ - ingVal = *--cali; - edVal = *--cali; - if (edVal == ingVal) { *cali = CALI_TRUE; } - else { *cali = CALI_FALSE; } - cali++; + case OP_EQUAL: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs == rhs); break; - case 0x7a: /* - */ - ingVal = *--cali; - edVal = *--cali; - rstVal = edVal - ingVal; - if (rstVal < CALI_MIN_VAL) { *cali = CALI_SubNG; } - else { *cali = rstVal; } - cali++; + case OP_SUB: + rhs = *--sp; + lhs = *--sp; + result = lhs - rhs; + *sp++ = result < 0 ? 0 : result; break; - case 0x79: /* + */ - ingVal = *--cali; - edVal = *--cali; - rstVal = edVal + ingVal; - if (rstVal > CALI_MAX_VAL) { *cali = CALI_OF; } - else { *cali = rstVal; } - cali++; + case OP_ADD: + rhs = *--sp; + lhs = *--sp; + result = lhs + rhs; + *sp++ = result > 0xffff ? 0xffff : result; break; - case 0x78: /* / */ - ingVal = *--cali; - edVal = *--cali; - if (ingVal == 0) { - *cali = CALI_NaN; - } else { - rstVal = edVal / ingVal; - *cali = rstVal; - } - cali++; + case OP_DIV: + rhs = *--sp; + lhs = *--sp; + *sp++ = rhs ? lhs / rhs : 0; break; - case 0x77: /* * */ - ingVal = *--cali; - edVal = *--cali; - rstVal = edVal * ingVal; - if (rstVal > CALI_MAX_VAL) { *cali = CALI_OF; } - else { *cali = rstVal; } - cali++; + case OP_MUL: + rhs = *--sp; + lhs = *--sp; + result = lhs * rhs; + *sp++ = result > 0xffff ? 0xffff : result; break; - case 0x76: /* XOR */ - ingVal = *--cali; - edVal = *--cali; - *cali = (edVal ^ ingVal); cali++; + case OP_XOR: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs ^ rhs); break; - case 0x75: /* OR */ - ingVal = *--cali; - edVal = *--cali; - *cali = (edVal | ingVal); cali++; + case OP_OR: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs | rhs); break; - case 0x74: /* AND */ - ingVal = *--cali; - edVal = *--cali; - *cali = (edVal & ingVal); cali++; + case OP_AND: + rhs = *--sp; + lhs = *--sp; + *sp++ = (lhs & rhs); break; - default: - if ((c0 & 0x40) == 0) { /* WORD const */ + default: // immediate value + if (c0 & 0x40) { // 0x0 - 0x33 + *sp++ = (c0 & 0x3f); + } else { // 0x34 - 0x3fff c1 = sl_getc(); - if (c0 == 0) { /* 34h-ffh */ - if (c1 <= 0x33) { - SYSERROR("Unknown Parameter @ %03d:%05x", sl_getPage(), sl_getIndex()); - } - } else { /* 100h- 3fff */ - c1 += ((c0 & 0x3f) * 256); - } - } else { /* byte const 0-33h */ - c1 = (c0 & 0x3f); + if (c0 == 0 && c1 <= 0x33) + SYSERROR("Invalid cali at %03d:%05x", sl_getPage(), sl_getIndex()); + *sp++ = (c0 & 0x3f) << 8 | c1; } - // printf("c1 = %d ",c1); - *cali = c1; cali++; } } } - c0 = *--cali; - if (cali != bufc) { - WARNING("Something is wrong @ %03d:%05x", sl_getPage(), sl_getIndex()); - cali = bufc; + if (sp != stack + 1) { + WARNING("Unexpected end of expression at %03d:%05x", sl_getPage(), sl_getIndex()); return 0; } - - return c0; + return *--sp; } diff --git a/test/System39.ain b/test/System39.ain index ff670da..e415a19 100644 Binary files a/test/System39.ain and b/test/System39.ain differ diff --git a/test/arith.adv b/test/arith.adv new file mode 100644 index 0000000..b91f9a4 --- /dev/null +++ b/test/arith.adv @@ -0,0 +1,35 @@ + MS FILE, "arith.adv": + ~AssertEquals 3+4, 7, __LINE__: + ~AssertEquals 50000+50000, 65535, __LINE__: + ~AssertEquals 10-3, 7, __LINE__: + ~AssertEquals 3-10, 0, __LINE__: + ~AssertEquals 3*4, 12, __LINE__: + ~AssertEquals 1000*1000, 65535, __LINE__: + ~AssertEquals 1000*1000-1, 65534, __LINE__: + ~AssertEquals 10/2, 5, __LINE__: + ~AssertEquals 10/3, 3, __LINE__: + ~AssertEquals 10/0, 0, __LINE__: + ~AssertEquals 10%3, 1, __LINE__: + ~AssertEquals 10%0, 0, __LINE__: + + ~AssertEquals 5&3, 1, __LINE__: + ~AssertEquals 5|3, 7, __LINE__: + ~AssertEquals 5^3, 6, __LINE__: + + ~AssertEquals 3<2, 0, __LINE__: + ~AssertEquals 3<3, 0, __LINE__: + ~AssertEquals 3<4, 1, __LINE__: + ~AssertEquals 3<=2, 0, __LINE__: + ~AssertEquals 3<=3, 1, __LINE__: + ~AssertEquals 3<=4, 1, __LINE__: + ~AssertEquals 3>2, 1, __LINE__: + ~AssertEquals 3>3, 0, __LINE__: + ~AssertEquals 3>4, 0, __LINE__: + ~AssertEquals 3>=2, 1, __LINE__: + ~AssertEquals 3>=3, 1, __LINE__: + ~AssertEquals 3>=4, 0, __LINE__: + ~AssertEquals 3=2, 0, __LINE__: + ~AssertEquals 3=3, 1, __LINE__: + ~AssertEquals 3\2, 1, __LINE__: + ~AssertEquals 3\3, 0, __LINE__: + %0: diff --git a/test/test.adv b/test/test.adv index 08e7ff5..36405a5 100644 --- a/test/test.adv +++ b/test/test.adv @@ -9,6 +9,7 @@ !tests_passed:0! !tests_failed:0! + %#arith.adv: %#array.adv: %#strvar.adv: %#stack.adv: diff --git a/test/test.hed b/test/test.hed index 296e8ed..8da7b91 100644 --- a/test/test.hed +++ b/test/test.hed @@ -1,6 +1,7 @@ #SYSTEM35 test.adv util.adv +arith.adv array.adv strvar.adv stack.adv diff --git a/test/testSA.ALD b/test/testSA.ALD index 557633f..1f066ac 100644 Binary files a/test/testSA.ALD and b/test/testSA.ALD differ