4.4BSD/usr/src/contrib/dipress/src/lib/libip/literal.c

Compare this file to the similar file:
Show the results in this format:

/*
 *  Interpress utilities
 *
 *  Written for Xerox Corporation by William LeFebvre
 *  24-May-1984
 *
 * Copyright (c) 1984, 1985, 1986 Xerox Corp.
 *
 * HISTORY
 * 15-Jul-86  Lee Moore (lee) at Xerox Webster Research Center
 *	Added AppendString1.
 *
 * 15-Jan-86  lee at Xerox, WRC
 *	Removed the rest of the Vax dependencies.
 *
 * 10-sep-85  lee moore
 *	Removed some dependencies on the Vax.
 *	Plenty more to be removed
 *
 * 29-apr-85  ed flint
 *	add conditional compilation for vax-11 c (vms)
 */

/*
 *  Subroutines to help build interpress files:
 *
 *  literal interface level - these routines produce interpress output at
 *			      the token level.
 */

/*
 *  NOTE:  Some of these "subroutines" are one-liners, so they are written
 *	   as macros for better efficiency.
 */

# define Rational_max	1073741824
# define ip_Buffsize	1024

#ifndef vax11c
# include <sys/param.h>
# include <math.h>
# include <stdio.h>
# include <ctype.h>
#endif

# include "iptokens.h"
# include "literal.h"		/* macro definitions for some routines */

# ifndef NULL
# define NULL (char *)0
# endif

#ifdef vax11c
# define NOFILE 20
#endif

# define   No	0
# define   Yes	1

static int  ip_fd = -1;			/* current Interpress file */
static char ip_filebuff[ip_Buffsize];	/* file buffer */
static char *ip_buffptr = NULL;		/* points in to ip_filebuff */
static int  ip_bytecnt;			/* number of bytes in ip_filebuff */
static char ip_files[NOFILE] = { 0 };	/* marks which files are ip files */

/*
 *  Definitions for the primitives suggested in the Interpress standard
 *  (XSIS 048302).  The following primitives are defined with macros in
 *  "literal.h":
 *
 *	AppendComment
 *	AppendIdentifier
 *	AppendInsertFile
 *	AppendString
 */


/*
 * Append a string but interpret the escape characters (different from
 * 	"AppendString").
 *
 * Algorithum: copy the old string, substituting escaped characters.
 */

AppendString1(string)

char *string; {
	char	*op,
		*new,
		*np;
	int	i,
		count;
	extern char *malloc();

	op = string;
	new = malloc((unsigned) strlen(string));
	np = new;
	count = 0;

	while (*op) {
		if (*op == '\\') {
			/* an escaped backslash? */
			if (*++op == '\\') {
				*np++ = *op++;
				count++;
			} else {
				i = 0;
				if (isascii(*op) && isdigit(*op))
					i = *op++ - '0';
				if (isascii(*op) && isdigit(*op))
					i = (*op++ - '0') + i*8;
				if (isascii(*op) && isdigit(*op))
					i = (*op++ - '0') + i*8;
				*np++ = (char) i;
				count++;
			}
		} else {
			*np++ = *op++;
			count++;
		}
	}

	append_Sequence(sequenceString, count, (unsigned char *) new);
	free(new);
}


/*
 * append an Op Code to the end of the master
 */

AppendOp(opcode)

int opcode;

{
    if (opcode > SHORT_OP_LIMIT)
    {
	/* has to be coded as a long op */
	append_n_byte_int((long)((LONG_OP << 8) | opcode), 2);
    }
    else
    {
	/* small enough to be a short op */
	append_byte((unsigned char)(SHORT_OP | opcode));
    }
}


AppendNumber(number)

double number;

{
    long d;
    double r;
    
    if (number == (double)(d = (long)number))
	AppendInteger(d);
    else
    {
	d = 1;
	while ((fabs(r = number * d) < Rational_max) &&
	       (d < Rational_max) &&
	       (r != (float)((int)(r))))
	{
	    d <<= 1;
	}
	AppendRational((long)r, d);
    }
}


/*
 * note that although the routine is called AppendInteger, it is really
 * AppendLong.  This is because alot of code wants to use 32 bit numbers.
 * If you want to pass it a 16bit int on the Vax, that will work too.
 */

AppendInteger(number)

long number;

{
    if (number < INTEGER_MIN || number > INTEGER_MAX)
    {
	append_integer_sequence(number);
    }
    else
    {
	append_short_number((short) number);
    }
}

AppendRational(value, divisor)

long 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(sequenceRational, len << 1, (unsigned char *)NULL);
    append_n_byte_int(value, len);
    append_n_byte_int(divisor, len);
}

#ifdef notdef
AppendIntegerVector(vector, num)

int *vector;	/* ??? */
int  number;

{
    
}
#endif


/*
 * Append Packed Pixel Vector
 *	if the data pointer is null, then just append the header and leave it
 *	at that.
 */

AppendPPVector(length, bitsPerPixel, pixelsPerScanLine, data)
int length, bitsPerPixel, pixelsPerScanLine;
unsigned char *data;
{
	int preambleSize = 2*sizeof(short);	/* two short ints */

	append_Sequence(sequencePackedPixelVector, length + preambleSize,
			(unsigned char *) 0);
	append_n_byte_int((long) bitsPerPixel, 2);
	append_n_byte_int((long) pixelsPerScanLine, 2);

	if (data != NULL)
		append_bytes(length, data);
}

/*
 * Append a Compressed Pixel Vector
 *	if the data pointer is null, then just append the header and leave it
 *	at that.
 */
AppendCPVector(length, breakTable, nRange, pixelsPerScanLine, data)
int length, breakTable, nRange, pixelsPerScanLine;
unsigned char *data;
{
	int preambleSize = 6;	/* three short ints */

	append_Sequence(sequenceCompressedPixelVector, length + preambleSize,
			(unsigned char *) 0);
	append_n_byte_int((long) breakTable, 2);
	append_n_byte_int((long) nRange, 2);
	append_n_byte_int((long) pixelsPerScanLine, 2);

	if(data != NULL)
		append_bytes(length, data);
}


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

/*
 *  append_Sequence(type, length, buff)
 *
 *  Append a sequence descriptor and its data bytes.  The descriptor is of
 *  type "type" and length "length".  "Buff" points to the buffer containing
 *  the data.  If "Buff" is null, don't write any data.
 */

append_Sequence(type, length, buff)

int  type;
int  length;
unsigned char *buff;

{
# ifdef notnow
    /* some day, we should make this check, but not today */
    if ((length & 0x7f000000) != 0)
    {
	/* too big to fit in a long ... */
    }
# endif

    /* check for use of an obsolete feature of this program */
    if (length < 0)
    {
	fprintf(stderr, "negative sequence!\n");
	abort();
    }

    if ((length & 0x7fffff00) != 0)
    {
	/* too big to fit in a short sequence */
	append_byte((unsigned char) (LONG_SEQUENCE | type));
	append_n_byte_int((long) length, 3);
    }
    else
    {
	append_byte((unsigned char) (SHORT_SEQUENCE | type));
	append_byte((unsigned char) length);
    }

    /* tack on data, if any */
    if (buff != NULL)
        append_bytes(length, buff);
}


/*
 * append_integer_sequence(number)
 *	A special version of append_sequence that handles integers.  Integers
 *	must be treated differently because the natural representation of an
 *	integer for a particular machine maybe byte swapped relative to the
 *	Xerox standard.
 */
append_integer_sequence(number)

long number;

{
    int length = bytes_in_int(number);

    append_byte((unsigned char) (SHORT_SEQUENCE | sequenceInteger));
    append_byte((unsigned char) length);
    append_n_byte_int(number, length);
}

/*
 * append_n_byte_int(number, length)
 *	Append N bytes of an integer to the interpress master.
 */

append_n_byte_int(number, length)

long number;
int length;	/* measured in bytes */

{
    switch( length ) {
	case 4:
		append_byte((unsigned char) (number >> 24));
	case 3:
		append_byte((unsigned char) (number >> 16));
	case 2:
		append_byte((unsigned char) (number >>  8));
	case 1:
		append_byte((unsigned char) number);
		break;
	default:
		fprintf(stderr, "append_n_byte_int: asked to append %d bytes\n", length);
	}
}
	

/*
 *  append_byte(value) - write out a byte
 */

append_byte(value)

unsigned char value;

{
    *ip_buffptr++ = value;
    if (++ip_bytecnt == ip_Buffsize)
    {
	if( write(ip_fd, ip_filebuff, ip_Buffsize) != ip_Buffsize )
		perror("iplib");

	ip_bytecnt = 0;
	ip_buffptr = ip_filebuff;
    }
}

/*
 *  append_bytes(length, buff) - write the buffer of bytes pointed to by
 *				 "buff" with length "length".
 */

append_bytes(length, buff)

int length;
unsigned char *buff;

{
    while (length-- > 0)
    {
	append_byte(*buff++);
    }
}


/* this routine assumes two's complement notation.
 * this routine sometime over estimates the size of an integer. why? 
 * is it the sign bit that must be watched out for?
 */

bytes_in_int(value)

long value;

{
    int i;
    long mask;

    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);
}

/*
 *  ip_select(fd) - select file descriptor "fd" as the Interpress file for
 *		    later use by the i/o routines supplied in this library.
 */

ip_select(fd)

int fd;

{
    if (ip_fd != -1)
    {
	ip_flush();
    }

    /* set our idea of current file descriptor and initialize the buffer */
    ip_fd = fd;
    ip_buffptr = ip_filebuff;
    ip_bytecnt = 0;

    /* check for initialization */
    if (!ip_files[fd])
    {
	/* not an Intepress or RES file -- initialize it */
	append_bytes(strlen(IP_Header), (unsigned char *) IP_Header);
	ip_files[fd] = Yes;
    }
}


/*
 *  res_select(fd) - select file descriptor "fd" as the RES file for
 *		    later use by the i/o routines supplied in this library.
 */

res_select(fd)

int fd;

{
    if (ip_fd != -1)
    {
	ip_flush();
    }

    /* set our idea of current file descriptor and initialize the buffer */
    ip_fd = fd;
    ip_buffptr = ip_filebuff;
    ip_bytecnt = 0;

    /* check for initialization */
    if (!ip_files[fd])
    {
	/* not an RES or Interpress file -- initialize it */
	append_bytes(strlen(RES_Header), (unsigned char *) RES_Header);
	ip_files[fd] = Yes;
    }
}

/*
 *  ip_raw_select(fd) - same as ip_select, but no header is placed at the
 *			front of the file.
 */

ip_raw_select(fd)

int fd;

{
    /* trick ip_select into thinking that it is already initialized */
    ip_files[fd] = Yes;

    /* do a normal select */
    ip_select(fd);
}

ip_close()

{
    if (ip_fd != -1)
    {
	ip_flush();
	ip_files[ip_fd] = No;
	(void) close(ip_fd);
	ip_fd = -1;
    }
}

ip_flush()

{
    /* flush the buffer */
    if (ip_Buffsize - ip_bytecnt > 0)
    {
	if( write(ip_fd, ip_filebuff, ip_bytecnt) != ip_bytecnt )
		perror("iplib");
    }
}