[comp.sources.amiga] v89i200: hp11 calculator emulator v1.01, Part03/03

page%swap@Sun.COM (Bob Page) (11/13/89)

Submitted-by: dg3i+@andrew.cmu.edu (David Gay)
Posting-number: Volume 89, Issue 200
Archive-name: applications/hp11.3

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	ins.c
#	ins.h
#	io.c
#	io.h
#	kbd.c
#	kbd.h
#	lmkdebug
#	lmkfile
#	o/dummy
#	od/dummy
#	prog_codes.c
#	prog_codes.h
#	support.c
#	support.h
# This is archive 3 of a 3-part kit.
# This archive created: Sun Nov 12 17:33:21 1989
echo "extracting ins.c"
sed 's/^X//' << \SHAR_EOF > ins.c
X#include "exec/types.h"
X#include "proto/dos.h"
X
X#include "math.h"
X#include "string.h"
X#include "stdio.h"
X
X#include "hp11/amiga/amiga.h"
X#include "hp11/hp11.h"
X#include "hp11/io.h"
X#include "hp11/support.h"
X#include "hp11/ins.h"
X#include "hp11/codes.h"
X
X#define FOREVER() for(;;)
X
X/* Declare the modules variables */
XBOOL enabled, entering, overflow;
X
XBOOL expo, decpt;
Xchar strx[13], expx[4];
X
X/* Function addresses */
XHP11Function insfunc[KCOMPLEX] =
X{
X   Sqrt,
X   Exp,
X   Exp10,
X   ExpYX,
X   Invert,
X   DoCHS,
X   Divide,
X   SIN,
X   COS,
X   TAN,
X   DoEEX,
X   Times,
X   RunStart,
X   Rdn,
X   ExgXY,
X   ENTER,
X   Minus,
X   DoPoint,
X   SigmaPlus,
X   Plus,
X
X   Pi,
X   XleY,
X   ExgXInd,
X   ToRect,
X   ExgXI,
X   DSE,
X   ISG,
X   XgtY,
X   PSE,
X   ClearSigma,
X   ClearReg,
X   Random,
X   DoPerm,
X   ToHMS,
X   ToRAD,
X   XneY,
X   FRAC,
X   Fact,
X   Estimate,
X   LinearRegression,
X   XeqY,
X
X   Sqr,
X   LN,
X   LOG,
X   Percent,
X   DeltaPercent,
X   ABS,
X   DEG,
X   RAD,
X   GRAD,
X   Xlt0,
X   ArcSIN,
X   ArcCOS,
X   ArcTAN,
X   ToPolar,
X   Xgt0,
X   RTN,
X   Rup,
X   RND,
X   CLX,
X   LSTX,
X   DoComb,
X   ToH,
X   ToDEG,
X   Xne0,
X   INT,
X   Mean,
X   SDev,
X   SigmaSub,
X   Xeq0,
X
X   STORandom,
X   RCLSigma,
X
X   HypSIN,
X   HypCOS,
X   HypTAN,
X
X   ArcHypSIN,
X   ArcHypCOS,
X   ArcHypTAN
X};
X
X/* Various functions used to conserve code space. Could be macros or simply
X  instructions */
Xvoid DISABLE() { enabled = FALSE; entering = FALSE; }
X
Xvoid ENABLE() { enabled = TRUE; entering = FALSE; }
X
Xvoid LisX(void)
X{
X   L = X;
X}
X
Xvoid XisY(void)
X{
X   X = Y;
X}
X
Xvoid YisX(void)
X{
X   Y = X;
X}
X
Xvoid YisZ(void)
X{
X   Y = Z;
X}
X
Xvoid ZisY(void)
X{
X   Z = Y;
X}
X
Xvoid ZisT(void)
X{
X   Z = T;
X}
X
Xvoid TisZ(void)
X{
X   T = Z;
X}
X
X/* Check r against HP11 limits */
Xdouble Check(r)
Xdouble r;
X{
X   if (fabs(r) > MAXHP11) {
X      r = MAXHP11 * sign(r);
X      overflow = TRUE; /* Overflow has occured */
X   }
X   else if (fabs(r) < MINHP11) r = 0.0;
X
X   return(r);
X}
X
Xvoid Drop(void) /* Drop stack & save X in L */
X{
X   ENABLE();
X   LisX(); XisY(); YisZ(); ZisT();
X/* L = X(); X = Y; Y = Z; Z = T; */
X}
X
Xvoid Enter(void) /* Move stack up */
X{
X   TisZ(); ZisY(); YisX();
X/* T = Z; Z = Y; Y = X; */
X}
X
Xvoid Lift(void) /* lift stack if enabled, ENABLE stack */
X{
X   if (enabled) Enter();
X   ENABLE();
X}
X
Xvoid SaveX(void) /* Frequent: L = X; ENABLE(); (most simple instructions eg sin do this) */
X{
X   LisX();
X   ENABLE();
X}
X
X/* Convert x from current trig setting to radians */
Xdouble from(double x)
X{
X   switch (Angles) {
X      case deg:return(FDEG(x));
X      case rad:return(x);
X      case grad:return(FGRAD(x));
X   }
X}
X
X/* Convert radian value to current trig setting */
Xdouble toa(double x)
X{
X   switch (Angles) {
X      case deg:return(TDEG(x));
X      case rad:return(x);
X      case grad:return(TGRAD(x));
X   }
X}
X
X/* Used by statistical formulae (terminology from HP11 doc) */
Xdouble M(void) { return(R[0] * R[2] - R[1] * R[1]); }
X#define N() (R[0] * R[4] - R[3] * R[3]) /* used only once */
Xdouble P(void) { return(R[0] * R[5] - R[1] * R[3]); }
X
Xdouble *Reg(int n) /* Return address of register n */
X{
X   if (n == OI) return(&I);
X   else if (n == OIND_R) /* indirection */
X      if (I >= 0.0 && I < 20.0) return(R + (int)I);
X      else return(NULL); /* Unknown reg */
X   else return(R + n);
X}
X
X/* Convert current input value to real, return false if fails (no exponent) */
Xvoid StdVal(void)
X{
X   X = atof(strx);
X}
X
X/* Convert current input value to real, return false if fails (exponent) */
Xvoid ExpoVal(void)
X{
X   char buf[80];
X
X   /* buf = strx + "E" + expx, with leading blanks stripped from expx */
X   strcat(strcat(strcpy(buf,strx),"E"), stpblk(expx));
X
X   X = atof(buf);
X}
X
X/* Act on key to modify current input value */
Xvoid EnterNum(key)
Xregister int key;
X{
X   register int lens;
X
X   if (!entering) { /* No current digit entry */
X      if (enabled) Enter(); /* lift stack ? */
X      entering = enabled = TRUE; /* stack enabled, number being entered */
X      expo = decpt = FALSE; /* No dec point or exponent */
X      strx[0] = ' '; strx[1] = '\0'; /* nb string empty (leading space for sign) */
X   }
X
X   lens = strlen(strx); /* Current string length */
X   if (key >= KFIG + 0 && key <= KFIG + 9) /* Add digit */
X      if (expo) { /* to exponent */
X	 expx[1] = expx[2]; expx[2] = key - KFIG + '0';
X      }
X      else {
X	 strx[lens] = key - KFIG + '0'; strx[lens + 1] = '\0';
X	 strx[scrpos(strx, 11) + 1] = '\0'; /* Cut string at end of hp11 screen pos
X	    ==> prevent display overflow */
X      }
X   else
X      switch (key) {
X	 case -IBACK: /* back-arrow, actions are passed as negative numbers to
X	    distinguish them from instructions */
X	    if (expo) /* Correct exponent */
X	       if (strcmp(expx, "-00") == 0) strcpy(expx, " 00");
X	       else if (strcmp(expx, " 00") == 0) expo = FALSE; /* delete exponent */
X	       else {
X		  expx[2] = expx[1]; expx[1] = '0';
X	       }
X	    else /* no exponent */
X	       if (lens == 2) { CLX(); return; } /* end of digit entry,
X		  must not evaluate current entry ==> exit */
X	       else {
X		  if (strx[lens - 1] == '.') decpt = FALSE;
X		  strx[lens - 1] = '\0'; /* cut last char from str by moving eos mark */
X	       }
X	    break;
X	 case KCHS:
X	    if (expo) { /* change exponent sign */
X	       expx[0] = (expx[0] == '-') ? ' ' : '-';
X	    }
X	    else { /* change number sign */
X	       strx[0] = (strx[0] == '-') ? ' ' : '-';
X	    }
X	    break;
X	 case KPOINT:
X	    if (!expo && !decpt) {
X	       decpt = TRUE;
X
X	       if (lens == 1) { strcpy(strx, " 0"); lens = 2; } /* if no digit entered, add a 0 */
X	       strx[lens] = '.'; strx[lens + 1] = '\0';
X	       strx[scrpos(strx, 11) + 1] = '\0';
X	    }
X	    break;
X	 case KEEX:
X	    if (!expo) {
X	       expo = TRUE;
X	       strcpy(expx, " 00");
X	       if (lens == 1) strcpy(strx, " 1"); /* if no digit entered, add a 1 */
X	    }
X      }
X   if (expo) ExpoVal();
X   else StdVal();
X}
X
Xvoid ExpYX() /* y^x */
X{
X   double t;
X
X   errno = 0; /* set return code to 0 */
X   t = pow(Y, X);
X   if (errno != 0) Error('0'); /* Check math library return code */
X   else {
X      Y = t;
X      Drop();
X   }
X}
X
Xvoid CHS(void)
X{
X   ENABLE();
X   X = -X;
X}
X
Xvoid DoCHS()
X{
X   if (entering) EnterNum(KCHS);
X   else CHS();
X}
X
Xvoid DoEEX()
X{
X   EnterNum(KEEX);
X}
X
Xvoid DoPoint()
X{
X   EnterNum(KPOINT);
X}
X
Xvoid Rdn()
X{
X   double t;
X
X   ENABLE();
X   t = X; XisY(); YisZ(); ZisT(); T = t;
X/* t = X; X = Y; Y = Z; Z = T; T = t; */
X}
X
Xvoid ExgXY() /* Exchange X & Y */
X{
X   double t;
X
X   ENABLE();
X   t = X; XisY(); Y = t;
X/* t = X; X = Y; Y = t; */
X}
X
Xvoid ClearReg()
X{
X   int i;
X
X   NEUTRAL();
X   for (i = 0; i < 20; i++) R[i] = 0.0;
X   I = 0;
X}
X
Xvoid Estimate() /* Statistics: estimate y from given x */
X{
X   double tm = M(), tr, ty, tp = P(); /* temporary results */
X
X   tr = tm * N();
X   ty = R[0] * tm;
X
X   if (tr < 0.0 || ty == 0.0) Error('2'); /* Stat error */
X   else {
X      Enter(); /* always lifts stack */
X      SaveX();
X
X      X = (tm * R[3] + tp * (R[0] * X - R[1])) / ty; /* estimate */
X      Y = tp / sqrt(tr); /* Correlation coefficient */
X   }
X}
X
Xvoid LinearRegression()
X{
X   double tm = M(), tp = P();
X
X   if (tm == 0.0 || R[0] == 0.0) Error('2');
X   else {
X      Lift(); /* Lift stack twice */
X      Enter();
X
X      Y = tp / tm;
X      X = (tm * R[3] - tp * R[1]) / (R[0] * tm);
X   }
X}
X
Xvoid Rup()
X{
X   double t;
X
X   ENABLE();
X   t = T; TisZ(); ZisY(); YisX(); X = t;
X/* t = T; T = Z; Z = Y; Y = X; X = t; */
X}
X
Xvoid SDev()
X{
X   double tx, ty, td;
X
X   td = R[0] * (R[0] - 1.0);
X
X   if (td == 0.0) Error('2');
X   else {
X      tx = M() / td;
X      ty = N() / td;
X
X      if (tx < 0.0 || ty < 0.0) Error('2');
X      else {
X	 Lift();
X	 Enter();
X
X	 X = sqrt(tx); Y = sqrt(ty);
X      }
X   }
X}
X
Xvoid FIX(n)
Xint n;
X{
X   NEUTRAL();
X   Mode = fix; Digits = n;
X   minfix = pow(10.0, (double)-Digits);
X}
X
Xvoid SCI(n)
Xint n;
X{
X   NEUTRAL();
X   Mode = sci; Digits = n;
X}
X
Xvoid ENG(n)
Xint n;
X{
X   NEUTRAL();
X   Mode = eng; Digits = n;
X}
X
Xvoid ExgXI() /* Exchange X with I */
X{
X   double t;
X
X   ENABLE();
X   t = I; I = X; X = t;
X}
X
Xvoid ExgXInd() /* Exchange X with (i) */
X{
X   double t, *ptr;
X
X   if (!(ptr = Reg(OIND_R))) Error('3'); /* get address of pointed register if exists */
X   else {
X      ENABLE();
X      t = *ptr; *ptr = X; X = t;
X   }
X}
X
Xvoid STO(n, type)
Xint n;
Xenum StoTypes type;
X{
X   double val;
X   register double *ptr;
X
X   if (ptr = Reg(n)) { /* Valid register */
X
X      switch (type) {
X	 case sto: val = X; break;
X	 case add: val = *ptr + X; break;
X	 case sub: val = *ptr - X; break;
X	 case mul: val = *ptr * X; break;
X	 case div: if (X == 0.0) {
X		      Error('0');
X		      return; /* exit if error */
X		   }
X		   else val = *ptr / X; break;
X      }
X
X      if (fabs(val) > MAXHP11) Error('1'); /* Register overflow */
X      else {
X	 *ptr = val;
X	 ENABLE();
X      }
X   }
X   else Error('3');
X}
X
Xvoid RCL(n)
Xint n;
X{
X   double *ptr;
X
X   if (ptr = Reg(n)) {
X      Lift();
X      X = *ptr;
X   }
X   else Error('3');
X}
X
Xvoid GTOLine(n) /* move to line n */
Xint n;
X{
X   if (n >= 0 && n <= lastIns) PC = n;
X   else Error('4');
X}
X
Xvoid ProgramEntry() /* Enter a program */
X{
X   register int i;
X   WORD code;
X   register int inprog = TRUE;
X
X   RelKey();
X
X   ENABLE();
X
X   do {
X      DisplayLine(); DispPRGM(TRUE); /* Program display */
X
X      switch (ReadKey(&code)) {
X	 case Instruction: /* Save it */
X	    if (lastIns == MAXPROG) Error('4'); /* Memory full */
X	    else {
X	       for (i = lastIns; i > PC; i--) Prog[i + 1] = Prog[i]; /* Move program up */
X	       lastIns++;
X	       Prog[++PC] = code; /* store instruction */
X	       retCnt = 0; /* Empty return stack */
X	    };
X	    break;
X	 case Action: /* Act on it */
X	    if (code >= IGTO_LINE) GTOLine(code - IGTO_LINE);
X	    else switch (code) {
X	       case ION: on = inprog = !RelKey(); break; /* Allow user to change his mind */
X	       case IP_R: case IRESET: inprog = FALSE; break; /* exit program mode */
X	       case IMEM: MEM(); break;
X	       case IBACK: /* delete line */
X		  if (PC != 0) {
X		     for (i = PC; i < lastIns; i++) Prog[i] = Prog[i + 1]; /* del line */
X		     lastIns--;
X		     PC--;
X		     retCnt = 0; /* empty stack when prog changed */
X		  }
X		  break;
X	       case ISST: if (PC++ == lastIns) PC = 0; break;
X	       case IBST: if (PC-- == 0) PC = lastIns; break;
X	       case IUSER: USER(); break;
X	       case ICLR_PRGM: lastIns = PC = 0; break;
X	    }
X	    break;
X      }
X      RelKey();
X   } while (inprog);
X}
X
Xvoid GTOLBL(int n)
X{
X   register int i;
X
X   if (n > 14) Error('4');
X   else { /* Do a circular search from current line */
X      for (i = PC + 1; i <= lastIns; i++) /* Search from current line */
X	 if (Prog[i] == KLBL + n) {
X	    PC = i; return; /* found, exit */
X	 }
X      for (i = 1; i < PC; i++) /* If that fails, search from start */
X	 if (Prog[i] == KLBL + n) {
X	    PC = i; return;
X	 }
X      Error('4');
X   }
X}
X
Xvoid GTO(n)
Xint n;
X{
X   if (n == OIND_G) /* Indirection */
X      if (I >= 0.0) GTOLBL((int)I); /* gto label if I >= 0 */
X      else GTOLine(-(int)I); /* gto line -I if i < 0 */
X   else GTOLBL(n);
X   if (!error) { /* success */
X      ENABLE();
X      if (running) PC--; /* Execute label instruction (even though useless),
X	 must decrement PC in run mode because incremented after end ins */
X      else retCnt = 0; /* in normal mode, GTO clears return stack */
X   }
X}
X
Xvoid BreakupI(int *limit, int *step) /* From I deduce loop limit & step.
X I is stored as nnnnn.lllss with nnnnn as the loop count, lll the limit &
X ss the step. If ss == 0, the step is taken as 1 */
X{
X   double t;
X
X   t = frac(I) * 1000.0;
X   *limit = (int)t;
X   *step = (int)(100.0 * (t - *limit));
X   if (*step == 0) *step = 1;
X}
X
Xvoid DSE()
X{
X   int limit, step;
X
X   ENABLE();
X   BreakupI(&limit, &step);
X   I -= step;
X
X   skip = (I <= limit);
X}
X
Xvoid ISG()
X{
X   int limit, step;
X
X   ENABLE();
X   BreakupI(&limit, &step);
X   I += step;
X
X   skip = (I > limit);
X}
X
Xvoid SF(n)
Xint n;
X{
X   ENABLE();
X   Flags |= (1 << n);
X}
X
Xvoid CF(n)
Xint n;
X{
X   ENABLE();
X   Flags &= ~(1 << n);
X}
X
Xvoid Set(n) /* Is flag n set ? */
Xint n;
X{
X   ENABLE();
X   skip = !(Flags & (1 << n));
X}
X
Xvoid PSE()
X{
X   BOOL oldrun = running;
X
X   NEUTRAL();
X   running = FALSE;
X   Disp();
X   Wait50(50);
X   running = oldrun;
X}
X
Xvoid RTN()
X{
X   ENABLE();
X   if (!running || retCnt == 0) { /* In normal mode RTN sets PC to 0 &
X      clears the return stack. In run mode, if the stack is empty, it also
X      sets PC to 0 & then it interrupts the program */
X      running = FALSE;
X      PC = 0; retCnt = 0;
X   }
X   else /* Return from subroutine */
X      PC = retStack[--retCnt];
X}
X
Xvoid GSB(n)
Xint n;
X{
X   if (retCnt == MAXSTACK) Error('5'); /* Stack full */
X   else {
X      if (running) {
X	 retStack[retCnt++] = PC; /* Save PC */
X	 GTO(n); /* Jump to prog line */
X	 if (error) retCnt--; /* If this fails, reclaim stack space */
X      }
X      else { /* in normal mode, GSB = GTO + R/S */
X	 retCnt = 0;
X	 GTO(n);
X	 running = !error;
X      }
X   }
X}
X
Xvoid HP11ColdReset() /* ColdReset HP11 (Menu option: New) */
X{
X   Display("  Pr Error");
X
X   DEG();
X   FIX(4);
X   PC = lastIns = 0;
X   running = User = comma = FALSE;
X   Flags = retCnt = 0;
X   ClearSigma(); L = 0.0;
X   ClearReg();
X
X   GetKey();
X}
X
Xvoid MEM() /* Display available memory */
X{
X   char mem[20];
X
X   NEUTRAL();
X   sprintf(mem, " P-%-4dr- .9", MAXPROG - lastIns);
X   /* There are always all the register hence the r- .9, %-4d left justifies the number
X     of lines in a 4 character field */
X   Display(mem);
X   RelKey();
X}
X
Xvoid PREFIX() /* Display digits of number in x */
X{
X   char *disp, buf[20];
X   int dec, sign;
X
X   NEUTRAL();
X
X   if (X != 0.0) {
X      disp = ecvt(X, 10, &dec, &sign); /* The ideal library function for this */
X      buf[0] = ' '; strcpy(buf + 1, disp);
X      Display(buf);
X   }
X   else Display(" 0000000000");
X
X   RelKey();
X}
X
Xvoid RND()
X{
X   double fx, tx;
X   char buf[20];
X
X   SaveX();
X
X   switch (Mode) {
X      case fix:
X	 fx = modf(X, &tx);
X	 X = tx + trunc(fx / minfix + 0.5) * minfix;
X	 break;
X      case sci: case eng:
X	 sprintf(buf, "%0.*e", Digits, X);
X	 X = atof(buf);
X	 break;
X   }
X}
X
Xvoid Sqrt()
X{
X   if (X < 0.0) Error('0');
X   else {
X      SaveX(); X = sqrt(X);
X   }
X}
X
Xvoid Exp() /* e^x */
X{
X   SaveX(); X = exp(X);
X}
X
Xvoid Exp10() /* 10^x */
X{
X   SaveX(); X = pow(10.0, X);
X}
X
Xvoid Invert() /* 1/x */
X{
X   if (X == 0.0) Error('0');
X   else {
X      SaveX(); X = 1.0 / X;
X   }
X}
X
Xvoid Divide()
X{
X   if (X == 0.0) Error('0');
X   else {
X      Y = Y / X;
X      Drop();
X   }
X}
X
Xvoid SIN()
X{
X   SaveX(); X = sin(from(X));
X}
X
Xvoid COS()
X{
X   SaveX(); X = cos(from(X));
X}
X
Xvoid TAN()
X{
X   SaveX(); X = tan(from(X));
X}
X
Xvoid Times()
X{
X   Y = Y * X;
X   Drop();
X}
X
Xvoid ENTER()
X{
X   DISABLE();
X   Enter();
X}
X
Xvoid Minus()
X{
X   Y = Y - X;
X   Drop();
X}
X
Xvoid SigmaPlus() /* Accumulate statistics */
X{
X   R[0] += 1.0;
X   R[1] = Check(R[1] + X);
X   R[2] = Check(R[2] + X * X);
X   R[3] = Check(R[3] + Y);
X   R[4] = Check(R[4] + Y * Y);
X   R[5] = Check(R[5] + X * Y);
X
X   DISABLE();
X   LisX(); X = R[0];
X}
X
Xvoid Plus()
X{
X   Y = Y + X;
X   Drop();
X}
X
Xvoid Pi()
X{
X   Lift();
X   X = PI;
X}
X
X
Xvoid ToRect()
X{
X   SaveX();
X   Rect(X, from(Y), &X, &Y);
X}
X
Xvoid ClearSigma() /* Clear statistics */
X{
X   NEUTRAL(); /* Doesn't really matter, could be anything (but the HP11 doc says
X      neutral so it will be neutral ... */
X   X = Y = Z = T = R[0] = R[1] = R[2] = R[3] = R[4] = R[5] = 0.0;
X}
X
Xvoid Random() /* Random number generator. This isn't the same as the HP11 one, for I
X   don't know what the HP11 uses. */
X{
X   Lift();
X   X = drand48();
X}
X
Xvoid DoPerm() /* P y,x */
X{
X   if (X <= Y && X > 0.0) {
X      Y = Perm((int)Y, (int)X);
X      Drop();
X   }
X   else Error('0');
X}
X
Xvoid ToHMS()
X{
X   SaveX(); X = hms(X);
X}
X
Xvoid ToRAD()
X{
X   SaveX(); X = FDEG(X);
X}
X
Xvoid FRAC()
X{
X   SaveX(); X = frac(X);
X}
X
Xvoid Fact() /* gamma/factorial function */
X{
X   SaveX();
X   if (X > MAXFACT) X = MAXHP11;
X   else if (X >= 0 && X == trunc(X)) X = factorial((int)X);
X   else X = gamma(1.0 + X);
X}
X
Xvoid Sqr()
X{
X   SaveX(); X = X * X;
X}
X
Xvoid LN()
X{
X   if (X <= 0.0) Error('0');
X   else {
X      SaveX(); X = log(X);
X   }
X}
X
Xvoid LOG()
X{
X   if (X <= 0.0) Error('0');
X   else {
X      SaveX(); X = log10(X);
X   }
X}
X
Xvoid Percent()
X{
X   /* doesn't drop stack */
X   SaveX(); X = X * Y / 100.0;
X}
X
Xvoid DeltaPercent() /* Percentage of difference between x & y */
X{
X   if (Y == 0.0) Error('0');
X   else {
X      SaveX(); X = 100.0 * (X - Y) / Y;
X   }
X}
X
Xvoid ABS()
X{
X   SaveX(); X = fabs(X);
X}
X
X
Xvoid DEG()
X{
X   NEUTRAL();
X   Angles = deg;
X}
X
Xvoid RAD()
X{
X   NEUTRAL();
X   Angles = rad;
X}
X
Xvoid GRAD()
X{
X   NEUTRAL();
X   Angles = grad;
X}
X
Xvoid ArcSIN()
X{
X   if (fabs(X) > 1.0) Error('0');
X   else {
X      SaveX(); X = toa(asin(X));
X   }
X}
X
Xvoid ArcCOS()
X{
X   if (fabs(X) > 1.0) Error('0');
X   else {
X      SaveX(); X = toa(acos(X));
X   }
X}
X
Xvoid ArcTAN()
X{
X   SaveX(); X = toa(atan(X));
X}
X
Xvoid ToPolar()
X{
X   SaveX();
X   Polar(X, Y, &X, &Y);
X   Y = toa(Y);
X}
X
Xvoid CLX()
X{
X   X = 0.0;
X   DISABLE();
X}
X
Xvoid LSTX()
X{
X   Lift();
X   X = L;
X}
X
Xvoid DoComb() /* C y,x */
X{
X   if (X <= Y && X > 0.0) {
X      Y = Comb((int)Y, (int)X);
X      Drop();
X   }
X   else Error('0');
X}
X
Xvoid ToH()
X{
X   SaveX(); X = hr(X);
X}
X
Xvoid ToDEG()
X{
X   SaveX(); X = TDEG(X);
X}
X
Xvoid INT()
X{
X   SaveX(); X = trunc(X);
X}
X
Xvoid Mean()
X{
X   if (R[0] == 0.0) Error('2');
X   else {
X      Lift();
X      Enter();
X
X      X = R[1] / R[0];
X      Y = R[3] / R[0];
X   }
X}
X
Xvoid SigmaSub() /* Correct error in statistics accumulation */
X{
X   R[0] -= 1.0;
X   R[1] = Check(R[1] - X);
X   R[2] = Check(R[2] - X * X);
X   R[3] = Check(R[3] - Y);
X   R[4] = Check(R[4] - Y * Y);
X   R[5] = Check(R[5] - X * Y);
X
X   DISABLE();
X   LisX(); X = R[0];
X}
X
Xvoid HypSIN()
X{
X   SaveX(); X = sinh(X);
X}
X
Xvoid HypCOS()
X{
X   SaveX(); X = cosh(X);
X}
X
Xvoid HypTAN()
X{
X   SaveX(); X = tanh(X);
X}
X
Xvoid ArcHypSIN()
X{
X   SaveX(); X = asinh(X);
X}
X
Xvoid ArcHypCOS()
X{
X   if (fabs(X) < 1.0) Error('0');
X   else {
X      SaveX(); X = acosh(X);
X   }
X}
X
Xvoid ArcHypTAN()
X{
X   if (fabs(X) > 1.0) Error('0');
X   else {
X      SaveX(); X = atanh(X);
X   }
X}
X
Xvoid STORandom() /* Set random generator seed */
X{
X   ENABLE();
X   srand48((long)X);
X   /* Use integer part of seed, something better could be used */
X}
X
Xvoid RCLSigma() /* Recall accumulated x & y totals */
X{
X   Lift();
X   Enter();
X
X   X = R[1]; Y = R[3];
X}
X
Xvoid USER() /* Toggle user mode */
X{
X   NEUTRAL();
X   User = !User;
X}
X
Xvoid RunStart() /* Should be called RunStop ! */
X{
X   NEUTRAL();
X   if (running) running = FALSE; /* Stop */
X   else { /* Run */
X      if (lastIns != 0) { /* if a program to run */
X	 running = TRUE;
X	 if (PC == 0) PC = 1; /* skip first line */
X      }
X
X      DisplayLine(); /* Display first line */
X      RelKey();
X   }
X}
X
Xvoid XleY()
X{
X   ENABLE();
X   skip = (X > Y); /* skip if condition fails */
X}
X
Xvoid Xlt0()
X{
X   ENABLE();
X   skip = (X >= 0.0);
X}
X
Xvoid XgtY()
X{
X   ENABLE();
X   skip = (X <= Y);
X}
X
Xvoid Xgt0()
X{
X   ENABLE();
X   skip = (X <= 0.0);
X}
X
Xvoid XneY()
X{
X   ENABLE();
X   skip = (X == Y);
X}
X
Xvoid Xne0()
X{
X   ENABLE();
X   skip = (X == 0.0);
X}
X
Xvoid XeqY()
X{
X   ENABLE();
X   skip = (X != Y);
X}
X
Xvoid Xeq0()
X{
X   ENABLE();
X   skip = (X != 0.0);
X}
X
Xvoid SST() /* Single step a program */
X{
X   if (lastIns == 0) { /* No program to single step through */
X      DisplayLine();
X      RelKey();
X   }
X   else {
X      if (PC == 0) PC = 1; /* skip line 0 */
X
X      DisplayLine();
X      RelKey();
X
X      running = TRUE; /* Pretend line is being run */
X      ExecIns(Prog[PC]); /* Exec ins */
X      if (!error && !overflow) { /* idem main loop */
X	 if (skip) PC++;
X	 PC++;
X	 while (PC > lastIns) {
X	    RTN();
X	    PC++;
X	 }
X      }
X      running = FALSE;
X
X   }
X}
X
Xvoid BST() /* move back one line (but don't correct its effect) */
X{
X   if (PC == 0) PC = lastIns;
X   else PC--;
X
X   DisplayLine();
X   RelKey();
X}
X
X
SHAR_EOF
echo "extracting ins.h"
sed 's/^X//' << \SHAR_EOF > ins.h
X/* HP11 numeric limits */
X#define MAXHP11 9.999999999E99
X#define MINHP11 1E-99
X#define MAXFACT 69.95757445
X
X/* The different type of sto operations. The order must reflect the ordering of
X  instruction codes in code.h */
Xenum StoTypes {sto, add, sub, mul, div};
X
Xextern BOOL enabled, entering, overflow; /* Various flags related to the instructions */
X
X/* Current entry value, used during number entry */
Xextern BOOL expo, decpt; /* expo true for an exponent present, decpt true for decimal point */
Xextern char strx[13], expx[4];
X
Xtypedef void (*HP11Function)(void);
X
Xextern HP11Function insfunc[];
X
X/* Function declarations */
X/* ===================== */
Xdouble Check(double); /* Check the argument for HP11 limits (1e-99 --> 1e100),
X   return adjusted value if out of limits */
Xvoid DISABLE(void); /* Disable stack */
Xvoid ENABLE(void); /* Enable stack */
Xvoid Enter(void); /* Do an "Enter" */
X#define NEUTRAL() { entering = FALSE; } /* Neutral operation, simply end
X number entry */
X
X/* Instructions */
Xvoid FIX(int); /* set display mode to FIX n */
Xvoid SCI(int);
Xvoid ENG(int);
Xvoid STO(int, enum StoTypes); /* Sto in reg n (0 <= n <= 21, with 20 = I, 21 = (i)),
X with desired operation */
Xvoid RCL(int); /* RCl, n same as for sto */
Xvoid EnterNum(int); /* Add keycode to current number */
Xvoid GTO(int); /* Goto label n (n = 0 to 9, A to E (10 to 14) or I (15) : indirection */
Xvoid SF(int), CF(int), Set(int);
Xvoid GSB(int); /* Call subprogram n (cf GTO) */
Xvoid GTOLine(int); /* Jump to line in prog */
X
X#ifdef ABS
X#undef ABS
X#endif
X
Xvoid Sqrt(void), Exp(void), Exp10(void), ExpYX(void), Invert(void),
X     Divide(void), SIN(void), COS(void), TAN(void), Times(void), Rdn(void),
X     ExgXY(void), ENTER(void), Minus(void), SigmaPlus(void), Plus(void),
X     Pi(void), ToRect(void), ClearSigma(void), ClearReg(void), Random(void),
X     DoPerm(void), ToHMS(void), ToRAD(void), FRAC(void), Fact(void),
X     Estimate(void), LinearRegression(void), Sqr(void), LN(void), LOG(void),
X     Percent(void), DeltaPercent(void), ABS(void), DEG(void), RAD(void),
X     GRAD(void), ArcSIN(void), ArcCOS(void), ArcTAN(void), ToPolar(void),
X     Rup(void), CLX(void), LSTX(void), DoComb(void), ToH(void), ToDEG(void),
X     INT(void), Mean(void), SDev(void), SigmaSub(void), HypSIN(void),
X     HypCOS(void), HypTAN(void), ArcHypSIN(void), ArcHypCOS(void),
X     ArcHypTAN(void), ExgXI(void), STORandom(void), RCLSigma(void), USER(void),
X     ProgarmEntry(void), RunStart(void), XleY(void), Xlt0(void),
X     DSE(void), ISG(void), XgtY(void), Xgt0(void), PSE(void), XneY(void),
X     Xne0(void), XeqY(void), Xeq0(void), RTN(void), SST(void), BST(void),
X     HP11ColdReset(void), MEM(void), PREFIX(void), RND(void), DoCHS(void),
X     DoPoint(void), DoEEX(void), ExgXInd(void), ProgramEntry(void);
X
SHAR_EOF
echo "extracting io.c"
sed 's/^X//' << \SHAR_EOF > io.c
X#include "exec/types.h"
X
X#include "stdlib.h"
X#include "stdio.h"
X#include <math.h>
X#include "string.h"
X
X#include "hp11/hp11.h"
X#include "hp11/amiga/amiga.h"
X#include "hp11/ins.h"
X#include "hp11/io.h"
X#include "hp11/kbd.h"
X#include "hp11/codes.h"
X#include "hp11/prog_codes.h"
X
X#define MAXRUN 4 /* Length of time running is displayed */
X
X#define FOREVER for (;;)
X
Xint comma;
X
Xstatic char *stpich(char *p, int c) /* insert character c at front of string p */
X{
X   movmem(p, p + 1, strlen(p) + 1);
X   *p = c;
X
X   return(p);
X}
X
Xint GetKey() /* Read a key & wait for its release */
X{
X   int key;
X
X   key = PollKey(TRUE);
X   RelKey();
X
X   return(key);
X}
X
Xenum KeyTypes ReadKey(code) /* Read a complete key sequence, & return
X its type, intrsuction or action. */
Xregister WORD *code;
X{
X   register struct Key *curtkey;
X   register int key, offset;
X   register BOOL noKey; /* if an invalid sequence is returned, don't read a new key,
X      reuse the one which caused the error. This is set to false when that happens */
X   register enum KeyTypes ret;
X
X   noKey = TRUE; /* no key read */
X
X   FOREVER {
X      offset = 0; /* f or g not pressed */
X
X      FOREVER { /* This loop reads a key from the main, f or g shifted keyboards.
X	 Further refinements (eg sto) are done algorithmically, to save space */
X	 if (noKey) key = PollKey(TRUE); /* obtain next key */
X	 Dispf(FALSE); Dispg(FALSE);
X	 noKey = TRUE;
X	 if (key == 31) { /* f pressed, toggle its status */
X	    offset = (offset == NUMKEYS) ? 0 : (Dispf(TRUE), NUMKEYS);
X	    RelKey();
X	 }
X	 else if (key == 32) { /* g */
X	    offset = (offset == NUMKEYS + NUMKEYS) ? 0 : (Dispg(TRUE), NUMKEYS + NUMKEYS);
X	    RelKey();
X	 }
X	 else break;/* got a key, exit from loop */
X      }
X      if (User && key < 5) offset ^= NUMKEYS; /* Toggle f for first five keys. This
X       doesn't affect g because the bit patterns are exclusive (42 & 84 = 0) */
X
X      Dispf(FALSE); Dispg(FALSE);
X
X      curtkey = mainKbd + offset + key; /* find address of (eventually shifted) key */
X
X      switch (curtkey->Sort) {
X	 case Action:
X	    *code = curtkey->Act;
X	    return(Action);
X	 case Instruction:
X	    *code = curtkey->Code;
X	    return(Instruction);
X	 case Prefix: /* Key is a prefix, execute corresponding routine */
X	    RelKey();
X	    ret = (*(curtkey->Suffix))(code);
X	    if (ret != Invalid) return(ret); /* if successful */
X
X	    key = *code; /* else, invalid keycode returnedin code field for reuse */
X	    noKey = FALSE; /* a key is already available */
X	    break;
X	 case Invalid: /* An inavlid f or g sequence was entered, retry it with
X	    the f or g prefix stripped. Therefore all obtainable main keyboard sequences
X	    must exist, otherwise the program enters an infinite loop retrying constantly
X	    the same nonexistent keycode */
X	    key %= NUMKEYS;
X	    noKey = FALSE;
X	    break;
X      }
X   }
X}
X
X/* Return position n on the liquid cristal display in string t */
Xint scrpos(t, n)
Xchar *t;
Xregister int n;
X{
X   register char *s = t;
X   register int pos;
X
X   pos = 0;
X   while (pos <= n && *s) { /* go on till end of string or beyond position n on display */
X      if (*s != '.' && *s != ',') pos++; /* . & , take no space on the display */
X      s++;
X   }
X   return((int)((s - t) - 1 - (pos - n))); /* pos - n  is there to take care of the overshoot. If
X   n is beyond the end of the string, the position returned may well be wildly beyond the
X   actual end of the string */
X}
X
X/* Return the length taken up on the screen by the string */
Xint scrlen(s)
Xregister char *s;
X{
X   register int cnt = 0;
X
X   while (*s) {
X      if (*s != '.' && *s != ',') cnt++; /* . & , take no space on the display */
X      s++;
X   }
X
X   return(cnt);
X}
X
X/* format string s in hp11 display format (without exponent) so that it takes
X n spaces in the display. s isn't modified */
Xstatic char *CvtStd(char *s, int n)
X{
X   static char buf[20];
X   register char *p;
X   register int i, nb;
X   register int digit_separator = comma ? '.' : ','; /* separator according to current setting */
X
X   strcpy(buf, s); /* copy string to safe work buffer */
X
X   if ((p = strchr(buf, '.')) == NULL) { /* find position of . */
X      p = buf + strlen(buf);
X      if (!entering) *p = comma ? ',' : '.';
X      *(p + 1) = '\0';
X   }
X   else if (comma) *p = ','; /* Replace . by , if necessary */
X
X   while ((p -= 3) - buf > 1) /* Add , (or .) to string every 3 digits */
X      stpich(p, digit_separator);
X
X   nb = n - scrlen(buf);
X   for (i = 1; i <= nb; i++) strcat(buf, " "); /* pad with spaces to required screen length */
X   buf[scrpos(buf, n) + 1] = '\0'; /* cut at n characters */
X
X   return(buf);
X}
X
X/* format string s in hp11 display format (with exponent) */
Xstatic char *CvtExpo(char *s, char *e)
X{
X   if (strlen(e) > 3) { /* deal with roundoff towards 1e100 when nb too big */
X      e = " 99"; /* exponent is 99 */
X      strncpy(s + 1, "9.999999999", strlen(s + 1)); /* mantissa is enough 9's */
X   }
X
X   return(strcat(CvtStd(s, 8), e));
X}
X
X/* convert x to scientific format with n digits. Returns it in a static buffer (from CvtStd) */
Xstatic char *Scient(double x, int n)
X{
X   char buf[20];
X   register char *pe;
X
X   sprintf(buf, "% .*E", n, x); /* Scientific format with n digits */
X   pe = strchr(buf, 'E'); /* split string into mantissa & exponent */
X   *pe++ = '\0';
X   /* if (*pe == '+') *pe = ' '; A + is displayed as a space by the Display routine anyway */
X
X   return(CvtExpo(buf, pe));
X}
X
X/* Convert x to fix n format */
Xstatic char *Fixed(double x, int n)
X{
X   char buf[80];
X
X   sprintf(buf, "% .*f", n, x);
X
X   return(CvtStd(buf, 11));
X}
X
X/* Eng n format */
Xstatic char *Engin(double x, int n)
X{
X   char expbuf[10], buf[80];
X   register char *pe;
X   double mantissa;
X   register int exponent, dif;
X
X   sprintf(buf, "%.*E", n, x); /* print enough digits */
X   *(pe = strchr(buf, 'E')) = '\0';
X   mantissa = atof(buf); /* get mantissa & exponent */
X   exponent = atoi(pe + 1);
X
X   /* Round exponent down to a multiple of 3 */
X   dif = exponent % 3;
X   if (dif < 0) dif += 3;
X   exponent -= dif; /* calculate new exponent & mantissa */
X   mantissa *= pow(10.0, (double)dif);
X
X   /* Convert them to string */
X   sprintf(buf, "% .*f", (n - dif > 0) ? n - dif : 0, mantissa);
X   sprintf(expbuf, "%c%02d", (exponent < 0) ? '-' : ' ', iabs(exponent)); /* pad exponent with 0's, hence %02d not %2d */
X
X   return(CvtExpo(buf, expbuf));
X}
X
X/* Display current trig mode */
Xstatic void DispAngle(void)
X{
X   switch (Angles) {
X      case grad:DispG(TRUE);
X      case rad:DispRAD(TRUE);
X      case deg:break;
X   }
X}
X
X/* Display current x value in normal mode, running in run mode */
Xvoid Disp()
X{
X   static int runcnt = MAXRUN;
X   static BOOL runon;
X
X   if (running) { /* Flash running on and off every MAXRUN calls */
X      if (fast) { /* Display Running only once in fast mode */
X	 if (!runon) {
X	    Display("  Running");
X	    runon = TRUE; /* Running displayed */
X	 }
X      }
X      else if (runcnt-- == 0) Display("");
X      else if (runcnt <= -MAXRUN) {
X	 runcnt = MAXRUN;
X	 Display("  Running");
X      }
X   }
X   else {
X      runon = FALSE; /* Running not displayed */
X      if (entering) /* Display number entry strings */
X	 if (expo) Display(CvtExpo(strx, expx)); /* with exponent */
X	 else Display(CvtStd(strx, 11));
X      else
X	 Display(NbStr(X));
X
X      DispAngle();
X      if (User) DispUSER(TRUE);
X   }
X}
X
Xchar *NbStr(x)
Xdouble x;
X{
X   switch (Mode) { /* Display x according to display mode */
X      case fix:if ((fabs(X) >= minfix / 2.0 || X == 0.0) && fabs(X) < 1E10) {
X		  /* Number can be displayed in fix mode */
X		  return(Fixed(X, Digits));
X	       }
X	       /* fall through for call to Scient */
X      case sci:return(Scient(X, Digits));
X      case eng:return(Engin(X, Digits));
X   }
X}
X
X/* Display Error n, & wait for a key to be pressed */
Xvoid Error(n)
Xint n;
X{
X   register char *buf;
X
X   entering = FALSE; /* end of digit entry */
X   error = TRUE; /* an error has occured */
X   buf = "  Error  ";
X   buf[8] = n; buf[9] ='\0';
X
X   if (!running) RelKey();
X   Display(buf);
X   GetKey();
X
X}
X
X/* Display current program line */
Xvoid DisplayLine()
X{
X   register int c1 = keycodes[Prog[PC]].c1, c2 = keycodes[Prog[PC]].c2,
X		c3 = keycodes[Prog[PC]].c3;
X   char _buf[20], _insbuf[20];
X   register char *buf = _buf, *insbuf = _insbuf;
X   register int point = comma ? ',' : '.'; /* separator according to current setting */
X
X   sprintf(buf, " %03d-", PC); /* prepare program line */
X
X   /* Prepare instruction buffer */
X   if (PC == 0) insbuf[0] = '\0'; /* nothing at line 0 */
X   else switch (keycodes[Prog[PC]].Type) { /* there are 6 methods for displaying a line */
X      case ONECODE: sprintf(insbuf, "%6d", c1); break; /*     nn eg SIN or 9 */
X      case TWOCODE: sprintf(insbuf, "%3d%3d", c1, c2); break; /*  nn nn eg g LOG */
X      case TWOCODE_9: sprintf(insbuf, "%4d%2d", c1, c2); break; /*  nn n eg STO 5*/
X      case TWOCODE_PT: sprintf(insbuf, "%4d %c%1d", c1, point, c2); break; /* nn .n eg RCL .6 */
X      case THREECODE: sprintf(insbuf, "%2d,%2d,%2d", c1, c2, c3); break; /* nn,nn,nn eg f HYP SIN */
X      case THREECODE_PT: sprintf(insbuf, "%2d,%2d, %c%1d", c1, c2, point, c3); break; /* nn,nn, .n eg STO + .0 */
X   }
X
X   Display(strcat(buf, insbuf));
X
X   DispAngle();
X   if (User) DispUSER(TRUE);
X}
X
SHAR_EOF
echo "extracting io.h"
sed 's/^X//' << \SHAR_EOF > io.h
Xextern int comma; /* The current comma setting : true if decimal point is a comma,
X false if it is a point */
X
Xenum KeyTypes ReadKey(WORD *); /* Read a complete key sequence */
Xvoid Disp(void); /* Display the current value of X register */
Xvoid Error(int); /* Display Error n */
Xint GetKey(void); /* Read a key from the HP11 (waiting for its release) */
Xint scrpos(char *, int); /* Return position n on the liquid cristal display in string t */
Xint scrlen(char *); /* Return the length taken up on the screen by the string */
Xvoid DisplayLine(void); /* Display current program line */
Xchar *NbStr(double); /* Convert number into string according to current mode */
SHAR_EOF
echo "extracting kbd.c"
sed 's/^X//' << \SHAR_EOF > kbd.c
X#include "exec/types.h"
X#include "hp11/hp11.h"
X#include "hp11/kbd.h"
X#include "hp11/codes.h"
X#include "hp11/io.h"
X
X/* Macros to initialise one field of the keyboard structure to a particular type.
X  This simpilfies (& clarifies) this initialisation. */
X#define CODE(code) {Instruction, (Decoder)(code) }
X#define ACT(act) {Action, (Decoder)(act) }
X#define PREFIX(adr) {Prefix, (adr) }
X#define INVALID() {Invalid, NULL }
X
X/* Often used macros which return their agument signaling that it is an instruction,
X  action or error */
X#define RETINS(val) { *code = (val); return(Instruction); }
X#define RETACT(val) { *code = (val); return(Action); }
X#define RETERR(key) { *code = (key); return(Invalid); }
X
X/* Keys which can follow GTO (or GSB). A -1 indicates am invalid sequence, otherwise
X  the value is the offset to add to KGTO to obtain the corresponding instruction.
X  IGTO_LINE is different and valid only for GTO, it indicates a GTO .nnn action */
Xstatic BYTE gto_decode[NUMKEYS] = {
X   10, 11, 12, 13, 14, -1, 7, 8, 9, -1,
X   -1, -1, -1, -1, OIND_G, -1, 4, 5, 6, -1,
X   -1, -1, -1, -1, -1, -1, 1, 2, 3, -1,
X   -1, -1, -1, -1, -1, -1, 0, IGTO_LINE, -1, -1,
X   -1, -1
X};
X
X/* For STO & RCL, cf above */
Xstatic BYTE sto_decode[NUMKEYS] = {
X   -1, -1, -1, -1, -1, -1, 7, 8, 9, ODIV,
X   -1, -1, -1, OIND_R, OI, -1, 4, 5, 6, OMUL,
X   -1, -1, -1, -1, -1, KRANDOM, 1, 2, 3, OSUB,
X   -1, -1, -1, -1, -1, -1, 0, KPOINT, KSIGMA_PLUS, OPLUS,
X   -1, -1
X};
X
X/* Functions which take a numeric argument only (eg eng) can use the numbers
X  from gto_decode, considering as invalid what isn't a number between 1 & 10 */
X#define nb_decode gto_decode
X
X/* Read 3 digits for GTO .nnn & return the value in line. If something other than
X  a number is entered, return the keycode of the first incorrect code & FALSE */
Xstatic BOOL GetLine(short *line)
X{
X   register int cnt = 0, key;
X   register int dec;
X
X   *line = 0;
X
X   do {
X      key = GetKey(); dec = nb_decode[key]; /* Get numeric value */
X      if (dec >= 0 && dec <= 9) { /* It is a digit */
X	 cnt++;
X	 *line = *line * 10 + dec;
X      }
X      else { /* error */
X	 *line = key;
X	 return(FALSE);
X      }
X   } while (cnt < 3);
X
X   /* 3 digits reads */
X   return(TRUE);
X}
X
X/* Decoder routine for FIX, SCI, ENG, SF, CF, Set. code returns the
X  instruction/action/keycode, start is the offset for the instruction being
X  decoded (eg KFIX), max is the maximum value which can be accepted (eg 1 for SF).
X  For SCI & ENG, a number beyond their max (7) is treated as if it was the max
X  value (So if you type 'f SCI 8' you will get 'f SCI 7' */
Xstatic enum KeyTypes NBDec(short *code, int start, int max)
X{
X   register int key, dec;
X
X   key = GetKey(); dec = nb_decode[key];
X
X   if (dec >= 0 && dec <= 9) { /* Is a digit */
X      if (dec <= max) RETINS(start + dec) /* valid ins */
X      else if (start == KSCI || start == KENG) RETINS(start + max)
X	 /* Special treatment for SCI & ENG */
X   }
X   RETERR(key);
X}
X
X/* Decoding for HYP & ArcHYP */
Xstatic enum KeyTypes HypDec(short *code, int start)
X{
X   int key;
X
X   key = GetKey();
X   if (key >= 12 /* SIN */ && key <= 14 /* TAN */) RETINS(start + key - 12)
X   else RETERR(key);
X}
X
X/* Decoding for GTO, GSB & LBL */
Xstatic enum KeyTypes JMPDec(short *code, int start)
X{
X   register int key, dec;
X   short val;
X
X   key = GetKey(); dec = gto_decode[key];
X
X   if (dec >= 0 && dec <= 15) RETINS(start + dec); /* 0 to 9, A to E */
X   switch (dec) {
X      case IGTO_LINE: if (start == KGTO) /* GTO .nnn */
X	 if (GetLine(&val)) RETACT(IGTO_LINE + val)
X	 else RETERR(val);
X      case OIND_G: if (start != KLBL) RETINS(start + OIND_G); /* GTO/GSB I */
X   }
X   RETERR(key);
X}
X
X/* Decoding for STO & RCL, deals with all possible STO's */
Xstatic enum KeyTypes REGDec(short *code, int start)
X{
X   register int dec, key, oldoff, offset = 0;
X
X   do {
X      key = GetKey();
X      dec = sto_decode[key];
X      oldoff = offset;
X
X      if ((dec >= 0 && dec <= 9) /* 0 to 9 end an instruction */
X	  || /* I & (i) end an instruction if no . was typed before. This
X	       is visible if the offset (ignoring + - * /) is 10 */
X	  ((offset % OPLUS) != 10 && (dec == OI || dec == OIND_R)))
X	 RETINS(start + offset + dec);
X      switch (dec) { /* Special cases & offsets */
X	 case KRANDOM: if (offset == 0 && start == KSTO) RETINS(KSTO_RANDOM); /* STO Random */
X	 case KSIGMA_PLUS: if (offset == 0 && start == KRCL) RETINS(KRCL_SIGMA); /* Recall stats */
X	 case KPOINT: if ((offset % OPLUS) == 0) offset += 10; /* Only one . allowed */
X	 case OPLUS: case ODIV: case OMUL: case OSUB: /* + - * / only if none yet */
X	    if (offset == 0 && start == KSTO) offset = dec;
X      }
X   } while (offset != oldoff);
X   /* if offset not changed then there was an error (the loop is repeated when
X      the offset changes) */
X   RETERR(key);
X}
X
X/* Decoding for prefixes */
X/* --------------------- */
Xstatic enum KeyTypes FIXDec(short *code)
X{
X   return(NBDec(code, KFIX, 9));
X}
X
Xstatic enum KeyTypes SCIDec(short *code)
X{
X   return(NBDec(code, KSCI, 7));
X}
X
Xstatic enum KeyTypes ENGDec(short *code)
X{
X   return(NBDec(code, KENG, 7));
X}
X
Xstatic enum KeyTypes SFDec(short *code)
X{
X   return(NBDec(code, KFLAGS + OSF, 1));
X}
X
Xstatic enum KeyTypes SETDec(short *code)
X{
X   return(NBDec(code, KFLAGS + OSET, 1));
X}
X
Xstatic enum KeyTypes CFDec(short *code)
X{
X   return(NBDec(code, KFLAGS + OCF, 1));
X}
X
Xstatic enum KeyTypes HYPDec(short *code)
X{
X   return(HypDec(code, KHYP));
X}
X
Xstatic enum KeyTypes ARCHYPDec(short *code)
X{
X   return(HypDec(code, KARCHYP));
X}
X
Xstatic enum KeyTypes LBLDec(short *code)
X{
X   return(JMPDec(code, KLBL));
X}
X
Xstatic enum KeyTypes GTODec(short *code)
X{
X   return(JMPDec(code, KGTO));
X}
X
Xstatic enum KeyTypes GSBDec(short *code)
X{
X   return(JMPDec(code, KGSB));
X}
X
Xstatic enum KeyTypes STODec(short *code)
X{
X   return(REGDec(code, KSTO));
X}
X
Xstatic enum KeyTypes RCLDec(short *code)
X{
X   return(REGDec(code, KRCL));
X}
X
X/* The main kbd, f & g */
X/* ------------------- */
Xstruct Key mainKbd[3 * NUMKEYS] = {
X/* First the main keyboard (unshifted). All the keys which can be entered
X  MUST not be INVALID(), otherwise the program enters an infinite loop */
X   CODE(KSQRT),
X   CODE(KEXP),
X   CODE(KEXP10),
X   CODE(KEXP_YX),
X   CODE(KINV),
X   CODE(KCHS),
X   CODE(KFIG + 7),
X   CODE(KFIG + 8),
X   CODE(KFIG + 9),
X   CODE(KDIV),
X   ACT(ISST),
X   PREFIX(GTODec),
X   CODE(KTRIG + OSIN),
X   CODE(KTRIG + OCOS),
X   CODE(KTRIG + OTAN),
X   CODE(KEEX),
X   CODE(KFIG + 4),
X   CODE(KFIG + 5),
X   CODE(KFIG + 6),
X   CODE(KMUL),
X   CODE(KR_S),
X   PREFIX(GSBDec),
X   CODE(KRDN),
X   CODE(KEXG_XY),
X   ACT(IBACK),
X   CODE(KENTER),
X   CODE(KFIG + 1),
X   CODE(KFIG + 2),
X   CODE(KFIG + 3),
X   CODE(KSUB),
X   ACT(ION),
X   INVALID(), /* Never tested : f */
X   INVALID(), /* Never tested : g */
X   PREFIX(STODec),
X   PREFIX(RCLDec),
X   INVALID(), /* This key does not exist : it is hidden by ENTER */
X   CODE(KFIG + 0),
X   CODE(KPOINT),
X   CODE(KSIGMA_PLUS),
X   CODE(KPLUS),
X   ACT(IRESET), /* These 2 are pseudo-keys */
X   ACT(IDISPLAY),
X/* now f codes, which can be INVALID() */
X   CODE(KGSB + OA),
X   CODE(KGSB + OB),
X   CODE(KGSB + OC),
X   CODE(KGSB + OD),
X   CODE(KGSB + OE),
X   CODE(KPI),
X   PREFIX(FIXDec),
X   PREFIX(SCIDec),
X   PREFIX(ENGDec),
X   CODE(KX_LE_Y),
X   PREFIX(LBLDec),
X   PREFIX(HYPDec),
X   CODE(KEXG_X_IND),
X   CODE(KRCL + OIND_R),
X   CODE(KRCL + OI),
X   CODE(KRECT),
X   CODE(KEXG_XI),
X   CODE(KDSE),
X   CODE(KISG),
X   CODE(KX_GT_Y),
X   CODE(KPSE),
X   CODE(KCLR_SIGMA),
X   ACT(ICLR_PRGM),
X   CODE(KCLR_REG),
X   ACT(ICLR_PREFIX),
X   CODE(KRANDOM),
X   CODE(KPERM),
X   CODE(KHMS),
X   CODE(KTO_RAD),
X   CODE(KX_NE_Y),
X   INVALID(), INVALID(), INVALID(), /* ON, f & g */
X   CODE(KFRAC),
X   ACT(IUSER),
X   INVALID(), /* dosen't exist */
X   CODE(KFACT),
X   CODE(KESTIMATE),
X   CODE(KLR),
X   CODE(KX_EQ_Y),
X   INVALID(), INVALID(),
X/* finally, g codes */
X   CODE(KSQR),
X   CODE(KLN),
X   CODE(KLOG),
X   CODE(KPERC),
X   CODE(KDELTA_PERC),
X   CODE(KABS),
X   CODE(KDEG),
X   CODE(KRAD),
X   CODE(KGRD),
X   CODE(KX_LT_0),
X   ACT(IBST),
X   PREFIX(ARCHYPDec),
X   CODE(KARC + OSIN),
X   CODE(KARC + OCOS),
X   CODE(KARC + OTAN),
X   CODE(KPOLAR),
X   PREFIX(SFDec),
X   PREFIX(CFDec),
X   PREFIX(SETDec),
X   CODE(KX_GT_0),
X   ACT(IP_R),
X   CODE(KRTN),
X   CODE(KRUP),
X   CODE(KRND),
X   CODE(KCLX),
X   CODE(KLSTX),
X   CODE(KCOMB),
X   CODE(KHR),
X   CODE(KTO_DEG),
X   CODE(KX_NE_0),
X   INVALID(), INVALID(), INVALID(),
X   CODE(KINT),
X   ACT(IMEM),
X   INVALID(),
X   CODE(KMEAN),
X   CODE(KSDEV),
X   CODE(KSIGMA_SUB),
X   CODE(KX_EQ_0),
X   INVALID(), INVALID()
X};
X
SHAR_EOF
echo "extracting kbd.h"
sed 's/^X//' << \SHAR_EOF > kbd.h
X/* Define type Decoder which is a function with a short * argument and which
X  return an enum KeyTypes. These functions do the keyboard decoding for prefixes */
Xtypedef enum KeyTypes (*Decoder)(short *);
X
X/* One key of the keyboard structure : */
Xstruct Key {
X   enum KeyTypes Sort; /* The type of key */
X   union { /* Different data for each type */
X      Decoder suffix; /* Prefix ==> decoder function */
X      LONG act; /* Action number */
X      LONG code; /* Instruction number */
X   } Data;
X};
X
X/* These defines are done to simplify access to the components */
X#define Act Data.act
X#define Code Data.code
X#define Suffix Data.suffix
X
Xextern struct Key mainKbd[3 * NUMKEYS]; /* The main, f & g key sequences */
SHAR_EOF
echo "extracting lmkdebug"
sed 's/^X//' << \SHAR_EOF > lmkdebug
XFLAGS = -v -cf -rr -ilcc: -d5
XFLAGS2 = -Hinclude:small.sym $(FLAGS)
XOBJ = od/
X
X.c.o:
X  lc $(FLAGS) -o$(OBJ) $*
X
Xhp11: $(OBJ)hp11.o $(OBJ)io.o $(OBJ)ins.o $(OBJ)kbd.o $(OBJ)prog_codes.o \
X      $(OBJ)support.o $(OBJ)indic.o $(OBJ)chip.o $(OBJ)menus.o $(OBJ)icon.o \
X      $(OBJ)amiga.o $(OBJ)chars.o
X    blink with hp11.debug
X
X$(OBJ)hp11.o: hp11.c hp11.h amiga/amiga.h io.h support.h ins.h codes.h
X
X$(OBJ)io.o: io.c hp11.h amiga/amiga.h ins.h io.h kbd.h codes.h prog_codes.h
X
X$(OBJ)ins.o: ins.c amiga/amiga.h hp11.h io.h support.h ins.h codes.h
X
X$(OBJ)kbd.o: kbd.c hp11.h kbd.h codes.h io.h
X
X$(OBJ)prog_codes.o: prog_codes.c prog_codes.h
X
X$(OBJ)support.o: support.c support.h
X
X$(OBJ)chars.o: amiga/chars.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)indic.o: amiga/indic.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)chip.o: amiga/chip.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)menus.o: amiga/menus.c hp11.h io.h ins.h amiga/menus.h amiga/internal.h amiga/cbio.h
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)icon.o: amiga/icon.c
X# Should be same as other amiga routines, but there is a bug ...
X
X$(OBJ)amiga.o: amiga/amiga.c hp11.h amiga/internal.h amiga/amiga.h amiga/menus.h
X  lc $(FLAGS2) -o$(OBJ) $*
X
SHAR_EOF
echo "extracting lmkfile"
sed 's/^X//' << \SHAR_EOF > lmkfile
XFLAGS = -v -cf -m1s -O -ilcc: -rr
XFLAGS2 = $(FLAGS)
XOBJ = o/
X
X.c.o:
X  lc $(FLAGS) -o$(OBJ) $*
X
Xhp11: $(OBJ)hp11.o $(OBJ)io.o $(OBJ)ins.o $(OBJ)kbd.o $(OBJ)prog_codes.o \
X      $(OBJ)support.o $(OBJ)indic.o $(OBJ)chip.o $(OBJ)menus.o $(OBJ)icon.o \
X      $(OBJ)amiga.o $(OBJ)chars.o
X    blink with hp11.lnk
X
X$(OBJ)hp11.o: hp11.c hp11.h amiga/amiga.h io.h support.h ins.h codes.h
X
X$(OBJ)io.o: io.c hp11.h amiga/amiga.h ins.h io.h kbd.h codes.h prog_codes.h
X
X$(OBJ)ins.o: ins.c amiga/amiga.h hp11.h io.h support.h ins.h codes.h
X
X$(OBJ)kbd.o: kbd.c hp11.h kbd.h codes.h io.h
X
X$(OBJ)prog_codes.o: prog_codes.c prog_codes.h
X
X$(OBJ)support.o: support.c support.h
X
X$(OBJ)chars.o: amiga/chars.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)indic.o: amiga/indic.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)chip.o: amiga/chip.c
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)menus.o: amiga/menus.c hp11.h io.h ins.h amiga/menus.h amiga/internal.h amiga/cbio.h
X  lc $(FLAGS2) -o$(OBJ) $*
X
X$(OBJ)icon.o: amiga/icon.c
X# Should be same as other amiga routines, but there is a bug ...
X
X$(OBJ)amiga.o: amiga/amiga.c hp11.h amiga/internal.h amiga/amiga.h amiga/menus.h
X  lc $(FLAGS2) -o$(OBJ) $*
X
SHAR_EOF
if `test ! -d o`
then
  mkdir o
  echo "mkdir o"
fi
echo "extracting o/dummy"
sed 's/^X//' << \SHAR_EOF > o/dummy
SHAR_EOF
if `test ! -d od`
then
  mkdir od
  echo "mkdir od"
fi
echo "extracting od/dummy"
sed 's/^X//' << \SHAR_EOF > od/dummy
SHAR_EOF
echo "extracting prog_codes.c"
sed 's/^X//' << \SHAR_EOF > prog_codes.c
X/* The actual codes used */
X#include "exec/types.h"
X
X#include "hp11/prog_codes.h"
X
X/* To decode an instruction, you use its code (from codes.h). Therefore,
X  if these are changed, you must change these keycodes as well */
Xstruct KeyCode keycodes[] = {
X   {ONECODE, 11},
X   {ONECODE, 12},
X   {ONECODE, 13},
X   {ONECODE, 14},
X   {ONECODE, 15},
X   {ONECODE, 16},
X   {ONECODE, 10},
X   {ONECODE, 23},
X   {ONECODE, 24},
X   {ONECODE, 25},
X   {ONECODE, 26},
X   {ONECODE, 20},
X   {ONECODE, 31},
X   {ONECODE, 33},
X   {ONECODE, 34},
X   {ONECODE, 36},
X   {ONECODE, 30},
X   {ONECODE, 48},
X   {ONECODE, 49},
X   {ONECODE, 40},
X/* f codes */
X   {TWOCODE, 42, 16},
X   {TWOCODE, 42, 10},
X   {TWOCODE, 42, 23},
X   {TWOCODE, 42, 26},
X   {TWOCODE_9, 42, 4},
X   {TWOCODE_9, 42, 5},
X   {TWOCODE_9, 42, 6},
X   {TWOCODE, 42, 20},
X   {TWOCODE, 42, 31},
X   {TWOCODE, 42, 32},
X   {TWOCODE, 42, 34},
X   {TWOCODE, 42, 36},
X   {TWOCODE_9, 42, 1},
X   {TWOCODE_9, 42, 2},
X   {TWOCODE_9, 42, 3},
X   {TWOCODE, 42, 30},
X   {TWOCODE, 42, 44},
X   {TWOCODE_9, 42,0},
X   {TWOCODE, 42, 48},
X   {TWOCODE, 42, 49},
X   {TWOCODE, 42, 40},
X/* g codes */
X   {TWOCODE, 43, 11},
X   {TWOCODE, 43, 12},
X   {TWOCODE, 43, 13},
X   {TWOCODE, 43, 14},
X   {TWOCODE, 43, 15},
X   {TWOCODE, 43, 16},
X   {TWOCODE_9, 43, 7},
X   {TWOCODE_9, 43, 8},
X   {TWOCODE_9, 43, 9},
X   {TWOCODE, 43, 10},
X   {TWOCODE, 43, 23},
X   {TWOCODE, 43, 24},
X   {TWOCODE, 43, 25},
X   {TWOCODE, 43, 26},
X   {TWOCODE, 43, 20},
X   {TWOCODE, 43, 32},
X   {TWOCODE, 43, 33},
X   {TWOCODE, 43, 34},
X   {TWOCODE, 43, 35},
X   {TWOCODE, 43, 36},
X   {TWOCODE_9, 43, 1},
X   {TWOCODE_9, 43, 2},
X   {TWOCODE_9, 43, 3},
X   {TWOCODE, 43, 30},
X   {TWOCODE, 43, 44},
X   {TWOCODE_9, 43, 0},
X   {TWOCODE, 43, 48},
X   {TWOCODE, 43, 49},
X   {TWOCODE, 43, 40},
X/* Miscellaneous */
X   {TWOCODE, 45, 36},
X   {TWOCODE, 45, 49},
X/* ARC */
X   {THREECODE, 42, 22, 23},
X   {THREECODE, 42, 22, 24},
X   {THREECODE, 42, 22, 25},
X   {THREECODE, 43, 22, 23},
X   {THREECODE, 43, 22, 24},
X   {THREECODE, 43, 22, 25},
X/* Flags */
X   {THREECODE, 43, 4, 0},
X   {THREECODE, 43, 4, 1},
X   {THREECODE, 43, 5, 0},
X   {THREECODE, 43, 5, 1},
X   {THREECODE, 43, 6, 0},
X   {THREECODE, 43, 6, 1},
X/* Figures */
X   {ONECODE, 0},
X   {ONECODE, 1},
X   {ONECODE, 2},
X   {ONECODE, 3},
X   {ONECODE, 4},
X   {ONECODE, 5},
X   {ONECODE, 6},
X   {ONECODE, 7},
X   {ONECODE, 8},
X   {ONECODE, 9},
X/* FIX, SCI, ENG */
X   {THREECODE, 42, 7, 0},
X   {THREECODE, 42, 7, 1},
X   {THREECODE, 42, 7, 2},
X   {THREECODE, 42, 7, 3},
X   {THREECODE, 42, 7, 4},
X   {THREECODE, 42, 7, 5},
X   {THREECODE, 42, 7, 6},
X   {THREECODE, 42, 7, 7},
X   {THREECODE, 42, 7, 8},
X   {THREECODE, 42, 7, 9},
X
X   {THREECODE, 42, 8, 0},
X   {THREECODE, 42, 8, 1},
X   {THREECODE, 42, 8, 2},
X   {THREECODE, 42, 8, 3},
X   {THREECODE, 42, 8, 4},
X   {THREECODE, 42, 8, 5},
X   {THREECODE, 42, 8, 6},
X   {THREECODE, 42, 8, 7},
X
X   {THREECODE, 42, 9, 0},
X   {THREECODE, 42, 9, 1},
X   {THREECODE, 42, 9, 2},
X   {THREECODE, 42, 9, 3},
X   {THREECODE, 42, 9, 4},
X   {THREECODE, 42, 9, 5},
X   {THREECODE, 42, 9, 6},
X   {THREECODE, 42, 9, 7},
X/* LBL, GTO, GSB */
X   {THREECODE, 42, 21, 0},
X   {THREECODE, 42, 21, 1},
X   {THREECODE, 42, 21, 2},
X   {THREECODE, 42, 21, 3},
X   {THREECODE, 42, 21, 4},
X   {THREECODE, 42, 21, 5},
X   {THREECODE, 42, 21, 6},
X   {THREECODE, 42, 21, 7},
X   {THREECODE, 42, 21, 8},
X   {THREECODE, 42, 21, 9},
X   {THREECODE, 42, 21, 11},
X   {THREECODE, 42, 21, 12},
X   {THREECODE, 42, 21, 13},
X   {THREECODE, 42, 21, 14},
X   {THREECODE, 42, 21, 15},
X
X   {TWOCODE_9, 22, 0},
X   {TWOCODE_9, 22, 1},
X   {TWOCODE_9, 22, 2},
X   {TWOCODE_9, 22, 3},
X   {TWOCODE_9, 22, 4},
X   {TWOCODE_9, 22, 5},
X   {TWOCODE_9, 22, 6},
X   {TWOCODE_9, 22, 7},
X   {TWOCODE_9, 22, 8},
X   {TWOCODE_9, 22, 9},
X   {TWOCODE, 22, 11},
X   {TWOCODE, 22, 12},
X   {TWOCODE, 22, 13},
X   {TWOCODE, 22, 14},
X   {TWOCODE, 22, 15},
X   {TWOCODE, 22, 25},
X
X   {TWOCODE_9, 32, 0},
X   {TWOCODE_9, 32, 1},
X   {TWOCODE_9, 32, 2},
X   {TWOCODE_9, 32, 3},
X   {TWOCODE_9, 32, 4},
X   {TWOCODE_9, 32, 5},
X   {TWOCODE_9, 32, 6},
X   {TWOCODE_9, 32, 7},
X   {TWOCODE_9, 32, 8},
X   {TWOCODE_9, 32, 9},
X   {TWOCODE, 32, 11},
X   {TWOCODE, 32, 12},
X   {TWOCODE, 32, 13},
X   {TWOCODE, 32, 14},
X   {TWOCODE, 32, 15},
X   {TWOCODE, 32, 25},
X/* STO, STO +, STO -, STO *, STO / */
X   {TWOCODE_9, 44, 0},
X   {TWOCODE_9, 44, 1},
X   {TWOCODE_9, 44, 2},
X   {TWOCODE_9, 44, 3},
X   {TWOCODE_9, 44, 4},
X   {TWOCODE_9, 44, 5},
X   {TWOCODE_9, 44, 6},
X   {TWOCODE_9, 44, 7},
X   {TWOCODE_9, 44, 8},
X   {TWOCODE_9, 44, 9},
X   {TWOCODE_PT, 44, 0},
X   {TWOCODE_PT, 44, 1},
X   {TWOCODE_PT, 44, 2},
X   {TWOCODE_PT, 44, 3},
X   {TWOCODE_PT, 44, 4},
X   {TWOCODE_PT, 44, 5},
X   {TWOCODE_PT, 44, 6},
X   {TWOCODE_PT, 44, 7},
X   {TWOCODE_PT, 44, 8},
X   {TWOCODE_PT, 44, 9},
X   {TWOCODE, 44, 25},
X   {TWOCODE, 44, 24},
X
X   {THREECODE, 44, 40, 0},
X   {THREECODE, 44, 40, 1},
X   {THREECODE, 44, 40, 2},
X   {THREECODE, 44, 40, 3},
X   {THREECODE, 44, 40, 4},
X   {THREECODE, 44, 40, 5},
X   {THREECODE, 44, 40, 6},
X   {THREECODE, 44, 40, 7},
X   {THREECODE, 44, 40, 8},
X   {THREECODE, 44, 40, 9},
X   {THREECODE_PT, 44, 40, 0},
X   {THREECODE_PT, 44, 40, 1},
X   {THREECODE_PT, 44, 40, 2},
X   {THREECODE_PT, 44, 40, 3},
X   {THREECODE_PT, 44, 40, 4},
X   {THREECODE_PT, 44, 40, 5},
X   {THREECODE_PT, 44, 40, 6},
X   {THREECODE_PT, 44, 40, 7},
X   {THREECODE_PT, 44, 40, 8},
X   {THREECODE_PT, 44, 40, 9},
X   {THREECODE, 44, 40, 25},
X   {THREECODE, 44, 40, 24},
X
X   {THREECODE, 44, 30, 0},
X   {THREECODE, 44, 30, 1},
X   {THREECODE, 44, 30, 2},
X   {THREECODE, 44, 30, 3},
X   {THREECODE, 44, 30, 4},
X   {THREECODE, 44, 30, 5},
X   {THREECODE, 44, 30, 6},
X   {THREECODE, 44, 30, 7},
X   {THREECODE, 44, 30, 8},
X   {THREECODE, 44, 30, 9},
X   {THREECODE_PT, 44, 30, 0},
X   {THREECODE_PT, 44, 30, 1},
X   {THREECODE_PT, 44, 30, 2},
X   {THREECODE_PT, 44, 30, 3},
X   {THREECODE_PT, 44, 30, 4},
X   {THREECODE_PT, 44, 30, 5},
X   {THREECODE_PT, 44, 30, 6},
X   {THREECODE_PT, 44, 30, 7},
X   {THREECODE_PT, 44, 30, 8},
X   {THREECODE_PT, 44, 30, 9},
X   {THREECODE, 44, 30, 25},
X   {THREECODE, 44, 30, 24},
X
X   {THREECODE, 44, 20, 0},
X   {THREECODE, 44, 20, 1},
X   {THREECODE, 44, 20, 2},
X   {THREECODE, 44, 20, 3},
X   {THREECODE, 44, 20, 4},
X   {THREECODE, 44, 20, 5},
X   {THREECODE, 44, 20, 6},
X   {THREECODE, 44, 20, 7},
X   {THREECODE, 44, 20, 8},
X   {THREECODE, 44, 20, 9},
X   {THREECODE_PT, 44, 20, 0},
X   {THREECODE_PT, 44, 20, 1},
X   {THREECODE_PT, 44, 20, 2},
X   {THREECODE_PT, 44, 20, 3},
X   {THREECODE_PT, 44, 20, 4},
X   {THREECODE_PT, 44, 20, 5},
X   {THREECODE_PT, 44, 20, 6},
X   {THREECODE_PT, 44, 20, 7},
X   {THREECODE_PT, 44, 20, 8},
X   {THREECODE_PT, 44, 20, 9},
X   {THREECODE, 44, 20, 25},
X   {THREECODE, 44, 20, 24},
X
X   {THREECODE, 44, 10, 0},
X   {THREECODE, 44, 10, 1},
X   {THREECODE, 44, 10, 2},
X   {THREECODE, 44, 10, 3},
X   {THREECODE, 44, 10, 4},
X   {THREECODE, 44, 10, 5},
X   {THREECODE, 44, 10, 6},
X   {THREECODE, 44, 10, 7},
X   {THREECODE, 44, 10, 8},
X   {THREECODE, 44, 10, 9},
X   {THREECODE_PT, 44, 10, 0},
X   {THREECODE_PT, 44, 10, 1},
X   {THREECODE_PT, 44, 10, 2},
X   {THREECODE_PT, 44, 10, 3},
X   {THREECODE_PT, 44, 10, 4},
X   {THREECODE_PT, 44, 10, 5},
X   {THREECODE_PT, 44, 10, 6},
X   {THREECODE_PT, 44, 10, 7},
X   {THREECODE_PT, 44, 10, 8},
X   {THREECODE_PT, 44, 10, 9},
X   {THREECODE, 44, 10, 25},
X   {THREECODE, 44, 10, 24},
X
X/* RCL */
X   {TWOCODE_9, 45, 0},
X   {TWOCODE_9, 45, 1},
X   {TWOCODE_9, 45, 2},
X   {TWOCODE_9, 45, 3},
X   {TWOCODE_9, 45, 4},
X   {TWOCODE_9, 45, 5},
X   {TWOCODE_9, 45, 6},
X   {TWOCODE_9, 45, 7},
X   {TWOCODE_9, 45, 8},
X   {TWOCODE_9, 45, 9},
X   {TWOCODE_PT, 45, 0},
X   {TWOCODE_PT, 45, 1},
X   {TWOCODE_PT, 45, 2},
X   {TWOCODE_PT, 45, 3},
X   {TWOCODE_PT, 45, 4},
X   {TWOCODE_PT, 45, 5},
X   {TWOCODE_PT, 45, 6},
X   {TWOCODE_PT, 45, 7},
X   {TWOCODE_PT, 45, 8},
X   {TWOCODE_PT, 45, 9},
X   {TWOCODE, 45, 25},
X   {TWOCODE, 45, 24},
X};
SHAR_EOF
echo "extracting prog_codes.h"
sed 's/^X//' << \SHAR_EOF > prog_codes.h
X/* There are 6 different ways in which program lines are displayed. cf io.c */
X#define ONECODE 0
X#define TWOCODE 1
X#define TWOCODE_9 2
X#define TWOCODE_PT 3
X#define THREECODE 4
X#define THREECODE_PT 5
X
Xstruct KeyCode {
X   BYTE Type; /* The display method */
X   BYTE c1, c2, c3; /* The codes to display */
X};
X
X/* This array is indexed by the instruction code (from codes.h). Therefore, if
X  that file is changed, the codes must also be changed. */
Xextern struct KeyCode keycodes[];
SHAR_EOF
echo "extracting support.c"
sed 's/^X//' << \SHAR_EOF > support.c
X#include "math.h"
X
X#include "hp11/support.h"
X
Xdouble sign(r)
Xdouble r;
X{
X   if (r < 0.0) return(-1.0);
X   else if (r == 0.0) return (0.0);
X   else return(1.0);
X}
X
Xvoid Rect(r, phi, x, y)
Xdouble r, phi, *x, *y;
X{
X   *x = r * cos(phi);
X   *y = r * sin(phi);
X}
X
Xvoid Polar(x, y, r, phi)
Xdouble x, y, *r, *phi;
X{
X   *r = sqrt(x * x + y * y);
X   *phi = atan2(y, x);
X}
X
Xdouble stirling(n)
Xdouble n;
X{
X   double y = 1 / (12 * n);
X
X   return (pow(n / E, n) * sqrt(2 * PI * n) * (1 + y * (1 + y * (0.5 - y * (4.6333333333333333 + y * 4.7583333333333333)))));
X}
X
Xdouble gamma(x)
Xdouble x;
X{
X   double fx, tx, res, i;
X
X   if (x >= 15.0) return(stirling(x - 1));
X   else {
X      if ((fx = modf(x, &tx)) < 0) { tx -= 1.0; fx += 1.0; } /* give real int & frac */
X
X      if (fx == 0 && tx < 0) return(-HUGE);
X      if (tx < -200) return(0.0); /* Underflow */
X
X      res = stirling(fx + 14.0);
X      for (i = 14.0; i >= tx; i -= 1.0) res /= i + fx;
X
X      return(res);
X   }
X}
X
Xdouble factorial(x)
Xint x;
X{
X   double r = 1.0;
X
X   if (x > 250) r = HUGE; /* Certainly too big */
X   else for (; x > 0; x--) r *= x;
X
X   return(r);
X}
X
Xdouble Perm(x, y)
Xint x, y;
X{
X   double i, res = 1.0, lim = x - y;
X
X   for (i = x; i > lim; i -= 1.0) res *= i;
X
X   return(res);
X}
X
Xdouble Comb(x, y)
Xint x,y;
X{
X   double i, lim = y, res = Perm(x, y);
X
X   for (i = 1; i <= lim; i += 1.0) res /= i;
X
X   return(res);
X}
X
Xdouble hr(x)
Xdouble x;
X{
X   double h, m, s;
X
X   /* f = modf(x, &i) returns the frcational part of x in f and the integral part in i (all double) */
X   m = 100.0 * modf(x, &h);
X   s = 100.0 * modf(m, &m);
X
X   return(h + m / 60.0 + s / 3600.0);
X}
X
Xdouble hms(x)
Xdouble x;
X{
X   double h, m, s;
X
X   m = 60.0 * modf(x, &h);
X   s = 60.0 * modf(m, &m);
X
X   return(h + m / 100.0 + s / 10000.0);
X}
X
Xdouble trunc(x)
Xdouble x;
X{
X   modf(x, &x);
X   return(x);
X}
X
Xdouble frac(x)
Xdouble x;
X{
X   return(modf(x, &x));
X}
X
Xdouble asinh(x)
Xdouble x;
X{
X   return(log(x + sqrt(x * x + 1)));
X}
X
Xdouble acosh(x)
Xdouble x;
X{
X   if (x < 1.0) return(0.0);
X   else return(log(x + sqrt(x * x -1)));
X}
X
Xdouble atanh(x)
Xdouble x;
X{
X   if (x > 1.0) return(0.0);
X   else return(log((1.0 + x) / (1.0 - x)) / 2.0);
X}
SHAR_EOF
echo "extracting support.h"
sed 's/^X//' << \SHAR_EOF > support.h
X/* Support routines for the HP11, but not HP11 specific */
X
X/* Macros to convert to/from grad's/degrees from/to radians */
X#define TDEG(x) (x) * (180.0 / PI)
X#define FDEG(x) (x) * (PI / 180.0)
X#define TGRAD(x) (x) * (200.0 / PI)
X#define FGRAD(x) (x) * (PI / 200.0)
X#define E 2.718281828
X
Xdouble sign(double); /* return the sign of the number */
Xvoid Rect(double, double, double *, double *); /* Convert from Polar to Rectangular */
Xvoid Polar(double, double, double *, double *); /* Convert from Rectangular to Polar */
Xdouble Perm(int, int); /* Compute the permutation of y items taken x at a time (ordered) */
Xdouble Comb(int, int); /* Compute the combination of y items taken x at a time (unorderd) */
Xdouble hr(double); /* Convert to decimal hours */
Xdouble hms(double); /* Convert from decimal hours to hh.mmss */
Xdouble trunc(double); /* Truncate double, returning a double */
Xdouble frac(double); /* Take the fractional part of a double */
Xdouble factorial(int); /* Compute the factorial */
Xdouble gamma(double); /* Compute the gamma function */
Xdouble stirling(double); /* Stirling's approximation */
X/* Hyperbolic reciprocal functions (the others are in the library) */
Xdouble asinh(double), acosh(double), atanh(double);
SHAR_EOF
echo "End of archive 3 (of 3)"
# if you want to concatenate archives, remove anything after this line
exit