/user/mgetty/frontends/X11/viewfax/g3hack.c

https://github.com/rhuitl/uClinux · C · 185 lines · 157 code · 10 blank · 18 comment · 43 complexity · 384788a7aa6283d32ad6fed1e6d323c7 MD5 · raw file

  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. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #define VERSION "0.3"
  16. #ifdef BSD
  17. #define strrchr rindex
  18. #endif
  19. extern int getopt();
  20. extern char *optarg;
  21. extern int optind, opterr;
  22. static char *progname;
  23. static char *banner = "\n%s version " VERSION "\n\n";
  24. static char *usage = "\
  25. usage: %s <-n count> <-h size> -o <outputfile> {inputfile}\n\n\
  26. Copy a g3-(1d)-fax file from stdin to stdout and delete any\n\
  27. more than `count' identical trailing lines (default 10).\n\
  28. Optionally skip `size'-byte header.\n\
  29. Optionally named outputfile (else stdout).\n";
  30. #define nxtbit() ((imask>>=1) ? ((ibits&imask)!=0) : \
  31. ((ibits=getchar()) == EOF) ? -1 : \
  32. (((imask=0x80)&ibits)!=0))
  33. #define putbit(b) \
  34. do { \
  35. if (b) \
  36. obits |= omask; \
  37. if ((omask >>= 1) == 0) { \
  38. this->line[this->length>>3] = obits; \
  39. omask = 0x80; \
  40. obits = 0; \
  41. } \
  42. this->length++; \
  43. if (this->length >= BUFSIZ<<3) { \
  44. fprintf(stderr, "%s: unreasonably long line\n", progname); \
  45. exit(1); \
  46. } \
  47. } while (0)
  48. static void
  49. copy(int nlines)
  50. {
  51. int ibits = 0, imask = 0; /* input bits and mask */
  52. int obits = 0; /* output bits */
  53. int omask = 0x80; /* output mask */
  54. int zeros = 0; /* number of consecutive zero bits */
  55. int thisempty = 1; /* empty line (so far) */
  56. int empties = 0; /* number of consecutive EOLs */
  57. int identcount = 0; /* number of consecutive identical lines */
  58. struct {
  59. char line[BUFSIZ];
  60. int length;
  61. } lines[2], *prev, *this, *temp;
  62. this = &lines[0];
  63. prev = &lines[1];
  64. this->length = prev->length = 0;
  65. while (1) {
  66. int bit = nxtbit();
  67. if (bit == -1)
  68. break; /* end of file */
  69. putbit(bit);
  70. if (bit == 0) {
  71. zeros++;
  72. continue;
  73. }
  74. if (zeros < 11) { /* not eol and not empty */
  75. zeros = 0;
  76. thisempty = 0;
  77. /* Get rid of any accumulated empties. Should only happen
  78. for the eol at the beginning of the first line (we
  79. switch from the |eol data| to the |data eol|
  80. viewpoint). */
  81. for ( ; empties; empties--)
  82. if (fwrite("\0\1", 1, 2, stdout) != 2)
  83. break;
  84. continue;
  85. }
  86. /* at end of line */
  87. zeros = 0;
  88. omask = 0x80;
  89. obits = 0;
  90. if (thisempty) {
  91. empties++;
  92. if (empties >= 5)
  93. break; /* 6 eols in a row */
  94. this->length = 0;
  95. continue;
  96. }
  97. thisempty = 1;
  98. /* at end of non-empty line */
  99. this->length = (this->length+7)&~7;
  100. this->line[(this->length-1)>>3] = 1; /* byte-align the eol */
  101. if (this->length == prev->length &&
  102. memcmp(this->line, prev->line, this->length>>3) == 0) {
  103. identcount++;
  104. this->length = 0;
  105. continue;
  106. }
  107. /* at end of non-matching line */
  108. for ( ; identcount; identcount--)
  109. if (fwrite(prev->line, 1, prev->length>>3, stdout) !=
  110. prev->length>>3)
  111. break;
  112. temp = prev;
  113. prev = this;
  114. this = temp;
  115. identcount = 1;
  116. this->length = 0;
  117. }
  118. if (identcount > nlines)
  119. identcount = nlines;
  120. for ( ; !ferror(stdout) && identcount; identcount--)
  121. fwrite(prev->line, 1, prev->length>>3, stdout);
  122. if (!ferror(stdout) && !thisempty)
  123. fwrite(this->line, 1, this->length>>3, stdout);
  124. for ( ; !ferror(stdout) && empties; empties--)
  125. fwrite("\0\1", 1, 2, stdout);
  126. if (ferror(stdout)) {
  127. fprintf(stderr, "%s: write error\n", progname);
  128. exit(1);
  129. }
  130. }
  131. int
  132. main(int argc, char **argv)
  133. {
  134. int c, err = 0;
  135. int header = 0;
  136. int nlines = 10;
  137. if ((progname = strrchr(argv[0], '/')) == NULL)
  138. progname = argv[0];
  139. else
  140. progname++;
  141. opterr = 0;
  142. while ((c = getopt(argc, argv, "h:n:o:v")) != EOF)
  143. switch (c) {
  144. case 'h':
  145. header = atoi(optarg);
  146. break;
  147. case 'n':
  148. nlines = atoi(optarg);
  149. break;
  150. case 'o':
  151. if (freopen(optarg, "w", stdout) == NULL) {
  152. perror(optarg);
  153. exit(1);
  154. }
  155. break;
  156. case 'v':
  157. fprintf(stderr, banner, progname);
  158. exit(0);
  159. case '?':
  160. err++;
  161. }
  162. if (err || optind < argc-1) {
  163. fprintf(stderr, banner, progname);
  164. fprintf(stderr, usage, progname);
  165. exit(1);
  166. }
  167. if (optind < argc && freopen(argv[optind], "r", stdin) == NULL) {
  168. perror(argv[optind]);
  169. exit(1);
  170. }
  171. while (header--)
  172. putchar(getchar());
  173. copy(nlines);
  174. exit(0);
  175. }