|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6912 (0x1b00)
Types: TextFile
Names: »SQ.C«
└─⟦1275f6521⟧ Bits:30005823 BD Software C Compiler v1.50a
└─⟦this⟧ »SQ.C«
/* This program compresses a file without loosing 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.
*/
/* CHANGE HISTORY:
* 1.3 Close files properly in case of error exit.
* 1.4 Break up long introductory lines.
* 1.4 Send introduction only to console.
* 1.4 Send errors only to console.
* 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.
* 1.5 Add debugging displays option '-'.
*/
\f
#define VERSION "1.5 08/29/81"
#include <bdscio.h>
#include <dio.h>
#include "sqcom.h"
#include "sq.h"
#define STDOUT 4 /* console only (error) stream */
main(argc, argv)
int argc;
char *argvÆÅ;
æ
int i,c;
int getchar(); /* Directed io version */
char inpargÆ16Å; /* parameter from input */
dioinit(&argc, argv); /* obey directed to args */
debug = FALSE;
fprintf(STDOUT,"File squeezer version %s byØnØtRichard GreenlawØnØt251 Colony Ct.ØnØtGahanna, Ohio 43230Øn", VERSION);
fprintf(STDOUT,"Accepts redirection and pipes.ØnOmit other parameters for help and promptØn");
/* 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) æ
fprintf(STDOUT, "Parameters are from command line or one-at-a-time from standardØninput and are output drives and input file names. Empty to quit.Øn");
do æ
fprintf(STDOUT, "Ø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 */
å
\f
obey(p)
char *p;
æ
char *q;
char outfileÆ16Å; /* output file spec. */
if(*p == '-') æ
/* toggle debug option */
debug = !debug;
return;
å
if(*(p + 1) == ':') æ
/* Got a drive */
if(isalpha(*p)) æ
if(*(p+2) == 'Ø0') æ
/* Change output drive */
printf("ØnOutput drive =%s",p);
outdrvÆ0Å = *p;
return;
å
å else æ
fprintf(STDOUT, "ØnERROR - Ignoring %s", p);
return;
å
å
/* Check for ambiguous (wild-card) name */
for(q = p; *q != 'Ø0'; ++q)
if(*q == '*' øø *q == '?') æ
fprintf(STDOUT, "ØnAmbiguous name %s ignored", p);
return;
å
/* First build output file name */
outfileÆ0Å = 'Ø0'; /* empty */
strcat(outfile, outdrv); /* drive */
strcat(outfile, (*(p + 1) == ':') ? p + 2 : p); /* input name */
/* Find and change output file type */
for(q = outfile; *q != 'Ø0'; ++q)
if(*q == '.')
if(*(q + 1) == 'Ø0')
*q = 'Ø0'; /* kill trailing dot */
else
switch(*(q+2)) æ
case 'q':
case 'Q':
fprintf(STDOUT, "Øn%s ignored ( already squeezed?)", p);
return;
case 'Ø0':
*(q+3) = 'Ø0';
/* fall thru */
default:
*(q + 2) = 'Q';
goto named;
å
/* No file type */
strcat(outfile, ".QQQ");
named:
squeeze(p, outfile);
å
\f
squeeze(infile, outfile)
char *infile, *outfile;
æ
int i, c;
struct _buf inbuff, outbuff; /* file buffers */
printf("Øn%s -> %s: ", infile, outfile);
if(fopen(infile, &inbuff) == ERROR) æ
fprintf(STDOUT, "Can't open %s for input pass 1Øn", infile);
return;
å
if(fcreat(outfile, &outbuff) == ERROR) æ
fprintf(STDOUT, "Can't create %sØn", outfile);
fclose(&inbuff);
return;
å
/* First pass - get properties of file */
crc = 0; /* initialize checksum */
printf("analyzing, ");
/*init_ncr();*/
init_huff(&inbuff);
fclose(&inbuff);
/* Write output file header with decoding info */
wrt_head(&outbuff, infile);
/* Second pass - encode the file */
printf("squeezing, ");
if(fopen(infile, &inbuff) == ERROR) æ
fprintf(STDOUT, "Can't open %s for input pass 2Øn", infile);
goto closeout;
å
/*init_ncr(); *//* For second pass */
/* Translate the input file into the output file */
while((c = gethuff(&inbuff)) != EOF)
if(putc(c, &outbuff) == ERROR) æ
fprintf(STDOUT, "ERROR - write failure in %sØn", outfile);
goto closeall;
å
printf(" done.");
closeall:
fclose(&inbuff);
closeout:
fflush(&outbuff);
fclose(&outbuff);
å
«eof»