/*% cc -O -s % -o type

*	TYPE - uses typesq.c for 'sqed' files
  derived from cnode 'cat', typesq, and others. W. Earnest 5/28/82
  Credit to the following and others for parts of the software:
	Dick Greenlaw	(usq)
	Bob Mathias	(typesq)
	Steve Passe	(cnode)
	Joe Shannon	(cnode)
	Chuck Forsberg (Unix version)
*/
char Version[] = {"type revised 7-16-82"};

#include <stdio.h>
/* #include <signal.h> */
#define ERROR (-1)
#define OK 0
#define PATHLEN 128

#define RECOGNIZE 0xFF76	/* unlikely pattern */
#define DLE 0x90		/* repeat byte flag */
#define SPEOF 256		/* special endfile token */
#define NUMVALS 257		/* 256 data values plus SPEOF*/
#define LARGE 30000

struct _sqleaf {		/* Decoding tree */
	int _children[2];	/* left, right */
};
struct _sqleaf Dnode[NUMVALS - 1];

int early_exit;
FILE *infile;

int Bpos;		/* last bit position read */
int Curin;		/* last byte value read */
int Repct;		/* Number of times to retirn value */
int Value;		/* current byte value or EOF */

sexit()
{
	early_exit++;
/*	signal(SIGINT, sexit); */
}

sequit()
{
	putchar('\n');
	exit(1);
}

main(p_argc, p_argv)
int p_argc;
char **p_argv;
{
	char file[PATHLEN];
	register char x;
/*	static char stobuf[BUFSIZ];  */
	extern sexit();


/*	signal(SIGINT, sexit);	 */
/*	signal(SIGQUIT, sequit); */
/*	setbuf(stdout, stobuf);  */
	if (p_argc < 2) {
		fprintf(stderr, "Usage: type name ...\n");
		exit(1);
	}

	for (x = 1;x < p_argc;++x) {
		fprintf(stderr, "\n\n======================== Listing %s ========================\n",p_argv[x]);
		switch (catvalid(file, p_argv[x])) {
		case 'q':
			switch (qsend(file)) {
			case ERROR:
				break;
			case 'a':
				send_text(file);
			}
			break;
		case 'a':
			send_text(file); break;
		case 'x':
			break;
		}
	}
	return (OK);
}

send_text(file)
char *file;
{
	register c;

	early_exit = 0;
	while( ((c = getc(infile)) != EOF) && (!early_exit) )
		putchar(c);
	fclose(infile);
	fflush(stdout);
	return (OK);
}

catvalid(pname, name)
char *pname;
char *name;
{
	if((infile=fopen(name, "rb"))==NULL) {
		fprintf(stderr, "Can't open %s\n", name);
		return ERROR;
	}
	strcpy(pname, name);
	return ('q');
}

/*
	The following code is primarily from typesq.c and utr.c.  Typesq
is a modification of USQ by Dick Greenlaw.  Those modifications (usq
to typesq) were made by Bob Mathias, I am responsible for the butchery
done to make it work with cat.

*/

qsend(fname)
char *fname;
{
	register i, c;
	register char *p;
	register int numnodes;			/* size of decoding tree */
	char origname[PATHLEN]; 	/* Original file name without drive */

	init_cr(); init_huff();

	if(portgetw(infile) != RECOGNIZE) {	/* Process header */
		rewind(infile);
		return 'a';                     /* not squeezed after all */
	}
	portgetw(infile);			/* discard checksum */
	p = origname;				/* Get original file name */
	do {					/* send it to array */
		*p = getc(infile);
	} while(*p++ != '\0');

	numnodes = portgetw(infile);
	if(numnodes < 0 || numnodes >= NUMVALS) {
		fprintf(stderr, "%s has invalid decode tree size\n", fname);
		fclose(infile);
		return ERROR;
	}
	/* Initialize for possible empty tree (SPEOF only) */
	Dnode[0]._children[0] = -(SPEOF + 1);
	Dnode[0]._children[1] = -(SPEOF + 1);

	for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
		Dnode[i]._children[0] = portgetw(infile);
		Dnode[i]._children[1] = portgetw(infile);
	}
	/* Get translated output bytes and write file */
	fprintf(stderr, "\n%s -> %s\n\n",fname,origname);
	early_exit = 0;
	while( ((c = getcr(infile)) != EOF) && (!early_exit) )
		putchar(c);
	fclose(infile);
	fflush(stdout);
	return OK;
}
/*** from utr.c - */
/* initialize decoding functions */

init_cr()
{
	Repct = 0;
}

init_huff()
{
	Bpos = 99;	/* force initial read */
}

/* Get bytes with decoding - this decodes repetition,
 * calls getuhuff to decode file stream into byte
 * level code with only repetition encoding.
 *
 * The code is simple passing through of bytes except
 * that DLE is encoded as DLE-zero and other values
 * repeated more than twice are encoded as value-DLE-count.
 */

int
getcr()
{
	register c;

	if(Repct > 0) {
		/* Expanding a repeated char */
		--Repct;
		return Value;
	} else {
		/* Nothing unusual */
		if((c = getuhuff()) != DLE) {
			/* It's not the special delimiter */
			Value = c;
			if(Value == EOF)
				Repct = LARGE;
			return Value;
		} else {
			/* Special token */
			if((Repct = getuhuff()) == 0)
				/* DLE, zero represents DLE */
				return DLE;
			else {
				/* Begin expanding repetition */
				Repct -= 2;	/* 2nd time */
				return Value;
			}
		}
	}
}
/* Decode file stream into a byte level code with only
 * repetition encoding remaining.
 */

int
getuhuff()
{
	register i;
	register bitval;

	/* Follow bit stream in tree to a leaf*/
	i = 0;	/* Start at root of tree */
	do {
		if(++Bpos > 7) {
			if((Curin = getc(infile)) == ERROR)
				return ERROR;
			Bpos = 0;
			/* move a level deeper in tree */
			i = Dnode[i]._children[1 & Curin];
		} else
			i = Dnode[i]._children[1 & (Curin >>= 1)];
	} while(i >= 0);

	/* Decode fake node index to original data value */
	i = -(i + 1);
	/* Decode special endfile token to normal EOF */
	i = (i == SPEOF) ? EOF : i;
	return i;
}
/*
 * Machine independent getw which always gets bytes in the same order
 *  as the CP/M version of SQ wrote them
 */
portgetw(f)
FILE *f;
{
	register c;

	c = getc(f)&0377;
	return c + (getc(f)<<8);
}

                                                                                                                                            
rrect modes */

  gtty(0,&cookedmode);			/* Save current mode for later */
  gtty(