/* encodings.c
 *
 */

#include <iptokens.h>
#include <stdio.h>

FILE *fpout = stdout;

AppendHeader(fp, string)
  FILE *fp;
  char *string;
  {
  fpout = fp;
  while (*string != (char) 0) append←byte(*string++);
  }


AppendIdentifier(string)
  char *string;
  {
  append←sequence←descriptor(sequenceIdentifier, strlen(string));
  while (*string != (char) 0) append←byte(*string++);
  }


AppendString(string)
  char *string;
  {
  append←sequence←descriptor(sequenceString, strlen(string));
  while (*string != (char) 0) append←byte(*string++);
  }


AppendComment(string)
  char *string;
  {
  append←sequence←descriptor(sequenceComment, strlen(string));
  while (*string != (char) 0) append←byte(*string++);
  }


AppendOp(opcode)
  int opcode;
  {
  if (opcode > SHORT←OP←LIMIT)
    {
    /* has to be coded as a long op */
    append←int((LONG←OP << 8) | opcode, 2);
    }
  else
    {
    /* small enough to be a short op */
    append←byte(SHORT←OP | opcode);
    }
  }


AppendInteger(number)
  int number;
  {
  if (number < INTEGER←MIN || number > INTEGER←MAX)
    {
    append←sequence←descriptor(sequenceInteger, bytes←in←int(number));
    append←int(number, bytes←in←int(number));
    }
  else
    {
    append←int(number+INTEGER←ZERO, 2);
    }
  }


AppendRational(value, divisor)
  int value, divisor;
  {
  int len←value, len←divisor, len;
  len←value = bytes←in←int(value);
  len←divisor = bytes←in←int(divisor);
  len = len←value > len←divisor ? len←value : len←divisor;
  append←sequence←descriptor(sequenceRational, 2*len);
  append←int(value, len);
  append←int(divisor, len);
  }


AppendPPV(length, bitsperPixel, scanlength)
  int length, bitsperPixel, scanlength;
  {
  append←sequence←descriptor(sequencePPV, length);
  append←int(bitsperPixel, 2);
  append←int(scanlength, 2);
  }

AppendCPV(length, breaktable, nrange, scanlength)
  int length, breaktable, nrange, scanlength;
  {
  append←sequence←descriptor(sequenceCPV, length);
  append←int(breaktable, 2);
  append←int(nrange, 2);
  append←int(scanlength, 2);
  }




/*
 *  The remainder of this file contains lower level primitives:
 */


#define err0 "encoding: sequence type is out-of-range.\n"
#define err1 "encoding: sequence length is out-of-range.\n"


append←sequence←descriptor(type, length)
  int  type;
  int  length;
  {
  if (type < 0 || type > 31) error(err0);
  if (length < 0 || length > LONG←SEQUENCE←LIMIT) error(err1);
  if (length > SHORT←SEQUENCE←LIMIT)
    {
    /* too big to fit in a short sequence */
    append←byte(LONG←SEQUENCE | type);
    append←int(length, 3);
    }
  else
    {
    append←byte(SHORT←SEQUENCE | type);
    append←byte(length);
    }
  }


append←int(d, n)
  int d;
  int n;
  {
  switch (n)
    {
    case 4: append←byte((d >> 24) & 0xff);
    case 3: append←byte((d >> 16) & 0xff);
    case 2: append←byte((d >> 8) & 0xff);
    case 1: append←byte(d & 0xff);
    }
  }



bytes←in←int(value)
  int value;
  {
  /* this routine assumes 4 bytes in an int and two's complement notation */
  int mask, i;
  if (value < 0)
    {
    /* takes the same space as its one's complemented value */
    value = ~value;
    }
  if (value == 0)
    {
    /* avoids infinite looping */
    return(1);
    }
  for (i = 4, mask = 0xff800000; (value & mask) == 0; i--, mask >>= 8) ;
  return(i);
  }

append←byte(value)
  int value;
  {
  unsigned char v;
  v = value & 0377;
  putc(v, fpout);
  }

/* Change Log
 *
 * William LeFebvre, 24-May-1984 12:15:19, Created Interpress library version.
 * K. Knox, 17-Dec-84 16:44:03, Greatly modified for use with RES files.
 * K. Knox,  1-Oct-85 14:34:56, Add AppendCPV function.
 * K. Knox,  2-Oct-85 14:12:04, Changed from file descriptor to file stream.
 *
 *
 */