|
|
1.1 root 1: static char sccsid[] = "@(#)cut.c 1.2";
2: #
3: /* cut : cut and paste columns of a table (projection of a relation) (GWRL) */
4: /* Release 1.5; handles single backspaces as produced by nroff */
5: # include <stdio.h> /* make: cc cut.c */
6: #include <errno.h>
7: # define NFIELDS 512 /* max no of fields or resulting line length */
8: # define BACKSPACE 8
9: main(argc, argv)
10: int argc;
11: char **argv;
12: {
13: int del = '\t';
14: int i, j, count, poscnt, r, s, t;
15: int endflag, supflag, cflag, fflag, backflag, filenr;
16: int sel[NFIELDS];
17: register int c;
18: register char *p1;
19: char *p2, outbuf[NFIELDS];
20: FILE *inptr;
21: endflag = supflag = cflag = fflag = 0;
22:
23:
24: for (i=0; i<NFIELDS; i++)
25: sel[i] = 0;
26: while (argc > 1 && argv[1][0] == '-'){
27: for (i = 1; (c = argv[1][i]) != '\0'; i++) {
28: switch(c) {
29: case 'd' :
30: del = argv[1][++i];
31: if (del == '\0') diag("no delimiter\n");
32: break;
33: case 's':
34: supflag++ ;
35: break;
36: case 'c':
37: cflag++ ;
38: break;
39: case 'f':
40: fflag++ ;
41: break;
42: default :
43: diag("Usage: cut [-s] [-d<char>] {-c<list> | -f<list>} file ...\n");
44: break;
45: }
46: if (!endflag && (cflag || fflag)) {
47: endflag = 1;
48: r = s = t = 0;
49: do {
50: c = argv[1][++i];
51: switch(c) {
52: case '-' :
53: if (r) diagl();
54: r = 1;
55: if (t == 0) s = 1;
56: else {
57: s = t;
58: t = 0;
59: }
60: continue;
61: case '\0' :
62: case ',' :
63: if (t >= NFIELDS) diagl();
64: if (r) {
65: if (t == 0) t = NFIELDS - 1;
66: if (t<s) diagl();
67: for(j = s; j <= t; j++) sel[j] = 1;
68: }
69: else sel[t] = (t > 0 ? 1 : 0);
70: r = s = t = 0;
71: if (c == '\0') {
72: i--;
73: break;
74: }
75: continue;
76: default :
77: if (c< '0' || c> '9') diagl();
78: t = 10*t + c - '0';
79: continue;
80: }
81: for (j = t = 0; j < NFIELDS; j++) t += sel[j];
82: if (t == 0) diag("no fields\n");
83: } while (c != '\0');
84: }
85: }
86: --argc;
87: ++argv;
88: } /* end options */
89: if (!(cflag || fflag)) diagl();
90:
91: --argc;
92: filenr = 1;
93: do { /* for all input files */
94: if (argc > 0) inptr = fopen(argv[filenr], "r");
95: else inptr = stdin;
96:
97: if (inptr == NULL)
98: diag(argv[filenr]);
99: endflag = 0;
100: do { /* for all lines of a file */
101: count = poscnt = backflag = 0;
102: p1 = &outbuf[0] - 1 ;
103: p2 = p1;
104: do { /* for all char of the line */
105: c = fgetc(inptr);
106: if (c == EOF) {
107: endflag = 1;
108: break;
109: }
110: if (count == NFIELDS - 1) diag("line too long\n");
111: if (c != '\n') *++p1 = c;
112: if (cflag && (c == BACKSPACE)) backflag++ ;
113: else
114: {
115: if ( !backflag ) poscnt += 1 ;
116: else backflag-- ;
117: }
118: if ( backflag > 1 ) diag("cannot handle multiple adjacent backspaces\n");
119: if ( ((c == '\n') && count > 0) || c == del || cflag) {
120: count += 1;
121: if (fflag) poscnt = count ;
122: if (sel[poscnt]) p2 = p1;
123: else p1 = p2;
124: }
125: }while (c != '\n');
126: if ( !endflag && (count > 0 || !supflag)) {
127: if (*p1 == del) *p1 = '\0';
128: else *++p1 = '\0'; /*suppress trailing delimiter*/
129: puts(outbuf);
130: }
131: } while (!endflag) ;
132: fclose(inptr);
133: } while(++filenr <= argc);
134: }
135:
136: diag(s)
137: char *s;
138: {
139: write(2, "cut: ", 5);
140: if(errno)
141: perror(s);
142: else
143: write(2,s,strlen(s));
144: exit(2);
145: }
146: diagl()
147: {
148: diag("bad list for c/f option\n");
149: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.