"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "viewfax-2.6/g3hack.c" of archive viewfax-2.6.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /* g3hack.c - hack identical lines off the end of a fax
    2  *
    3  * This program is in the public domain.  If it does not work or
    4  * causes you any sort of grief, blame the public, not me.
    5  *
    6  * fdc@cliwe.ping.de, 1995-06-24
    7  *
    8  * v2 1995-06-25 - fixed some boundary problems, added named input
    9  * v3 1995-06-28 - changed write-error detection
   10  *
   11  */
   12 
   13 #include <stdio.h>
   14 #include <stdlib.h>
   15 #include <string.h>
   16 
   17 #define VERSION "0.3"
   18 
   19 #ifdef BSD
   20 #define strrchr rindex
   21 #endif
   22 
   23 extern int getopt();
   24 extern char *optarg;
   25 extern int optind, opterr;
   26 
   27 static char *progname;
   28 static char *banner = "\n%s version " VERSION "\n\n";
   29 static char *usage = "\
   30 usage: %s <-n count> <-h size> -o <outputfile> {inputfile}\n\n\
   31 Copy a g3-(1d)-fax file from stdin to stdout and delete any\n\
   32    more than `count' identical trailing lines (default 10).\n\
   33 Optionally skip `size'-byte header.\n\
   34 Optionally named outputfile (else stdout).\n";
   35 
   36 #define nxtbit()	((imask>>=1) ? ((ibits&imask)!=0) :		\
   37 			 ((ibits=getchar()) == EOF) ? -1 :		\
   38 			 (((imask=0x80)&ibits)!=0))
   39 #define putbit(b)							\
   40     do {								\
   41 	if (b)								\
   42 	    obits |= omask;						\
   43 	if ((omask >>= 1) == 0) {					\
   44 	    this->line[this->length>>3] = obits;			\
   45 	    omask = 0x80;						\
   46 	    obits = 0;							\
   47 	}								\
   48 	this->length++;							\
   49 	if (this->length >= BUFSIZ<<3) {				\
   50 	    fprintf(stderr, "%s: unreasonably long line\n", progname);	\
   51 	    exit(1);							\
   52 	}								\
   53     } while (0)
   54 
   55 static void
   56 copy(int nlines)
   57 {
   58     int ibits = 0, imask = 0;	/* input bits and mask */
   59     int obits = 0;		/* output bits */
   60     int omask = 0x80;		/* output mask */
   61     int zeros = 0;		/* number of consecutive zero bits */
   62     int thisempty = 1;		/* empty line (so far) */
   63     int empties = 0;		/* number of consecutive EOLs */
   64     int identcount = 0;		/* number of consecutive identical lines */
   65     struct {
   66 	char line[BUFSIZ];
   67 	int length;
   68     } lines[2], *prev, *this, *temp;
   69 
   70     this = &lines[0];
   71     prev = &lines[1];
   72     this->length = prev->length = 0;
   73     while (1) {
   74 	int bit = nxtbit();
   75 	if (bit == -1)
   76 	    break;		/* end of file */
   77 	putbit(bit);
   78 	if (bit == 0) {
   79 	    zeros++;
   80 	    continue;
   81 	}
   82 	if (zeros < 11) {	/* not eol and not empty */
   83 	    zeros = 0;
   84 	    thisempty = 0;
   85 	    /* Get rid of any accumulated empties.  Should only happen
   86 	       for the eol at the beginning of the first line (we
   87 	       switch from the |eol data| to the |data eol|
   88 	       viewpoint). */
   89 	    for ( ; empties; empties--)
   90 		if (fwrite("\0\1", 1, 2, stdout) != 2)
   91 		    break;
   92 	    continue;
   93 	}
   94 	/* at end of line */
   95 	zeros = 0;
   96 	omask = 0x80;
   97 	obits = 0;
   98 	if (thisempty) {
   99 	    empties++;
  100 	    if (empties >= 5)
  101 		break;		/* 6 eols in a row */
  102 	    this->length = 0;
  103 	    continue;
  104 	}
  105 	thisempty = 1;
  106 	/* at end of non-empty line */
  107 	this->length = (this->length+7)&~7;
  108 	this->line[(this->length-1)>>3] = 1; /* byte-align the eol */
  109 	if (this->length == prev->length &&
  110 	    memcmp(this->line, prev->line, this->length>>3) == 0) {
  111 	    identcount++;
  112 	    this->length = 0;
  113 	    continue;
  114 	}
  115 	/* at end of non-matching line */
  116 	for ( ; identcount; identcount--)
  117 	    if (fwrite(prev->line, 1, prev->length>>3, stdout) !=
  118 		prev->length>>3)
  119 		break;
  120 	temp = prev;
  121 	prev = this;
  122 	this = temp;
  123 	identcount = 1;
  124 	this->length = 0;
  125     }
  126     if (identcount > nlines)
  127 	identcount = nlines;
  128     for ( ; !ferror(stdout) && identcount; identcount--)
  129 	    fwrite(prev->line, 1, prev->length>>3, stdout);
  130     if (!ferror(stdout) && !thisempty)
  131 	    fwrite(this->line, 1, this->length>>3, stdout);
  132     for ( ; !ferror(stdout) && empties; empties--)
  133 	fwrite("\0\1", 1, 2, stdout);
  134     if (ferror(stdout)) {
  135 	fprintf(stderr, "%s: write error\n", progname);
  136 	exit(1);
  137     }
  138 }
  139 
  140 int
  141 main(int argc, char **argv)
  142 {
  143     int c, err = 0;
  144     int header = 0;
  145     int nlines = 10;
  146 
  147     if ((progname = strrchr(argv[0], '/')) == NULL)
  148 	progname = argv[0];
  149     else
  150 	progname++;
  151     opterr = 0;
  152     while ((c = getopt(argc, argv, "h:n:o:v")) != EOF)
  153 	switch (c) {
  154 	case 'h':
  155 	    header = atoi(optarg);
  156 	    break;
  157 	case 'n':
  158 	    nlines = atoi(optarg);
  159 	    break;
  160 	case 'o':
  161 	    if (freopen(optarg, "w", stdout) == NULL) {
  162 		perror(optarg);
  163 		exit(1);
  164 	    }
  165 	    break;
  166 	case 'v':
  167 	    fprintf(stderr, banner, progname);
  168 	    exit(0);
  169 	case '?':
  170 	    err++;
  171 	}
  172     if (err || optind < argc-1) {
  173 	fprintf(stderr, banner, progname);
  174 	fprintf(stderr, usage, progname);
  175 	exit(1);
  176     }
  177     if (optind < argc && freopen(argv[optind], "r", stdin) == NULL) {
  178 	perror(argv[optind]);
  179 	exit(1);
  180     }
  181     while (header--)
  182 	putchar(getchar());
  183     copy(nlines);
  184     exit(0);
  185 }