/* SQ.C CHANGE HISTORY:
* 1.7 Add checkurk() memory check, changed credits 8-14-83 -CAF
* Check for proper linking and sufficient memory to execute
* Made inbuff and outbuff global for speed gain.
* 1.6 Add wild card expansion (wildexp) 6-12-82 -CAF
* 1.5 Fix BUG that caused a rare few squeezed files
* to be incorrect and fail the USQ crc check.
* The problem was that some 17 bit codes were
* generated but are not supported by other code.
* THIS IS A MAJOR CHANGE affecting TR2.C and SQ.H and
* requires recompilation of all files which are part
* of SQ. Two basic changes were made: tree depth is now
* used as a tie breaker when weights are equal. This
* makes the tree shallower. Although that may always be
* sufficient, an error trap was added to cause rescaling
* of the counts if any code > 16 bits long is generated.
* Add debugging displays option '-'.
* 1.4 Break up long introductory lines.
* Send introduction only to console.
* Send errors only to console.
* 1.3 Close files properly in case of error exit.
*
* This program compresses a file without losing information.
* The usq.com program is required to unsqueeze the file
* before it can be used.
*
* Typical compression rates are:
* .COM 6% (Don't bother)
* .ASM 33% (using full ASCII set)
* .DIC 46% (using only uppercase and a few others)
* Squeezing a really big file takes a few minutes.
*
* Useage:
* SQ item ...
* where ... represents more (optional) items and
* "item" is either:
* drive: to change the output drive
* file input file
* drive:file input file
* - toggle debugging display mode
*
* If no such items are given on the command line you will be
* prompted for commands (one at a time). An empty command
* terminates the program.
*
* SQ uses the dio package, so input and output can be redirected
* by special items on the command line such as:
* <file reads console input from file
* >file sends console output to file
* +file sends console output to console and file
* Also console output of another program using dio can be piped
* to the input of this one or vice-versa. Example:
* A>fls parameters |sq
* where fls might be a program that expands patterns like *.com
* to a list of ambiguous file names for sq to squeeze.
*
* The squeezed file name is formed by changing the second
* letter of the file type to Q. If there is no file type,
* the squeezed file type is QQQ. If the name exists it is
* overwritten!
*
* Examples:
* A>SQ GRUMP makes GRUMP.QQQ on A:
* A>SQ D:CRAP.XYZ makes CRAP.XQZ on A:
* A>SQ B: D:CRAP.COM makes CRAP.CQM on B:
* B>SQ X.A C: Y.B makes X.AQ on B: and Y.BQ on C:
*
* The transformations compress strings of identical bytes and
* then encode each resulting byte value and EOF as bit strings
* having lengths in inverse proportion to their frequency of
* occurrance in the intermediate input stream. The latter uses
* the Huffman algorithm. Decoding information is included in
* the squeezed file, so squeezing short files or files with
* uniformly distributed byte values will actually increase size.
*/
/* Sneak in a few "local externs": N.B. sq.crl must be linked first! */
char outfile[16]; /* output file spec. */
unsigned Sentinel; /* be sure this doesn't get munged ! */
#define SENTINEL 055555
main(argc, argv)
int argc;
char *argv[];
{
int i,c;
int getchar(); /* Directed io version */
char inparg[16]; /* parameter from input */
checkurk(); /* check for armageddon */
Sentinel = SENTINEL; /* unlikely value */
wildexp(&argc, &argv); /* do the shell's work */
dioinit(&argc, argv); /* obey directed to args */
debug = FALSE;
/* Initialize output drive to default drive */
outdrv[0] = '\0';
/* But prepare for a specific drive */
outdrv[1] = ':';
outdrv[2] = '\0'; /* string terminator */
/* Process the parameters in order */
for(i = 1; i < argc; ++i)
obey(argv[i]);
if(argc < 2) {
if(! _diflag) {
fprintf(STDERR,"File squeezer %s\n", VERSION);
fprintf(STDERR,"Conceived by Richard Greenlaw Modified by Chuck Forsberg et al.\n");
fprintf(STDERR,"Accepts redirection and pipes.\n");
fprintf(STDERR, "Parameters (from command line or singly from stdin)\nconsist of output drives and input file names.\n");
}
do {
fprintf(STDERR, "\n*");
for(i = 0; i < 16; ++i) {
if((c = getchar()) == EOF)
c = '\n'; /* fake empty (exit) command */
if((inparg[i] = c) == '\n') {
inparg[i] = '\0';
break;
}
}
if(inparg[0] != '\0')
obey(inparg);
} while(inparg[0] != '\0');
}
dioflush(); /* clean up any directed io */
if (Sentinel != SENTINEL)
fprintf(STDERR,"out of memory: translation suspect\007\n");
}