home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / mslang / proclc / pc.c < prev    next >
Text File  |  1994-03-22  |  13KB  |  642 lines

  1. /***********************************************************
  2.         PROGRAMMER'S CALCULATOR - TSR-MODULE 
  3.       Copyright (c) 1992-94 by Omega Point, Inc.
  4. ************************************************************/
  5.  
  6. #include "cr.h"
  7. typedef  dword (*fpl)();
  8.  
  9. #define CHK_STACK (0)    /* Set to 0 if no stack check, 1 if check */
  10.  
  11. #define MAX_EXPR (80)
  12. #define MAX_RPN  (20)
  13. #define MAX_SUSP (20)
  14.  
  15. #define BIN_PREF (0x60)     /* Back-Quote for binary input */
  16. #define ASGN_PREF (0x27) /* Single Quote - Assignement operator */
  17.  
  18. #define TYPE_VAL (-1)     /* Token type for value */
  19. #define TYPE_ERR (-2)     /* Token type for error */
  20.  
  21. #define RAD2  (0)
  22. #define RAD10 (1)
  23. #define RAD16 (2)
  24. #define WS1   (0)
  25. #define WS2   (1)
  26. #define WS4   (2)
  27.  
  28. #if CHK_STACK
  29. word free_stk=0xffff;
  30. #endif
  31.  
  32. char oper_stk[MAX_SUSP]; /* Suspended operators stack */
  33. dword rpn_stk[MAX_RPN];     /* RPN stack values, out-string temp buffer */
  34. char expr[MAX_EXPR+2];     /* User typed expression   */
  35.  
  36. char *nxc;    /* Input pointer for expression scan */
  37. dword tok_val;    /* Numeric token value */
  38. dword last_val; /* Value of last expression */
  39. int last_tok;    /* Last token value */
  40. int last_var;    /* Last variable name */
  41. dword vars[26];    /* 26-variables (A-Z) */
  42. dword *rs;    /* Current position on RPN stack (values) */
  43. char *os;    /* Current position on operator stack */
  44.  
  45. /** Configuration parameters **/
  46.  
  47. dword wmask=(dword)(-1);
  48. char sgn=1,radix=RAD10,wsz=WS4;
  49.  
  50. /*******************************************
  51.     OPERATOR EVALUATORS
  52. ********************************************/
  53.  
  54. dword cast_val(np)
  55. register dword *np;
  56. {
  57.   if (sgn)
  58.     {
  59.     if (wsz==WS4) return(*np);
  60.       else if (wsz==WS2) return((long)((int)(*np)));
  61.     else return((long) ((char)(*np)) );
  62.     }
  63.   else return(*np&wmask);
  64. }
  65.  
  66. dword op_or(arg)
  67. register dword *arg;
  68. {
  69.   return(arg[0]|arg[1]);
  70. }
  71.  
  72. dword op_xor(arg)
  73. register dword *arg;
  74. {
  75.   return(arg[0]^arg[1]);
  76. }
  77.  
  78. dword op_and(arg)
  79. register dword *arg;
  80. {
  81.   return(arg[0]&arg[1]);
  82. }
  83.  
  84. dword op_shl(arg)
  85. register dword *arg;
  86. {
  87.   return(arg[0]<<(int)arg[1]);
  88. }
  89.  
  90. dword op_shr(arg)
  91. register dword *arg;
  92. {
  93.   register cnt=*(((int*)arg)+2);
  94.   if (sgn)
  95.     {
  96.     if (wsz==WS4)
  97.     return((long)arg[0]>>cnt);
  98.     else if (wsz==WS2)
  99.     return( (long)(*((int*)arg)>>cnt));
  100.     else
  101.     return( (long)(*((char*)arg)>>cnt));
  102.     }
  103.   else
  104.     return((wmask&arg[0])>>cnt);
  105. }
  106.  
  107. dword op_rol(arg)
  108. register dword *arg;
  109. {
  110.   register cnt=*(((int*)arg)+2);
  111.   if (wsz==WS1)
  112.     return((long)b_rol(*(int*)arg,cnt));
  113.   else if (wsz==WS2)
  114.     return((long)w_rol(*(word*)arg,cnt));
  115.   else
  116.     return(ww_rol(arg[0],cnt));
  117. }
  118.  
  119.  
  120. dword op_ror(arg)
  121. register dword *arg;
  122. {
  123.   register cnt=*(((int*)arg)+2);
  124.   if (wsz==WS1)
  125.     return((long)b_ror(*(int*)arg,cnt));
  126.   else if (wsz==WS2)
  127.     return((long)w_ror(*(word*)arg,cnt));
  128.   else
  129.     return(ww_ror(arg[0],cnt));
  130. }
  131.  
  132. dword op_add(arg)
  133. register dword *arg;
  134. {
  135.   return(arg[0]+arg[1]);
  136. }
  137.  
  138. dword op_sub(arg)
  139. register dword *arg;
  140. {
  141.   return(arg[0]-arg[1]);
  142. }
  143.  
  144. dword op_mul(arg)
  145. register dword *arg;
  146. {
  147.   return(arg[0]*arg[1]);
  148. }
  149.  
  150. dword op_div(arg)
  151. register dword *arg;
  152. {
  153.   if (arg[1])
  154.     {
  155.     if (sgn)
  156.     return((long)arg[0]/(long)arg[1]);
  157.     else
  158.     return(arg[0]/arg[1]);
  159.     }
  160.  
  161.   else return(-1);
  162. }
  163.  
  164. dword op_mod(arg)
  165. register dword *arg;
  166. {
  167.   if (arg[1])
  168.     {
  169.     if (sgn)
  170.     return((long)arg[0]%(long)arg[1]);
  171.     else
  172.     return(arg[0]%arg[1]);
  173.     }
  174.   else return (0);
  175. }
  176.  
  177. dword op_not(arg)
  178. register dword *arg;
  179. {
  180.   rs++;
  181.   return(~arg[1]);
  182. }
  183.  
  184.  
  185. dword op_neg(arg)
  186. register dword *arg;
  187. {
  188.   rs++;
  189.   return(-arg[1]);
  190. }
  191.  
  192. dword op_nul(arg)
  193. register dword *arg;
  194. {
  195.    rs++;
  196.    return(arg[1]);
  197. }
  198.  
  199.  
  200. dword op_asgn(arg)
  201. register dword *arg;
  202. { register vn=last_var;
  203.  
  204.    last_var=-1;
  205.    if (vn<0) rs=rpn_stk; /* Force error if no variable given */
  206.      else vars[vn]=*arg; /* Else perform assignement */
  207.    return(*arg);
  208. }
  209.  
  210. /** OPERATOR PRECEDENCE TABLES **/
  211.  
  212. /*          ? | ^ &  <  >  [  ]  +  -  /  %  *  \  ~ FF FE  (  )  '  */
  213. char fa[]={55,3,5,7, 9, 9, 9, 9,11,11,13,13,13,13,16,16,16,77, 0, 1 }; 
  214. char ga[]={56,4,6,8,10,10,10,10,12,12,14,14,14,14,15,15,15, 0,-1,88 }; 
  215.  
  216. char oper[]="|^&<>[]+-/%∙\\~\xff\xfe()\x1a";
  217. char oper2[]="<>[]";
  218.  
  219. fpl exe[]={op_nul,op_or,op_xor,op_and,op_shl,op_shr,op_rol,op_ror,op_add,
  220.        op_sub,op_div,op_mod,op_mul,op_mod,op_not,op_neg,op_nul,
  221.        op_nul,op_nul,op_asgn};
  222.  
  223. eval_oper()
  224. {
  225.      rs-=1;
  226.      *rs = exe[str_pos(*os,oper)](rs);
  227.      *rs=cast_val(rs);
  228.      os--;
  229.      if (rs<=rpn_stk) return(0);
  230.        else return(1);
  231. }
  232.  
  233. /***********************************************
  234.     TOKEN EXTRACTION
  235. ************************************************/
  236.  
  237.  
  238. low_ci()
  239. {
  240.   register int c;
  241.   register char *s=nxc;
  242.     while (*s==0x20) s++;
  243.     c=*s++;
  244.     if ((c==';')||(!c)) return(0);
  245.     nxc=s;
  246.     if ((c>='A')&&(c<='Z')) return(c+0x20);
  247.       else return(c);
  248. }
  249.  
  250. /** Get next token from the expression string **/
  251.  
  252. next_tok()
  253. {          /* Tok > 0 --> Oper,Tok=-1:value,Tok=-2:err,Tok=0 Done */
  254.    register char *s;
  255.    register int c;
  256.  
  257.     c=low_ci();
  258.     if (!c) return(c);
  259.  
  260.     if (str_pos(c,oper2)) /* Check 2 char operators */
  261.       {
  262.       if (c!=low_ci())
  263.          return(TYPE_ERR);
  264.       else return(c);
  265.       }
  266.  
  267.     if ((last_tok>=0)&&(last_tok!=')'))
  268.       {
  269.       if (c=='-') return(0xff);    /* Unary Minus */
  270.       if (c=='+') return(0xfe);    /* Unary + as NOP */
  271.       }
  272.  
  273.     if (str_pos(c,oper)) return(c);
  274.  
  275.     last_var=-1;
  276.  
  277.     if (c=='?')          /* ? stands for LAST VALUE  */
  278.       {
  279.       tok_val=last_val;
  280.       return(TYPE_VAL);
  281.       }
  282.  
  283.     if ((c>='a')&&(c<='z'))  /* Valid variable letters */
  284.       {
  285.       last_var=c = c-'a';
  286.       tok_val=vars[c];
  287.       return(TYPE_VAL);
  288.       }
  289.  
  290.     /*** Extract number ***/
  291.  
  292.     s=nxc-1;
  293.     if ((c<='9')&&(c>'0')) /* Decimal 1-9 starting digit */
  294.       {
  295.       s=dec2ul(s,&tok_val);
  296.       }
  297.     else if (c=='0')    /* Hex - Start with leading 0 */
  298.       {
  299.       s++;
  300.       if ((*s=='x')||(*s=='X')) s++;
  301.       if ((*s=='+')||(*s=='-')) s--;
  302.       s=hex2ul(s,&tok_val);
  303.       }
  304.     else if (c==BIN_PREF)    /* Binary string */
  305.       {
  306.       s=bin2ul(s+1,&tok_val);
  307.       }
  308.     else s=0;
  309.     if (!s) return(TYPE_ERR);
  310.     nxc=s;
  311.     return(TYPE_VAL);
  312. }
  313.  
  314. /**************************************************
  315.     EXPRESSION EVALUATOR
  316. ***************************************************/
  317.  
  318. eval_expr(s)
  319. char *s;
  320. { int t,fp,gp;
  321.  
  322.    nxc=s; last_tok=0;
  323.    rs=rpn_stk; *rs=0;
  324.    os=oper_stk; *os='(';
  325.  
  326.    do  {
  327.     t=next_tok();
  328.     last_tok=t;
  329.  
  330.     if (t==TYPE_VAL)    /* Variable */
  331.       {
  332.       rs++; 
  333.       if (rs>=&rpn_stk[MAX_RPN])
  334.         return(0);
  335.       *rs=cast_val(&tok_val);
  336.       continue;
  337.       }
  338.  
  339.     if (t==TYPE_ERR)    /* Error in expression */
  340.       return(0);
  341.  
  342.     if (!t)            /* End of string reached */
  343.       if (os>oper_stk) t=')';
  344.       else break;
  345.  
  346.     fp=fa[str_pos(t,oper)];    /* fp=Operator input precedence */
  347.     do {
  348.        if (os<oper_stk) 
  349.         {
  350.         os=oper_stk;
  351.         *os='(';
  352.         }
  353.        gp=ga[str_pos(*os,oper)]; /* gp=Operator stack prec. */
  354.        if (fp<=gp) 
  355.           if (!eval_oper()) return(0);
  356.     } while (fp<gp);
  357.  
  358.     if (fp>0) *(++os)=(char)t;
  359.     if (os>=&oper_stk[MAX_SUSP]) return(0);
  360.  
  361.    } while(1);
  362.  
  363.    if (rs!=rpn_stk+1) return(0);
  364.    last_val=cast_val(rs);
  365.    return(1);
  366. }
  367.  
  368. /***************************************************
  369.     CALCULATOR COMMADS
  370. ****************************************************/
  371.  
  372. #define ALT_X    (45<<8)
  373. #define CMD_EQU  (-2)
  374.  
  375. #define DEC_RL (12)
  376. #define HEX_RL (10)
  377. #define BIN_RL (37)
  378.  
  379. byte atr_expr=0x1f,atr_rslt=0x4e;    /* Screen Attributes */
  380. byte atr_rad=0x4b;
  381. word sep_let=0x20;
  382.  
  383. int sdx=80,sdy=1;    /* Window size */
  384. int x0=0,y0=24;        /* Window Left Upper Corner */
  385. int rx0=0,rlen=DEC_RL;    /* Result x-pos, length */
  386. int ex0=DEC_RL;        /* Expression x-pos & length */
  387. int expr_w=MAX_EXPR-DEC_RL;
  388.           /* BIN        DEC     HEX  */
  389. char rlen_tbl[3*3]={12,21,39, 7,9,14, 6,8,12 };
  390. char rad_let[3]={'B','D','H'};
  391.  
  392. cvt_num(nump,strp)
  393. char *strp;
  394. dword *nump;
  395. {  register char *s=strp;
  396.    register char *v;
  397.  
  398.      v=(char*)nump + (1 << wsz);
  399.      if (radix==RAD2)
  400.        {
  401.        do {
  402.       v--;
  403.       s=b2bin(*((int *)v),s);
  404.       *s++='.';        /* Separate in 8 digit chunks */
  405.       }
  406.        while (v>(char*)nump);
  407.        s[-1]=0x20;
  408.        }
  409.     else do 
  410.        {
  411.        v--;
  412.        s=b2hex(*((int *)v),s);
  413.        }
  414.        while (v>(char*)nump);
  415.     
  416. }
  417.  
  418. show_result(k)
  419. {
  420.   register char *s=(char*)rpn_stk;
  421.   dword tmp;
  422.  
  423.    rlen=rlen_tbl[3*radix+wsz];
  424.    ex0=rlen; expr_w=MAX_EXPR-rlen;
  425.  
  426.    *s=rad_let[radix];  *(word*)(s+1)=':';
  427.    vid_atr=atr_rad; crs_x=0;
  428.    dsp(s);
  429.    *(word*)(fil_chr(s,0x20,rlen)-1) = sep_let;
  430.    s+=3;        /* Leave extra 2 blanks for output formating */
  431.    *s='?';        /* Fill fo error case (will get overwritten ) */
  432.    if (k)
  433.      {
  434.      tmp=cast_val(&last_val);
  435.      if (sgn && *(((int*)(&tmp))+1)<0)    /* Signed & negative */
  436.     {
  437.     s[-1]='-'; tmp= -((long)tmp);
  438.     }
  439.      tmp &= wmask;
  440.      if (radix==RAD10) ul2dec(tmp,s);
  441.        else cvt_num(&tmp,s);
  442.      }
  443.    vid_atr=atr_rslt;
  444.    dsp(((char*)rpn_stk)+2);
  445. }
  446.  
  447. /** KEY-FILTER FOR STRING EDITOR **/
  448.  
  449. word filter()
  450. {
  451.   register word k,bk;
  452.   while (!anykey())
  453.     if (_hkey_again) return(K_ESC);
  454.   k=pckey(); bk=(byte)k;
  455.   if (bk=='=') bk=CMD_EQU;           /* We don't display '=' key */
  456.   if ((bk==0xd)&&(kbflag&3)) k=K_F10; /* Shift-CR, or F10 */
  457.   if (bk==ASGN_PREF) bk=0x221a; /* Make arrow (graphic char entry)*/
  458.   if (bk=='*') bk=0xf9;        /* Make nice small multiply symbol */
  459.   if (bk>0x1f) k=bk;        /* If plain ASCII - pass low part */
  460.   return(k);            /* If cursor/func key - pass full key */
  461. }
  462.  
  463. /***************************************************
  464.     CALCULATOR COMMAND LOOP
  465. ****************************************************/
  466. static int edit_pos=1,ok=1;
  467. char *stf_ptr;
  468.  
  469.  
  470. run_calc()
  471. { int k,stf;
  472.   register n;
  473.   register char *s;
  474.   
  475.   (int)stf_ptr=stf=0;    /* Cancell any key stuffing */
  476.   do
  477.     {
  478.     show_result(ok);
  479.     if (stf)        /* Stuff-keys was set */
  480.     {
  481.     n=radix;
  482.     s=((char*)rpn_stk)+2;    /* Point into sign field */
  483.     if (n!=RAD10)
  484.       {
  485.       if (n==RAD16)
  486.         {
  487.         s[-1]=*s;
  488.         *s='0';
  489.         }
  490.       s++;        /* Skip leading 0 */
  491.       if (stf<0)    /* C format */
  492.         {
  493.         if (n==RAD16)
  494.           ins_chr('x',s);
  495.         }
  496.       else        /* ASM format */
  497.         {
  498.         s=s+str_pos(sep_let,s);
  499.         s--;
  500.         if (n==RAD2) *s='b';
  501.            else *s='h';
  502.         }
  503.       s=(char*)rpn_stk;
  504.       }
  505.     while (*s==0x20) s++;
  506.     stf_ptr=s;
  507.     add_tsc_event((long)1);
  508.     return;
  509.     }
  510.     crs_x=ex0; vid_atr=atr_expr;
  511.     if (!(*expr)) edit_pos=1;
  512.     s=expr;
  513.     k=edit_str(s,expr_w,&edit_pos,filter);
  514.     s+=edit_pos;
  515.  
  516.     if (((byte)k)&&(k>0)) k=(byte)k;
  517.     switch (k)
  518.     {
  519.     case ALT_X:    if (unload_safe())
  520.               uninstall();
  521.     case 0x1b:    return;
  522.  
  523.     case CK_RIGHT:    n=str_pos(';',s);
  524.             if (!n) edit_pos=-1;
  525.               else edit_pos += n;
  526.             break;
  527.  
  528.     case CK_LEFT:    while (s>expr)
  529.               if (*s--==';') break;
  530.             if ((edit_pos=s-expr)<=0)
  531.               edit_pos=str_len(expr)-1;
  532.             break;
  533.  
  534.     case K_UP:   move_win(-1); break;
  535.     case K_DN:   move_win(1); break;
  536.  
  537.     case 'U'-64: sgn=0; break;
  538.     case 'S'-64: sgn=1; break;
  539.  
  540.     case 'B'-64: radix=RAD2;break;
  541.     case 'D'-64: radix=RAD10;break;
  542.     case 'H'-64: radix=RAD16;break;
  543.  
  544.     case 'C'-64:    wsz=WS1; wmask=0xff;
  545.             break;
  546.     case 'I'-64:    wsz=WS2; wmask=0xffff;
  547.             break;
  548.     case 'L'-64:    wsz=WS4; wmask=(dword)-1;
  549.             break;
  550.     case K_F5:    stf=-1;break;    /* C format */
  551.     case K_F6:    stf= 1;break;    /* ASM format */
  552.     }
  553.  
  554.     s=expr;
  555.     do{
  556.       n=str_pos(';',s);
  557.       if (0==(ok=eval_expr(s)))
  558.         {
  559.         edit_pos=nxc-expr;
  560.         break;
  561.         }
  562.       s+=n;
  563.       }
  564.     while (*s && n && (expr+edit_pos)>=s );
  565.  
  566.     if (k==K_F10 && ok)
  567.       expr[0]=0;
  568.     }
  569.    while(1);
  570. }
  571.  
  572. /***********************************************
  573.     TSR MODE ENTRY/EXIT HANDLERS
  574. ************************************************/
  575.  
  576. /** Save/Restore foreground screen **/
  577.  
  578. extern word scr_buf[];
  579.  
  580. chg_scr(func)
  581. fp func;
  582. {
  583.    crs_x=x0; crs_y=y0;
  584.    (*func)(sdx,sdy,scr_buf);
  585. }
  586.  
  587. /** MOVE EDIT WINDOW UP/DOWN **/
  588.  
  589. move_win(n)
  590. {
  591.   chg_scr(put_blk);    /* Restore screen */
  592.   y0+=n;
  593.   if (y0<0) y0=scr_len-1;
  594.     else if (y0>=scr_len) y0=0;
  595.   chg_scr(get_blk);
  596. }
  597.  
  598.  
  599. /******************************************************************
  600.         HOTKEY SERVICE FUNCTION 
  601. *******************************************************************/
  602.  
  603. isr()
  604. {
  605. #if CHK_STACK
  606. word n;
  607.     if (free_stk==0xffff) _watch_stack();
  608.       else last_val=free_stk;
  609. #endif
  610.     chk_video();    /* Update video param's */
  611.     save_crs();        /* Save foreground cursor */
  612.     chg_scr(get_blk);   /* Save foreground screen */
  613.     _hkey_again=0;    /* We use hotkey as ON/OFF button */
  614.     run_calc();        /* Do calculator command loop */
  615.     chg_scr(put_blk);    /* Restore foreground screen */
  616.     restore_crs();    /* Restore foreground cursor */
  617.  
  618. #if CHK_STACK
  619.     n=_unused_stack();
  620.     if (n<free_stk) free_stk=n;    
  621. #endif
  622. }
  623.  
  624. /**************************************************************
  625.     TINY SCHEDULER SERCVICE FUNCTION
  626.  --------------------------------------------------------------
  627.   Used to stuff keys (result) to foreground application.
  628. ***************************************************************/
  629.  
  630. tmr_isr()
  631.   register char *s=stf_ptr;
  632.  
  633.     if (!s) return;
  634.     if ('.'==*s) s++;
  635.     if (*s<'-') return;
  636.     if (!anykey()) stuff_key(*s++);
  637.     stf_ptr=s;
  638.     add_tsc_event((long)1);
  639.  
  640. }
  641.