|
|
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: static char sccsid[] = "@(#)cut.c 5.3 (Berkeley) 6/24/90"; ! 28: #endif /* not lint */ ! 29: ! 30: #include <stdio.h> ! 31: #include <ctype.h> ! 32: #if COHERENT ! 33: #include <string.h> ! 34: #define _BSD_LINE_MAX BUFSIZ /* compatibility */ ! 35: #else ! 36: #include <limits.h> ! 37: #endif ! 38: ! 39: int cflag; ! 40: char dchar; ! 41: int dflag; ! 42: int fflag; ! 43: int sflag; ! 44: long strtol(); ! 45: ! 46: main(argc, argv) ! 47: int argc; ! 48: char **argv; ! 49: { ! 50: extern char *optarg; ! 51: extern int errno, optind; ! 52: FILE *fp; ! 53: int ch, (*fcn)(), c_cut(), f_cut(); ! 54: char *strerror(); ! 55: ! 56: dchar = '\t'; /* default delimiter is \t */ ! 57: ! 58: while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF) ! 59: switch(ch) { ! 60: case 'c': ! 61: fcn = c_cut; ! 62: get_list(optarg); ! 63: cflag = 1; ! 64: break; ! 65: case 'd': ! 66: dchar = *optarg; ! 67: dflag = 1; ! 68: break; ! 69: case 'f': ! 70: get_list(optarg); ! 71: fcn = f_cut; ! 72: fflag = 1; ! 73: break; ! 74: case 's': ! 75: sflag = 1; ! 76: break; ! 77: case '?': ! 78: default: ! 79: usage(); ! 80: } ! 81: argc -= optind; ! 82: argv += optind; ! 83: ! 84: if (fflag) { ! 85: if (cflag) ! 86: usage(); ! 87: } else if (!cflag || dflag || sflag) ! 88: usage(); ! 89: ! 90: if (*argv) ! 91: for (; *argv; ++argv) { ! 92: if (!(fp = fopen(*argv, "r"))) { ! 93: (void)fprintf(stderr, ! 94: "cut: %s: %s\n", *argv, strerror(errno)); ! 95: exit(1); ! 96: } ! 97: (*fcn)(fp, *argv); ! 98: } ! 99: else ! 100: (*fcn)(stdin, "stdin"); ! 101: exit(0); ! 102: } ! 103: ! 104: int autostart, autostop, maxval; ! 105: ! 106: char positions[_BSD_LINE_MAX + 1]; ! 107: ! 108: get_list(list) ! 109: char *list; ! 110: { ! 111: register char *pos; ! 112: register int setautostart, start, stop; ! 113: char *p, *strtok(); ! 114: ! 115: /* ! 116: * set a byte in the positions array to indicate if a field or ! 117: * column is to be selected; use +1, it's 1-based, not 0-based. ! 118: * This parser is less restrictive than the Draft 9 POSIX spec. ! 119: * POSIX doesn't allow lists that aren't in increasing order or ! 120: * overlapping lists. We also handle "-3-5" although there's no ! 121: * real reason too. ! 122: */ ! 123: for (; p = strtok(list, ", \t"); list = NULL) { ! 124: setautostart = start = stop = 0; ! 125: if (*p == '-') { ! 126: ++p; ! 127: setautostart = 1; ! 128: } ! 129: if (isdigit(*p)) { ! 130: start = stop = strtol(p, &p, 10); ! 131: if (setautostart && start > autostart) ! 132: autostart = start; ! 133: } ! 134: if (*p == '-') { ! 135: if (isdigit(p[1])) ! 136: stop = strtol(p + 1, &p, 10); ! 137: if (*p == '-') { ! 138: ++p; ! 139: if (!autostop || autostop > stop) ! 140: autostop = stop; ! 141: } ! 142: } ! 143: if (*p) ! 144: badlist("illegal list value"); ! 145: if (!stop || !start) ! 146: badlist("values may not include zero"); ! 147: if (stop > _BSD_LINE_MAX) { ! 148: /* positions used rather than allocate a new buffer */ ! 149: (void)sprintf(positions, "%d too large (max %d)", ! 150: stop, _BSD_LINE_MAX); ! 151: badlist(positions); ! 152: } ! 153: if (maxval < stop) ! 154: maxval = stop; ! 155: for (pos = positions + start; start++ <= stop; *pos++ = 1); ! 156: } ! 157: ! 158: /* overlapping ranges */ ! 159: if (autostop && maxval > autostop) ! 160: maxval = autostop; ! 161: ! 162: /* set autostart */ ! 163: if (autostart) ! 164: memset(positions + 1, '1', autostart); ! 165: } ! 166: ! 167: /* ARGSUSED */ ! 168: c_cut(fp, fname) ! 169: FILE *fp; ! 170: char *fname; ! 171: { ! 172: register int ch, col; ! 173: register char *pos; ! 174: ! 175: for (;;) { ! 176: pos = positions + 1; ! 177: for (col = maxval; col; --col) { ! 178: if ((ch = getc(fp)) == EOF) ! 179: return; ! 180: if (ch == '\n') ! 181: break; ! 182: if (*pos++) ! 183: putchar(ch); ! 184: } ! 185: if (ch != '\n') ! 186: if (autostop) ! 187: while ((ch = getc(fp)) != EOF && ch != '\n') ! 188: putchar(ch); ! 189: else ! 190: while ((ch = getc(fp)) != EOF && ch != '\n'); ! 191: putchar('\n'); ! 192: } ! 193: } ! 194: ! 195: f_cut(fp, fname) ! 196: FILE *fp; ! 197: char *fname; ! 198: { ! 199: register int ch, field, isdelim; ! 200: register char *pos, *p, sep; ! 201: int output; ! 202: char lbuf[_BSD_LINE_MAX + 1]; ! 203: ! 204: for (sep = dchar, output = 0; fgets(lbuf, sizeof(lbuf), fp);) { ! 205: for (isdelim = 0, p = lbuf;; ++p) { ! 206: if (!(ch = *p)) { ! 207: (void)fprintf(stderr, ! 208: "cut: %s: line too long.\n", fname); ! 209: exit(1); ! 210: } ! 211: /* this should work if newline is delimiter */ ! 212: if (ch == sep) ! 213: isdelim = 1; ! 214: if (ch == '\n') { ! 215: if (!isdelim && !sflag) ! 216: (void)printf("%s", lbuf); ! 217: break; ! 218: } ! 219: } ! 220: if (!isdelim) ! 221: continue; ! 222: ! 223: pos = positions + 1; ! 224: for (field = maxval, p = lbuf; field; --field, ++pos) { ! 225: if (*pos) { ! 226: if (output++) ! 227: putchar(sep); ! 228: while ((ch = *p++) != '\n' && ch != sep) ! 229: putchar(ch); ! 230: } else ! 231: while ((ch = *p++) != '\n' && ch != sep); ! 232: if (ch == '\n') ! 233: break; ! 234: } ! 235: if (ch != '\n') ! 236: if (autostop) { ! 237: if (output) ! 238: putchar(sep); ! 239: for (; (ch = *p) != '\n'; ++p) ! 240: putchar(ch); ! 241: } else ! 242: for (; (ch = *p) != '\n'; ++p); ! 243: putchar('\n'); ! 244: } ! 245: } ! 246: ! 247: badlist(msg) ! 248: char *msg; ! 249: { ! 250: (void)fprintf(stderr, "cut: [-cf] list: %s.\n", msg); ! 251: exit(1); ! 252: } ! 253: ! 254: usage() ! 255: { ! 256: (void)fprintf(stderr, ! 257: "usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n"); ! 258: exit(1); ! 259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.