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 + -
显示快捷键?