home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3994 < prev    next >
Encoding:
Text File  |  1991-09-09  |  23.9 KB  |  845 lines

  1. Path: wupost!sdd.hp.com!mips!pacbell.com!jcwasik
  2. From: jcwasik@PacBell.COM (Joe Wasik)
  3. Newsgroups: alt.sources
  4. Subject: LINEL -- PREDICT PAPER-SPACE FOR PRINT FILE, part 1/1
  5. Message-ID: <1991Sep5.163807.21279@PacBell.COM>
  6. Date: 5 Sep 91 16:38:07 GMT
  7. Sender: news@PacBell.COM (Pacific Bell Netnews)
  8. Organization: Pacific * Bell
  9. Lines: 834
  10.  
  11. This program "linel" tries to predict paper-space that a file expects
  12. to use.  It takes linewraps, formfeeds, backspaces, etc into account
  13. and tells you number of lines, pages, etc.
  14.  
  15. See the manpage for options.  Linel assumes somethings that you may need
  16. to override.
  17. --- cut here ---
  18. # This is a shell archive.  Remove anything before this line,
  19. # then unpack it by saving it in a file and typing "sh file".
  20. #
  21. # Contents:  README linel.1 linel.c
  22.  
  23. echo x - README
  24. sed 's/^@//' > "README" <<'@//E*O*F README//'
  25. Linel is a program to predict the appearance and paper space needed by
  26. a print file.
  27.  
  28. There is no make file, but make's default rules will work.  So, either
  29. type "make linel" or "cc -O linel.c -o linel".  See the manpage for runtime
  30. instructions.
  31.  
  32. If you have any comments, constructive or otherwise, send them to
  33. jcwasik@clib.pacbell.com
  34. @//E*O*F README//
  35. chmod u=rw,g=rw,o=r README
  36.  
  37. echo x - linel.1
  38. sed 's/^@//' > "linel.1" <<'@//E*O*F linel.1//'
  39. @.TH LINEL 1
  40. @.SH NAME
  41. linel - predict line count and page count of file without printing it
  42. @.SH SYNOPSIS
  43. @.B "linel" 
  44. [
  45. @.B "\-h"
  46. (help) ] [
  47. @.B "\-b"
  48. ] [
  49. @.B "\-f"
  50. ] [
  51. @.B "\-o"
  52. offset ] [
  53. @.B "\-t"
  54. tabs ] [
  55. @.B "\-v"
  56. ] [
  57. @.B "\-w"
  58. wrap position ]
  59. @.P
  60. [
  61. @.B "\-p"
  62. lines on page ] [ file1... filex | - (stdin) ]"
  63. @.SH DESCRIPTION
  64. \fILinel\fP tries to predict the paper space to print a file, i.e.
  65. \fIlinel\fP expands all tabs, takes margins and line wrap into account, and
  66. then delivers a number of statistics.  These are:
  67. @.IP
  68. Number of pages.
  69. @.br
  70. Number of print lines.
  71. @.br
  72. Number of raw characters.
  73. @.br
  74. Number of print positions.
  75. @.br
  76. Number of binary characters.
  77. @.br
  78. Number of print positions in longest line.
  79. @.P
  80. The output of \fIlinel\fP appears similar to that of the \fIwc(1)\fP command,
  81. i.e.  all numbers are on one line with the file's name at the right end.  By
  82. giving it more than one file, an additional line of totals appears.
  83. \fILinel\fP can also take input from stdin.  Either a \- (dash) on the command
  84. line or by omitting the filename you can force \fIlinel\fP to take input from
  85. stdin.  The dash may be interspersed with file names.
  86. @.P
  87. \fILinel\fP is most useful with printers that cannot find top of form once a
  88. line has wrapped.  \fILinel\fP warns a potential problem by indicating how
  89. many print characters are in the longest line.
  90. @.SH Options
  91. @.IP "\-h" 8
  92. Display help-screen and exit without processing any files or other command
  93. line options.
  94. @.IP "\-b"
  95. Printer cannot act upon backspace, treat the backspace as a binary character,
  96. i.e.  do nothing.  By default, when it finds a backspace, \fIlinel\fP retreats
  97. the logical printhead one position.
  98. @.IP "\-f"
  99. Printer cannot act upon formfeed.  Like the backspace, treat the formfeed as a
  100. binary character.  By default, when it finds a formfeed, \fIlinel\fP advances
  101. a logical page.
  102. @.IP "\-v"
  103. Verbose output.  Now, \fIlinel\fP's output does not look like \fIwc(1)\fP's
  104. output.
  105. @.IP "\-o  \fIn\fP"
  106. Assume a margin of \fIn\fP characters. Works like the \fIpr(1)\fP command. The
  107. default margin is zero.
  108. @.IP "\-t  \fIn\fP"
  109. A tab character expands into spaces so that the next character position is
  110. a whole multiple of \fIn\fP.  If \fIn\fP is zero, treat the tab character as
  111. a binary character.  By default, \fIn\fP is \fB8\fP.
  112. @.IP "\-w  \fIn\fP"
  113. Wrap line after \fIn\fP characters.  If \fIn\fP is zero, no line ever wraps. The
  114. report of \fIprint positions in longest line\fP won't ever exceed this value.
  115. @.IP "\-p  \fIn\fP"
  116. Advance page count when lines per page passes \fIn\fP.  If set to zero, page
  117. count advances only when formfeeds are found and recognized.  By default,
  118. \fIlinel\fP thinks a logical page should have \fB55\fP lines.
  119. @.P
  120. \fILionel\fP always counts at least one page.  Therefore, a file with one
  121. recognized formfeed will report at least two pages.
  122. @.P
  123. A line that gets wrapped will still wrap around to position 1, not the right
  124. margin as specified with the \fI-o n\fP option.  This is the way that
  125. \fIpr(1)\fP works.
  126. @.P
  127. \fILinel\fP tries to act like most printers and copies behaviors from other
  128. Unix commands.  Specifically \fIlinel\fP looks at:
  129. @.P
  130. When run on a DOS file that sits on a Unix system, \fIlinel\fP reports one
  131. binary character for each end-of-line.  Unix systems use a different scheme to
  132. terminate lines.  Take a look at the \fIflip(1)\fP command.
  133. @.IP Tabs 14
  134. Expands all tabs to spaces.  The number of spaces depends on the position of
  135. the printhead when it sees the tab.  A tab found on the wrapped part of a line
  136. acts as if the second line started at position 1 (not at the margin!).  A tab
  137. that causes a line to wrap, generates as many spaces as if the line didn't
  138. wrap.  The tab value can be adjusted with a command line option.
  139. @.IP Binary
  140. Binary characters are ignored.  It is not predictable what a binary
  141. character's effect on a page would be.  \fILinel\fP counts the binary
  142. characters that it finds and, at end, the total is displayed.  By using
  143. command line options, \fIlinel\fP can treat backspaces, formfeeds, and tabs as
  144. binary characters.
  145. @.IP Backspace
  146. If the printer knows the backspace, the logical printhead moves back one
  147. position -- unless it is already at the first position.  If a line has
  148. wrapped, a backspace at the first position of the new line will not move the
  149. printhead up to the previous line.  If a line has backspaces immediately
  150. preceding a newline, those backspaces are ignored, i.e.  if printed they would
  151. have no effect on the page.
  152. @.IP Formfeed
  153. If the printer knows formfeeds and one is found, a new line is started and a
  154. new page is counted.  If \fIlinel\fP finds a formfeed after data but before a
  155. newline than the formfeed also acts as a new line.
  156. @.SH WARNING
  157. Compile time options may change \fIlinel\fP's default behavior.
  158. @.P
  159. \fILinel\fP cannot interpret escape sequences.  It will instead read them
  160. as binary and printable characters.
  161. @.SH "SEE ALSO"
  162. flip(by Rahul Dhesi), pr(1), wc(1)
  163. @//E*O*F linel.1//
  164. chmod u=rw,g=rw,o=r linel.1
  165.  
  166. echo x - linel.c
  167. sed 's/^@//' > "linel.c" <<'@//E*O*F linel.c//'
  168. /*
  169. ** Source name: linel.c
  170. **
  171. ** Written and tested on System V 3.1.1
  172. **
  173. ** Input args (command line):
  174. **    command line options
  175. **    file names 
  176. **
  177. ** Output args:
  178. **    return code, < 0 if error, 0 if ok
  179. **
  180. ** Synopsis:
  181. **    Program analysis input, which may come from files or from
  182. **    standard-input.  Program counts line lengths in order to allow
  183. **    prediction of what print-outs of these files might look like.
  184. */
  185.  
  186. #include <stdio.h>
  187. #include <string.h>
  188. #include <ctype.h>
  189.  
  190. /*
  191. ** COMPILE-TIME DEFAULTS:
  192. */
  193.  
  194. /*
  195. ** Number of characters normally in a tab (Override with -t option)
  196. */
  197.  
  198. #ifndef TABNUM
  199. #define    TABNUM        8L
  200. #endif
  201.  
  202. /*
  203. ** Buffer size of name of input file
  204. **    (You may get this from /usr/include/limits.h)
  205. */
  206.  
  207. #ifndef PATH_MAX
  208. #define PATH_MAX    1024
  209. #endif
  210.  
  211. /*
  212. ** Left hand margin size (offset, override with -o option)
  213. **    (Always gets added to count of printable chars for each line)
  214. */
  215.  
  216. #ifndef MARGIN
  217. #define MARGIN        0L
  218. #endif
  219.  
  220. /*
  221. ** Default at verbose or not (-v toggles this)
  222. */
  223.  
  224. #ifndef VERBOSE
  225. #define VERBOSE        0
  226. #endif
  227.  
  228. /*
  229. ** Default at formfeed or not (-f toggles this)
  230. **    (On: formfeed is printable, starts a new line)
  231. **    (Off: formfeed is binary char -- printer doesn't know it)
  232. */
  233.  
  234. #ifndef FORMFEED
  235. #define FORMFEED    1
  236. #endif
  237.  
  238. /*
  239. **
  240. ** Default at backspace or not (-b toggles this)
  241. **    (On: backspace is printable, moves printhead back on position)
  242. **    (Off: backspace is binary char -- printer doesn't know it)
  243. **    (Note, backspace never moves to previous line)
  244. */
  245.  
  246. #ifndef BACKSPACE
  247. #define BACKSPACE    1
  248. #endif
  249.  
  250. /*
  251. ** Wrap value (Override with -w)
  252. **    Leave at zero if printer discards what's past right margin
  253. **    Otherwise this should be where printer breaks line
  254. */
  255.  
  256. #ifndef WRAPPOS
  257. #define WRAPPOS        0L
  258. #endif
  259.  
  260. /*
  261. ** Number of printing lines on page (Override with -p)
  262. */
  263.  
  264. #ifndef PAGELEN
  265. #define PAGELEN        55L
  266. #endif
  267.  
  268. /*
  269. ** end of COMPILE-TIME DEFAULTS
  270. */
  271.  
  272. #define USAGE "Usage %s: [-h (help)] [-b] [-f] [-o offset] [-t tabs] [-v]\n\t [-w wrap position] [-p lines on page] [file1... filex | stdin ]\n"
  273.  
  274. #define EOLFLAG    -99L
  275. #define BINFLAG    -98L
  276. #define BCKFLAG    -97L
  277. #define FFFLAG    -96L
  278.  
  279. /*
  280. ** Debug mode not at startup, -d toggles this
  281. */
  282.  
  283. #ifndef DEBUG
  284. #define DEBUG        0
  285. #else
  286. #define DEBUG        1
  287. #endif
  288.  
  289. char *pname;                    /* this program's name */
  290. int debug = DEBUG;                /* cmdline opt, debug needed */
  291. long tabnum = TABNUM;                /* cmdline opt, chars in tab */
  292. long margin = MARGIN;                /* cmdline opt, margin size */
  293. int verbose = VERBOSE;                /* cmdline opt, verbose flag */
  294. int formfeed = FORMFEED;            /* cmdline opt, formfeed flag */
  295. int backspace = BACKSPACE;            /* cmdline opt, backspace flg */
  296. long wrappos = WRAPPOS;                /* cmdline opt, wrap position */
  297. long pagelen = PAGELEN;                /* cmdline opt, lines on page */
  298. int helptext = 0;                /* cmdline opt, help screen */
  299.  
  300. /* define this structure for use by functions */
  301. struct counter {
  302.     long file_page_cnt;                /* count pages */
  303.     long file_line_cnt;                /* count all lines */
  304.     long file_raw_cnt;                /* count all chars as 1 */
  305.     long file_prnt_cnt;                /* count printing chars */
  306.     long file_bin_cnt;                /* count binary chars */
  307.     long line_prnt_cnt;                /* count printing chars */
  308. };
  309.  
  310. int
  311. main(argc,argv)
  312. int argc;
  313. char **argv;
  314. {
  315.     int next;                    /* really optind of getopt() */
  316.     int status = 0;                /* return code to caller */
  317.     int i;                    /* loop var */
  318.     struct counter totals;            /* if more than one file */
  319.     void do_help();                /* help function */
  320.  
  321.     /* store pointer to this program's name */
  322.     pname = *argv;        
  323.  
  324.     /*
  325.     ** go get command line options
  326.     ** if an error was found, tell user and exit
  327.     */
  328.     if ((next = options(argc, argv)) == -1) {
  329.     (void) Usage();
  330.     return(-1);
  331.     }
  332.  
  333.     /* if requested display help -- always exit */
  334.     if (helptext) {
  335.     (void) do_help();
  336.     return(0);
  337.     }
  338.  
  339.     /* initialize counters for totals */
  340.     totals.file_page_cnt = 0L;
  341.     totals.file_line_cnt = 0L;
  342.     totals.file_raw_cnt = 0L;
  343.     totals.file_prnt_cnt = 0L;
  344.     totals.file_bin_cnt = 0L;
  345.     totals.line_prnt_cnt = 0L;
  346.  
  347.     /*
  348.     ** if next=argc, all args were options, so no file names, process stdin
  349.     ** if file names, then loop through them, processing each one
  350.     ** accumulate status so that good file doesn't hide result from bad one
  351.     */
  352.     if (next == argc) {
  353.     status = do_file("-", &totals);
  354.     } else {
  355.     for (i = next; i < argc; i++) {
  356.         status += do_file(argv[i], &totals);
  357.     }
  358.     }
  359.  
  360.     /*
  361.     ** print totals stats
  362.     ** but only if not stdin and and more than 1 file
  363.     */
  364.     if (next != argc && argc - next > 1) {
  365.     (void) print_stats(&totals, "total");
  366.     }
  367.  
  368.     if (debug) {
  369.     (void) fprintf(stderr, "debug: exit status: %d\n", status);
  370.     }
  371.  
  372.     /* exit with return value */
  373.     return(status);
  374. }
  375.  
  376. /*
  377. ** Function name: Usage()
  378. **
  379. ** Synopsis:
  380. **    Print usage message and ensure buffers are flushed
  381. */
  382.  
  383. int
  384. Usage()
  385. {
  386.     (void) fflush(stdout);
  387.     (void) fprintf(stderr, USAGE, pname);
  388.     (void) fflush(stderr);
  389.     return(0);
  390. }
  391.  
  392. /*
  393. ** Function name: options()
  394. **
  395. ** Input args:
  396. **    The same are as a main would usually get
  397. **
  398. ** Output args:
  399. **    Optind, integer, argc of next argument which should be a file name
  400. **
  401. ** Synopsis:
  402. **    This function scans the command line and sets a bunch of global flags
  403. **    based on what it finds.
  404. */
  405.  
  406. int
  407. options(argc, argv)
  408. int argc;
  409. char **argv;
  410. {
  411.     int i;                    /* temp or loop variable */
  412.     extern int optind;                /* see getopt(3C) */
  413.     extern char *optarg;            /* see getopt(3C) */
  414.     long atol();                /* see strtol(3C) */
  415.  
  416.     /*
  417.     ** analize the command line
  418.     ** note that some options are toggles
  419.     */
  420.     while ((i = getopt(argc, argv, "?bdfho:p:t:vw:")) != EOF) {
  421.     switch(i) {
  422.         case 'b':    backspace = (backspace ? 0 : 1);
  423.             break;
  424.         case 'd':    debug = (debug ? 0 : 1);
  425.             break;
  426.         case 'f':    formfeed = (formfeed ? 0 : 1);
  427.             break;
  428.         case 'h':    helptext++;
  429.             break;
  430.         case 'o':    margin = atol(optarg);
  431.             break;
  432.         case 'p':    pagelen = atol(optarg);
  433.             break;
  434.         case 't':    tabnum = atol(optarg);
  435.             break;
  436.         case 'v':    verbose = (verbose ? 0 : 1);
  437.             break;
  438.         case 'w':    wrappos = atol(optarg);
  439.             break;
  440.         default:    return(-1);
  441.     }
  442.     }
  443.  
  444.     if (debug) {
  445.     (void) fprintf(stderr,
  446.         "debug: -d:%d -f:%d, -b:%d, -v:%d, -p:%ld, -t:%ld, -o:%ld -w:%ld\n",
  447.         debug, formfeed, backspace, verbose, pagelen,
  448.             tabnum, margin, wrappos);
  449.     }
  450.  
  451.     /*
  452.     ** if this printer wraps, the indicated position cannot precede margin
  453.     */
  454.     if (wrappos && margin >= wrappos) {
  455.     (void) fprintf(stderr, "%s: offset & wrap position conflict\n", pname);
  456.     return(-1);
  457.     }
  458.  
  459.     /* send the pos of next arg (a filename) to caller */
  460.     return(optind);
  461. }
  462.  
  463. /*
  464. ** Function name: do_help()
  465. **
  466. ** Synopsis:
  467. **    Just display help
  468. */
  469.  
  470. void
  471. do_help()
  472. {
  473.     (void) fputs("\n", stdout);
  474.     (void) fputs("linel: version 1.1\n", stdout);
  475.     (void) fputs("\n", stdout);
  476.     (void) Usage();
  477.     (void) fputs("\n", stdout);
  478.     (void) fputs("-h    Help screen\n", stdout);
  479.     (void) fputs("-b    Print device does not know backspace\n", stdout);
  480.     (void) fputs("-f    Print device does not know formfeed\n", stdout);
  481.     (void) fputs("-v    Provide verbose output, not like wc(1)\n", stdout);
  482.     (void) fputs("-o n    Left margin (offset) at printer is n\n", stdout);
  483.     (void) fputs("-p n    Number of printing lines per page is n\n", stdout);
  484.     (void) fputs("-t n    Tab causes move to next multiple of n\n", stdout);
  485.     (void) fputs("-w n    Printer wraps line after n characters\n", stdout);
  486.     (void) fputs("\n", stdout);
  487. }
  488.  
  489. /*
  490. ** Function name: do_file()
  491. **
  492. ** Input args:
  493. **    argv, char pointer, name of a file or "-" if stdin
  494. **    totals, struct pointer, where to put program totals
  495. **
  496. ** Output args:
  497. **    status, integer, could come from another module
  498. **        0 if OK, -1 if bad
  499. **
  500. ** Synopsis:
  501. **    Take filename, open it, then process it
  502. */
  503.  
  504. int
  505. do_file(argv, totals)
  506. char *argv;                    /* file name */
  507. struct counter *totals;                /* totals for all files */
  508. {
  509.     char infile[PATH_MAX];            /* buffer for input file name */
  510.     FILE *ifp;                    /* input file pointer */
  511.     void perror();                /* avoid lint problems */
  512.     long rc;                    /* return code */
  513.     long do_char();                /* check char function */
  514.     struct counter tmpcount;            /* create accumulate buffer */
  515.     struct counter count;            /* create counter buffer */
  516.     char c;                    /* char being examined */
  517.     long backspace_cnt;                /* count trailing backspaces */
  518.     long pageline_cnt;                /* count lines on one page */
  519.  
  520.     /*
  521.     ** determine input
  522.     ** if a dash, then assume stdin, so set flags and save stdin string
  523.     /* if no dash, then save file name and open the file 
  524.     */
  525.     if (!strcmp(argv, "-")) {
  526.     ifp = stdin;
  527.     (void) strcpy(infile, "stdin");
  528.     } else {
  529.     (void) strcpy(infile, argv);
  530.     if ((ifp = fopen(argv, "r")) == NULL) {
  531.         (void) perror(pname);
  532.         return(-1);
  533.     }
  534.     }
  535.  
  536.     if (debug) {
  537.     (void) fprintf(stderr, "debug: opening \"%s\"\n", infile);
  538.     }
  539.  
  540.     /* purge the buffers before we begin */
  541.     (void) fflush(stdout);
  542.     (void) fflush(stderr);
  543.  
  544.     /* initialize counters */
  545.     tmpcount.file_page_cnt = 1L;
  546.     tmpcount.file_line_cnt = 0L;
  547.     tmpcount.file_raw_cnt = 0L;
  548.     tmpcount.file_prnt_cnt = 0L;
  549.     tmpcount.file_bin_cnt = 0L;
  550.     tmpcount.line_prnt_cnt = margin;
  551.     count.file_page_cnt = 0L;
  552.     count.file_line_cnt = 0L;
  553.     count.file_raw_cnt = 0L;
  554.     count.file_prnt_cnt = 0L;
  555.     count.file_bin_cnt = 0L;
  556.     count.line_prnt_cnt = 0L;
  557.     pageline_cnt = 0L;
  558.  
  559.     /* clearout error code (macro) */
  560.     clearerr(ifp);
  561.  
  562.     /*
  563.     ** loop through the input file -- one character at a time
  564.     ** if end-of-file then exit loop
  565.     ** if error then report it, close file, and exit to next file
  566.     ** always count raw characters for file
  567.     ** go examine character
  568.     ** if eol (end-of-line) then
  569.     **    add trailing backspaces back to printable count
  570.     **      (the printhead was past the current position)
  571.     **    see if this line has most printable chars so far?
  572.     **        if more than previous high, save new high
  573.     **    add printable count for line to file
  574.     **    count the line
  575.     **    reset print counter for line to margin size
  576.     **    reset backspace counter for next line
  577.     **    if we're doing pages and we just filled one
  578.     **        reset page-line count to 1 (first one)
  579.     **        count the page
  580.     ** else (not eol) if ff (formfeed) char then
  581.     **    add trailing backspaces back to printable count
  582.     **    (the printhead was past the current position)
  583.     **    if print-count says something's on this line besides margin then
  584.     **        see if this line has most printable chars so far?
  585.     **        if more than previous high, save new high
  586.     **        add printable count for line to file
  587.     **        count the line
  588.     **        reset print counter for line to margin size
  589.     **    reset backspace counter for next line
  590.     **    reset page-line count to 1 (first one)
  591.     **    count the page
  592.     ** else (not eol and not ff ) if backspace char then
  593.     **    if there are print positions?
  594.     **        yes, so move back one print position
  595.     **        (move even if this means going into the margin)
  596.     ** else (not eol and not ff and not backspace) if binary char then
  597.     **    accumulate countert for binary chars
  598.     ** else (not eol and not ff and not backspace and not binary char) then
  599.     **    accumulate printable counters for line
  600.     **    if this printer wraps and we've exceeded line's capacity then
  601.     **        (this is a new line, see above)
  602.     **        calculate new print position by removing 1st part of line
  603.     **        add same value to file-print-cnt
  604.     **        add one to line count
  605.     **        discard counted, trailing backspaces
  606.     **        if we're doing pages and we just filled one
  607.     **                reset line count to 1 (first one)
  608.     **            count the page
  609.     **    else (we did not need to wrap line)
  610.     **        if there are trailing backspace chars?
  611.     **            remove one (it just got printed over)
  612.     **            this way we only count TRAILING backspace chars
  613.     */
  614.     while (1) {
  615.     c = getc(ifp);
  616.     if (feof(ifp)) break;
  617.     if (ferror(ifp)) {
  618.         (void) perror(pname);
  619.         (void) close(ifp);
  620.         return(-1);
  621.     }
  622.     tmpcount.file_raw_cnt++;
  623.     rc = do_char(c, tmpcount.line_prnt_cnt);
  624.     if (rc == EOLFLAG) {
  625.         tmpcount.line_prnt_cnt += backspace_cnt;
  626.         if (tmpcount.line_prnt_cnt > count.line_prnt_cnt) {
  627.         count.line_prnt_cnt = tmpcount.line_prnt_cnt;
  628.         }
  629.         tmpcount.file_prnt_cnt += tmpcount.line_prnt_cnt;
  630.         tmpcount.file_line_cnt++;
  631.         tmpcount.line_prnt_cnt = margin;
  632.         backspace_cnt = 0L;
  633.         if (pagelen && ++pageline_cnt > pagelen) {
  634.         pageline_cnt = 1L;
  635.         tmpcount.file_page_cnt++;
  636.         }
  637.     } else if (rc == FFFLAG) {
  638.         tmpcount.line_prnt_cnt += backspace_cnt;
  639.         if (tmpcount.line_prnt_cnt > margin) {
  640.         if (tmpcount.line_prnt_cnt > count.line_prnt_cnt) {
  641.             count.line_prnt_cnt = tmpcount.line_prnt_cnt;
  642.         }
  643.         tmpcount.file_prnt_cnt += tmpcount.line_prnt_cnt;
  644.         tmpcount.file_line_cnt++;
  645.         tmpcount.line_prnt_cnt = margin;
  646.         }
  647.         backspace_cnt = 0L;
  648.         pageline_cnt = 1L;
  649.         tmpcount.file_page_cnt++;
  650.     } else if (rc == BCKFLAG) {
  651.         if (tmpcount.line_prnt_cnt > 0L) {
  652.         backspace_cnt++;
  653.         tmpcount.line_prnt_cnt--;
  654.         }
  655.     } else if (rc == BINFLAG) {
  656.         tmpcount.file_bin_cnt++;
  657.     } else {
  658.         tmpcount.line_prnt_cnt += rc;
  659.         if (wrappos && tmpcount.line_prnt_cnt > wrappos) {
  660.         count.line_prnt_cnt = wrappos;
  661.         tmpcount.file_prnt_cnt += wrappos;
  662.         tmpcount.line_prnt_cnt -= wrappos;
  663.         tmpcount.file_line_cnt++;
  664.         backspace_cnt = 0L;
  665.         if (pagelen && ++pageline_cnt > pagelen) {
  666.             pageline_cnt = 1L;
  667.             tmpcount.file_page_cnt++;
  668.         }
  669.         } else {
  670.         if (backspace_cnt) backspace_cnt--;
  671.         }
  672.     }
  673.     } /* end while */
  674.     
  675.     /* move these values to their permanent locations */
  676.     count.file_page_cnt = tmpcount.file_page_cnt;
  677.     count.file_line_cnt = tmpcount.file_line_cnt;
  678.     count.file_raw_cnt = tmpcount.file_raw_cnt;
  679.     count.file_prnt_cnt = tmpcount.file_prnt_cnt;
  680.     count.file_bin_cnt = tmpcount.file_bin_cnt;
  681.  
  682.     /* accumulate file totals in case we have > 1 file */
  683.     totals->file_page_cnt += count.file_page_cnt;
  684.     totals->file_line_cnt += count.file_line_cnt;
  685.     totals->file_raw_cnt += count.file_raw_cnt;
  686.     totals->file_prnt_cnt += count.file_prnt_cnt;
  687.     totals->file_bin_cnt += count.file_bin_cnt;
  688.  
  689.     /* file totals again, look for largest at that level */
  690.     if (count.line_prnt_cnt > totals->line_prnt_cnt) {
  691.     totals->line_prnt_cnt = count.line_prnt_cnt;
  692.     }
  693.  
  694.     /* print stats for one file */
  695.     (void) print_stats(&count, infile);
  696.  
  697.     /* if not stdin, then close the input file */
  698.     if (ifp != stdin) {
  699.     (void) fclose(ifp);
  700.     }
  701.  
  702.     return(0);
  703. }
  704.  
  705. /*
  706. ** Function name: do_char()
  707. **
  708. ** Input args:
  709. **    c, integer, the character being examine
  710. **    p, long, the current print position
  711. **
  712. ** Output args:
  713. **    char count, long, the number of positions to move print head
  714. **        (could be set to EOLFLAG if end-of-line was found)
  715. **
  716. ** Synopsis:
  717. **    Identify the character being read
  718. */
  719.  
  720. long
  721. do_char(c,p)
  722. int c;                    /* character being examined */
  723. long p;                    /* current print position */
  724. {
  725.     long remainder;            /* intermediate computed vaue */
  726.  
  727.     /*
  728.     ** examine the character
  729.     ** if tab
  730.     **    if we have a tab value, compute using remainder and number of pos
  731.     **    if no tab value, then return bin flag (printer must not know tab!)
  732.     ** if backspace
  733.     **    if backspace flag then return backspace else return binary char
  734.     ** if newline
  735.     **    return flag
  736.     ** if formfeed
  737.     **    if formfeed flag then return newline else return binary char
  738.     */
  739.     switch(c) {
  740.     case '\t':
  741.         if (tabnum) {
  742.         remainder = ((++p)+tabnum)%tabnum;
  743.         if (remainder == 0) {
  744.             return(1L);
  745.         } else {
  746.             return(1L + tabnum - remainder);
  747.         }
  748.         } else {
  749.         return(BINFLAG);
  750.         }
  751.     case '\b':
  752.         if (backspace) {
  753.         return(BCKFLAG);
  754.         } else {
  755.         return(BINFLAG);
  756.         }
  757.     case '\n':
  758.         return(EOLFLAG);
  759.     case '\f':
  760.         if (formfeed) {
  761.         return(FFFLAG);
  762.         } else {
  763.         return(BINFLAG);
  764.         }
  765.     }
  766.  
  767.     /*
  768.     ** if none of the above then return whether this char
  769.     **    was binary or, if not, the advance one space
  770.     */
  771.     if (isprint(c)) {
  772.     return(1L);
  773.     } else {
  774.     return(BINFLAG);
  775.     }
  776. }
  777.  
  778. /*
  779. ** Function: prnt_stats()
  780. **
  781. ** Input args:
  782. **    count, struct pointer, contains numbers that need printing
  783. **    filename, string, name of file being processed
  784. **
  785. ** Synopsys:
  786. **    Just print what we're passed
  787. */
  788.  
  789. int
  790. print_stats(count, filename)
  791. struct counter *count;                /* where numbers to print are */
  792. char *filename;                    /* file name */
  793. {
  794.     /*
  795.     ** print format depends on commandline flag
  796.     ** ensure order is the same regardless of format
  797.     ** short format modeled after wc(1) command
  798.     */
  799.     if (verbose) {
  800.     (void) fprintf(stdout,
  801.         "results for: %s\n", filename);
  802.     (void) fprintf(stdout,
  803.         "total pages in file: %ld\n", count->file_page_cnt);
  804.     (void) fprintf(stdout,
  805.         "total lines in file: %ld\n", count->file_line_cnt);
  806.     (void) fprintf(stdout,
  807.         "total characters in file: %ld\n", count->file_raw_cnt);
  808.     (void) fprintf(stdout,
  809.         "total printing positions in file: %ld\n", count->file_prnt_cnt);
  810.     (void) fprintf(stdout,
  811.         "total binary characters in file: %ld\n", count->file_bin_cnt);
  812.     (void) fprintf(stdout,
  813.         "most printing positions in line: %ld\n", count->line_prnt_cnt);
  814.     } else {
  815.     (void) fprintf(stdout, "%7ld%7ld%7ld%7ld%7ld%7ld %s\n",
  816.         count->file_page_cnt,
  817.         count->file_line_cnt,
  818.         count->file_raw_cnt,
  819.         count->file_prnt_cnt,
  820.         count->file_bin_cnt,
  821.         count->line_prnt_cnt,
  822.         filename);
  823.     }
  824.     return(0);
  825. }
  826. /* eof */
  827. @//E*O*F linel.c//
  828. chmod u=rw,g=rw,o=r linel.c
  829.  
  830. echo Inspecting for damage in transit...
  831. temp=/tmp/shar$$; dtemp=/tmp/.shar$$
  832. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  833. cat > $temp <<\!!!
  834.       9     56    339 README
  835.     124    846   4911 linel.1
  836.     659   2561  17601 linel.c
  837.     792   3463  22851 total
  838. !!!
  839. wc  README linel.1 linel.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  840. if [ -s $dtemp ]
  841. then echo "Ouch [diff of wc output]:" ; cat $dtemp
  842. else echo "No problems found."
  843. fi
  844. exit 0
  845.