pr.c

来自「早期freebsd实现」· C语言 代码 · 共 1,805 行 · 第 1/3 页

C
1,805
字号
/*- * Copyright (c) 1991 Keith Muller. * Copyright (c) 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)pr.c	8.2 (Berkeley) 4/16/94";#endif /* not lint */#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <ctype.h>#include <errno.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "pr.h"#include "extern.h"/* * pr:	a printing and pagination filter. If multiple input files *	are specified, each is read, formatted, and written to standard *	output. By default, input is seperated into 66-line pages, each *	with a header that includes the page number, date, time and the *	files pathname. * *	Complies with posix P1003.2/D11 *//* * 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 *//* * misc globals */FILE	*err;			/* error message file pointer */int	addone;			/* page length is odd with double space */int	errcnt;			/* error count on file processing */char	digs[] = "0123456789";	/* page number translation map */intmain(argc, argv)        int argc;        char *argv[];{	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);}/* * onecol:	print files with only one column of output. *		Line length is unlimited. */intonecol(argc, 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);	}	/*	 * loop by file	 */	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;		/*		 * loop by page		 */		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;				}				/*				 * whole line rcvd. reset tab proc. state				 */				++linecnt;				lrgln = 0;				ops = 0;				ips = 0;			}			/*			 * fill to end of page			 */			if (linecnt && prtail(lines-linecnt-lrgln, lrgln))				return(1);			/*			 * On EOF go to next file			 */			if (cnt < 0)				break;			++pagecnt;		}		if (inf != stdin)			(void)fclose(inf);	}	if (eoptind < argc)		return(1);	return(0);}/* * vertcol:	print files with more than one column of output down a page */intvertcol(argc, 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;	/*	 * 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) {		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 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;			}			/*			 * 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 ......			 */			--cvc;			/*			 * check to see if last page needs to be reordered			 */			if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){				pln = cvc/clcnt;				if (cvc % clcnt)					++pln;				/*				 * print header				 */				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);				}				/*				 * pad to end of page				 */				if (prtail((lines - pln), 0))					return(1);				/*				 * done with output, go to next file				 */				break;			}			/*			 * determine how many lines to output			 */			if (i > 0)				pln = lines;			else				pln = j;			/*			 * print header			 */			if (pln && !nohead && prhead(hbuf, fname, pagecnt))				return(1);			/*			 * output each line			 */			for (i = 0; i < pln; ++i) {				ptbf = buf + lindy[i];				if ((j = lstdat[i] - ptbf) <= offst)					break;				if (otln(ptbf, j, &ips, &ops, 0))					return(1);			}			/*			 * pad to end of page			 */			if (pln && prtail((lines - pln), 0))				return(1);			/*			 * if EOF go to next file			 */			if (cnt < 0)				break;			++pagecnt;		}		if (inf != stdin)			(void)fclose(inf);	}	if (eoptind < argc)		return(1);	return(0);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?