Annotation of 43BSDReno/usr.bin/cut/cut.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.