home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
library
/
mslang
/
proclc
/
pc.c
< prev
next >
Wrap
Text File
|
1994-03-22
|
13KB
|
642 lines
/***********************************************************
PROGRAMMER'S CALCULATOR - TSR-MODULE
Copyright (c) 1992-94 by Omega Point, Inc.
************************************************************/
#include "cr.h"
typedef dword (*fpl)();
#define CHK_STACK (0) /* Set to 0 if no stack check, 1 if check */
#define MAX_EXPR (80)
#define MAX_RPN (20)
#define MAX_SUSP (20)
#define BIN_PREF (0x60) /* Back-Quote for binary input */
#define ASGN_PREF (0x27) /* Single Quote - Assignement operator */
#define TYPE_VAL (-1) /* Token type for value */
#define TYPE_ERR (-2) /* Token type for error */
#define RAD2 (0)
#define RAD10 (1)
#define RAD16 (2)
#define WS1 (0)
#define WS2 (1)
#define WS4 (2)
#if CHK_STACK
word free_stk=0xffff;
#endif
char oper_stk[MAX_SUSP]; /* Suspended operators stack */
dword rpn_stk[MAX_RPN]; /* RPN stack values, out-string temp buffer */
char expr[MAX_EXPR+2]; /* User typed expression */
char *nxc; /* Input pointer for expression scan */
dword tok_val; /* Numeric token value */
dword last_val; /* Value of last expression */
int last_tok; /* Last token value */
int last_var; /* Last variable name */
dword vars[26]; /* 26-variables (A-Z) */
dword *rs; /* Current position on RPN stack (values) */
char *os; /* Current position on operator stack */
/** Configuration parameters **/
dword wmask=(dword)(-1);
char sgn=1,radix=RAD10,wsz=WS4;
/*******************************************
OPERATOR EVALUATORS
********************************************/
dword cast_val(np)
register dword *np;
{
if (sgn)
{
if (wsz==WS4) return(*np);
else if (wsz==WS2) return((long)((int)(*np)));
else return((long) ((char)(*np)) );
}
else return(*np&wmask);
}
dword op_or(arg)
register dword *arg;
{
return(arg[0]|arg[1]);
}
dword op_xor(arg)
register dword *arg;
{
return(arg[0]^arg[1]);
}
dword op_and(arg)
register dword *arg;
{
return(arg[0]&arg[1]);
}
dword op_shl(arg)
register dword *arg;
{
return(arg[0]<<(int)arg[1]);
}
dword op_shr(arg)
register dword *arg;
{
register cnt=*(((int*)arg)+2);
if (sgn)
{
if (wsz==WS4)
return((long)arg[0]>>cnt);
else if (wsz==WS2)
return( (long)(*((int*)arg)>>cnt));
else
return( (long)(*((char*)arg)>>cnt));
}
else
return((wmask&arg[0])>>cnt);
}
dword op_rol(arg)
register dword *arg;
{
register cnt=*(((int*)arg)+2);
if (wsz==WS1)
return((long)b_rol(*(int*)arg,cnt));
else if (wsz==WS2)
return((long)w_rol(*(word*)arg,cnt));
else
return(ww_rol(arg[0],cnt));
}
dword op_ror(arg)
register dword *arg;
{
register cnt=*(((int*)arg)+2);
if (wsz==WS1)
return((long)b_ror(*(int*)arg,cnt));
else if (wsz==WS2)
return((long)w_ror(*(word*)arg,cnt));
else
return(ww_ror(arg[0],cnt));
}
dword op_add(arg)
register dword *arg;
{
return(arg[0]+arg[1]);
}
dword op_sub(arg)
register dword *arg;
{
return(arg[0]-arg[1]);
}
dword op_mul(arg)
register dword *arg;
{
return(arg[0]*arg[1]);
}
dword op_div(arg)
register dword *arg;
{
if (arg[1])
{
if (sgn)
return((long)arg[0]/(long)arg[1]);
else
return(arg[0]/arg[1]);
}
else return(-1);
}
dword op_mod(arg)
register dword *arg;
{
if (arg[1])
{
if (sgn)
return((long)arg[0]%(long)arg[1]);
else
return(arg[0]%arg[1]);
}
else return (0);
}
dword op_not(arg)
register dword *arg;
{
rs++;
return(~arg[1]);
}
dword op_neg(arg)
register dword *arg;
{
rs++;
return(-arg[1]);
}
dword op_nul(arg)
register dword *arg;
{
rs++;
return(arg[1]);
}
dword op_asgn(arg)
register dword *arg;
{ register vn=last_var;
last_var=-1;
if (vn<0) rs=rpn_stk; /* Force error if no variable given */
else vars[vn]=*arg; /* Else perform assignement */
return(*arg);
}
/** OPERATOR PRECEDENCE TABLES **/
/* ? | ^ & < > [ ] + - / % * \ ~ FF FE ( ) ' */
char fa[]={55,3,5,7, 9, 9, 9, 9,11,11,13,13,13,13,16,16,16,77, 0, 1 };
char ga[]={56,4,6,8,10,10,10,10,12,12,14,14,14,14,15,15,15, 0,-1,88 };
char oper[]="|^&<>[]+-/%∙\\~\xff\xfe()\x1a";
char oper2[]="<>[]";
fpl exe[]={op_nul,op_or,op_xor,op_and,op_shl,op_shr,op_rol,op_ror,op_add,
op_sub,op_div,op_mod,op_mul,op_mod,op_not,op_neg,op_nul,
op_nul,op_nul,op_asgn};
eval_oper()
{
rs-=1;
*rs = exe[str_pos(*os,oper)](rs);
*rs=cast_val(rs);
os--;
if (rs<=rpn_stk) return(0);
else return(1);
}
/***********************************************
TOKEN EXTRACTION
************************************************/
low_ci()
{
register int c;
register char *s=nxc;
while (*s==0x20) s++;
c=*s++;
if ((c==';')||(!c)) return(0);
nxc=s;
if ((c>='A')&&(c<='Z')) return(c+0x20);
else return(c);
}
/** Get next token from the expression string **/
next_tok()
{ /* Tok > 0 --> Oper,Tok=-1:value,Tok=-2:err,Tok=0 Done */
register char *s;
register int c;
c=low_ci();
if (!c) return(c);
if (str_pos(c,oper2)) /* Check 2 char operators */
{
if (c!=low_ci())
return(TYPE_ERR);
else return(c);
}
if ((last_tok>=0)&&(last_tok!=')'))
{
if (c=='-') return(0xff); /* Unary Minus */
if (c=='+') return(0xfe); /* Unary + as NOP */
}
if (str_pos(c,oper)) return(c);
last_var=-1;
if (c=='?') /* ? stands for LAST VALUE */
{
tok_val=last_val;
return(TYPE_VAL);
}
if ((c>='a')&&(c<='z')) /* Valid variable letters */
{
last_var=c = c-'a';
tok_val=vars[c];
return(TYPE_VAL);
}
/*** Extract number ***/
s=nxc-1;
if ((c<='9')&&(c>'0')) /* Decimal 1-9 starting digit */
{
s=dec2ul(s,&tok_val);
}
else if (c=='0') /* Hex - Start with leading 0 */
{
s++;
if ((*s=='x')||(*s=='X')) s++;
if ((*s=='+')||(*s=='-')) s--;
s=hex2ul(s,&tok_val);
}
else if (c==BIN_PREF) /* Binary string */
{
s=bin2ul(s+1,&tok_val);
}
else s=0;
if (!s) return(TYPE_ERR);
nxc=s;
return(TYPE_VAL);
}
/**************************************************
EXPRESSION EVALUATOR
***************************************************/
eval_expr(s)
char *s;
{ int t,fp,gp;
nxc=s; last_tok=0;
rs=rpn_stk; *rs=0;
os=oper_stk; *os='(';
do {
t=next_tok();
last_tok=t;
if (t==TYPE_VAL) /* Variable */
{
rs++;
if (rs>=&rpn_stk[MAX_RPN])
return(0);
*rs=cast_val(&tok_val);
continue;
}
if (t==TYPE_ERR) /* Error in expression */
return(0);
if (!t) /* End of string reached */
if (os>oper_stk) t=')';
else break;
fp=fa[str_pos(t,oper)]; /* fp=Operator input precedence */
do {
if (os<oper_stk)
{
os=oper_stk;
*os='(';
}
gp=ga[str_pos(*os,oper)]; /* gp=Operator stack prec. */
if (fp<=gp)
if (!eval_oper()) return(0);
} while (fp<gp);
if (fp>0) *(++os)=(char)t;
if (os>=&oper_stk[MAX_SUSP]) return(0);
} while(1);
if (rs!=rpn_stk+1) return(0);
last_val=cast_val(rs);
return(1);
}
/***************************************************
CALCULATOR COMMADS
****************************************************/
#define ALT_X (45<<8)
#define CMD_EQU (-2)
#define DEC_RL (12)
#define HEX_RL (10)
#define BIN_RL (37)
byte atr_expr=0x1f,atr_rslt=0x4e; /* Screen Attributes */
byte atr_rad=0x4b;
word sep_let=0x20;
int sdx=80,sdy=1; /* Window size */
int x0=0,y0=24; /* Window Left Upper Corner */
int rx0=0,rlen=DEC_RL; /* Result x-pos, length */
int ex0=DEC_RL; /* Expression x-pos & length */
int expr_w=MAX_EXPR-DEC_RL;
/* BIN DEC HEX */
char rlen_tbl[3*3]={12,21,39, 7,9,14, 6,8,12 };
char rad_let[3]={'B','D','H'};
cvt_num(nump,strp)
char *strp;
dword *nump;
{ register char *s=strp;
register char *v;
v=(char*)nump + (1 << wsz);
if (radix==RAD2)
{
do {
v--;
s=b2bin(*((int *)v),s);
*s++='.'; /* Separate in 8 digit chunks */
}
while (v>(char*)nump);
s[-1]=0x20;
}
else do
{
v--;
s=b2hex(*((int *)v),s);
}
while (v>(char*)nump);
}
show_result(k)
{
register char *s=(char*)rpn_stk;
dword tmp;
rlen=rlen_tbl[3*radix+wsz];
ex0=rlen; expr_w=MAX_EXPR-rlen;
*s=rad_let[radix]; *(word*)(s+1)=':';
vid_atr=atr_rad; crs_x=0;
dsp(s);
*(word*)(fil_chr(s,0x20,rlen)-1) = sep_let;
s+=3; /* Leave extra 2 blanks for output formating */
*s='?'; /* Fill fo error case (will get overwritten ) */
if (k)
{
tmp=cast_val(&last_val);
if (sgn && *(((int*)(&tmp))+1)<0) /* Signed & negative */
{
s[-1]='-'; tmp= -((long)tmp);
}
tmp &= wmask;
if (radix==RAD10) ul2dec(tmp,s);
else cvt_num(&tmp,s);
}
vid_atr=atr_rslt;
dsp(((char*)rpn_stk)+2);
}
/** KEY-FILTER FOR STRING EDITOR **/
word filter()
{
register word k,bk;
while (!anykey())
if (_hkey_again) return(K_ESC);
k=pckey(); bk=(byte)k;
if (bk=='=') bk=CMD_EQU; /* We don't display '=' key */
if ((bk==0xd)&&(kbflag&3)) k=K_F10; /* Shift-CR, or F10 */
if (bk==ASGN_PREF) bk=0x221a; /* Make arrow (graphic char entry)*/
if (bk=='*') bk=0xf9; /* Make nice small multiply symbol */
if (bk>0x1f) k=bk; /* If plain ASCII - pass low part */
return(k); /* If cursor/func key - pass full key */
}
/***************************************************
CALCULATOR COMMAND LOOP
****************************************************/
static int edit_pos=1,ok=1;
char *stf_ptr;
run_calc()
{ int k,stf;
register n;
register char *s;
(int)stf_ptr=stf=0; /* Cancell any key stuffing */
do
{
show_result(ok);
if (stf) /* Stuff-keys was set */
{
n=radix;
s=((char*)rpn_stk)+2; /* Point into sign field */
if (n!=RAD10)
{
if (n==RAD16)
{
s[-1]=*s;
*s='0';
}
s++; /* Skip leading 0 */
if (stf<0) /* C format */
{
if (n==RAD16)
ins_chr('x',s);
}
else /* ASM format */
{
s=s+str_pos(sep_let,s);
s--;
if (n==RAD2) *s='b';
else *s='h';
}
s=(char*)rpn_stk;
}
while (*s==0x20) s++;
stf_ptr=s;
add_tsc_event((long)1);
return;
}
crs_x=ex0; vid_atr=atr_expr;
if (!(*expr)) edit_pos=1;
s=expr;
k=edit_str(s,expr_w,&edit_pos,filter);
s+=edit_pos;
if (((byte)k)&&(k>0)) k=(byte)k;
switch (k)
{
case ALT_X: if (unload_safe())
uninstall();
case 0x1b: return;
case CK_RIGHT: n=str_pos(';',s);
if (!n) edit_pos=-1;
else edit_pos += n;
break;
case CK_LEFT: while (s>expr)
if (*s--==';') break;
if ((edit_pos=s-expr)<=0)
edit_pos=str_len(expr)-1;
break;
case K_UP: move_win(-1); break;
case K_DN: move_win(1); break;
case 'U'-64: sgn=0; break;
case 'S'-64: sgn=1; break;
case 'B'-64: radix=RAD2;break;
case 'D'-64: radix=RAD10;break;
case 'H'-64: radix=RAD16;break;
case 'C'-64: wsz=WS1; wmask=0xff;
break;
case 'I'-64: wsz=WS2; wmask=0xffff;
break;
case 'L'-64: wsz=WS4; wmask=(dword)-1;
break;
case K_F5: stf=-1;break; /* C format */
case K_F6: stf= 1;break; /* ASM format */
}
s=expr;
do{
n=str_pos(';',s);
if (0==(ok=eval_expr(s)))
{
edit_pos=nxc-expr;
break;
}
s+=n;
}
while (*s && n && (expr+edit_pos)>=s );
if (k==K_F10 && ok)
expr[0]=0;
}
while(1);
}
/***********************************************
TSR MODE ENTRY/EXIT HANDLERS
************************************************/
/** Save/Restore foreground screen **/
extern word scr_buf[];
chg_scr(func)
fp func;
{
crs_x=x0; crs_y=y0;
(*func)(sdx,sdy,scr_buf);
}
/** MOVE EDIT WINDOW UP/DOWN **/
move_win(n)
{
chg_scr(put_blk); /* Restore screen */
y0+=n;
if (y0<0) y0=scr_len-1;
else if (y0>=scr_len) y0=0;
chg_scr(get_blk);
}
/******************************************************************
HOTKEY SERVICE FUNCTION
*******************************************************************/
isr()
{
#if CHK_STACK
word n;
if (free_stk==0xffff) _watch_stack();
else last_val=free_stk;
#endif
chk_video(); /* Update video param's */
save_crs(); /* Save foreground cursor */
chg_scr(get_blk); /* Save foreground screen */
_hkey_again=0; /* We use hotkey as ON/OFF button */
run_calc(); /* Do calculator command loop */
chg_scr(put_blk); /* Restore foreground screen */
restore_crs(); /* Restore foreground cursor */
#if CHK_STACK
n=_unused_stack();
if (n<free_stk) free_stk=n;
#endif
}
/**************************************************************
TINY SCHEDULER SERCVICE FUNCTION
--------------------------------------------------------------
Used to stuff keys (result) to foreground application.
***************************************************************/
tmr_isr()
{
register char *s=stf_ptr;
if (!s) return;
if ('.'==*s) s++;
if (*s<'-') return;
if (!anykey()) stuff_key(*s++);
stf_ptr=s;
add_tsc_event((long)1);
}