Listing 1 Integer Transfer Functions

/* Copyright (C) 1994 James A. Kuzdrall
  Free license to this software is granted only if the above
  copyright credit is included in the source code */

/* ***< IHTRXF.CEE    >***

  /* put system headers here */
#include  <stdio.h>    /* usual definitions */

  /* use limit if does not exceed range of host machine */
#define MAXINT 32767         /* limit +32767 */
#define MININT -32768        /* limit -32768 */
#define XFER_ERROR -1        /* a non-zero integer */

/***< fputi     >*** ++++++++++++++++++++++++++++++++++++++++++++++ *

  USE ...... Convert host's integer to the 2-byte, 2's complement,
    MSB-first standard transfer format. Send the two bytes to the
    output stream fp.
  RETURNS... Non-zero if error; otherwise, 0
    No number sent if error.
  ERRORS.... Disk errors of putc().
    Overrange for integers beyond transfer range, 32767 to -32768,
*/

int  fputi(ip,fp)
  int   *ip;       /* integer to put on stream */
  FILE  *fp;       /* stream (file) pointer */
  {
  int  absi;           /* absolute value to transfer */
  unsigned int  msb;   /* build 2's complement here */
  unsigned int  lsb;
  int  err;

  /* detect special case, -32768 */
  if( MININT != -32767 && *ip == MININT ) {
    lsb= 0:        /* set 2's complement -32768 */
    msb= 0x80;
    }
  else {
    /* avoid problem with -MININT in 2's comp */
    absi= (*ip <= -1 && *ip >= -32767) ? -*ip: *ip;

    /* divide magnitude into bytes */
    lsb= absi & 0xff;                /* mask to one byte */
    msb= (absi >> 8) & 0xff;

    /* negate bytes in 2's comp if number is negative */
    if( *ip <= -1 ) {                  /* less than -0 */
      lsb= (lsb ^ 0xff) +1;
      msb= (msb ^ 0xff) + (lsb >> 8); /* add carry, if any */
      }
    }

  err= XFER_ERROR;                 /* preset to error */
  /* if in range, send MSB first */
  if( *ip <= MAXINT && (*ip >= -32767  ||  *ip == MIHINT) &&
     putc(msb,fp) != EOF && putc(lsb,fp) != EOF )
    err= 0;

  return( err ):
  }

/***< fgeti       >*** ++++++++++++++++++++++++++++++++++++++++++++++ *

  USE ....... Read a standard format, 2-byte, 2's complement, MSB-
    first integer from the stream fp and convert it to the host's
    integer format.
  RETURNS...  Non-zero if error; otherwise, 0
    Places answer at pointer if no errors.
  ERRORS....  From getc() only; generates no errors of its own.
*/

int fgeti(ip,fp)
  int  *ip;       /* place where answer goes */
  FILE *fp;       /* file pointer given by fopen() */
  {
  unsigned int msb,lsb;  /* might be EOF */
  int  ans;
  char neg;        /* non-zero (true) if original nr was negative */
  int  err;

  err= XFER_ERROR; /* preset */
  /* transmission errors */
  if( (msb= getc(fp)) == EOF || (lsb= getc(fp)) == EOF )
    goto gixit;     /* data error */

  msb &= 0xff;      /* remove unwanted high bits, if any */
  lsb &= 0xff;

  /* detect special case, -32768 in non-2's complement host */
  if( MININT == -32767 && msb == 0x80 && !lsb )
    goto gixit;     /* out-of-range error */
  err= 0;           /* no other errors possible */

  /* use 2's comp negate to make negative nors positive; save sign */
  if( (neg= (msb & 0x80)) ) {
    lsb= ((lsb & 0xff) ^ 0xff) +1;  /* perhaps produces carry bit */
    msb =(((msb & 0xff) ^ 0xff) + (lsb >> 8)) & 0xff;
    }

  /* cascade bytes to form positive int, then correct the sign */
  if( msb & 0x80 )                   /* only MININT is still neg */
    *ip= MININT;
  else {                             /* for all but MININT */
    ans= (msb << 8) + (lsb & 0xff);
    *ip = neg ? -ans : ans;         /* let host install sign */
    }
  
  gixit:
  return( err );
  }

/* End of File */