📄 parser.c
字号:
/* Parser.c (C) 1990, Mark C. Peterson, CompuServe [70441,3353]
All rights reserved.
Code may be used in any program provided the author is credited
either during program execution or in the documentation. Source
code may be distributed only in combination with public domain or
shareware source code. Source code may be modified provided the
copyright notice and this message is left unchanged and all
modifications are clearly documented.
I would appreciate a copy of any work which incorporates this code,
however this is optional.
Mark C. Peterson
405-C Queen St. Suite #181
Southington, CT 06489
(203) 276-9721
*/
/* Chuck Ebbert (CompuServe [76306,1226] ) changed code marked 'CAE fp' */
/* for fast 387 floating-point math. See PARSERA.ASM and PARSERFP.C */
/* (13 Dec 1992.) */
/* */
/* Modified 12 July 1993 by CAE to fix crash when formula not found. */
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <time.h>
#include "mpmath.h"
#include "prototyp.h"
#ifdef WATCH_MP
double x1, y1, x2, y2;
#endif
enum MATH_TYPE MathType = D_MATH;
/* moved _LCMPLX and union ARg to mpmath.h -6-20-90 TIW */
/* PB 910417 added MAX_OPS and MAX_ARGS defines */
/* TW 960101 made all defines depend on MAX_OPS */
#define MAX_OPS 250
#define MAX_ARGS 100
#define MAX_BOXX 8192 /* max size of boxx array */
unsigned Max_Ops = MAX_OPS;
unsigned Max_Args = MAX_ARGS;
struct PEND_OP {
void (far *f)(void);
int p;
};
/* CAE fp added MAX_STORES and LOADS */
/* MAX_STORES must be even to make Unix alignment work */
/* TW made dependent on Max_Ops */
#define MAX_STORES ((Max_Ops/4)*2) /* at most only half the ops can be stores */
#define MAX_LOADS ((unsigned)(Max_Ops*.8)) /* and 80% can be loads */
/* PB 901103 made some of the following static for safety */
static struct PEND_OP far *o;
static void parser_allocate(void);
union Arg *Arg1, *Arg2;
/* PB 910417 removed unused "a" array */
/* CAE fp made some of the following non-static for PARSERA.ASM */
/* Some of these variables should be renamed for safety */
union Arg s[20], far * far *Store, far * far *Load; /* static CAE fp */
int StoPtr, LodPtr, OpPtr; /* static CAE fp */
void (far * far *f)(void) = (void(far * far *)(void))0; /* static CAE fp */
unsigned posp, vsp, LastOp; /* CAE fp made non-static */
static unsigned n, ErrPtr, NextOp, InitN;
static int paren, SyntaxErr, ExpectingArg;
struct ConstArg far *v = (struct ConstArg far *)0; /* was static CAE fp */
int InitLodPtr, InitStoPtr, InitOpPtr, LastInitOp; /* was static CAE fp */
static int Delta16;
double fgLimit; /* TIW 05-04-91 */
static double fg;
static int ShiftBack; /* TIW 06-18-90 */
static int SetRandom; /* MCP 11-21-91 */
static int Randomized;
static unsigned long RandNum;
int uses_p1, uses_p2, uses_p3;
#ifndef XFRACT
#define ChkLongDenom(denom)\
if (denom == 0 || (overflow && save_release > 1920)) {\
overflow = 1;\
return;\
}
#endif
#define ChkFloatDenom(denom)\
if (fabs(denom) <= DBL_MIN) {\
overflow = 1;\
return;\
}
#ifndef TESTING_MATH
#define dShiftx dx1[row]
#define dShifty dy1[col]
#define lShiftx lx1[row]
#define lShifty ly1[col]
#else
#define dShiftx 0.0
#define dShifty 0.0
#define lShiftx 0L
#define lShifty 0L
#endif
#define LastSqr v[4].a
#if (_MSC_VER >= 700)
#pragma code_seg ("parser1_text") /* place following in an overlay */
#endif
#define NO_MATCH_RIGHT_PAREN 8
#define NO_LEFT_BRACKET_FIRST_LINE 9
#define UNEXPECTED_EOF 10
#define INVALID_SYM_USING_NOSYM 11
#define FORMULA_TOO_LARGE 12
#define INSUFFICIENT_MEM_FOR_TYPE_FORMULA 13
#define COULD_NOT_OPEN_FILE_WHERE_FORMULA_LOCATED 14
static char far *ParseErrs(int which)
{
int lasterr;
static FCODE e0[] = {"Should be an Argument"};
static FCODE e1[] = {"Should be an Operator"};
static FCODE e2[] = {"')' needs a matching '('"};
static FCODE e3[] = {"Need more ')'"};
static FCODE e4[] = {"Undefined Operator"};
static FCODE e5[] = {"Undefined Function"};
static FCODE e6[] = {"More than one ','"};
static FCODE e7[] = {"Table overflow"};
static FCODE e8[] = {"Didn't find matching ')'"};
static FCODE e9[] = {"No '{' found on first line"};
static FCODE e10[] = {"Unexpected EOF!"};
static FCODE e11[] = {"Invalid symmetry declared, will use NOSYM"};
static FCODE e12[] = {"Formula is too large"};
static FCODE e13[] = {"Insufficient memory to run fractal type 'formula'"};
static FCODE e14[] = {"Could not open file where formula located"};
static FCODE e15[] = {"Invalid ParseErrs code"}; /* last one */
static FCODE * far ErrStrings[] =
{e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15};
lasterr = sizeof(ErrStrings)/sizeof(ErrStrings[0]) - 1;
if(which > lasterr)
which = lasterr;
return((char far *)ErrStrings[which]);
}
#if (_MSC_VER >= 700)
#pragma code_seg () /* back to normal segment */
#endif
/* use the following when only float functions are implemented to
get MP math and Integer math */
#ifndef XFRACT
#define FUNCT
#ifdef FUNCT /* use function form save space - isn't really slower */
static void mStkFunct(void (*fct)(void)) /* call lStk via dStk */
{
Arg1->d = MPC2cmplx(Arg1->m);
(*fct)();
Arg1->m = cmplx2MPC(Arg1->d);
}
static void lStkFunct(void (*fct)(void)) /* call lStk via dStk */
{
double y;
/*
intermediate variable needed for safety because of
different size of double and long in Arg union
*/
y = (double)Arg1->l.y / fg;
Arg1->d.x = (double)Arg1->l.x / fg;
Arg1->d.y = y;
(*fct)();
if(fabs(Arg1->d.x) < fgLimit && fabs(Arg1->d.y) < fgLimit) {
Arg1->l.x = (long)(Arg1->d.x * fg);
Arg1->l.y = (long)(Arg1->d.y * fg);
}
else
overflow = 1;
}
#else /* use Macro form for (?) greater speed */
/* call lStk via dStk */
#define mStkFunct(fct) \
Arg1->d = MPC2cmplx(Arg1->m);\
(*fct)();\
Arg1->m = cmplx2MPC(Arg1->d);
/* call lStk via dStk */
#define lStkFunct(fct) {\
double y;\
y = (double)Arg1->l.y / fg;\
Arg1->d.x = (double)Arg1->l.x / fg;\
Arg1->d.y = y;\
(*fct)();\
if(fabs(Arg1->d.x) < fgLimit && fabs(Arg1->d.y) < fgLimit) {\
Arg1->l.x = (long)(Arg1->d.x * fg);\
Arg1->l.y = (long)(Arg1->d.y * fg);\
}\
else\
overflow = 1;\
}
#endif
#endif
/* Random number code, MCP 11-21-91 */
unsigned long NewRandNum(void)
{
return(RandNum = ((RandNum << 15) + rand15()) ^ RandNum);
}
void lRandom(void)
{
v[7].a.l.x = NewRandNum() >> (32 - bitshift);
v[7].a.l.y = NewRandNum() >> (32 - bitshift);
}
void dRandom(void)
{
long x, y;
/* Use the same algorithm as for fixed math so that they will generate
the same fractals when the srand() function is used. */
x = NewRandNum() >> (32 - bitshift);
y = NewRandNum() >> (32 - bitshift);
v[7].a.d.x = ((double)x / (1L << bitshift));
v[7].a.d.y = ((double)y / (1L << bitshift));
}
#ifndef XFRACT
void mRandom(void)
{
long x, y;
/* Use the same algorithm as for fixed math so that they will generate
the same fractals when the srand() function is used. */
x = NewRandNum() >> (32 - bitshift);
y = NewRandNum() >> (32 - bitshift);
v[7].a.m.x = *fg2MP(x, bitshift);
v[7].a.m.y = *fg2MP(y, bitshift);
}
#endif
void SetRandFnct(void)
{
unsigned Seed;
if(!SetRandom)
RandNum = Arg1->l.x ^ Arg1->l.y;
Seed = (unsigned)RandNum ^ (unsigned)(RandNum >> 16);
srand(Seed);
SetRandom = 1;
/* Clear out the seed */
NewRandNum();
NewRandNum();
NewRandNum();
}
void RandomSeed(void)
{
time_t ltime;
/* Use the current time to randomize the random number sequence. */
time(<ime);
srand((unsigned int)ltime);
NewRandNum();
NewRandNum();
NewRandNum();
Randomized = 1;
}
#ifndef XFRACT
void lStkSRand(void)
{
SetRandFnct();
lRandom();
Arg1->l = v[7].a.l;
}
#endif
#ifndef XFRACT
void mStkSRand(void)
{
Arg1->l.x = Arg1->m.x.Mant ^ (long)Arg1->m.x.Exp;
Arg1->l.y = Arg1->m.y.Mant ^ (long)Arg1->m.y.Exp;
SetRandFnct();
mRandom();
Arg1->m = v[7].a.m;
}
#endif
void dStkSRand(void)
{
Arg1->l.x = (long)(Arg1->d.x * (1L << bitshift));
Arg1->l.y = (long)(Arg1->d.y * (1L << bitshift));
SetRandFnct();
dRandom();
Arg1->d = v[7].a.d;
}
void (*StkSRand)(void) = dStkSRand;
void dStkAbs(void) {
Arg1->d.x = fabs(Arg1->d.x);
Arg1->d.y = fabs(Arg1->d.y);
}
#ifndef XFRACT
void mStkAbs(void) {
if(Arg1->m.x.Exp < 0)
Arg1->m.x.Exp = -Arg1->m.x.Exp;
if(Arg1->m.y.Exp < 0)
Arg1->m.y.Exp = -Arg1->m.y.Exp;
}
void lStkAbs(void) {
Arg1->l.x = labs(Arg1->l.x);
Arg1->l.y = labs(Arg1->l.y);
}
#endif
void (*StkAbs)(void) = dStkAbs;
void dStkSqr(void) {
LastSqr.d.x = Arg1->d.x * Arg1->d.x;
LastSqr.d.y = Arg1->d.y * Arg1->d.y;
Arg1->d.y = Arg1->d.x * Arg1->d.y * 2.0;
Arg1->d.x = LastSqr.d.x - LastSqr.d.y;
LastSqr.d.x += LastSqr.d.y;
LastSqr.d.y = 0;
}
#ifndef XFRACT
void mStkSqr(void) {
LastSqr.m.x = *MPmul(Arg1->m.x, Arg1->m.x);
LastSqr.m.y = *MPmul(Arg1->m.y, Arg1->m.y);
Arg1->m.y = *MPmul(Arg1->m.x, Arg1->m.y);
Arg1->m.y.Exp++;
Arg1->m.x = *MPsub(LastSqr.m.x, LastSqr.m.y);
LastSqr.m.x = *MPadd(LastSqr.m.x, LastSqr.m.y);
LastSqr.m.y.Mant = (long)(LastSqr.m.y.Exp = 0);
}
void lStkSqr(void) {
LastSqr.l.x = multiply(Arg1->l.x, Arg1->l.x, bitshift);
LastSqr.l.y = multiply(Arg1->l.y, Arg1->l.y, bitshift);
Arg1->l.y = multiply(Arg1->l.x, Arg1->l.y, bitshift) << 1;
Arg1->l.x = LastSqr.l.x - LastSqr.l.y;
LastSqr.l.x += LastSqr.l.y;
LastSqr.l.y = 0L;
}
#endif
void (*StkSqr)(void) = dStkSqr;
void dStkAdd(void) {
Arg2->d.x += Arg1->d.x;
Arg2->d.y += Arg1->d.y;
Arg1--;
Arg2--;
}
#ifndef XFRACT
void mStkAdd(void) {
Arg2->m = MPCadd(Arg2->m, Arg1->m);
Arg1--;
Arg2--;
}
void lStkAdd(void) {
Arg2->l.x += Arg1->l.x;
Arg2->l.y += Arg1->l.y;
Arg1--;
Arg2--;
}
#endif
void (*StkAdd)(void) = dStkAdd;
void dStkSub(void) {
Arg2->d.x -= Arg1->d.x;
Arg2->d.y -= Arg1->d.y;
Arg1--;
Arg2--;
}
#ifndef XFRACT
void mStkSub(void) {
Arg2->m = MPCsub(Arg2->m, Arg1->m);
Arg1--;
Arg2--;
}
void lStkSub(void) {
Arg2->l.x -= Arg1->l.x;
Arg2->l.y -= Arg1->l.y;
Arg1--;
Arg2--;
}
#endif
void (*StkSub)(void) = dStkSub;
void dStkConj(void) {
Arg1->d.y = -Arg1->d.y;
}
#ifndef XFRACT
void mStkConj(void) {
Arg1->m.y.Exp ^= 0x8000;
}
void lStkConj(void) {
Arg1->l.y = -Arg1->l.y;
}
#endif
void (*StkConj)(void) = dStkConj;
void dStkFloor(void) {
Arg1->d.x = floor(Arg1->d.x);
Arg1->d.y = floor(Arg1->d.y);
}
#ifndef XFRACT
void mStkFloor(void) {
mStkFunct(dStkFloor); /* call lStk via dStk */
}
void lStkFloor(void) {
/*
* Kill fractional part. This operation truncates negative numbers
* toward negative infinity as desired.
*/
Arg1->l.x = (Arg1->l.x) >> bitshift;
Arg1->l.y = (Arg1->l.y) >> bitshift;
Arg1->l.x = (Arg1->l.x) << bitshift;
Arg1->l.y = (Arg1->l.y) << bitshift;
}
#endif
void (*StkFloor)(void) = dStkFloor;
void dStkCeil(void) {
Arg1->d.x = ceil(Arg1->d.x);
Arg1->d.y = ceil(Arg1->d.y);
}
#ifndef XFRACT
void mStkCeil(void) {
mStkFunct(dStkCeil); /* call lStk via dStk */
}
void lStkCeil(void) {
/* the shift operation does the "floor" operation, so we
negate everything before the operation */
Arg1->l.x = (-Arg1->l.x) >> bitshift;
Arg1->l.y = (-Arg1->l.y) >> bitshift;
Arg1->l.x = -((Arg1->l.x) << bitshift);
Arg1->l.y = -((Arg1->l.y) << bitshift);
}
#endif
void (*StkCeil)(void) = dStkCeil;
void dStkTrunc(void) {
Arg1->d.x = (int)(Arg1->d.x);
Arg1->d.y = (int)(Arg1->d.y);
}
#ifndef XFRACT
void mStkTrunc(void) {
mStkFunct(dStkTrunc); /* call lStk via dStk */
}
void lStkTrunc(void) {
/* shifting and shifting back truncates positive numbers,
so we make the numbers positive */
int signx, signy;
signx = sign(Arg1->l.x);
signy = sign(Arg1->l.y);
Arg1->l.x = labs(Arg1->l.x);
Arg1->l.y = labs(Arg1->l.y);
Arg1->l.x = (Arg1->l.x) >> bitshift;
Arg1->l.y = (Arg1->l.y) >> bitshift;
Arg1->l.x = (Arg1->l.x) << bitshift;
Arg1->l.y = (Arg1->l.y) << bitshift;
Arg1->l.x = signx*Arg1->l.x;
Arg1->l.y = signy*Arg1->l.y;
}
#endif
void (*StkTrunc)(void) = dStkTrunc;
void dStkRound(void) {
Arg1->d.x = floor(Arg1->d.x+.5);
Arg1->d.y = floor(Arg1->d.y+.5);
}
#ifndef XFRACT
void mStkRound(void) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -