math.c revision 4d9b34d9
14d9b34d9Smrg/* $XConsortium: math.c,v 1.17 91/07/25 17:51:34 rws Exp $
24d9b34d9Smrg * $MIT: contrib/programs/xcalc/math.c,v 3.2 1999/12/14 18:53:00 gjcoram Exp$
34d9b34d9Smrg * $XFree86: xc/programs/xcalc/math.c,v 1.5tsi Exp $
44d9b34d9Smrg * $XdotOrg: xc/programs/xcalc/math.c,v 1.3 2004/05/23 20:03:49 alanc Exp $
54d9b34d9Smrg *
64d9b34d9Smrg *  math.c  -  mathematics functions for a hand calculator under X
74d9b34d9Smrg *
84d9b34d9Smrg *  Author:    John H. Bradley, University of Pennsylvania
94d9b34d9Smrg *                (bradley@cis.upenn.edu)
104d9b34d9Smrg *                     March, 1987
114d9b34d9Smrg *
124d9b34d9Smrg *  RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena
134d9b34d9Smrg *
144d9b34d9Smrg *  Modified to be a client of the Xt toolkit and the Athena widget set by
154d9b34d9Smrg *  Donna Converse, MIT X Consortium.  This is all that remains of the
164d9b34d9Smrg *  original calculator, and it still needs to be rewritten.  The HP
174d9b34d9Smrg *  functionality should be separated from the TI functionality.
184d9b34d9Smrg *  Beware the HP functions: there are still errors here.
194d9b34d9Smrg *
204d9b34d9Smrg *  Geoffrey Coram fixed most of the HP mode bugs.
214d9b34d9Smrg */
224d9b34d9Smrg
234d9b34d9Smrg#include <stdio.h>
244d9b34d9Smrg#include <X11/Xos.h>
254d9b34d9Smrg#include <math.h>
264d9b34d9Smrg#include <signal.h>
274d9b34d9Smrg#if !defined(IEEE) && defined(SVR4)
284d9b34d9Smrg#include <siginfo.h>
294d9b34d9Smrg#endif
304d9b34d9Smrg#include <setjmp.h>
314d9b34d9Smrg#include "xcalc.h"
324d9b34d9Smrg#include <errno.h>
334d9b34d9Smrg#include <X11/Xlocale.h>
344d9b34d9Smrg
354d9b34d9Smrg#ifdef _CRAY		/* kludge around Cray STDC compiler */
364d9b34d9Smrgdouble (*log_p)() = log;
374d9b34d9Smrg#define log ((*log_p))
384d9b34d9Smrgdouble (*exp_p)() = exp;
394d9b34d9Smrg#define exp ((*exp_p))
404d9b34d9Smrgdouble (*sqrt_p)() = sqrt;
414d9b34d9Smrg#define sqrt ((*sqrt_p))
424d9b34d9Smrgdouble (*log10_p)() = log10;
434d9b34d9Smrg#define log10 ((*log10_p))
444d9b34d9Smrgdouble (*atan2_p)() = atan2;
454d9b34d9Smrg#define atan2 ((*atan2_p))
464d9b34d9Smrgdouble (*asin_p)() = asin;
474d9b34d9Smrg#define asin ((*asin_p))
484d9b34d9Smrgdouble (*acos_p)() = acos;
494d9b34d9Smrg#define acos ((*acos_p))
504d9b34d9Smrgdouble (*atan_p)() = atan;
514d9b34d9Smrg#define atan ((*atan_p))
524d9b34d9Smrgdouble (*sin_p)() = sin;
534d9b34d9Smrg#define sin ((*sin_p))
544d9b34d9Smrgdouble (*cos_p)() = cos;
554d9b34d9Smrg#define cos ((*cos_p))
564d9b34d9Smrgdouble (*tan_p)() = tan;
574d9b34d9Smrg#define tan ((*tan_p))
584d9b34d9Smrgdouble (*pow_p)() = pow;
594d9b34d9Smrg#define pow ((*pow_p))
604d9b34d9Smrg#endif /* _CRAY */
614d9b34d9Smrg
624d9b34d9Smrg#ifndef PI		/* sometimes defined in math.h */
634d9b34d9Smrg#define PI          3.14159265358979
644d9b34d9Smrg#endif
654d9b34d9Smrg#define E           2.71828182845904
664d9b34d9Smrg#define MAXDISP     11
674d9b34d9Smrg#define DEG 0		/* DRG mode.  used for trig calculations */
684d9b34d9Smrg#define RAD 1
694d9b34d9Smrg#define GRAD 2
704d9b34d9Smrg#define min(a,b) ((a) < (b) ? (a) : (b))
714d9b34d9Smrg#define max(a,b) ((a) > (b) ? (a) : (b))
724d9b34d9Smrg#define True	1
734d9b34d9Smrg#define False   0
744d9b34d9Smrg
754d9b34d9Smrgextern int	rpn;
764d9b34d9Smrgextern char 	dispstr[];
774d9b34d9Smrgextern void draw();
784d9b34d9Smrgextern void ringbell();
794d9b34d9Smrgextern void setflag();
804d9b34d9Smrgextern void Quit();
814d9b34d9Smrg
824d9b34d9Smrg#ifndef IEEE
834d9b34d9Smrg    jmp_buf env;
844d9b34d9Smrg#endif
854d9b34d9Smrg
864d9b34d9Smrg
874d9b34d9Smrg/* This section is all of the state machine that implements the calculator
884d9b34d9Smrg * functions.  Much of it is shared between the infix and rpn modes.
894d9b34d9Smrg */
904d9b34d9Smrg
914d9b34d9Smrgint 	flagINV, flagPAREN, flagM, drgmode;	/* display flags */
924d9b34d9Smrg
934d9b34d9Smrgstatic double drg2rad=PI/180.0;  /* Conversion factors for trig funcs */
944d9b34d9Smrgstatic double rad2drg=180.0/PI;
954d9b34d9Smrgstatic int entered=1;  /* true if display contains a valid number.
964d9b34d9Smrg                          if==2, then use 'dnum', rather than the string
974d9b34d9Smrg                          stored in the display.  (for accuracy)
984d9b34d9Smrg                          if==3, then error occurred, only CLR & AC work */
994d9b34d9Smrg/* entered seems to be overloaded - dmc */
1004d9b34d9Smrgstatic int lift_enabled = 0;	/* for rpn mode only */
1014d9b34d9Smrg
1024d9b34d9Smrgstatic int CLR    =0;  /* CLR clears display.  if 1, clears acc, also */
1034d9b34d9Smrgstatic int Dpoint=0;  /* to prevent using decimal pt twice in a # */
1044d9b34d9Smrgstatic int clrdisp=1;  /* if true clears display before entering # */
1054d9b34d9Smrgstatic int lastop =kCLR;
1064d9b34d9Smrgstatic int memop  =kCLR;
1074d9b34d9Smrgstatic int exponent=0;
1084d9b34d9Smrgstatic double acc =0.0;
1094d9b34d9Smrgstatic double dnum=0.0;
1104d9b34d9Smrg#define XCALC_MEMORY 10
1114d9b34d9Smrgstatic double mem[XCALC_MEMORY] = { 0.0 };
1124d9b34d9Smrg
1134d9b34d9Smrgstatic void   DrawDisplay(void);
1144d9b34d9Smrgstatic void   PushOp(int op);
1154d9b34d9Smrgstatic int    PopOp(void);
1164d9b34d9Smrgstatic int    isopempty(void);
1174d9b34d9Smrg#ifdef DEBUG
1184d9b34d9Smrgstatic void   showstack(char *string);
1194d9b34d9Smrg#endif
1204d9b34d9Smrgstatic void   PushNum(double num);
1214d9b34d9Smrgstatic double PopNum(void);
1224d9b34d9Smrgstatic void   RollNum(int dir);
1234d9b34d9Smrgstatic void   ClearStacks(void);
1244d9b34d9Smrgstatic int    priority(int op);
1254d9b34d9Smrg
1264d9b34d9Smrg/*
1274d9b34d9Smrg * The following is to deal with the unfortunate assumption that if errno
1284d9b34d9Smrg * is non-zero then an error has occurred.  On some systems (e.g. Ultrix),
1294d9b34d9Smrg * sscanf will call lower level routines that will set errno.
1304d9b34d9Smrg */
1314d9b34d9Smrg
1324d9b34d9Smrgstatic void
1334d9b34d9Smrgparse_double (src, fmt, dp)
1344d9b34d9Smrg    char *src;
1354d9b34d9Smrg    char *fmt;
1364d9b34d9Smrg    double *dp;
1374d9b34d9Smrg{
1384d9b34d9Smrg    int olderrno = errno;
1394d9b34d9Smrg
1404d9b34d9Smrg    (void) sscanf (src, fmt, dp);
1414d9b34d9Smrg    errno = olderrno;
1424d9b34d9Smrg    return;
1434d9b34d9Smrg}
1444d9b34d9Smrg
1454d9b34d9Smrg
1464d9b34d9Smrg/*********************************/
1474d9b34d9Smrgint pre_op(keynum)
1484d9b34d9Smrg     int keynum;
1494d9b34d9Smrg{
1504d9b34d9Smrg    if (keynum==-1) return(0);
1514d9b34d9Smrg
1524d9b34d9Smrg    errno = 0;			/* for non-IEEE machines */
1534d9b34d9Smrg
1544d9b34d9Smrg    if ( (entered==3) && !(keynum==kCLR || keynum==kOFF)) {
1554d9b34d9Smrg      if (rpn) {
1564d9b34d9Smrg	clrdisp++;
1574d9b34d9Smrg      } else {
1584d9b34d9Smrg        ringbell();
1594d9b34d9Smrg        return(1);	/* the intent was probably not to do the operation */
1604d9b34d9Smrg      }
1614d9b34d9Smrg    }
1624d9b34d9Smrg
1634d9b34d9Smrg    if (keynum != kCLR) CLR=0;
1644d9b34d9Smrg    return(0);
1654d9b34d9Smrg}
1664d9b34d9Smrg
1674d9b34d9Smrg#ifndef IEEE
1684d9b34d9Smrg
1694d9b34d9Smrg/* cannot assign result of setjmp under ANSI C, use global instead */
1704d9b34d9Smrgstatic volatile int SignalKind;
1714d9b34d9Smrgstatic volatile int SignalCode;
1724d9b34d9Smrg
1734d9b34d9Smrgvoid fail_op()
1744d9b34d9Smrg{
1754d9b34d9Smrg    if (SignalKind == SIGFPE)
1764d9b34d9Smrg    switch (SignalCode) {
1774d9b34d9Smrg#ifdef SVR4
1784d9b34d9Smrg      case FPE_INTDIV:		/* integer divide by zero */
1794d9b34d9Smrg      case FPE_FLTDIV:		/* floating point divide by zero */
1804d9b34d9Smrg	strcpy(dispstr, "divide by 0");
1814d9b34d9Smrg	break;
1824d9b34d9Smrg      case FPE_INTOVF:		/* integer overflow */
1834d9b34d9Smrg      case FPE_FLTOVF:		/* floating point overflow */
1844d9b34d9Smrg	strcpy(dispstr, "overflow");
1854d9b34d9Smrg	break;
1864d9b34d9Smrg      case FPE_FLTUND:		/* floating point underflow */
1874d9b34d9Smrg	strcpy(dispstr, "underflow");
1884d9b34d9Smrg	break;
1894d9b34d9Smrg      case FPE_FLTRES:		/* floating point inexact result */
1904d9b34d9Smrg	strcpy(dispstr, "inexact result");
1914d9b34d9Smrg	break;
1924d9b34d9Smrg      case FPE_FLTINV:		/* invalid floating point operation */
1934d9b34d9Smrg	strcpy(dispstr, "invalid op");
1944d9b34d9Smrg	break;
1954d9b34d9Smrg      case FPE_FLTSUB:		/* subscript out of range */
1964d9b34d9Smrg	strcpy(dispstr, "out of range");
1974d9b34d9Smrg	break;
1984d9b34d9Smrg
1994d9b34d9Smrg#endif /*SVR4*/
2004d9b34d9Smrg
2014d9b34d9Smrg#ifdef FPE_FLTDIV_TRAP
2024d9b34d9Smrg      case FPE_FLTDIV_TRAP:  strcpy(dispstr,"div by zero"); break;
2034d9b34d9Smrg#endif
2044d9b34d9Smrg#ifdef FPE_FLTDIV_FAULT
2054d9b34d9Smrg           case FPE_FLTDIV_FAULT: strcpy(dispstr,"div by zero"); break;
2064d9b34d9Smrg#endif
2074d9b34d9Smrg#ifdef FPE_FLTOVF_TRAP
2084d9b34d9Smrg           case FPE_FLTOVF_TRAP:  strcpy(dispstr,"overflow"); break;
2094d9b34d9Smrg#endif
2104d9b34d9Smrg#ifdef FPE_FLTOVF_FAULT
2114d9b34d9Smrg           case FPE_FLTOVF_FAULT: strcpy(dispstr,"overflow"); break;
2124d9b34d9Smrg#endif
2134d9b34d9Smrg#ifdef FPE_FLTUND_TRAP
2144d9b34d9Smrg           case FPE_FLTUND_TRAP:  strcpy(dispstr,"underflow"); break;
2154d9b34d9Smrg#endif
2164d9b34d9Smrg#ifdef FPE_FLTUND_FAULT
2174d9b34d9Smrg           case FPE_FLTUND_FAULT: strcpy(dispstr,"underflow"); break;
2184d9b34d9Smrg#endif
2194d9b34d9Smrg           default:               strcpy(dispstr,"error");
2204d9b34d9Smrg    }
2214d9b34d9Smrg    else
2224d9b34d9Smrg	if (SignalKind == SIGILL)
2234d9b34d9Smrg	    strcpy(dispstr, "illegal operand");
2244d9b34d9Smrg
2254d9b34d9Smrg    entered=3;
2264d9b34d9Smrg    DrawDisplay();
2274d9b34d9Smrg    return;
2284d9b34d9Smrg}
2294d9b34d9Smrg
2304d9b34d9Smrg
2314d9b34d9Smrg/* keep SVR4 compiler from complaining about scope of arg declaration below */
2324d9b34d9Smrgtypedef struct sigcontext * sigcontextstructp;
2334d9b34d9Smrg/*ARGSUSED*/
2344d9b34d9Smrgsignal_t fperr(sig,code,scp)
2354d9b34d9Smrg  int sig,code;
2364d9b34d9Smrg  sigcontextstructp scp;
2374d9b34d9Smrg{
2384d9b34d9Smrg#if defined(SYSV) || defined(SVR4) || defined(linux)
2394d9b34d9Smrg    signal(SIGFPE,(signal_t (*)())fperr);
2404d9b34d9Smrg#endif
2414d9b34d9Smrg    SignalKind = sig;
2424d9b34d9Smrg    SignalCode = code;
2434d9b34d9Smrg    longjmp(env,1);
2444d9b34d9Smrg}
2454d9b34d9Smrg
2464d9b34d9Smrg/* for VAX BSD4.3 */
2474d9b34d9Smrg/*ARGSUSED*/
2484d9b34d9Smrgsignal_t illerr(sig,code,scp)
2494d9b34d9Smrg  int sig,code;
2504d9b34d9Smrg  sigcontextstructp scp;
2514d9b34d9Smrg{
2524d9b34d9Smrg    /* not reset when caught? */
2534d9b34d9Smrg    signal(SIGILL,(signal_t (*)())illerr);
2544d9b34d9Smrg
2554d9b34d9Smrg    SignalKind = sig;
2564d9b34d9Smrg    SignalCode = code;
2574d9b34d9Smrg    longjmp(env,1);
2584d9b34d9Smrg}
2594d9b34d9Smrg
2604d9b34d9Smrg#endif	/* not IEEE */
2614d9b34d9Smrg
2624d9b34d9Smrg
2634d9b34d9Smrgvoid post_op()
2644d9b34d9Smrg{
2654d9b34d9Smrg#ifdef DEBUG
2664d9b34d9Smrg    showstack("\0");
2674d9b34d9Smrg#endif
2684d9b34d9Smrg#ifndef IEEE
2694d9b34d9Smrg    if (errno) {
2704d9b34d9Smrg        strcpy(dispstr,"error");
2714d9b34d9Smrg        DrawDisplay();
2724d9b34d9Smrg        entered=3;
2734d9b34d9Smrg        errno=0;
2744d9b34d9Smrg        }
2754d9b34d9Smrg#endif
2764d9b34d9Smrg}
2774d9b34d9Smrg/*-------------------------------------------------------------------------*/
2784d9b34d9Smrgstatic void
2794d9b34d9SmrgDrawDisplay(void)
2804d9b34d9Smrg{
2814d9b34d9Smrg    if ((int) strlen(dispstr) > 12) {	 /* strip out some decimal digits */
2824d9b34d9Smrg        char tmp[32];
2834d9b34d9Smrg        char *estr = index(dispstr,'e');  /* search for exponent part */
2844d9b34d9Smrg        if (!estr) dispstr[12]='\0';      /* no exp, just trunc. */
2854d9b34d9Smrg        else {
2864d9b34d9Smrg            if ((int) strlen(estr) <= 4)
2874d9b34d9Smrg                sprintf(tmp,"%.8s",dispstr); /* leftmost 8 chars */
2884d9b34d9Smrg            else
2894d9b34d9Smrg                sprintf(tmp,"%.7s",dispstr); /* leftmost 7 chars */
2904d9b34d9Smrg            strcat (tmp,estr);            /* plus exponent */
2914d9b34d9Smrg            strcpy (dispstr,tmp);
2924d9b34d9Smrg            }
2934d9b34d9Smrg        }
2944d9b34d9Smrg    draw(dispstr);
2954d9b34d9Smrg    setflag(XCalc_MEMORY, (flagM));
2964d9b34d9Smrg    setflag(XCalc_INVERSE, (flagINV));
2974d9b34d9Smrg    setflag(XCalc_DEGREE, (drgmode==DEG));
2984d9b34d9Smrg    setflag(XCalc_RADIAN, (drgmode==RAD));
2994d9b34d9Smrg    setflag(XCalc_GRADAM, (drgmode==GRAD));
3004d9b34d9Smrg    setflag(XCalc_PAREN, (flagPAREN));
3014d9b34d9Smrg}
3024d9b34d9Smrg
3034d9b34d9Smrg/*-------------------------------------------------------------------------*/
3044d9b34d9Smrgvoid
3054d9b34d9Smrgnumeric(keynum)
3064d9b34d9Smrg     int keynum;
3074d9b34d9Smrg{
3084d9b34d9Smrg    char	st[2];
3094d9b34d9Smrg    int		cell = 0;
3104d9b34d9Smrg
3114d9b34d9Smrg  flagINV=0;
3124d9b34d9Smrg
3134d9b34d9Smrg  if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) {
3144d9b34d9Smrg      switch (keynum) {
3154d9b34d9Smrg	case kONE:	cell = 1; break;
3164d9b34d9Smrg	case kTWO:	cell = 2; break;
3174d9b34d9Smrg	case kTHREE:	cell = 3; break;
3184d9b34d9Smrg	case kFOUR:	cell = 4; break;
3194d9b34d9Smrg	case kFIVE:	cell = 5; break;
3204d9b34d9Smrg	case kSIX:	cell = 6; break;
3214d9b34d9Smrg	case kSEVEN:	cell = 7; break;
3224d9b34d9Smrg	case kEIGHT:	cell = 8; break;
3234d9b34d9Smrg	case kNINE:	cell = 9; break;
3244d9b34d9Smrg	case kZERO:	cell = 0; break;
3254d9b34d9Smrg      }
3264d9b34d9Smrg      switch (memop) {
3274d9b34d9Smrg      case kSTO:
3284d9b34d9Smrg	mem[cell] = dnum;
3294d9b34d9Smrg	lift_enabled = 1;
3304d9b34d9Smrg	entered = 2;
3314d9b34d9Smrg	clrdisp++;
3324d9b34d9Smrg	break;
3334d9b34d9Smrg      case kRCL:
3344d9b34d9Smrg	PushNum(dnum);
3354d9b34d9Smrg	dnum = mem[cell];
3364d9b34d9Smrg	sprintf(dispstr, "%.8g", dnum);
3374d9b34d9Smrg	lift_enabled = 1;
3384d9b34d9Smrg        entered = 1;
3394d9b34d9Smrg	clrdisp++;
3404d9b34d9Smrg	break;
3414d9b34d9Smrg      case kSUM:
3424d9b34d9Smrg	mem[cell] += dnum;
3434d9b34d9Smrg	lift_enabled = 1;
3444d9b34d9Smrg	entered = 2;
3454d9b34d9Smrg	clrdisp++;
3464d9b34d9Smrg	break;
3474d9b34d9Smrg      }
3484d9b34d9Smrg      memop = kCLR;
3494d9b34d9Smrg      DrawDisplay();
3504d9b34d9Smrg      return;
3514d9b34d9Smrg  }
3524d9b34d9Smrg
3534d9b34d9Smrg  if (clrdisp) {
3544d9b34d9Smrg    dispstr[0]='\0';
3554d9b34d9Smrg    exponent=Dpoint=0;
3564d9b34d9Smrg/*    if (rpn && entered==2)
3574d9b34d9Smrg      PushNum(dnum);
3584d9b34d9Smrg */
3594d9b34d9Smrg    if (rpn & lift_enabled)
3604d9b34d9Smrg	PushNum(dnum);
3614d9b34d9Smrg  }
3624d9b34d9Smrg  if ((int) strlen(dispstr) >= MAXDISP)
3634d9b34d9Smrg    return;
3644d9b34d9Smrg
3654d9b34d9Smrg    switch (keynum){
3664d9b34d9Smrg      case kONE:	st[0] = '1'; break;
3674d9b34d9Smrg      case kTWO:	st[0] = '2'; break;
3684d9b34d9Smrg      case kTHREE:	st[0] = '3'; break;
3694d9b34d9Smrg      case kFOUR:	st[0] = '4'; break;
3704d9b34d9Smrg      case kFIVE:	st[0] = '5'; break;
3714d9b34d9Smrg      case kSIX:	st[0] = '6'; break;
3724d9b34d9Smrg      case kSEVEN:	st[0] = '7'; break;
3734d9b34d9Smrg      case kEIGHT:	st[0] = '8'; break;
3744d9b34d9Smrg      case kNINE:	st[0] = '9'; break;
3754d9b34d9Smrg      case kZERO:	st[0] = '0'; break;
3764d9b34d9Smrg    }
3774d9b34d9Smrg    st[1] = '\0';
3784d9b34d9Smrg    strcat(dispstr,st);
3794d9b34d9Smrg
3804d9b34d9Smrg  DrawDisplay();
3814d9b34d9Smrg  if (clrdisp && keynum != kZERO)
3824d9b34d9Smrg    clrdisp=0; /*no leading 0s*/
3834d9b34d9Smrg  memop = keynum;
3844d9b34d9Smrg  entered=1;
3854d9b34d9Smrg  lift_enabled = 0;
3864d9b34d9Smrg}
3874d9b34d9Smrg
3884d9b34d9Smrgvoid
3894d9b34d9Smrgbkspf(void)
3904d9b34d9Smrg{
3914d9b34d9Smrg
3924d9b34d9Smrg  lift_enabled = 0;
3934d9b34d9Smrg
3944d9b34d9Smrg  if (! flagINV)
3954d9b34d9Smrg  {
3964d9b34d9Smrg      if (entered!=1) {
3974d9b34d9Smrg	  clearf();
3984d9b34d9Smrg	  return;
3994d9b34d9Smrg      }
4004d9b34d9Smrg      if (clrdisp)
4014d9b34d9Smrg	  return;
4024d9b34d9Smrg      if ((int) strlen(dispstr) > 0) {
4034d9b34d9Smrg#ifndef X_LOCALE
4044d9b34d9Smrg          const char *dp = localeconv()->decimal_point;
4054d9b34d9Smrg          size_t dp_len = strlen(dp);
4064d9b34d9Smrg          size_t ds_len = strlen(dispstr);
4074d9b34d9Smrg          if (ds_len >= dp_len && strcmp(dispstr + ds_len - dp_len, dp) == 0)
4084d9b34d9Smrg             Dpoint=0;
4094d9b34d9Smrg#else
4104d9b34d9Smrg	  if (dispstr[strlen(dispstr)-1] == '.')
4114d9b34d9Smrg             Dpoint=0;
4124d9b34d9Smrg#endif
4134d9b34d9Smrg	  dispstr[strlen(dispstr)-1] = 0;
4144d9b34d9Smrg      }
4154d9b34d9Smrg      if (strlen(dispstr) == 0) {
4164d9b34d9Smrg	  strcat(dispstr, "0");
4174d9b34d9Smrg	  clrdisp++;
4184d9b34d9Smrg      }
4194d9b34d9Smrg  }
4204d9b34d9Smrg  else
4214d9b34d9Smrg  {
4224d9b34d9Smrg      strcpy(dispstr, "0");
4234d9b34d9Smrg      dnum = 0.0;
4244d9b34d9Smrg      clrdisp++;
4254d9b34d9Smrg      flagINV = 0;
4264d9b34d9Smrg  }
4274d9b34d9Smrg  DrawDisplay();
4284d9b34d9Smrg}
4294d9b34d9Smrg
4304d9b34d9Smrgvoid
4314d9b34d9Smrgdecf(void)
4324d9b34d9Smrg{
4334d9b34d9Smrg  flagINV=0;
4344d9b34d9Smrg  if (clrdisp) {
4354d9b34d9Smrg      if (rpn && lift_enabled)
4364d9b34d9Smrg	PushNum(dnum);
4374d9b34d9Smrg      strcpy(dispstr,"0");
4384d9b34d9Smrg  }
4394d9b34d9Smrg  if (!Dpoint) {
4404d9b34d9Smrg#ifndef X_LOCALE
4414d9b34d9Smrg    strcat(dispstr, localeconv()->decimal_point);
4424d9b34d9Smrg#else
4434d9b34d9Smrg    strcat(dispstr, ".");
4444d9b34d9Smrg#endif
4454d9b34d9Smrg    DrawDisplay();
4464d9b34d9Smrg    Dpoint++;
4474d9b34d9Smrg  }
4484d9b34d9Smrg  clrdisp=0;
4494d9b34d9Smrg  entered=1;
4504d9b34d9Smrg}
4514d9b34d9Smrg
4524d9b34d9Smrgvoid
4534d9b34d9Smrgeef(void)
4544d9b34d9Smrg{
4554d9b34d9Smrg  flagINV=0;
4564d9b34d9Smrg  if (clrdisp) {
4574d9b34d9Smrg      if (rpn && lift_enabled)
4584d9b34d9Smrg	PushNum(dnum);
4594d9b34d9Smrg      strcpy(dispstr, rpn ? "1" : "0");
4604d9b34d9Smrg  }
4614d9b34d9Smrg  if (!exponent) {
4624d9b34d9Smrg    strcat(dispstr,"E+");
4634d9b34d9Smrg    DrawDisplay();
4644d9b34d9Smrg    exponent=strlen(dispstr)-1;  /* where the '-' goes */
4654d9b34d9Smrg  }
4664d9b34d9Smrg  clrdisp=0;
4674d9b34d9Smrg  entered=1;
4684d9b34d9Smrg}
4694d9b34d9Smrg
4704d9b34d9Smrgvoid
4714d9b34d9Smrgclearf(void)
4724d9b34d9Smrg{
4734d9b34d9Smrg  flagINV=0;
4744d9b34d9Smrg  if (CLR && !rpn) { /* clear all */
4754d9b34d9Smrg    ClearStacks();
4764d9b34d9Smrg    flagPAREN=0;
4774d9b34d9Smrg  }
4784d9b34d9Smrg  CLR++;
4794d9b34d9Smrg  exponent=Dpoint=0;
4804d9b34d9Smrg  clrdisp=1;
4814d9b34d9Smrg  entered=1;
4824d9b34d9Smrg  strcpy(dispstr,"0");
4834d9b34d9Smrg  DrawDisplay();
4844d9b34d9Smrg}
4854d9b34d9Smrg
4864d9b34d9Smrgvoid
4874d9b34d9Smrgnegf(void)
4884d9b34d9Smrg{
4894d9b34d9Smrg  flagINV=0;
4904d9b34d9Smrg  if (exponent) {       /* neg the exponent */
4914d9b34d9Smrg    if (dispstr[exponent]=='-')
4924d9b34d9Smrg      dispstr[exponent]='+';
4934d9b34d9Smrg    else
4944d9b34d9Smrg      dispstr[exponent]='-';
4954d9b34d9Smrg    DrawDisplay();
4964d9b34d9Smrg    return;
4974d9b34d9Smrg  }
4984d9b34d9Smrg
4994d9b34d9Smrg  if (strcmp("0",dispstr)==0)
5004d9b34d9Smrg    return;			/* don't neg a zero */
5014d9b34d9Smrg  if (dispstr[0]=='-')	 	/* already neg-ed */
5024d9b34d9Smrg    strcpy(dispstr,dispstr+1);  /* move str left once */
5034d9b34d9Smrg  else {			/* not neg-ed.  add a '-' */
5044d9b34d9Smrg    char tmp[32];
5054d9b34d9Smrg    sprintf(tmp,"-%s",dispstr);
5064d9b34d9Smrg    strcpy(dispstr,tmp);
5074d9b34d9Smrg  }
5084d9b34d9Smrg  if (entered==2)
5094d9b34d9Smrg    dnum = -1.0 * dnum;
5104d9b34d9Smrg  DrawDisplay();
5114d9b34d9Smrg}
5124d9b34d9Smrg
5134d9b34d9Smrg/* Two operand functions for infix calc */
5144d9b34d9Smrgvoid
5154d9b34d9Smrgtwoop(int keynum)
5164d9b34d9Smrg{
5174d9b34d9Smrg  if (flagINV) {
5184d9b34d9Smrg    flagINV=0;
5194d9b34d9Smrg    DrawDisplay();
5204d9b34d9Smrg  }
5214d9b34d9Smrg
5224d9b34d9Smrg  if (!entered) {		/* something like "5+*" */
5234d9b34d9Smrg    if (!isopempty())
5244d9b34d9Smrg      (void) PopOp();			/* replace the prev op */
5254d9b34d9Smrg    PushOp(keynum);		/* with the new one */
5264d9b34d9Smrg    return;
5274d9b34d9Smrg  }
5284d9b34d9Smrg
5294d9b34d9Smrg  if (entered==1)
5304d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
5314d9b34d9Smrg
5324d9b34d9Smrg  clrdisp=CLR=1;
5334d9b34d9Smrg  entered=Dpoint=exponent=0;
5344d9b34d9Smrg
5354d9b34d9Smrg  if (!isopempty()) {  /* there was a previous op */
5364d9b34d9Smrg    lastop=PopOp();   /* get it */
5374d9b34d9Smrg
5384d9b34d9Smrg    if (lastop==kLPAR) {  /* put it back */
5394d9b34d9Smrg      PushOp(kLPAR);
5404d9b34d9Smrg      PushOp(keynum);
5414d9b34d9Smrg      PushNum(dnum);
5424d9b34d9Smrg      return;
5434d9b34d9Smrg    }
5444d9b34d9Smrg
5454d9b34d9Smrg    /* now, if the current op (keynum) is of
5464d9b34d9Smrg       higher priority than the lastop, the current
5474d9b34d9Smrg       op and number are just pushed on top
5484d9b34d9Smrg       Priorities:  (Y^X) > *,/ > +,- */
5494d9b34d9Smrg
5504d9b34d9Smrg    if (priority(keynum) > priority(lastop)) {
5514d9b34d9Smrg      PushNum(dnum);
5524d9b34d9Smrg      PushOp(lastop);
5534d9b34d9Smrg      PushOp(keynum);
5544d9b34d9Smrg    } else {  /* execute lastop on lastnum and dnum, push
5554d9b34d9Smrg	       result and current op on stack */
5564d9b34d9Smrg      acc=PopNum();
5574d9b34d9Smrg      switch (lastop) { /* perform the operation */
5584d9b34d9Smrg      case kADD: acc += dnum;  break;
5594d9b34d9Smrg      case kSUB: acc -= dnum;  break;
5604d9b34d9Smrg      case kMUL: acc *= dnum;  break;
5614d9b34d9Smrg      case kDIV: acc /= dnum;  break;
5624d9b34d9Smrg      case kPOW: acc =  pow(acc,dnum);  break;
5634d9b34d9Smrg	}
5644d9b34d9Smrg      PushNum(acc);
5654d9b34d9Smrg      PushOp(keynum);
5664d9b34d9Smrg      sprintf(dispstr,"%.8g",acc);
5674d9b34d9Smrg      DrawDisplay();
5684d9b34d9Smrg      dnum=acc;
5694d9b34d9Smrg    }
5704d9b34d9Smrg  }
5714d9b34d9Smrg  else { /* op stack is empty, push op and num */
5724d9b34d9Smrg    PushOp(keynum);
5734d9b34d9Smrg    PushNum(dnum);
5744d9b34d9Smrg  }
5754d9b34d9Smrg}
5764d9b34d9Smrg
5774d9b34d9Smrg/* Two operand functions for rpn calc */
5784d9b34d9Smrgvoid
5794d9b34d9Smrgtwof(int keynum)
5804d9b34d9Smrg{
5814d9b34d9Smrg  if (flagINV) {
5824d9b34d9Smrg    flagINV=0;
5834d9b34d9Smrg    DrawDisplay();
5844d9b34d9Smrg  }
5854d9b34d9Smrg  if (!entered)
5864d9b34d9Smrg    return;
5874d9b34d9Smrg  if (entered==1)
5884d9b34d9Smrg    parse_double(dispstr, "%lf", &dnum);
5894d9b34d9Smrg  acc = PopNum();
5904d9b34d9Smrg  switch(keynum) {
5914d9b34d9Smrg  case kADD: acc += dnum;  break;
5924d9b34d9Smrg  case kSUB: acc -= dnum;  break;
5934d9b34d9Smrg  case kMUL: acc *= dnum;  break;
5944d9b34d9Smrg  case kDIV: acc /= dnum;  break;
5954d9b34d9Smrg  case kPOW: acc =  pow(acc,dnum);  break;
5964d9b34d9Smrg  case kXXY: PushNum(dnum);
5974d9b34d9Smrg  }
5984d9b34d9Smrg  sprintf(dispstr, "%.8g", acc);
5994d9b34d9Smrg  DrawDisplay();
6004d9b34d9Smrg  clrdisp++;
6014d9b34d9Smrg  Dpoint = exponent = 0;
6024d9b34d9Smrg  entered = 2;
6034d9b34d9Smrg  lift_enabled = 1;
6044d9b34d9Smrg  dnum = acc;
6054d9b34d9Smrg}
6064d9b34d9Smrg
6074d9b34d9Smrgvoid
6084d9b34d9Smrgentrf(void)
6094d9b34d9Smrg{
6104d9b34d9Smrg  flagINV=0;
6114d9b34d9Smrg  if (!entered)
6124d9b34d9Smrg    return;
6134d9b34d9Smrg
6144d9b34d9Smrg  clrdisp=CLR=1;
6154d9b34d9Smrg  Dpoint=exponent=0;
6164d9b34d9Smrg
6174d9b34d9Smrg  if (entered==1)
6184d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
6194d9b34d9Smrg  entered=2;
6204d9b34d9Smrg  memop = kENTR;
6214d9b34d9Smrg  PushNum(dnum);
6224d9b34d9Smrg  lift_enabled = 0;
6234d9b34d9Smrg}
6244d9b34d9Smrg
6254d9b34d9Smrgvoid
6264d9b34d9Smrgequf(void)
6274d9b34d9Smrg{
6284d9b34d9Smrg  flagINV=0;
6294d9b34d9Smrg  if (!entered)
6304d9b34d9Smrg    return;
6314d9b34d9Smrg
6324d9b34d9Smrg  clrdisp=CLR=1;
6334d9b34d9Smrg  Dpoint=exponent=0;
6344d9b34d9Smrg
6354d9b34d9Smrg  if (entered==1)
6364d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
6374d9b34d9Smrg  entered=2;
6384d9b34d9Smrg
6394d9b34d9Smrg  PushNum(dnum);
6404d9b34d9Smrg
6414d9b34d9Smrg  while (!isopempty()) {  /* do all pending ops */
6424d9b34d9Smrg    dnum=PopNum();
6434d9b34d9Smrg    acc=PopNum();
6444d9b34d9Smrg    lastop=PopOp();
6454d9b34d9Smrg    switch (lastop) {
6464d9b34d9Smrg    case kADD:  acc += dnum;
6474d9b34d9Smrg		break;
6484d9b34d9Smrg    case kSUB:  acc -= dnum;
6494d9b34d9Smrg		break;
6504d9b34d9Smrg    case kMUL:  acc *= dnum;
6514d9b34d9Smrg		break;
6524d9b34d9Smrg    case kDIV:  acc /= dnum;
6534d9b34d9Smrg		break;
6544d9b34d9Smrg    case kPOW:  acc = pow(acc,dnum);
6554d9b34d9Smrg		break;
6564d9b34d9Smrg    case kLPAR:	flagPAREN--;
6574d9b34d9Smrg		PushNum(acc);
6584d9b34d9Smrg		break;
6594d9b34d9Smrg    }
6604d9b34d9Smrg    dnum=acc;
6614d9b34d9Smrg    PushNum(dnum);
6624d9b34d9Smrg  }
6634d9b34d9Smrg
6644d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
6654d9b34d9Smrg  DrawDisplay();
6664d9b34d9Smrg}
6674d9b34d9Smrg
6684d9b34d9Smrgvoid
6694d9b34d9Smrglparf(void)
6704d9b34d9Smrg{
6714d9b34d9Smrg  flagINV=0;
6724d9b34d9Smrg  PushOp(kLPAR);
6734d9b34d9Smrg  flagPAREN++;
6744d9b34d9Smrg  DrawDisplay();
6754d9b34d9Smrg}
6764d9b34d9Smrg
6774d9b34d9Smrgvoid
6784d9b34d9Smrgrollf(void)
6794d9b34d9Smrg{
6804d9b34d9Smrg  if (!entered)
6814d9b34d9Smrg    return;
6824d9b34d9Smrg  if (entered==1)
6834d9b34d9Smrg    parse_double(dispstr, "%lf", &dnum);
6844d9b34d9Smrg  entered = 2;
6854d9b34d9Smrg  lift_enabled = 1;
6864d9b34d9Smrg  RollNum(flagINV);
6874d9b34d9Smrg  flagINV=0;
6884d9b34d9Smrg  clrdisp++;
6894d9b34d9Smrg  sprintf(dispstr, "%.8g", dnum);
6904d9b34d9Smrg  DrawDisplay();
6914d9b34d9Smrg}
6924d9b34d9Smrg
6934d9b34d9Smrgvoid
6944d9b34d9Smrgrparf(void)
6954d9b34d9Smrg{
6964d9b34d9Smrg  flagINV=0;
6974d9b34d9Smrg  if (!entered)
6984d9b34d9Smrg    return;
6994d9b34d9Smrg
7004d9b34d9Smrg  if (!flagPAREN)
7014d9b34d9Smrg    return;
7024d9b34d9Smrg
7034d9b34d9Smrg  clrdisp++;
7044d9b34d9Smrg  Dpoint=exponent=0;
7054d9b34d9Smrg
7064d9b34d9Smrg  if (entered==1)
7074d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
7084d9b34d9Smrg  entered=2;
7094d9b34d9Smrg
7104d9b34d9Smrg  PushNum(dnum);
7114d9b34d9Smrg  while (!isopempty() && (lastop=PopOp())!=kLPAR) {
7124d9b34d9Smrg    /* do all pending ops, back to left paren */
7134d9b34d9Smrg    dnum=PopNum();
7144d9b34d9Smrg    acc=PopNum();
7154d9b34d9Smrg    switch (lastop) {
7164d9b34d9Smrg    case kADD:  acc += dnum;
7174d9b34d9Smrg		break;
7184d9b34d9Smrg    case kSUB:  acc -= dnum;
7194d9b34d9Smrg		break;
7204d9b34d9Smrg    case kMUL:  acc *= dnum;
7214d9b34d9Smrg		break;
7224d9b34d9Smrg    case kDIV:  acc /= dnum;
7234d9b34d9Smrg		break;
7244d9b34d9Smrg    case kPOW:  acc = pow(acc,dnum);
7254d9b34d9Smrg		break;
7264d9b34d9Smrg    }
7274d9b34d9Smrg    dnum=acc;
7284d9b34d9Smrg    PushNum(dnum);
7294d9b34d9Smrg  }
7304d9b34d9Smrg  (void) PopNum();
7314d9b34d9Smrg  flagPAREN--;
7324d9b34d9Smrg  entered=2;
7334d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
7344d9b34d9Smrg  DrawDisplay();
7354d9b34d9Smrg}
7364d9b34d9Smrg
7374d9b34d9Smrgvoid
7384d9b34d9Smrgdrgf(void)
7394d9b34d9Smrg{
7404d9b34d9Smrg  if (flagINV) {
7414d9b34d9Smrg    if (entered==1)
7424d9b34d9Smrg      parse_double(dispstr,"%lf",&dnum);
7434d9b34d9Smrg    switch (drgmode) {
7444d9b34d9Smrg    case DEG:  dnum=dnum*PI/180.0;    break;
7454d9b34d9Smrg    case RAD:  dnum=dnum*200.0/PI;    break;
7464d9b34d9Smrg    case GRAD: dnum=dnum*90.0/100.0;  break;
7474d9b34d9Smrg    }
7484d9b34d9Smrg    entered=2;
7494d9b34d9Smrg    clrdisp=1;
7504d9b34d9Smrg    flagINV=0;
7514d9b34d9Smrg    sprintf(dispstr,"%.8g",dnum);
7524d9b34d9Smrg  }
7534d9b34d9Smrg
7544d9b34d9Smrg  flagINV=0;
7554d9b34d9Smrg  drgmode = (drgmode + 1) % 3;
7564d9b34d9Smrg  switch (drgmode) {
7574d9b34d9Smrg  case DEG:  drg2rad=PI / 180.0;
7584d9b34d9Smrg	     rad2drg=180.0 / PI;
7594d9b34d9Smrg	     break;
7604d9b34d9Smrg  case RAD:  drg2rad=1.0;
7614d9b34d9Smrg	     rad2drg=1.0;
7624d9b34d9Smrg	     break;
7634d9b34d9Smrg  case GRAD: drg2rad=PI / 200.0;
7644d9b34d9Smrg	     rad2drg=200.0 / PI;
7654d9b34d9Smrg	     break;
7664d9b34d9Smrg  }
7674d9b34d9Smrg  DrawDisplay();
7684d9b34d9Smrg}
7694d9b34d9Smrg
7704d9b34d9Smrgvoid
7714d9b34d9Smrginvf(void)
7724d9b34d9Smrg{
7734d9b34d9Smrg  flagINV = ~flagINV;
7744d9b34d9Smrg  DrawDisplay();
7754d9b34d9Smrg}
7764d9b34d9Smrg
7774d9b34d9Smrgvoid
7784d9b34d9Smrgmemf(int keynum)
7794d9b34d9Smrg{
7804d9b34d9Smrg    memop = keynum;
7814d9b34d9Smrg    if (entered==1)
7824d9b34d9Smrg      parse_double(dispstr,"%lf",&dnum);
7834d9b34d9Smrg    entered = 2;
7844d9b34d9Smrg    clrdisp++;
7854d9b34d9Smrg    lift_enabled = 0;
7864d9b34d9Smrg}
7874d9b34d9Smrg
7884d9b34d9Smrgvoid
7894d9b34d9Smrgoneop(int keynum)
7904d9b34d9Smrg{
7914d9b34d9Smrg  int i,j;
7924d9b34d9Smrg  double dtmp;
7934d9b34d9Smrg
7944d9b34d9Smrg  if (entered==1)
7954d9b34d9Smrg    parse_double(dispstr,"%lf",&dnum);
7964d9b34d9Smrg  entered = 2;
7974d9b34d9Smrg
7984d9b34d9Smrg  switch (keynum) {  /* do the actual math fn. */
7994d9b34d9Smrg  case kE:     if (rpn && memop != kENTR) PushNum(dnum); dnum=E;  break;
8004d9b34d9Smrg  case kPI:    if (rpn && memop != kENTR) PushNum(dnum); dnum=PI;  break;
8014d9b34d9Smrg  case kRECIP: dnum=1.0/dnum;  break;
8024d9b34d9Smrg  case kSQR:   flagINV = !flagINV; /* fall through to */
8034d9b34d9Smrg  case kSQRT:  if (flagINV) dnum=dnum*dnum;
8044d9b34d9Smrg	       else dnum=sqrt(dnum);
8054d9b34d9Smrg	       break;
8064d9b34d9Smrg  case k10X:   flagINV = !flagINV; /* fall through to */
8074d9b34d9Smrg  case kLOG:   if (flagINV) dnum=pow(10.0,dnum);
8084d9b34d9Smrg  	       else dnum=log10(dnum);
8094d9b34d9Smrg	       break;
8104d9b34d9Smrg  case kEXP:   flagINV = !flagINV; /* fall through to */
8114d9b34d9Smrg  case kLN:    if (flagINV) dnum=exp(dnum);
8124d9b34d9Smrg	       else dnum=log(dnum);
8134d9b34d9Smrg	       break;
8144d9b34d9Smrg  case kSIN:   if (flagINV) dnum=asin(dnum)*rad2drg;
8154d9b34d9Smrg	       else dnum=sin(dnum*drg2rad);
8164d9b34d9Smrg	       break;
8174d9b34d9Smrg  case kCOS:   if (flagINV) dnum=acos(dnum)*rad2drg;
8184d9b34d9Smrg	       else dnum=cos(dnum*drg2rad);
8194d9b34d9Smrg	       break;
8204d9b34d9Smrg  case kTAN:   if (flagINV) dnum=atan(dnum)*rad2drg;
8214d9b34d9Smrg	       else dnum=tan(dnum*drg2rad);
8224d9b34d9Smrg	       break;
8234d9b34d9Smrg  case kSTO:   mem[0]=dnum;  flagM=!(mem[0]==0.0);  break;
8244d9b34d9Smrg  case kRCL:   if (rpn && lift_enabled) PushNum(dnum);
8254d9b34d9Smrg               dnum=mem[0];  flagM=!(mem[0]==0.0);  break;
8264d9b34d9Smrg  case kSUM:   mem[0]+=dnum; flagM=!(mem[0]==0.0);  break;
8274d9b34d9Smrg  case kEXC:   dtmp=dnum; dnum=mem[0];  mem[0]=dtmp;
8284d9b34d9Smrg	       flagM=!(mem[0]==0.0);  break;
8294d9b34d9Smrg  case kFACT:  if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) {
8304d9b34d9Smrg		 strcpy(dispstr,"error");
8314d9b34d9Smrg		 entered=3;
8324d9b34d9Smrg		 break;
8334d9b34d9Smrg	       }
8344d9b34d9Smrg	       i=(int) (floor(dnum));
8354d9b34d9Smrg	       for (j=1,dnum=1.0; j<=i; j++)
8364d9b34d9Smrg		 dnum*=(float) j;
8374d9b34d9Smrg	       break;
8384d9b34d9Smrg  }
8394d9b34d9Smrg
8404d9b34d9Smrg  if (entered==3) {  /* error */
8414d9b34d9Smrg    DrawDisplay();
8424d9b34d9Smrg    return;
8434d9b34d9Smrg  }
8444d9b34d9Smrg
8454d9b34d9Smrg  memop = keynum;
8464d9b34d9Smrg  entered=2;
8474d9b34d9Smrg  clrdisp=1;
8484d9b34d9Smrg  flagINV=0;
8494d9b34d9Smrg  lift_enabled = 1;
8504d9b34d9Smrg  sprintf(dispstr,"%.8g",dnum);
8514d9b34d9Smrg  DrawDisplay();
8524d9b34d9Smrg}
8534d9b34d9Smrg
8544d9b34d9Smrgvoid
8554d9b34d9Smrgofff(void)
8564d9b34d9Smrg{
8574d9b34d9Smrg  /* full reset */
8584d9b34d9Smrg  int i;
8594d9b34d9Smrg  ResetCalc();
8604d9b34d9Smrg  entered=clrdisp=1;
8614d9b34d9Smrg  lift_enabled = 0;
8624d9b34d9Smrg  dnum=mem[0]=0.0;
8634d9b34d9Smrg  if (rpn)
8644d9b34d9Smrg      for (i=1; i < XCALC_MEMORY; i++)
8654d9b34d9Smrg	  mem[i]=0.0;
8664d9b34d9Smrg  exponent=Dpoint=0;
8674d9b34d9Smrg  DrawDisplay();
8684d9b34d9Smrg}
8694d9b34d9Smrg
8704d9b34d9Smrg
8714d9b34d9Smrg#define STACKMAX 32
8724d9b34d9Smrgstatic int opstack[STACKMAX];
8734d9b34d9Smrgstatic int opsp;
8744d9b34d9Smrgstatic double numstack[STACKMAX];
8754d9b34d9Smrgstatic int numsp;
8764d9b34d9Smrg
8774d9b34d9Smrg
8784d9b34d9Smrg/*******/
8794d9b34d9Smrgstatic void
8804d9b34d9SmrgPushOp(op)
8814d9b34d9Smrg   int op;
8824d9b34d9Smrg/*******/
8834d9b34d9Smrg{
8844d9b34d9Smrg  if (opsp==STACKMAX) {strcpy(dispstr,"stack error");  entered=3;}
8854d9b34d9Smrg  else opstack[opsp++]=op;
8864d9b34d9Smrg}
8874d9b34d9Smrg
8884d9b34d9Smrg/*******/
8894d9b34d9Smrgstatic int
8904d9b34d9SmrgPopOp(void)
8914d9b34d9Smrg/*******/
8924d9b34d9Smrg{
8934d9b34d9Smrg  if (opsp==0) {
8944d9b34d9Smrg      strcpy(dispstr,"stack error");
8954d9b34d9Smrg      entered=3;
8964d9b34d9Smrg      return(kNOP);
8974d9b34d9Smrg  } else
8984d9b34d9Smrg    return(opstack[--opsp]);
8994d9b34d9Smrg}
9004d9b34d9Smrg
9014d9b34d9Smrg/*******/
9024d9b34d9Smrgstatic int
9034d9b34d9Smrgisopempty(void)
9044d9b34d9Smrg/*******/
9054d9b34d9Smrg{
9064d9b34d9Smrg  return( opsp ? 0 : 1 );
9074d9b34d9Smrg}
9084d9b34d9Smrg
9094d9b34d9Smrg#ifdef DEBUG
9104d9b34d9Smrgstatic void
9114d9b34d9Smrgshowstack(string)
9124d9b34d9Smrg    char	*string;
9134d9b34d9Smrg{
9144d9b34d9Smrg    fprintf(stderr, "%s: %lf %lf %lf\n", string, numstack[0], numstack[1],
9154d9b34d9Smrg	    numstack[2]);
9164d9b34d9Smrg}
9174d9b34d9Smrg#endif
9184d9b34d9Smrg
9194d9b34d9Smrg/*******/
9204d9b34d9Smrgstatic void
9214d9b34d9SmrgPushNum(num)
9224d9b34d9Smrg double num;
9234d9b34d9Smrg/*******/
9244d9b34d9Smrg{
9254d9b34d9Smrg  if (rpn) {
9264d9b34d9Smrg      numstack[2] = numstack[1];
9274d9b34d9Smrg      numstack[1] = numstack[0];
9284d9b34d9Smrg      numstack[0] = num;
9294d9b34d9Smrg      return;
9304d9b34d9Smrg  }
9314d9b34d9Smrg  if (numsp==STACKMAX) {
9324d9b34d9Smrg      strcpy(dispstr,"stack error");
9334d9b34d9Smrg      entered=3;
9344d9b34d9Smrg  } else
9354d9b34d9Smrg    numstack[numsp++]=num;
9364d9b34d9Smrg}
9374d9b34d9Smrg
9384d9b34d9Smrg/*******/
9394d9b34d9Smrgstatic double
9404d9b34d9SmrgPopNum(void)
9414d9b34d9Smrg/*******/
9424d9b34d9Smrg{
9434d9b34d9Smrg    if (rpn) {
9444d9b34d9Smrg	double tmp = numstack[0];
9454d9b34d9Smrg	numstack[0] = numstack[1];
9464d9b34d9Smrg	numstack[1] = numstack[2];
9474d9b34d9Smrg	return(tmp);
9484d9b34d9Smrg    }
9494d9b34d9Smrg    if (numsp==0) {
9504d9b34d9Smrg	strcpy(dispstr,"stack error");
9514d9b34d9Smrg	entered=3;
9524d9b34d9Smrg	return 0.0;
9534d9b34d9Smrg    } else
9544d9b34d9Smrg      return(numstack[--numsp]);
9554d9b34d9Smrg}
9564d9b34d9Smrg
9574d9b34d9Smrg/*******/
9584d9b34d9Smrgstatic void
9594d9b34d9SmrgRollNum(int dir)
9604d9b34d9Smrg/*******/
9614d9b34d9Smrg{
9624d9b34d9Smrg    double tmp;
9634d9b34d9Smrg
9644d9b34d9Smrg    if (dir) {				/* roll up */
9654d9b34d9Smrg	tmp         = dnum;
9664d9b34d9Smrg	dnum        = numstack[2];
9674d9b34d9Smrg	numstack[2] = numstack[1];
9684d9b34d9Smrg	numstack[1] = numstack[0];
9694d9b34d9Smrg	numstack[0] = tmp;
9704d9b34d9Smrg    } else {				/* roll down */
9714d9b34d9Smrg	tmp         = dnum;
9724d9b34d9Smrg	dnum        = numstack[0];
9734d9b34d9Smrg	numstack[0] = numstack[1];
9744d9b34d9Smrg	numstack[1] = numstack[2];
9754d9b34d9Smrg	numstack[2] = tmp;
9764d9b34d9Smrg    }
9774d9b34d9Smrg}
9784d9b34d9Smrg
9794d9b34d9Smrg
9804d9b34d9Smrg/*******/
9814d9b34d9Smrgstatic void
9824d9b34d9SmrgClearStacks(void)
9834d9b34d9Smrg/*******/
9844d9b34d9Smrg{
9854d9b34d9Smrg    if (rpn)
9864d9b34d9Smrg      numstack[0] = numstack[1] = numstack[2] = 0.;
9874d9b34d9Smrg    opsp=numsp=0;
9884d9b34d9Smrg}
9894d9b34d9Smrg
9904d9b34d9Smrg
9914d9b34d9Smrg/*******/
9924d9b34d9Smrgstatic int
9934d9b34d9Smrgpriority(op)
9944d9b34d9Smrg         int op;
9954d9b34d9Smrg/*******/
9964d9b34d9Smrg{
9974d9b34d9Smrg    switch (op) {
9984d9b34d9Smrg        case kPOW: return(2);
9994d9b34d9Smrg        case kMUL:
10004d9b34d9Smrg        case kDIV: return(1);
10014d9b34d9Smrg        case kADD:
10024d9b34d9Smrg        case kSUB: return(0);
10034d9b34d9Smrg        }
10044d9b34d9Smrg    return 0;
10054d9b34d9Smrg}
10064d9b34d9Smrg
10074d9b34d9Smrg
10084d9b34d9Smrg/********/
10094d9b34d9Smrgvoid
10104d9b34d9SmrgResetCalc(void)
10114d9b34d9Smrg/********/
10124d9b34d9Smrg{
10134d9b34d9Smrg    flagM=flagINV=flagPAREN=0;  drgmode=DEG;
10144d9b34d9Smrg    setflag(XCalc_MEMORY, False);
10154d9b34d9Smrg    setflag(XCalc_INVERSE, False);
10164d9b34d9Smrg    setflag(XCalc_PAREN, False);
10174d9b34d9Smrg    setflag(XCalc_RADIAN, False);
10184d9b34d9Smrg    setflag(XCalc_GRADAM, False);
10194d9b34d9Smrg    setflag(XCalc_DEGREE, True);
10204d9b34d9Smrg    strcpy(dispstr,"0");
10214d9b34d9Smrg    draw(dispstr);
10224d9b34d9Smrg    ClearStacks();
10234d9b34d9Smrg    drg2rad=PI/180.0;
10244d9b34d9Smrg    rad2drg=180.0/PI;
10254d9b34d9Smrg}
1026