|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
7: *
8: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)cut.c 5.3 (Berkeley) 6/24/90";
31: #endif /* not lint */
32:
33: #include <limits.h>
34: #include <stdio.h>
35: #include <ctype.h>
36:
37: int cflag;
38: char dchar;
39: int dflag;
40: int fflag;
41: int sflag;
42:
43: main(argc, argv)
44: int argc;
45: char **argv;
46: {
47: extern char *optarg;
48: extern int errno, optind;
49: FILE *fp;
50: int ch, (*fcn)(), c_cut(), f_cut();
51: char *strerror();
52:
53: dchar = '\t'; /* default delimiter is \t */
54:
55: while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF)
56: switch(ch) {
57: case 'c':
58: fcn = c_cut;
59: get_list(optarg);
60: cflag = 1;
61: break;
62: case 'd':
63: dchar = *optarg;
64: dflag = 1;
65: break;
66: case 'f':
67: get_list(optarg);
68: fcn = f_cut;
69: fflag = 1;
70: break;
71: case 's':
72: sflag = 1;
73: break;
74: case '?':
75: default:
76: usage();
77: }
78: argc -= optind;
79: argv += optind;
80:
81: if (fflag) {
82: if (cflag)
83: usage();
84: } else if (!cflag || dflag || sflag)
85: usage();
86:
87: if (*argv)
88: for (; *argv; ++argv) {
89: if (!(fp = fopen(*argv, "r"))) {
90: (void)fprintf(stderr,
91: "cut: %s: %s\n", *argv, strerror(errno));
92: exit(1);
93: }
94: fcn(fp, *argv);
95: }
96: else
97: fcn(stdin, "stdin");
98: exit(0);
99: }
100:
101: int autostart, autostop, maxval;
102:
103: char positions[_BSD_LINE_MAX + 1];
104:
105: get_list(list)
106: char *list;
107: {
108: register char *pos;
109: register int setautostart, start, stop;
110: char *p, *strtok();
111:
112: /*
113: * set a byte in the positions array to indicate if a field or
114: * column is to be selected; use +1, it's 1-based, not 0-based.
115: * This parser is less restrictive than the Draft 9 POSIX spec.
116: * POSIX doesn't allow lists that aren't in increasing order or
117: * overlapping lists. We also handle "-3-5" although there's no
118: * real reason too.
119: */
120: for (; p = strtok(list, ", \t"); list = NULL) {
121: setautostart = start = stop = 0;
122: if (*p == '-') {
123: ++p;
124: setautostart = 1;
125: }
126: if (isdigit(*p)) {
127: start = stop = strtol(p, &p, 10);
128: if (setautostart && start > autostart)
129: autostart = start;
130: }
131: if (*p == '-') {
132: if (isdigit(p[1]))
133: stop = strtol(p + 1, &p, 10);
134: if (*p == '-') {
135: ++p;
136: if (!autostop || autostop > stop)
137: autostop = stop;
138: }
139: }
140: if (*p)
141: badlist("illegal list value");
142: if (!stop || !start)
143: badlist("values may not include zero");
144: if (stop > _BSD_LINE_MAX) {
145: /* positions used rather than allocate a new buffer */
146: (void)sprintf(positions, "%d too large (max %d)",
147: stop, _BSD_LINE_MAX);
148: badlist(positions);
149: }
150: if (maxval < stop)
151: maxval = stop;
152: for (pos = positions + start; start++ <= stop; *pos++ = 1);
153: }
154:
155: /* overlapping ranges */
156: if (autostop && maxval > autostop)
157: maxval = autostop;
158:
159: /* set autostart */
160: if (autostart)
161: memset(positions + 1, '1', autostart);
162: }
163:
164: /* ARGSUSED */
165: c_cut(fp, fname)
166: FILE *fp;
167: char *fname;
168: {
169: register int ch, col;
170: register char *pos;
171:
172: for (;;) {
173: pos = positions + 1;
174: for (col = maxval; col; --col) {
175: if ((ch = getc(fp)) == EOF)
176: return;
177: if (ch == '\n')
178: break;
179: if (*pos++)
180: putchar(ch);
181: }
182: if (ch != '\n')
183: if (autostop)
184: while ((ch = getc(fp)) != EOF && ch != '\n')
185: putchar(ch);
186: else
187: while ((ch = getc(fp)) != EOF && ch != '\n');
188: putchar('\n');
189: }
190: }
191:
192: f_cut(fp, fname)
193: FILE *fp;
194: char *fname;
195: {
196: register int ch, field, isdelim;
197: register char *pos, *p, sep;
198: int output;
199: char lbuf[_BSD_LINE_MAX + 1];
200:
201: for (sep = dchar, output = 0; fgets(lbuf, sizeof(lbuf), fp);) {
202: for (isdelim = 0, p = lbuf;; ++p) {
203: if (!(ch = *p)) {
204: (void)fprintf(stderr,
205: "cut: %s: line too long.\n", fname);
206: exit(1);
207: }
208: /* this should work if newline is delimiter */
209: if (ch == sep)
210: isdelim = 1;
211: if (ch == '\n') {
212: if (!isdelim && !sflag)
213: (void)printf("%s", lbuf);
214: break;
215: }
216: }
217: if (!isdelim)
218: continue;
219:
220: pos = positions + 1;
221: for (field = maxval, p = lbuf; field; --field, ++pos) {
222: if (*pos) {
223: if (output++)
224: putchar(sep);
225: while ((ch = *p++) != '\n' && ch != sep)
226: putchar(ch);
227: } else
228: while ((ch = *p++) != '\n' && ch != sep);
229: if (ch == '\n')
230: break;
231: }
232: if (ch != '\n')
233: if (autostop) {
234: if (output)
235: putchar(sep);
236: for (; (ch = *p) != '\n'; ++p)
237: putchar(ch);
238: } else
239: for (; (ch = *p) != '\n'; ++p);
240: putchar('\n');
241: }
242: }
243:
244: badlist(msg)
245: char *msg;
246: {
247: (void)fprintf(stderr, "cut: [-cf] list: %s.\n", msg);
248: exit(1);
249: }
250:
251: usage()
252: {
253: (void)fprintf(stderr,
254: "usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n");
255: exit(1);
256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.