home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- 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);
-
- }