|
|
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.