/*  readhex.c
    L. Stewart April 8, 1982  1:56 PM
 */
extern int ssenable();
extern ssreturn();
extern wf();
extern debug();
extern getchar();
extern storeb();
extern isdigit();
extern uc();

int recadr, reclen, rectype, recchk;  /* record fields */
int bframe;  /* incoming data address */
int stframe, stbyte;  /* contents of start record */
int rherr[3];

#define	SYNTAX	1
#define	CHKSUM	2
#define	DONE	3
#define	DEL	4

loadhex()
  {
  int retval;
  retval = ssenable(rherr);
  if (retval) {
    switch (retval) {
      case SYNTAX: {
        waitfordel();
        wf("\rsyntax error\r");
        break;
        };
      case CHKSUM: {
        waitfordel();
        wf("\rchecksum error\r");
        break;
        };
      case DONE: break;
      case DEL: {
        wf("\raborted\r");
        break;
        };
      default: {
        debug("bad smallsig code");
        break;
        };
      };
    return;
    };
  for (;;) getrec();
  };

waitfordel()
  {
  wf("\r Type DEL to continue.\r");
  while((getchar() & 0177) != 0177);
  };

getrec()
  {  /* read a record */
  recchk = 0;
  getcolon();
  reclen = getbyte();
  recadr = getword();
  rectype = getbyte();
  switch (rectype) {
    case 0: { getdata(); break; };
    case 1: { getend(); break; };
    case 2: { getadr(); break; };
    case 3: { getstart(); break; };
    default: { rherr("unknown record type"); break; };
    };
  };

getend()
  {
  rl(0);
  cksum();
  /* done with input */
  locerr(DONE);
  };

getstart()
  {
  rl(4);
  stframe = getword();
  stbyte = getword();
  cksum();
  };

getadr()
  {
  rl(2);
  bframe = getword();
  cksum();
  };

getdata()
  {
  int i, bbyteadr, bvalue;
  bbyteadr = recadr;
  bbyteadr += (bframe << 4);
  for (i=0;i<reclen; i+=1) {
    bvalue = getbyte();
    storeb(bvalue, bbyteadr);
    bbyteadr += 1;
    };
  cksum();
  };

rl(el)
  int el;
  {
  if ((reclen != el) || (recadr != 0)) locerr(SYNTAX);
  };

int getword()
  {
  int v;
  v = getbyte() << 8;
  v += getbyte();
  return (v);
  };

int getbyte()
  {
  int v;
  v = gethexchar() << 4;
  v += gethexchar();
  recchk += v;
  return (v);
  };

cksum()
  {
  getbyte();
  if ((recchk & 0xff) != 0) locerr(CHKSUM);
  if (getdelchar() != '\r') locerr(SYNTAX);
  };

int gethexchar()
  {
  char c;
  int v;
  c = getdelchar();
  if (isdigit(c)) {
    v = (c - '0') & 0xff;
    return (v);
    };
  c = uc(c);
  if (c >= 'A' && c <='F') {
    v = (c - 'A' + 10) & 0xff;
    return (v);
    };
  locerr(SYNTAX);
  };

getcolon()
  {
  char c;
  c = getdelchar();
  if (c != ':') locerr(SYNTAX);
  };

char getdelchar()
  {
  char c;
  c = getchar() & 0177;
  if (c == 0177) locerr(DEL);
  return(c);
  };

locerr(arg)
  int arg;
  {
  ssreturn(rherr, arg);
  };