-/* $OpenBSD: pr.c,v 1.4 1997/01/15 23:43:00 millert Exp $ */
+/* $OpenBSD: pr.c,v 1.5 1997/04/23 08:08:28 grr Exp $ */
/*-
* Copyright (c) 1991 Keith Muller.
#ifndef lint
/* from: static char sccsid[] = "@(#)pr.c 8.1 (Berkeley) 6/6/93"; */
-static char *rcsid = "$OpenBSD: pr.c,v 1.4 1997/01/15 23:43:00 millert Exp $";
+static char *rcsid = "$OpenBSD: pr.c,v 1.5 1997/04/23 08:08:28 grr Exp $";
#endif /* not lint */
#include <sys/types.h>
* Complies with posix P1003.2/D11
*/
+/*
+ * pr: more boundary conditions than a four-legged porcupine
+ *
+ * the original version didn't support form-feeds, while many of the ad-hoc
+ * pr implementations out there do. Addding this and making it work reasonably
+ * in all four output modes required quite a bit of hacking and a few minor
+ * bugs were noted and fixed in the processs. Some implementations have this
+ * as the as -f, some as -F so we accept either.
+ *
+ * The impelmentation of form feeds on top of the existing I/O structure is
+ * a bit ideosyncratic. Basically they are treated as temporary end-of-file
+ * conditions and an additional level of "loop on form feed" is added to each
+ * of the output modes to continue after such a transient end-of-file's. This
+ * has the general benefit of making the existing header/trailer logic work
+ * and provides a usable framework for rational behavior in multi-column modes.
+ *
+ * The orginal "efficient" implementation of the "skip to page N" option was
+ * bogus and I substituted the basic inhibit printing until page N approach.
+ * This is still fairly bogus vis-a-vis numbering pages on multiple files
+ * restarting at one, but at least lets you consistantly reprint some large
+ * document starting in the middle, in any of the output modes.
+ *
+ * Additional support for overprinting via <back-space> or <return> would
+ * be nice, but is not trivial across tab interpretation, output formatting
+ * and the different operating modes. Support for line-wrapping, either
+ * strict or word-wrapped would be really useful and not all that hard to
+ * kludge into the inln() implementation. The general notion is that -wc n
+ * would specify width and wrapping with a marker character c and -Wc n
+ * would add word wrapping with a minimum width n and delimiters c, defaulting
+ * to tab, blank, and -, and column width. Word wrapping always involves
+ * painful policy questions which are difficult to specify unless you just
+ * hardwire in some fixed rules. Think quotes, punctuation and white-space
+ * elimination and whether you'd do the same thing with a C program and
+ * something like columninated newspaper text.
+ *
+ * George Robbins <grr@tharsis.com> 4/22/97.
+ */
+
/*
* parameter variables
*/
-int pgnm; /* starting page number */
-int clcnt; /* number of columns */
-int colwd; /* column data width - multiple columns */
-int across; /* mult col flag; write across page */
-int dspace; /* double space flag */
-char inchar; /* expand input char */
-int ingap; /* expand input gap */
-int formfeed; /* use formfeed as trailer */
-char *header; /* header name instead of file name */
-char ochar; /* contract output char */
-int ogap; /* contract output gap */
-int lines; /* number of lines per page */
-int merge; /* merge multiple files in output */
-char nmchar; /* line numbering append char */
-int nmwd; /* width of line number field */
-int offst; /* number of page offset spaces */
-int nodiag; /* do not report file open errors */
-char schar; /* text column separation character */
-int sflag; /* -s option for multiple columns */
-int nohead; /* do not write head and trailer */
-int pgwd; /* page width with multiple col output */
-char *timefrmt; /* time conversion string */
+int pgnm; /* starting page number */
+int skipping; /* we're skipping to page pgnum */
+int clcnt; /* number of columns */
+int colwd; /* column data width - multiple columns */
+int across; /* mult col flag; write across page */
+int dspace; /* double space flag */
+char inchar; /* expand input char */
+int ingap; /* expand input gap */
+int formfeed; /* use formfeed as trailer */
+int inform; /* grok formfeeds in input */
+char *header; /* header name instead of file name */
+char ochar; /* contract output char */
+int ogap; /* contract output gap */
+int lines; /* number of lines per page */
+int merge; /* merge multiple files in output */
+char nmchar; /* line numbering append char */
+int nmwd; /* width of line number field */
+int offst; /* number of page offset spaces */
+int nodiag; /* do not report file open errors */
+char schar; /* text column separation character */
+int sflag; /* -s option for multiple columns */
+int nohead; /* do not write head and trailer */
+int pgwd; /* page width with multiple col output */
+char *timefrmt; /* time conversion string */
/*
* misc globals
*/
-FILE *err; /* error message file pointer */
-int addone; /* page length is odd with double space */
-int errcnt; /* error count on file processing */
+FILE *err; /* error message file pointer */
+int addone = 0; /* page length is odd with double space */
+int errcnt = 0; /* error count on file processing */
+int beheaded = 0; /* header / trailer link */
char digs[] = "0123456789"; /* page number translation map */
int
main(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- int ret_val;
+ int ret_val;
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- (void)signal(SIGINT, terminate);
- ret_val = setup(argc, argv);
- if (!ret_val) {
- /*
- * select the output format based on options
- */
- if (merge)
- ret_val = mulfile(argc, argv);
- else if (clcnt == 1)
- ret_val = onecol(argc, argv);
- else if (across)
- ret_val = horzcol(argc, argv);
- else
- ret_val = vertcol(argc, argv);
- } else
- usage();
- flsh_errs();
- if (errcnt || ret_val)
- exit(1);
- return(0);
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGINT, terminate);
+ ret_val = setup(argc, argv);
+ if (!ret_val) {
+ /*
+ * select the output format based on options
+ */
+ if (merge)
+ ret_val = mulfile(argc, argv);
+ else if (clcnt == 1)
+ ret_val = onecol(argc, argv);
+ else if (across)
+ ret_val = horzcol(argc, argv);
+ else
+ ret_val = vertcol(argc, argv);
+ } else
+ usage();
+ flsh_errs();
+ if (errcnt || ret_val)
+ exit(1);
+ return(0);
}
/*
- * onecol: print files with only one column of output.
- * Line length is unlimited.
+ * onecol: print files with only one column of output.
+ * Line length is unlimited.
*/
int
onecol(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- register int cnt = -1;
- register int off;
- register int lrgln;
- register int linecnt;
- register int num;
- int lncnt;
- int pagecnt;
- int ips;
- int ops;
- int cps;
- char *obuf;
- char *lbuf;
- char *nbuf;
- char *hbuf;
- char *ohbuf;
- FILE *inf;
- char *fname;
- int mor;
-
- if (nmwd)
- num = nmwd + 1;
- else
- num = 0;
- off = num + offst;
-
- /*
- * allocate line buffer
- */
- if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
- /*
- * allocate header buffer
- */
- if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
-
- ohbuf = hbuf + offst;
- nbuf = obuf + offst;
- lbuf = nbuf + num;
- if (num)
- nbuf[--num] = nmchar;
- if (offst) {
- (void)memset(obuf, (int)' ', offst);
- (void)memset(hbuf, (int)' ', offst);
- }
+ register int off;
+ register int lrgln;
+ register int linecnt;
+ register int num;
+ int cnt;
+ int rc;
+ int lncnt;
+ int pagecnt;
+ int ips;
+ int ops;
+ int cps;
+ char *obuf;
+ char *lbuf;
+ char *nbuf;
+ char *hbuf;
+ char *ohbuf;
+ FILE *inf;
+ char *fname;
+ int mor;
+
+ if (nmwd)
+ num = nmwd + 1;
+ else
+ num = 0;
+ off = num + offst;
+
+ /*
+ * allocate line buffer
+ */
+ if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * allocate header buffer
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ ohbuf = hbuf + offst;
+ nbuf = obuf + offst;
+ lbuf = nbuf + num;
+
+ if (num)
+ nbuf[--num] = nmchar;
+
+ if (offst) {
+ (void)memset(obuf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ pagecnt = 0;
+ lncnt = 0;
/*
- * loop by file
+ * loop by "form"
*/
- while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
- if (pgnm) {
- /*
- * skip to specified page
- */
- if (inskip(inf, pgnm, lines))
- continue;
- pagecnt = pgnm;
- } else
- pagecnt = 1;
- lncnt = 0;
+ for(;;) {
+
+ /*
+ * loop by page
+ */
+ for(;;) {
+ linecnt = 0;
+ lrgln = 0;
+ ops = 0;
+ ips = 0;
+ cps = 0;
/*
- * loop by page
+ * loop by line
*/
- for(;;) {
- linecnt = 0;
- lrgln = 0;
- ops = 0;
- ips = 0;
- cps = 0;
-
- /*
- * loop by line
- */
- while (linecnt < lines) {
- /*
- * input next line
- */
- if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0)
- break;
- if (!linecnt && !nohead &&
- prhead(hbuf, fname, pagecnt))
- return(1);
-
- /*
- * start of new line.
- */
- if (!lrgln) {
- if (num)
- addnum(nbuf, num, ++lncnt);
- if (otln(obuf,cnt+off, &ips, &ops, mor))
- return(1);
- } else if (otln(lbuf, cnt, &ips, &ops, mor))
- return(1);
-
- /*
- * if line bigger than buffer, get more
- */
- if (mor) {
- lrgln = 1;
- continue;
- }
+ while (linecnt < lines) {
- /*
- * whole line rcvd. reset tab proc. state
- */
- ++linecnt;
- lrgln = 0;
- ops = 0;
- ips = 0;
- }
+ /*
+ * input next line
+ */
+ rc = inln(inf,lbuf,LBUF,&cnt,&cps,0,&mor);
+ if (cnt >= 0) {
+ if (!lrgln)
+ if (!linecnt && prhead(hbuf, fname, ++pagecnt))
+ return(1);
/*
- * fill to end of page
+ * start new line or continue a long one
*/
- if (linecnt && prtail(lines-linecnt-lrgln, lrgln))
+ if (!lrgln) {
+ if (num)
+ addnum(nbuf, num, ++lncnt);
+ if (otln(obuf,cnt+off, &ips, &ops, mor))
+ return(1);
+ } else
+ if (otln(lbuf, cnt, &ips, &ops, mor))
return(1);
/*
- * On EOF go to next file
+ * if line bigger than buffer, get more
*/
- if (cnt < 0)
- break;
- ++pagecnt;
+ if (mor) {
+ lrgln = 1;
+ } else {
+ /*
+ * whole line rcvd. reset tab proc. state
+ */
+ ++linecnt;
+ lrgln = 0;
+ ops = 0;
+ ips = 0;
+ }
+ }
+
+ if (rc != NORMAL)
+ break;
}
- if (inf != stdin)
- (void)fclose(inf);
+
+ /*
+ * fill to end of page
+ */
+ if (prtail(lines - linecnt, lrgln))
+ return(1);
+
+ /*
+ * unless END continue
+ */
+ if (rc == END)
+ break;
+ }
+
+ /*
+ * On EOF go to next file
+ */
+ if (rc == END)
+ break;
}
- if (eoptind < argc)
- return(1);
+
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+ /*
+ * If we didn't process all the files, return error
+ */
+ if (eoptind < argc)
+ return(1);
+ else
return(0);
}
/*
* vertcol: print files with more than one column of output down a page
+ * the general approach is to buffer a page of data, then print
*/
int
vertcol(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- register char *ptbf;
- register char **lstdat;
- register int i;
- register int j;
- register int cnt = -1;
- register int pln;
- register int *indy;
- int cvc;
- int *lindy;
- int lncnt;
- int stp;
- int pagecnt;
- int col = colwd + 1;
- int mxlen = pgwd + offst + 1;
- int mclcnt = clcnt - 1;
- struct vcol *vc;
- int mvc;
- int tvc;
- int cw = nmwd + 1;
- int fullcol;
- char *buf;
- char *hbuf;
- char *ohbuf;
- char *fname;
- FILE *inf;
- int ips = 0;
- int cps = 0;
- int ops = 0;
- int mor = 0;
-
- /*
- * allocate page buffer
- */
- if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
-
- /*
- * allocate page header
- */
- if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
- ohbuf = hbuf + offst;
- if (offst)
- (void)memset(hbuf, (int)' ', offst);
-
- /*
- * col pointers when no headers
- */
- mvc = lines * clcnt;
- if ((vc =
- (struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) {
- mfail();
- return(1);
- }
-
- /*
- * pointer into page where last data per line is located
- */
- if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){
- mfail();
- return(1);
- }
-
- /*
- * fast index lookups to locate start of lines
- */
- if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
- mfail();
- return(1);
- }
- if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
- mfail();
- return(1);
- }
-
- if (nmwd)
- fullcol = col + cw;
- else
- fullcol = col;
+ register char *ptbf;
+ register char **lstdat;
+ register int i;
+ register int j;
+ register int pln;
+ register int *indy;
+ int cnt;
+ int rc;
+ int cvc;
+ int *lindy;
+ int lncnt;
+ int stp;
+ int pagecnt;
+ int col = colwd + 1;
+ int mxlen = pgwd + offst + 1;
+ int mclcnt = clcnt - 1;
+ struct vcol *vc;
+ int mvc;
+ int tvc;
+ int cw = nmwd + 1;
+ int fullcol;
+ char *buf;
+ char *hbuf;
+ char *ohbuf;
+ char *fname;
+ FILE *inf;
+ int ips = 0;
+ int cps = 0;
+ int ops = 0;
+ int mor = 0;
+
+ /*
+ * allocate page buffer
+ */
+ if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * allocate page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ ohbuf = hbuf + offst;
+ if (offst)
+ (void)memset(hbuf, (int)' ', offst);
+
+ /*
+ * col pointers when no headers
+ */
+ mvc = lines * clcnt;
+ if ((vc=(struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * pointer into page where last data per line is located
+ */
+ if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){
+ mfail();
+ return(1);
+ }
+
+ /*
+ * fast index lookups to locate start of lines
+ */
+ if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
+ mfail();
+ return(1);
+ }
+ if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ if (nmwd)
+ fullcol = col + cw;
+ else
+ fullcol = col;
+
+ /*
+ * initialize buffer lookup indexes and offset area
+ */
+ for (j = 0; j < lines; ++j) {
+ lindy[j] = j * mxlen;
+ indy[j] = lindy[j] + offst;
+ if (offst) {
+ ptbf = buf + lindy[j];
+ (void)memset(ptbf, (int)' ', offst);
+ ptbf += offst;
+ } else
+ ptbf = buf + indy[j];
+ lstdat[j] = ptbf;
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ pagecnt = 0;
+ lncnt = 0;
/*
- * initialize buffer lookup indexes and offset area
+ * loop by "form"
*/
- for (j = 0; j < lines; ++j) {
- lindy[j] = j * mxlen;
- indy[j] = lindy[j] + offst;
- if (offst) {
- ptbf = buf + lindy[j];
- (void)memset(ptbf, (int)' ', offst);
- ptbf += offst;
- } else
- ptbf = buf + indy[j];
- lstdat[j] = ptbf;
- }
+ for (;;) {
- /*
- * loop by file
- */
- while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
- if (pgnm) {
- /*
- * skip to requested page
- */
- if (inskip(inf, pgnm, lines))
- continue;
- pagecnt = pgnm;
- } else
- pagecnt = 1;
- lncnt = 0;
+ /*
+ * loop by page
+ */
+ for(;;) {
/*
- * loop by page
+ * loop by column
*/
- for(;;) {
+ cvc = 0;
+ for (i = 0; i < clcnt; ++i) {
+ j = 0;
+ /*
+ * if last column, do not pad
+ */
+ if (i == mclcnt)
+ stp = 1;
+ else
+ stp = 0;
+
+ /*
+ * loop by line
+ */
+ for(;;) {
/*
- * loop by column
+ * is this first column
*/
- cvc = 0;
- for (i = 0; i < clcnt; ++i) {
- j = 0;
- /*
- * if last column, do not pad
- */
- if (i == mclcnt)
- stp = 1;
- else
- stp = 0;
- /*
- * loop by line
- */
- for(;;) {
- /*
- * is this first column
- */
- if (!i) {
- ptbf = buf + indy[j];
- lstdat[j] = ptbf;
- } else
- ptbf = lstdat[j];
- vc[cvc].pt = ptbf;
-
- /*
- * add number
- */
- if (nmwd) {
- addnum(ptbf, nmwd, ++lncnt);
- ptbf += nmwd;
- *ptbf++ = nmchar;
- }
-
- /*
- * input next line
- */
- cnt = inln(inf,ptbf,colwd,&cps,1,&mor);
- vc[cvc++].cnt = cnt;
- if (cnt < 0)
- break;
- ptbf += cnt;
-
- /*
- * pad all but last column on page
- */
- if (!stp) {
- /*
- * pad to end of column
- */
- if (sflag)
- *ptbf++ = schar;
- else if ((pln = col-cnt) > 0) {
- (void)memset(ptbf,
- (int)' ',pln);
- ptbf += pln;
- }
- }
- /*
- * remember last char in line
- */
- lstdat[j] = ptbf;
- if (++j >= lines)
- break;
- }
- if (cnt < 0)
- break;
- }
+ if (!i) {
+ ptbf = buf + indy[j];
+ lstdat[j] = ptbf;
+ } else
+ ptbf = lstdat[j];
+ vc[cvc].pt = ptbf;
/*
- * when -t (no header) is specified the spec requires
- * the min number of lines. The last page may not have
- * balanced length columns. To fix this we must reorder
- * the columns. This is a very slow technique so it is
- * only used under limited conditions. Without -t, the
- * balancing of text columns is unspecified. To NOT
- * balance the last page, add the global variable
- * nohead to the if statement below e.g.
- *
- * if ((cnt < 0) && nohead && cvc ......
+ * add number
*/
- --cvc;
+ if (nmwd) {
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
/*
- * check to see if last page needs to be reordered
+ * input next line
*/
- if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){
- pln = cvc/clcnt;
- if (cvc % clcnt)
- ++pln;
-
+ rc = inln(inf,ptbf,colwd,&cnt,&cps,1,&mor);
+ vc[cvc++].cnt = cnt;
+ if (cnt >= 0) {
+ ptbf += cnt;
+
+ /*
+ * pad all but last column on page
+ */
+ if (!stp) {
/*
- * print header
+ * pad to end of column
*/
- if (!nohead && prhead(hbuf, fname, pagecnt))
- return(1);
- for (i = 0; i < pln; ++i) {
- ips = 0;
- ops = 0;
- if (offst&& otln(buf,offst,&ips,&ops,1))
- return(1);
- tvc = i;
-
- for (j = 0; j < clcnt; ++j) {
- /*
- * determine column length
- */
- if (j == mclcnt) {
- /*
- * last column
- */
- cnt = vc[tvc].cnt;
- if (nmwd)
- cnt += cw;
- } else if (sflag) {
- /*
- * single ch between
- */
- cnt = vc[tvc].cnt + 1;
- if (nmwd)
- cnt += cw;
- } else
- cnt = fullcol;
- if (otln(vc[tvc].pt, cnt, &ips,
- &ops, 1))
- return(1);
- tvc += pln;
- if (tvc >= cvc)
- break;
- }
- /*
- * terminate line
- */
- if (otln(buf, 0, &ips, &ops, 0))
- return(1);
+ if (sflag)
+ *ptbf++ = schar;
+ else if ((pln = col-cnt) > 0) {
+ (void)memset(ptbf,
+ (int)' ',pln);
+ ptbf += pln;
}
+ }
+
+ /*
+ * remember last char in line
+ */
+ lstdat[j] = ptbf;
+ if (++j >= lines)
+ break;
+ } /* end of if cnt >= 0 */
+
+ if (rc != NORMAL)
+ break;
+ } /* end of for line */
+
+ if (rc != NORMAL)
+ break;
+ } /* end of for column */
+
+ /*
+ * when -t (no header) is specified the spec requires
+ * the min number of lines. The last page may not have
+ * balanced length columns. To fix this we must reorder
+ * the columns. This is a very slow technique so it is
+ * only used under limited conditions. Without -t, the
+ * balancing of text columns is unspecified. To NOT
+ * balance the last page, add the global variable
+ * nohead to the if statement below e.g.
+ */
+
+ /*
+ * print header iff we got anything on the first read
+ */
+ if (vc[0].cnt >= 0) {
+ if (prhead(hbuf, fname, ++pagecnt))
+ return(1);
+
+ /*
+ * check to see if "last" page needs to be reordered
+ */
+ --cvc;
+ if ((rc != NORMAL) && cvc && ((mvc-cvc) >= clcnt)){
+ pln = cvc/clcnt;
+ if (cvc % clcnt)
+ ++pln;
+
+ for (i = 0; i < pln; ++i) {
+ ips = 0;
+ ops = 0;
+ if (offst && otln(buf,offst,&ips,&ops,1))
+ return(1);
+ tvc = i;
+
+ for (j = 0; j < clcnt; ++j) {
/*
- * pad to end of page
- */
- if (prtail((lines - pln), 0))
- return(1);
- /*
- * done with output, go to next file
+ * determine column length
*/
- break;
+ if (j == mclcnt) {
+ /*
+ * last column
+ */
+ cnt = vc[tvc].cnt;
+ if (nmwd)
+ cnt += cw;
+ } else if (sflag) {
+ /*
+ * single ch between
+ */
+ cnt = vc[tvc].cnt + 1;
+ if (nmwd)
+ cnt += cw;
+ } else
+ cnt = fullcol;
+
+ if (otln(vc[tvc].pt, cnt, &ips, &ops, 1))
+ return(1);
+ tvc += pln;
+ if (tvc > cvc)
+ break;
+ }
+ /*
+ * terminate line
+ */
+ if (otln(buf, 0, &ips, &ops, 0))
+ return(1);
}
+ } else {
+
/*
+ * just a normal page...
* determine how many lines to output
*/
if (i > 0)
- pln = lines;
+ pln = lines;
else
- pln = j;
-
- /*
- * print header
- */
- if (pln && !nohead && prhead(hbuf, fname, pagecnt))
- return(1);
+ pln = j;
/*
* output each line
*/
for (i = 0; i < pln; ++i) {
- ptbf = buf + lindy[i];
- if ((j = lstdat[i] - ptbf) <= offst)
- break;
+ ptbf = buf + lindy[i];
+ if ((j = lstdat[i] - ptbf) <= offst)
+ break;
+ else {
+ ips = 0;
+ ops = 0;
if (otln(ptbf, j, &ips, &ops, 0))
- return(1);
+ return(1);
+ }
}
+ }
+ }
- /*
- * pad to end of page
- */
- if (pln && prtail((lines - pln), 0))
- return(1);
+ /*
+ * pad to end of page
+ */
+ if (prtail((lines - pln), 0))
+ return(1);
- /*
- * if EOF go to next file
- */
- if (cnt < 0)
- break;
- ++pagecnt;
- }
- if (inf != stdin)
- (void)fclose(inf);
+ /*
+ * if FORM continue
+ */
+ if (rc != NORMAL)
+ break;
+ }
+
+ /*
+ * if EOF go to next file
+ */
+ if (rc == END)
+ break;
}
- if (eoptind < argc)
- return(1);
+
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+
+ if (eoptind < argc)
+ return(1);
+ else
return(0);
}
/*
- * horzcol: print files with more than one column of output across a page
+ * horzcol: print files with more than one column of output across a page
*/
int
horzcol(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- register char *ptbf;
- register int pln;
- register int cnt = -1;
- register char *lstdat;
- register int col = colwd + 1;
- register int j;
- register int i;
- int lncnt;
- int pagecnt;
- char *buf;
- char *hbuf;
- char *ohbuf;
- char *fname;
- FILE *inf;
- int ips = 0;
- int cps = 0;
- int ops = 0;
- int mor = 0;
-
- if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
+ register char *ptbf;
+ register int pln;
+ register char *lstdat;
+ register int col = colwd + 1;
+ register int j;
+ register int i;
+ int cnt;
+ int rc;
+ int lncnt;
+ int pagecnt;
+ char *buf;
+ char *hbuf;
+ char *ohbuf;
+ char *fname;
+ FILE *inf;
+ int cps = 0;
+ int mor = 0;
+ int ips = 0;
+ int ops = 0;
+
+ if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ ohbuf = hbuf + offst;
+ if (offst) {
+ (void)memset(buf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ pagecnt = 0;
+ lncnt = 0;
/*
- * page header
+ * loop by form
*/
- if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
- ohbuf = hbuf + offst;
- if (offst) {
- (void)memset(buf, (int)' ', offst);
- (void)memset(hbuf, (int)' ', offst);
- }
+ for (;;) {
- /*
- * loop by file
- */
- while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
- if (pgnm) {
- if (inskip(inf, pgnm, lines))
- continue;
- pagecnt = pgnm;
- } else
- pagecnt = 1;
- lncnt = 0;
+ /*
+ * loop by page
+ */
+ for(;;) {
/*
- * loop by page
+ * loop by line
*/
- for(;;) {
+ for (i = 0; i < lines; ++i) {
+ ptbf = buf + offst;
+ lstdat = ptbf;
+ j = 0;
+
+ /*
+ * loop by col
+ */
+ for(;;) {
+ if (nmwd) {
+ /*
+ * add number to column
+ */
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
/*
- * loop by line
+ * input line
*/
- for (i = 0; i < lines; ++i) {
- ptbf = buf + offst;
- lstdat = ptbf;
- j = 0;
- /*
- * loop by col
- */
- for(;;) {
- if (nmwd) {
- /*
- * add number to column
- */
- addnum(ptbf, nmwd, ++lncnt);
- ptbf += nmwd;
- *ptbf++ = nmchar;
- }
- /*
- * input line
- */
- if ((cnt = inln(inf,ptbf,colwd,&cps,1,
- &mor)) < 0)
- break;
- ptbf += cnt;
- lstdat = ptbf;
-
- /*
- * if last line skip padding
- */
- if (++j >= clcnt)
- break;
-
- /*
- * pad to end of column
- */
- if (sflag)
- *ptbf++ = schar;
- else if ((pln = col - cnt) > 0) {
- (void)memset(ptbf,(int)' ',pln);
- ptbf += pln;
- }
- }
+ rc = inln(inf,ptbf,colwd,&cnt,&cps,1, &mor);
+ if (cnt >= 0) {
+ if (!i && !j && prhead(hbuf, fname, ++pagecnt))
+ return(1);
+
+ ptbf += cnt;
+ lstdat = ptbf;
+
+ /*
+ * if last line skip padding
+ */
+ if (++j >= clcnt)
+ break;
- /*
- * determine line length
- */
- if ((j = lstdat - buf) <= offst)
- break;
- if (!i && !nohead &&
- prhead(hbuf, fname, pagecnt))
- return(1);
- /*
- * output line
- */
- if (otln(buf, j, &ips, &ops, 0))
- return(1);
+ /*
+ * pad to end of column
+ */
+ if (sflag)
+ *ptbf++ = schar;
+ else if ((pln = col - cnt) > 0) {
+ (void)memset(ptbf,(int)' ',pln);
+ ptbf += pln;
+ }
}
+ if (rc != NORMAL)
+ break;
+ }
+
+ /*
+ * output line if any columns on it
+ */
+ if (j) {
+ if (otln(buf, lstdat-buf, &ips, &ops, 0))
+ return(1);
+ }
- /*
- * pad to end of page
- */
- if (i && prtail(lines-i, 0))
- return(1);
-
- /*
- * if EOF go to next file
- */
- if (cnt < 0)
- break;
- ++pagecnt;
+ if (rc != NORMAL)
+ break;
}
- if (inf != stdin)
- (void)fclose(inf);
+
+ /*
+ * pad to end of page
+ */
+ if (prtail(lines - i, 0))
+ return(1);
+
+ /*
+ * if FORM continue
+ */
+ if (rc == END)
+ break;
+ }
+ /*
+ * if EOF go to next file
+ */
+ if (rc == END)
+ break;
}
- if (eoptind < argc)
- return(1);
- return(0);
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+ if (eoptind < argc)
+ return(1);
+ return(0);
}
/*
- * mulfile: print files with more than one column of output and
- * more than one file concurrently
+ * mulfile: print files with more than one column of output and
+ * more than one file concurrently
*/
int
mulfile(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- register char *ptbf;
- register int j;
- register int pln;
- register int cnt;
- register char *lstdat;
- register int i;
- FILE **fbuf;
- int actf;
- int lncnt;
- int col;
- int pagecnt;
- int fproc;
- char *buf;
- char *hbuf;
- char *ohbuf;
- char *fname;
- int ips = 0;
- int cps = 0;
- int ops = 0;
- int mor = 0;
-
- /*
- * array of FILE *, one for each operand
- */
- if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) {
- mfail();
- return(1);
- }
-
- /*
- * page header
- */
- if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
- mfail();
- return(1);
+ register char *ptbf;
+ register int j;
+ register int pln;
+ int *rc;
+ int cnt;
+ register char *lstdat;
+ register int i;
+ FILE **fbuf;
+ int actf;
+ int lncnt;
+ int col;
+ int pagecnt;
+ int fproc;
+ char *buf;
+ char *hbuf;
+ char *ohbuf;
+ char *fname;
+ int ips = 0;
+ int cps = 0;
+ int ops = 0;
+ int mor = 0;
+
+ /*
+ * array of FILE *, one for each operand
+ */
+ if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * array of int *, one for each operand
+ */
+ if ((rc = (int *)malloc((unsigned)clcnt*sizeof(int))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+ ohbuf = hbuf + offst;
+
+ /*
+ * do not know how many columns yet. The number of operands provide an
+ * upper bound on the number of columns. We use the number of files
+ * we can open successfully to set the number of columns. The operation
+ * of the merge operation (-m) in relation to unsuccesful file opens
+ * is unspecified by posix.
+ *
+ * XXX - this seems moderately bogus, you'd think that specifying
+ * "pr -2 a b c d" would run though all the files in pairs, but
+ * the existing code says up two files, or fewer if one is bogus.
+ * fixing it would require modifying the looping structure, so be it.
+ */
+ j = 0;
+ while (j < clcnt) {
+ if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) != NULL) {
+ rc[j] = NORMAL;
+ j++;
}
- ohbuf = hbuf + offst;
+ }
- /*
- * do not know how many columns yet. The number of operands provide an
- * upper bound on the number of columns. We use the number of files
- * we can open successfully to set the number of columns. The operation
- * of the merge operation (-m) in relation to unsuccesful file opens
- * is unspecified by posix.
- */
- j = 0;
- while (j < clcnt) {
- if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL)
- break;
- if (pgnm && (inskip(fbuf[j], pgnm, lines)))
- fbuf[j] = NULL;
- ++j;
- }
-
- /*
- * if no files, exit
- */
- if (!j)
- return(1);
-
- /*
- * calculate page boundries based on open file count
- */
+ /*
+ * if no files, exit
+ */
+ if (j)
clcnt = j;
- if (nmwd) {
- colwd = (pgwd - clcnt - nmwd)/clcnt;
- pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
- } else {
- colwd = (pgwd + 1 - clcnt)/clcnt;
- pgwd = ((colwd + 1) * clcnt) - 1;
- }
- if (colwd < 1) {
- (void)fprintf(err,
- "pr: page width too small for %d columns\n", clcnt);
- return(1);
- }
- actf = clcnt;
- col = colwd + 1;
+ else
+ return(1);
+
+ /*
+ * calculate page boundries based on open file count
+ */
+ if (nmwd) {
+ colwd = (pgwd - clcnt - nmwd)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
+ } else {
+ colwd = (pgwd + 1 - clcnt)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - 1;
+ }
+ if (colwd < 1) {
+ (void)fprintf(err,
+ "pr: page width too small for %d columns\n", clcnt);
+ return(1);
+ }
+ col = colwd + 1;
+
+ /*
+ * line buffer
+ */
+ if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+ if (offst) {
+ (void)memset(buf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+
+ pagecnt = 0;
+ lncnt = 0;
+ actf = clcnt;
+
+ /*
+ * continue to loop while any file still has data
+ */
+ while (actf > 0) {
/*
- * line buffer
+ * loop on "form"
*/
- if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
- mfail();
- return(1);
- }
- if (offst) {
- (void)memset(buf, (int)' ', offst);
- (void)memset(hbuf, (int)' ', offst);
- }
- if (pgnm)
- pagecnt = pgnm;
- else
- pagecnt = 1;
- lncnt = 0;
+ for (;;) {
+
+ /*
+ * loop by line
+ */
+ for (i = 0; i < lines; ++i) {
+ ptbf = buf + offst;
+ lstdat = ptbf;
+ if (nmwd) {
+ /*
+ * add line number to line
+ */
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
- /*
- * continue to loop while any file still has data
- */
- while (actf > 0) {
+ fproc = 0;
/*
- * loop by line
+ * loop by column
*/
- for (i = 0; i < lines; ++i) {
- ptbf = buf + offst;
- lstdat = ptbf;
- if (nmwd) {
- /*
- * add line number to line
- */
- addnum(ptbf, nmwd, ++lncnt);
- ptbf += nmwd;
- *ptbf++ = nmchar;
- }
- j = 0;
- fproc = 0;
-
- /*
- * loop by column
- */
- for (j = 0; j < clcnt; ++j) {
- if (fbuf[j] == NULL) {
- /*
- * empty column; EOF
- */
- cnt = 0;
- } else if ((cnt = inln(fbuf[j], ptbf, colwd,
- &cps, 1, &mor)) < 0) {
- /*
- * EOF hit; no data
- */
- if (fbuf[j] != stdin)
- (void)fclose(fbuf[j]);
- fbuf[j] = NULL;
- --actf;
- cnt = 0;
- } else {
- /*
- * process file data
- */
- ptbf += cnt;
- lstdat = ptbf;
- fproc++;
- }
-
- /*
- * if last ACTIVE column, done with line
- */
- if (fproc >= actf)
- break;
-
- /*
- * pad to end of column
- */
- if (sflag) {
- *ptbf++ = schar;
- } else if ((pln = col - cnt) > 0) {
- (void)memset(ptbf, (int)' ', pln);
- ptbf += pln;
- }
+ for (j = 0; j < clcnt; ++j) {
+ if (rc[j] == NORMAL ) {
+ rc[j] = inln(fbuf[j], ptbf, colwd, &cnt, &cps, 1, &mor);
+ if (cnt >= 0) {
+ /*
+ * process file data
+ */
+ ptbf += cnt;
+ lstdat = ptbf;
+ fproc++;
+ } else
+ cnt = 0;
+
+ if (rc[j] == END) {
+ /*
+ * EOF close file
+ */
+ if (fbuf[j] != stdin)
+ (void)fclose(fbuf[j]);
+ --actf;
}
+ } else
+ cnt = 0;
- /*
- * calculate data in line
- */
- if ((j = lstdat - buf) <= offst)
- break;
-
- if (!i && !nohead && prhead(hbuf, fname, pagecnt))
- return(1);
-
- /*
- * output line
- */
- if (otln(buf, j, &ips, &ops, 0))
- return(1);
+ /*
+ * if last ACTIVE column, done with line
+ */
+ if (fproc >= actf)
+ break;
- /*
- * if no more active files, done
- */
- if (actf <= 0) {
- ++i;
- break;
+ /*
+ * pad to end of column
+ */
+ if (sflag) {
+ *ptbf++ = schar;
+ } else {
+ if (cnt >= 0)
+ pln = col - cnt;
+ else
+ pln = col;
+ if (pln > 0) {
+ (void)memset(ptbf, (int)' ', pln);
+ ptbf += pln;
}
+ }
}
/*
- * pad to end of page
+ * if there was anything to do, print it
*/
- if (i && prtail(lines-i, 0))
+ if (fproc != 0) {
+ if (!i && prhead(hbuf, fname, ++pagecnt))
return(1);
- ++pagecnt;
- }
- if (eoptind < argc)
- return(1);
- return(0);
-}
-/*
- * inln(): input a line of data (unlimited length lines supported)
- * Input is optionally expanded to spaces
- *
- * inf: file
- * buf: buffer
- * lim: buffer length
- * cps: column positon 1st char in buffer (large line support)
- * trnc: throw away data more than lim up to \n
- * mor: set if more data in line (not truncated)
- */
-int
-inln(inf, buf, lim, cps, trnc, mor)
- FILE *inf;
- char *buf;
- register int lim;
- int *cps;
- int trnc;
- int *mor;
-{
- register int col;
- register int gap = ingap;
- register int ch = EOF;
- register char *ptbuf;
- register int chk = (int)inchar;
-
- ptbuf = buf;
-
- if (gap) {
- /*
- * expanding input option
- */
- while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
- /*
- * is this the input "tab" char
- */
- if (ch == chk) {
- /*
- * expand to number of spaces
- */
- col = (ptbuf - buf) + *cps;
- col = gap - (col % gap);
+ /*
+ * output line
+ */
+ if (otln(buf, lstdat-buf, &ips, &ops, 0))
+ return(1);
+ } else
+ break;
+ }
- /*
- * if more than this line, push back
- */
- if ((col > lim) && (ungetc(ch, inf) == EOF))
- return(1);
+ /*
+ * pad to end of page
+ */
+ if (prtail(lines - i, 0))
+ return(1);
- /*
- * expand to spaces
- */
- while ((--col >= 0) && (--lim >= 0))
- *ptbuf++ = ' ';
- continue;
- }
- if (ch == '\n')
- break;
- *ptbuf++ = ch;
- }
- } else {
- /*
- * no expansion
- */
- while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
- if (ch == '\n')
- break;
- *ptbuf++ = ch;
- }
- }
- col = ptbuf - buf;
- if (ch == EOF) {
- *mor = 0;
- *cps = 0;
- if (!col)
- return(-1);
- return(col);
- }
- if (ch == '\n') {
- /*
- * entire line processed
- */
- *mor = 0;
- *cps = 0;
- return(col);
+ for (j = 0; j < clcnt; ++j)
+ if (rc[j] != END)
+ rc[j] = NORMAL;
+
+ if (actf <= 0)
+ break;
}
+ if (actf <= 0)
+ break;
+ }
+ if (eoptind < argc)
+ return(1);
+ return(0);
+}
+
+/*
+ * inln(): input a line of data (unlimited length lines supported)
+ * Input is optionally expanded to spaces
+ * Returns 0 if normal LF, FORM on Formfeed, and END on EOF
+ *
+ * inf: file
+ * buf: buffer
+ * lim: buffer length
+ * cnt: line length or -1 if no line (EOF for example)
+ * cps: column positon 1st char in buffer (large line support)
+ * trnc: throw away data more than lim up to \n
+ * mor: set if more data in line (not truncated)
+ */
+int
+inln(inf, buf, lim, cnt, cps, trnc, mor)
+ FILE *inf;
+ char *buf;
+ register int lim;
+ int *cnt;
+ int *cps;
+ int trnc;
+ int *mor;
+{
+ register int col;
+ register int gap = ingap;
+ register int ch = EOF;
+ register char *ptbuf;
+ register int chk = (int)inchar;
+
+ ptbuf = buf;
+ if (gap) {
/*
- * line was larger than limit
+ * expanding input option
*/
- if (trnc) {
+ while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
+ /*
+ * is this the input "tab" char
+ */
+ if (ch == chk) {
/*
- * throw away rest of line
+ * expand to number of spaces
*/
- while ((ch = getc(inf)) != EOF) {
- if (ch == '\n')
- break;
+ col = (ptbuf - buf) + *cps;
+ col = gap - (col % gap);
+
+ /*
+ * if more than this line, push back
+ */
+ if ((col > lim) && (ungetc(ch, inf) == EOF)) {
+ *cnt = -1;
+ return(END); /* shouldn't happen */
}
- *cps = 0;
- *mor = 0;
- } else {
+
/*
- * save column offset if not truncated
+ * expand to spaces
*/
- *cps += col;
- *mor = 1;
+ while ((--col >= 0) && (--lim >= 0))
+ *ptbuf++ = ' ';
+ continue;
+ }
+ if (ch == '\n' || inform && ch == INFF)
+ break;
+ *ptbuf++ = ch;
+ }
+ } else {
+ /*
+ * no expansion
+ */
+ while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
+ if (ch == '\n' || inform && ch == INFF)
+ break;
+ *ptbuf++ = ch;
+ }
+ }
+ col = ptbuf - buf;
+ if (ch == EOF) {
+ *mor = 0;
+ *cps = 0;
+ *cnt = col ? col : -1;
+ return(END);
+ }
+ if (inform && ch == INFF) {
+ *mor = 0;
+ *cps = 0;
+ *cnt = col;
+ return(FORM);
+ }
+ if (ch == '\n') {
+ /*
+ * entire line processed
+ */
+ *mor = 0;
+ *cps = 0;
+ *cnt = col;
+ return(NORMAL);
+ }
+
+ /*
+ * line was larger than limit
+ */
+ if (trnc) {
+ /*
+ * throw away rest of line
+ */
+ while ((ch = getc(inf)) != EOF) {
+ if (ch == '\n')
+ break;
}
+ *cps = 0;
+ *mor = 0;
+ } else {
+ /*
+ * save column offset if not truncated
+ */
+ *cps += col;
+ *mor = 1;
+ }
- return(col);
+ *cnt = col;
+ return(NORMAL);
}
/*
- * otln(): output a line of data. (Supports unlimited length lines)
- * output is optionally contracted to tabs
+ * otln(): output a line of data. (Supports unlimited length lines)
+ * output is optionally contracted to tabs
*
- * buf: output buffer with data
- * cnt: number of chars of valid data in buf
- * svips: buffer input column position (for large lines)
- * svops: buffer output column position (for large lines)
- * mor: output line not complete in this buf; more data to come.
- * 1 is more, 0 is complete, -1 is no \n's
+ * buf: output buffer with data
+ * cnt: number of chars of valid data in buf
+ * svips: buffer input column position (for large lines)
+ * svops: buffer output column position (for large lines)
+ * mor: output line not complete in this buf; more data to come.
+ * 1 is more, 0 is complete, -1 is no \n's
*/
int
otln(buf, cnt, svips, svops, mor)
- register char *buf;
- int cnt;
- int *svops;
- int *svips;
- int mor;
+ register char *buf;
+ int cnt;
+ int *svops;
+ int *svips;
+ int mor;
{
- register int ops; /* last col output */
- register int ips; /* last col in buf examined */
- register int gap = ogap;
- register int tbps;
- register char *endbuf;
+ register int ops; /* last col output */
+ register int ips; /* last col in buf examined */
+ register int gap = ogap;
+ register int tbps;
+ register char *endbuf;
+
+ /* skipping is only changed at header time not mid-line! */
+ if (skipping)
+ return (0);
- if (ogap) {
+ if (ogap) {
+ /*
+ * contracting on output
+ */
+ endbuf = buf + cnt;
+ ops = *svops;
+ ips = *svips;
+ while (buf < endbuf) {
+ /*
+ * count number of spaces and ochar in buffer
+ */
+ if (*buf == ' ') {
+ ++ips;
+ ++buf;
+ continue;
+ }
+
+ /*
+ * simulate ochar processing
+ */
+ if (*buf == ochar) {
+ ips += gap - (ips % gap);
+ ++buf;
+ continue;
+ }
+
+ /*
+ * got a non space char; contract out spaces
+ */
+ while (ops < ips) {
/*
- * contracting on output
+ * use as many ochar as will fit
*/
- endbuf = buf + cnt;
- ops = *svops;
- ips = *svips;
- while (buf < endbuf) {
- /*
- * count number of spaces and ochar in buffer
- */
- if (*buf == ' ') {
- ++ips;
- ++buf;
- continue;
- }
-
- /*
- * simulate ochar processing
- */
- if (*buf == ochar) {
- ips += gap - (ips % gap);
- ++buf;
- continue;
- }
-
- /*
- * got a non space char; contract out spaces
- */
- while (ops < ips) {
- /*
- * use as many ochar as will fit
- */
- if ((tbps = ops + gap - (ops % gap)) > ips)
- break;
- if (putchar(ochar) == EOF) {
- pfail();
- return(1);
- }
- ops = tbps;
- }
-
- while (ops < ips) {
- /*
- * finish off with spaces
- */
- if (putchar(' ') == EOF) {
- pfail();
- return(1);
- }
- ++ops;
- }
-
- /*
- * output non space char
- */
- if (putchar(*buf++) == EOF) {
- pfail();
- return(1);
- }
- ++ips;
- ++ops;
+ if ((tbps = ops + gap - (ops % gap)) > ips)
+ break;
+ if (putchar(ochar) == EOF) {
+ pfail();
+ return(1);
}
+ ops = tbps;
+ }
- if (mor > 0) {
- /*
- * if incomplete line, save position counts
- */
- *svops = ops;
- *svips = ips;
- return(0);
+ while (ops < ips) {
+ /*
+ * finish off with spaces
+ */
+ if (putchar(' ') == EOF) {
+ pfail();
+ return(1);
}
+ ++ops;
+ }
- if (mor < 0) {
- while (ops < ips) {
- /*
- * use as many ochar as will fit
- */
- if ((tbps = ops + gap - (ops % gap)) > ips)
- break;
- if (putchar(ochar) == EOF) {
- pfail();
- return(1);
- }
- ops = tbps;
- }
- while (ops < ips) {
- /*
- * finish off with spaces
- */
- if (putchar(' ') == EOF) {
- pfail();
- return(1);
- }
- ++ops;
- }
- return(0);
+ /*
+ * output non space char
+ */
+ if (putchar(*buf++) == EOF) {
+ pfail();
+ return(1);
+ }
+ ++ips;
+ ++ops;
+ }
+
+ if (mor > 0) {
+ /*
+ * if incomplete line, save position counts
+ */
+ *svops = ops;
+ *svips = ips;
+ return(0);
+ }
+
+ if (mor < 0) {
+ while (ops < ips) {
+ /*
+ * use as many ochar as will fit
+ */
+ if ((tbps = ops + gap - (ops % gap)) > ips)
+ break;
+ if (putchar(ochar) == EOF) {
+ pfail();
+ return(1);
}
- } else {
+ ops = tbps;
+ }
+ while (ops < ips) {
/*
- * output is not contracted
+ * finish off with spaces
*/
- if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
- pfail();
- return(1);
+ if (putchar(' ') == EOF) {
+ pfail();
+ return(1);
}
- if (mor != 0)
- return(0);
+ ++ops;
+ }
+ return(0);
}
-
+ } else {
/*
- * process line end and double space as required
+ * output is not contracted
*/
- if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
- pfail();
- return(1);
+ if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
+ pfail();
+ return(1);
}
- return(0);
+ if (mor != 0)
+ return(0);
+ }
+
+ /*
+ * process line end and double space as required
+ */
+ if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
+ pfail();
+ return(1);
+ }
+ return(0);
}
+#ifdef notused
/*
- * inskip(): skip over pgcnt pages with lncnt lines per page
- * file is closed at EOF (if not stdin).
+ * inskip(): skip over pgcnt pages with lncnt lines per page
+ * file is closed at EOF (if not stdin).
*
- * inf FILE * to read from
- * pgcnt number of pages to skip
- * lncnt number of lines per page
+ * inf FILE * to read from
+ * pgcnt number of pages to skip
+ * lncnt number of lines per page
*/
int
inskip(inf, pgcnt, lncnt)
- FILE *inf;
- register int pgcnt;
- register int lncnt;
+ FILE *inf;
+ register int pgcnt;
+ register int lncnt;
{
- register int c;
- register int cnt;
+ register int c;
+ register int cnt;
- while(--pgcnt > 0) {
- cnt = lncnt;
- while ((c = getc(inf)) != EOF) {
- if ((c == '\n') && (--cnt == 0))
- break;
- }
- if (c == EOF) {
- if (inf != stdin)
- (void)fclose(inf);
- return(1);
- }
+ while(--pgcnt > 0) {
+ cnt = lncnt;
+ while ((c = getc(inf)) != EOF) {
+ if ((c == '\n') && (--cnt == 0))
+ break;
}
- return(0);
+ if (c == EOF) {
+ if (inf != stdin)
+ (void)fclose(inf);
+ return(1);
+ }
+ }
+ return(0);
}
+#endif
/*
- * nxtfile: returns a FILE * to next file in arg list and sets the
- * time field for this file (or current date).
+ * nxtfile: returns a FILE * to next file in arg list and sets the
+ * time field for this file (or current date).
*
- * buf array to store proper date for the header.
- * dt if set skips the date processing (used with -m)
+ * buf array to store proper date for the header.
+ * dt if set skips the date processing (used with -m)
*/
FILE *
nxtfile(argc, argv, fname, buf, dt)
- int argc;
- char **argv;
- char **fname;
- char *buf;
- int dt;
+ int argc;
+ char **argv;
+ char **fname;
+ char *buf;
+ int dt;
{
- FILE *inf = NULL;
- struct timeval tv;
- struct timezone tz;
- struct tm *timeptr = NULL;
- struct stat statbuf;
- time_t curtime;
- static int twice = -1;
-
- ++twice;
- if (eoptind >= argc) {
- /*
- * no file listed; default, use standard input
- */
- if (twice)
- return(NULL);
- clearerr(stdin);
- inf = stdin;
- if (header != NULL)
- *fname = header;
- else
- *fname = FNAME;
- if (nohead)
- return(inf);
+ FILE *inf = NULL;
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *timeptr = NULL;
+ struct stat statbuf;
+ time_t curtime;
+ static int twice = -1;
+
+ ++twice;
+ if (eoptind >= argc) {
+ /*
+ * no file listed; default, use standard input
+ */
+ if (twice)
+ return(NULL);
+ clearerr(stdin);
+ inf = stdin;
+ if (header != NULL)
+ *fname = header;
+ else
+ *fname = FNAME;
+ if (nohead)
+ return(inf);
+ if (gettimeofday(&tv, &tz) < 0) {
+ ++errcnt;
+ (void)fprintf(err, "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ eoptind = argc - 1;
+ return(NULL);
+ }
+ curtime = tv.tv_sec;
+ timeptr = localtime(&curtime);
+ }
+ for (; eoptind < argc; ++eoptind) {
+ if (strcmp(argv[eoptind], "-") == 0) {
+ /*
+ * process a "-" for filename
+ */
+ clearerr(stdin);
+ inf = stdin;
+ if (header != NULL)
+ *fname = header;
+ else
+ *fname = FNAME;
+ ++eoptind;
+ if (nohead || (dt && twice))
+ return(inf);
+ if (gettimeofday(&tv, &tz) < 0) {
+ ++errcnt;
+ (void)fprintf(err,
+ "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ return(NULL);
+ }
+ curtime = tv.tv_sec;
+ timeptr = localtime(&curtime);
+ } else {
+ /*
+ * normal file processing
+ */
+ if ((inf = fopen(argv[eoptind], "r")) == NULL) {
+ ++errcnt;
+ if (nodiag)
+ continue;
+ (void)fprintf(err, "pr: Cannot open %s, %s\n",
+ argv[eoptind], strerror(errno));
+ continue;
+ }
+ if (header != NULL)
+ *fname = header;
+ else if (dt)
+ *fname = FNAME;
+ else
+ *fname = argv[eoptind];
+ ++eoptind;
+ if (nohead || (dt && twice))
+ return(inf);
+
+ if (dt) {
if (gettimeofday(&tv, &tz) < 0) {
- ++errcnt;
- (void)fprintf(err, "pr: cannot get time of day, %s\n",
- strerror(errno));
- eoptind = argc - 1;
- return(NULL);
+ ++errcnt;
+ (void)fprintf(err,
+ "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ return(NULL);
}
curtime = tv.tv_sec;
timeptr = localtime(&curtime);
- }
- for (; eoptind < argc; ++eoptind) {
- if (strcmp(argv[eoptind], "-") == 0) {
- /*
- * process a "-" for filename
- */
- clearerr(stdin);
- inf = stdin;
- if (header != NULL)
- *fname = header;
- else
- *fname = FNAME;
- ++eoptind;
- if (nohead || (dt && twice))
- return(inf);
- if (gettimeofday(&tv, &tz) < 0) {
- ++errcnt;
- (void)fprintf(err,
- "pr: cannot get time of day, %s\n",
- strerror(errno));
- return(NULL);
- }
- curtime = tv.tv_sec;
- timeptr = localtime(&curtime);
- } else {
- /*
- * normal file processing
- */
- if ((inf = fopen(argv[eoptind], "r")) == NULL) {
- ++errcnt;
- if (nodiag)
- continue;
- (void)fprintf(err, "pr: Cannot open %s, %s\n",
- argv[eoptind], strerror(errno));
- continue;
- }
- if (header != NULL)
- *fname = header;
- else if (dt)
- *fname = FNAME;
- else
- *fname = argv[eoptind];
- ++eoptind;
- if (nohead || (dt && twice))
- return(inf);
-
- if (dt) {
- if (gettimeofday(&tv, &tz) < 0) {
- ++errcnt;
- (void)fprintf(err,
- "pr: cannot get time of day, %s\n",
- strerror(errno));
- return(NULL);
- }
- curtime = tv.tv_sec;
- timeptr = localtime(&curtime);
- } else {
- if (fstat(fileno(inf), &statbuf) < 0) {
- ++errcnt;
- (void)fclose(inf);
- (void)fprintf(err,
- "pr: Cannot stat %s, %s\n",
- argv[eoptind], strerror(errno));
- return(NULL);
- }
- timeptr = localtime(&(statbuf.st_mtime));
- }
+ } else {
+ if (fstat(fileno(inf), &statbuf) < 0) {
+ ++errcnt;
+ (void)fclose(inf);
+ (void)fprintf(err,
+ "pr: Cannot stat %s, %s\n",
+ argv[eoptind], strerror(errno));
+ return(NULL);
}
- break;
- }
- if (inf == NULL)
- return(NULL);
-
- /*
- * set up time field used in header
- */
- if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
- ++errcnt;
- if (inf != stdin)
- (void)fclose(inf);
- (void)fputs("pr: time conversion failed\n", err);
- return(NULL);
+ timeptr = localtime(&(statbuf.st_mtime));
+ }
}
- return(inf);
+ break;
+ }
+ if (inf == NULL)
+ return(NULL);
+
+ /*
+ * set up time field used in header
+ */
+ if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
+ ++errcnt;
+ if (inf != stdin)
+ (void)fclose(inf);
+ (void)fputs("pr: time conversion failed\n", err);
+ return(NULL);
+ }
+ return(inf);
}
/*
- * addnum(): adds the line number to the column
- * Truncates from the front or pads with spaces as required.
- * Numbers are right justified.
+ * addnum(): adds the line number to the column
+ * Truncates from the front or pads with spaces as required.
+ * Numbers are right justified.
*
- * buf buffer to store the number
- * wdth width of buffer to fill
- * line line number
+ * buf buffer to store the number
+ * wdth width of buffer to fill
+ * line line number
*
- * NOTE: numbers occupy part of the column. The posix
- * spec does not specify if -i processing should or should not
- * occur on number padding. The spec does say it occupies
- * part of the column. The usage of addnum currently treats
- * numbers as part of the column so spaces may be replaced.
+ * NOTE: numbers occupy part of the column. The posix
+ * spec does not specify if -i processing should or should not
+ * occur on number padding. The spec does say it occupies
+ * part of the column. The usage of addnum currently treats
+ * numbers as part of the column so spaces may be replaced.
*/
void
addnum(buf, wdth, line)
- register char *buf;
- register int wdth;
- register int line;
+ register char *buf;
+ register int wdth;
+ register int line;
{
- register char *pt = buf + wdth;
-
- do {
- *--pt = digs[line % 10];
- line /= 10;
- } while (line && (pt > buf));
-
- /*
- * pad with space as required
- */
- while (pt > buf)
- *--pt = ' ';
+ register char *pt = buf + wdth;
+
+ do {
+ *--pt = digs[line % 10];
+ line /= 10;
+ } while (line && (pt > buf));
+
+ /*
+ * pad with space as required
+ */
+ while (pt > buf)
+ *--pt = ' ';
}
/*
- * prhead(): prints the top of page header
+ * prhead(): prints the top of page header
*
- * buf buffer with time field (and offset)
- * cnt number of chars in buf
- * fname fname field for header
- * pagcnt page number
+ * buf buffer with time field (and offset)
+ * cnt number of chars in buf
+ * fname fname field for header
+ * pagcnt page number
+ *
+ * prhead() should be used carefully, we don't want to print out headers
+ * for null input files or orphan headers at the end of files, and also
+ * trailer processing is typically conditional on whether you've called
+ * prhead() at least once for a file and incremented pagecnt.. Exactly
+ * how to determine whether to print a header is a little different in
+ * the context each output mode, but we let the caller figure that out.
*/
int
prhead(buf, fname, pagcnt)
- char *buf;
- char *fname;
- int pagcnt;
+ char *buf;
+ char *fname;
+ int pagcnt;
{
- int ips = 0;
- int ops = 0;
-
- if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
- pfail();
- return(1);
- }
- /*
- * posix is not clear if the header is subject to line length
- * restrictions. The specification for header line format
- * in the spec clearly does not limit length. No pr currently
- * restricts header length. However if we need to truncate in
- * an reasonable way, adjust the length of the printf by
- * changing HDFMT to allow a length max as an arguement printf.
- * buf (which contains the offset spaces and time field could
- * also be trimmed
- *
- * note only the offset (if any) is processed for tab expansion
- */
- if (offst && otln(buf, offst, &ips, &ops, -1))
- return(1);
- (void)printf(HDFMT,buf+offst, fname, pagcnt);
- return(0);
+ int ips = 0;
+ int ops = 0;
+
+ beheaded = 1;
+
+ if (skipping && pagcnt >= pgnm)
+ skipping = 0;
+
+ if (nohead || skipping)
+ return (0);
+
+ if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
+ pfail();
+ return(1);
+ }
+ /*
+ * posix is not clear if the header is subject to line length
+ * restrictions. The specification for header line format
+ * in the spec clearly does not limit length. No pr currently
+ * restricts header length. However if we need to truncate in
+ * an reasonable way, adjust the length of the printf by
+ * changing HDFMT to allow a length max as an arguement printf.
+ * buf (which contains the offset spaces and time field could
+ * also be trimmed
+ *
+ * note only the offset (if any) is processed for tab expansion
+ */
+ if (offst && otln(buf, offst, &ips, &ops, -1))
+ return(1);
+ (void)printf(HDFMT,buf+offst, fname, pagcnt);
+ return(0);
}
/*
- * prtail(): pad page with empty lines (if required) and print page trailer
- * if requested
+ * prtail(): pad page with empty lines (if required) and print page trailer
+ * if requested
*
- * cnt number of lines of padding needed
- * incomp was a '\n' missing from last line output
+ * cnt number of lines of padding needed
+ * incomp was a '\n' missing from last line output
+ *
+ * prtail() can now be invoked unconditionally, with the notion that if
+ * we haven't printed a hearder, these no need for a trailer
*/
int
prtail(cnt, incomp)
- register int cnt;
- int incomp;
+ register int cnt;
+ int incomp;
{
- if (nohead) {
- /*
- * only pad with no headers when incomplete last line
- */
- if (incomp &&
- ((dspace && (putchar('\n') == EOF)) ||
- (putchar('\n') == EOF))) {
- pfail();
- return(1);
- }
- /*
- * but honor the formfeed request
- */
- if (formfeed) {
- if (putchar('\f') == EOF) {
- pfail();
- return(1);
- }
+ /*
+ * if were's skipping to page N or haven't put out anything yet just exit
+ */
+ if (skipping || beheaded == 0)
+ return (0);
+ beheaded = 0;
+
+ /*
+ * if noheaders, only terminate an incomplete last line
+ */
+ if (nohead) {
+
+ if (incomp) {
+ if (dspace)
+ if (putchar('\n') == EOF) {
+ pfail();
+ return(1);
}
- return(0);
+ if (putchar('\n') == EOF) {
+ pfail();
+ return(1);
+ }
}
+ /*
+ * but honor the formfeed request
+ */
+ if (formfeed)
+ if (putchar(OUTFF) == EOF) {
+ pfail();
+ return(1);
+ }
+
+ } else {
/*
* if double space output two \n
+ *
+ * XXX this all seems bogus, why are we doing it here???
+ * page length is in terms of output lines and only the input is
+ * supposed to be double spaced... otln() users should be doing
+ * something like linect+=(dspace ? 2:1).
*/
if (dspace)
- cnt *= 2;
+ cnt *= 2;
/*
* if an odd number of lines per page, add an extra \n
*/
if (addone)
- ++cnt;
+ ++cnt;
/*
- * pad page
+ * either put out a form-feed or pad page with blanks
*/
if (formfeed) {
- if ((incomp && (putchar('\n') == EOF)) ||
- (putchar('\f') == EOF)) {
- pfail();
- return(1);
+ if (incomp)
+ if (putchar('\n') == EOF) {
+ pfail();
+ return(1);
}
- return(0);
- }
- cnt += TAILLEN;
- while (--cnt >= 0) {
+ if (putchar(OUTFF) == EOF) {
+ pfail();
+ return(1);
+ }
+
+ } else {
+
+ if (incomp)
+ cnt++;
+
+ cnt += TAILLEN;
+ while (--cnt >= 0) {
if (putchar('\n') == EOF) {
- pfail();
- return(1);
+ pfail();
+ return(1);
}
+ }
}
- return(0);
+ }
+
+ return(0);
}
/*
- * terminate(): when a SIGINT is recvd
+ * terminate(): when a SIGINT is recvd
*/
void
terminate(which_sig)
- int which_sig;
+ int which_sig;
{
- flsh_errs();
- exit(1);
+ flsh_errs();
+ exit(1);
}
/*
- * flsh_errs(): output saved up diagnostic messages after all normal
- * processing has completed
+ * flsh_errs(): output saved up diagnostic messages after all normal
+ * processing has completed
*/
void
flsh_errs()
{
- char buf[BUFSIZ];
-
- (void)fflush(stdout);
- (void)fflush(err);
- if (err == stderr)
- return;
- rewind(err);
- while (fgets(buf, BUFSIZ, err) != NULL)
- (void)fputs(buf, stderr);
+ char buf[BUFSIZ];
+
+ (void)fflush(stdout);
+ (void)fflush(err);
+ if (err == stderr)
+ return;
+ rewind(err);
+ while (fgets(buf, BUFSIZ, err) != NULL)
+ (void)fputs(buf, stderr);
}
void
mfail()
{
- (void)fputs("pr: memory allocation failed\n", err);
+ (void)fputs("pr: memory allocation failed\n", err);
}
void
pfail()
{
- (void)fprintf(err, "pr: write failure, %s\n", strerror(errno));
+ (void)fprintf(err, "pr: write failure, %s\n", strerror(errno));
}
void
usage()
{
- (void)fputs(
- "usage: pr [+page] [-col] [-adFmrt] [-e[ch][gap]] [-h header]\n",err);
- (void)fputs(
- " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
- (void)fputs(
- " [-s[ch]] [-w width] [-] [file ...]\n", err);
+ (void)fputs(
+ "usage: pr [+page] [-col] [-adfFmrt] [-e[ch][gap]] [-h header]\n",err);
+ (void)fputs(
+ " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
+ (void)fputs(
+ " [-s[ch]] [-w width] [-] [file ...]\n", err);
}
/*
- * setup: Validate command args, initialize and perform sanity
- * checks on options
+ * setup: Validate command args, initialize and perform sanity
+ * checks on options
*/
int
setup(argc, argv)
- register int argc;
- register char **argv;
+ register int argc;
+ register char **argv;
{
- register int c;
- int eflag = 0;
- int iflag = 0;
- int wflag = 0;
- int cflag = 0;
-
- if (isatty(fileno(stdout))) {
- /*
- * defer diagnostics until processing is done
- */
- if ((err = tmpfile()) == NULL) {
- (void)fputs("Cannot defer diagnostic messages\n",stderr);
- return(1);
- }
- } else
- err = stderr;
- while ((c = egetopt(argc, argv, "#adFmrte?h:i?l:n?o:s?w:")) != -1) {
- switch (c) {
- case '+':
- if ((pgnm = atoi(eoptarg)) < 1) {
- (void)fputs("pr: +page number must be 1 or more\n",
- err);
- return(1);
- }
- break;
- case '-':
- if ((clcnt = atoi(eoptarg)) < 1) {
- (void)fputs("pr: -columns must be 1 or more\n",err);
- return(1);
- }
- if (clcnt > 1)
- ++cflag;
- break;
- case 'a':
- ++across;
- break;
- case 'd':
- ++dspace;
- break;
- case 'e':
- ++eflag;
- if ((eoptarg != NULL) && !isdigit(*eoptarg))
- inchar = *eoptarg++;
- else
- inchar = INCHAR;
- if ((eoptarg != NULL) && isdigit(*eoptarg)) {
- if ((ingap = atoi(eoptarg)) < 0) {
- (void)fputs(
- "pr: -e gap must be 0 or more\n", err);
- return(1);
- }
- if (ingap == 0)
- ingap = INGAP;
- } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
- (void)fprintf(err,
- "pr: invalid value for -e %s\n", eoptarg);
- return(1);
- } else
- ingap = INGAP;
- break;
- case 'F':
- ++formfeed;
- break;
- case 'h':
- header = eoptarg;
- break;
- case 'i':
- ++iflag;
- if ((eoptarg != NULL) && !isdigit(*eoptarg))
- ochar = *eoptarg++;
- else
- ochar = OCHAR;
- if ((eoptarg != NULL) && isdigit(*eoptarg)) {
- if ((ogap = atoi(eoptarg)) < 0) {
- (void)fputs(
- "pr: -i gap must be 0 or more\n", err);
- return(1);
- }
- if (ogap == 0)
- ogap = OGAP;
- } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
- (void)fprintf(err,
- "pr: invalid value for -i %s\n", eoptarg);
- return(1);
- } else
- ogap = OGAP;
- break;
- case 'l':
- if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) {
- (void)fputs(
- "pr: Number of lines must be 1 or more\n",err);
- return(1);
- }
- break;
- case 'm':
- ++merge;
- break;
- case 'n':
- if ((eoptarg != NULL) && !isdigit(*eoptarg))
- nmchar = *eoptarg++;
- else
- nmchar = NMCHAR;
- if ((eoptarg != NULL) && isdigit(*eoptarg)) {
- if ((nmwd = atoi(eoptarg)) < 1) {
- (void)fputs(
- "pr: -n width must be 1 or more\n",err);
- return(1);
- }
- } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
- (void)fprintf(err,
- "pr: invalid value for -n %s\n", eoptarg);
- return(1);
- } else
- nmwd = NMWD;
- break;
- case 'o':
- if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){
- (void)fputs("pr: -o offset must be 1 or more\n",
- err);
- return(1);
- }
- break;
- case 'r':
- ++nodiag;
- break;
- case 's':
- ++sflag;
- if (eoptarg == NULL)
- schar = SCHAR;
- else
- schar = *eoptarg++;
- if (*eoptarg != '\0') {
- (void)fprintf(err,
- "pr: invalid value for -s %s\n", eoptarg);
- return(1);
- }
- break;
- case 't':
- ++nohead;
- break;
- case 'w':
- ++wflag;
- if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){
- (void)fputs(
- "pr: -w width must be 1 or more \n",err);
- return(1);
- }
- break;
- case '?':
- default:
- return(1);
- }
- }
+ register int c;
+ int eflag = 0;
+ int iflag = 0;
+ int wflag = 0;
+ int cflag = 0;
+ if (isatty(fileno(stdout))) {
/*
- * default and sanity checks
+ * defer diagnostics until processing is done
*/
- if (!clcnt) {
- if (merge) {
- if ((clcnt = argc - eoptind) <= 1) {
- clcnt = CLCNT;
- merge = 0;
- }
- } else
- clcnt = CLCNT;
+ if ((err = tmpfile()) == NULL) {
+ (void)fputs("Cannot defer diagnostic messages\n",stderr);
+ return(1);
}
- if (across) {
- if (clcnt == 1) {
- (void)fputs("pr: -a flag requires multiple columns\n",
- err);
- return(1);
+ } else
+ err = stderr;
+ while ((c = egetopt(argc, argv, "#adfFmrte?h:i?l:n?o:s?w:")) != EOF) {
+ switch (c) {
+ case '+':
+ if ((pgnm = atoi(eoptarg)) < 1) {
+ (void)fputs("pr: +page number must be 1 or more\n",
+ err);
+ return(1);
+ }
+ ++skipping;
+ break;
+ case '-':
+ if ((clcnt = atoi(eoptarg)) < 1) {
+ (void)fputs("pr: -columns must be 1 or more\n",err);
+ return(1);
+ }
+ if (clcnt > 1)
+ ++cflag;
+ break;
+ case 'a':
+ ++across;
+ break;
+ case 'd':
+ ++dspace;
+ break;
+ case 'e':
+ ++eflag;
+ if ((eoptarg != NULL) && !isdigit(*eoptarg))
+ inchar = *eoptarg++;
+ else
+ inchar = INCHAR;
+ if ((eoptarg != NULL) && isdigit(*eoptarg)) {
+ if ((ingap = atoi(eoptarg)) < 0) {
+ (void)fputs(
+ "pr: -e gap must be 0 or more\n", err);
+ return(1);
}
- if (merge) {
- (void)fputs("pr: -m cannot be used with -a\n", err);
- return(1);
+ if (ingap == 0)
+ ingap = INGAP;
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -e %s\n", eoptarg);
+ return(1);
+ } else
+ ingap = INGAP;
+ break;
+ case 'f':
+ case 'F':
+ ++formfeed;
+ break;
+ case 'h':
+ header = eoptarg;
+ break;
+ case 'i':
+ ++iflag;
+ if ((eoptarg != NULL) && !isdigit(*eoptarg))
+ ochar = *eoptarg++;
+ else
+ ochar = OCHAR;
+ if ((eoptarg != NULL) && isdigit(*eoptarg)) {
+ if ((ogap = atoi(eoptarg)) < 0) {
+ (void)fputs(
+ "pr: -i gap must be 0 or more\n", err);
+ return(1);
+ }
+ if (ogap == 0)
+ ogap = OGAP;
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -i %s\n", eoptarg);
+ return(1);
+ } else
+ ogap = OGAP;
+ break;
+ case 'l':
+ if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) {
+ (void)fputs(
+ "pr: Number of lines must be 1 or more\n",err);
+ return(1);
+ }
+ break;
+ case 'm':
+ ++merge;
+ break;
+ case 'n':
+ if ((eoptarg != NULL) && !isdigit(*eoptarg))
+ nmchar = *eoptarg++;
+ else
+ nmchar = NMCHAR;
+ if ((eoptarg != NULL) && isdigit(*eoptarg)) {
+ if ((nmwd = atoi(eoptarg)) < 1) {
+ (void)fputs(
+ "pr: -n width must be 1 or more\n",err);
+ return(1);
}
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -n %s\n", eoptarg);
+ return(1);
+ } else
+ nmwd = NMWD;
+ break;
+ case 'o':
+ if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){
+ (void)fputs("pr: -o offset must be 1 or more\n",
+ err);
+ return(1);
+ }
+ break;
+ case 'r':
+ ++nodiag;
+ break;
+ case 's':
+ ++sflag;
+ if (eoptarg == NULL)
+ schar = SCHAR;
+ else
+ schar = *eoptarg++;
+ if (*eoptarg != '\0') {
+ (void)fprintf(err,
+ "pr: invalid value for -s %s\n", eoptarg);
+ return(1);
+ }
+ break;
+ case 't':
+ ++nohead;
+ break;
+ case 'w':
+ ++wflag;
+ if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){
+ (void)fputs(
+ "pr: -w width must be 1 or more \n",err);
+ return(1);
+ }
+ break;
+ case '?':
+ default:
+ return(1);
}
- if (!wflag) {
- if (sflag)
- pgwd = SPGWD;
- else
- pgwd = PGWD;
+ }
+
+ /*
+ * default and sanity checks
+ */
+ inform++;
+
+ if (!clcnt) {
+ if (merge) {
+ if ((clcnt = argc - eoptind) <= 1) {
+ clcnt = CLCNT;
+#ifdef stupid
+ merge = 0;
+#endif
+ }
+ } else
+ clcnt = CLCNT;
+ }
+ if (across) {
+ if (clcnt == 1) {
+ (void)fputs("pr: -a flag requires multiple columns\n",
+ err);
+ return(1);
}
- if (cflag || merge) {
- if (!eflag) {
- inchar = INCHAR;
- ingap = INGAP;
- }
- if (!iflag) {
- ochar = OCHAR;
- ogap = OGAP;
- }
+ if (merge) {
+ (void)fputs("pr: -m cannot be used with -a\n", err);
+ return(1);
}
- if (cflag) {
- if (merge) {
- (void)fputs(
- "pr: -m cannot be used with multiple columns\n", err);
- return(1);
- }
- if (nmwd) {
- colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
- pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
- } else {
- colwd = (pgwd + 1 - clcnt)/clcnt;
- pgwd = ((colwd + 1) * clcnt) - 1;
- }
- if (colwd < 1) {
- (void)fprintf(err,
- "pr: page width is too small for %d columns\n",clcnt);
- return(1);
- }
+ }
+ if (!wflag) {
+ if (sflag)
+ pgwd = SPGWD;
+ else
+ pgwd = PGWD;
+ }
+ if (cflag || merge) {
+ if (!eflag) {
+ inchar = INCHAR;
+ ingap = INGAP;
}
- if (!lines)
- lines = LINES;
-
- /*
- * make sure long enough for headers. if not disable
- */
- if (lines <= HEADLEN + TAILLEN)
- ++nohead;
- else if (!nohead)
- lines -= HEADLEN + TAILLEN;
-
- /*
- * adjust for double space on odd length pages
- */
- if (dspace) {
- if (lines == 1)
- dspace = 0;
- else {
- if (lines & 1)
- ++addone;
- lines /= 2;
- }
+ if (!iflag) {
+ ochar = OCHAR;
+ ogap = OGAP;
}
+ }
+ if (cflag) {
+ if (merge) {
+ (void)fputs(
+ "pr: -m cannot be used with multiple columns\n", err);
+ return(1);
+ }
+ if (nmwd) {
+ colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
+ pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
+ } else {
+ colwd = (pgwd + 1 - clcnt)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - 1;
+ }
+ if (colwd < 1) {
+ (void)fprintf(err,
+ "pr: page width is too small for %d columns\n",clcnt);
+ return(1);
+ }
+ }
+ if (!lines)
+ lines = LINES;
+
+ /*
+ * make sure long enough for headers. if not disable
+ */
+ if (lines <= HEADLEN + TAILLEN)
+ ++nohead;
+ else if (!nohead)
+ lines -= HEADLEN + TAILLEN;
+
+ /*
+ * adjust for double space on odd length pages
+ */
+ if (dspace) {
+ if (lines == 1)
+ dspace = 0;
+ else {
+ if (lines & 1)
+ ++addone;
+ lines /= 2;
+ }
+ }
- if ((timefrmt = getenv("LC_TIME")) == NULL)
- timefrmt = TIMEFMT;
- return(0);
+ if ((timefrmt = getenv("LC_TIME")) == NULL)
+ timefrmt = TIMEFMT;
+ return(0);
}