pr.c

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

C
1,805
字号
/* * horzcol:	print files with more than one column of output across a page */inthorzcol(argc, 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);	}	/*	 * 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) {		if (pgnm) {			if (inskip(inf, pgnm, lines))				continue;			pagecnt = pgnm;		} else			pagecnt = 1;		lncnt = 0;		/*		 * loop by page		 */		for(;;) {			/*			 * loop by 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;					}				}				/*				 * 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 page			 */			if (i && prtail(lines-i, 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);}/* * mulfile:	print files with more than one column of output and *		more than one file concurrently */intmulfile(argc, 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);	}	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	 */	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;	/*	 * 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);	}	if (pgnm)		pagecnt = pgnm;	else		pagecnt = 1;	lncnt = 0;	/*	 * continue to loop while any file still has data	 */	while (actf > 0) {		/*		 * 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;			}			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;				}			}			/*			 * 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 no more active files, done			 */			if (actf <= 0) {				++i;				break;			}		}		/*		 * pad to end of page		 */		if (i && prtail(lines-i, 0))			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) */intinln(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);				/*				 * if more than this line, push back				 */				if ((col > lim) && (ungetc(ch, inf) == EOF))					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);	}	/*	 * 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);}/* * 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 */intotln(buf, cnt, svips, svops, 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;	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) {				/*				 * 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 (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);				}				ops = tbps;			}			while (ops < ips) {				/*				 * finish off with spaces				 */				if (putchar(' ') == EOF) {					pfail();					return(1);				}				++ops;			}			return(0);		}	} else {		/*		 * output is not contracted		 */		if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {			pfail();			return(1);		}		if (mor != 0)			return(0);	}	/*	 * process line end and double space as required	 */	if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {		pfail();		return(1);

⌨️ 快捷键说明

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