[BACK]Return to cut.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cut

Annotation of src/usr.bin/cut/cut.c, Revision 1.6

1.6     ! aaron       1: /*     $OpenBSD: cut.c,v 1.5 1997/11/05 00:18:44 deraadt Exp $ */
1.1       deraadt     2: /*     $NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1989, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the University of
                     22:  *     California, Berkeley and its contributors.
                     23:  * 4. Neither the name of the University nor the names of its contributors
                     24:  *    may be used to endorse or promote products derived from this software
                     25:  *    without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     28:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     30:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     31:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     32:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     33:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     34:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     35:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     36:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     37:  * SUCH DAMAGE.
                     38:  */
                     39:
                     40: #ifndef lint
                     41: static char copyright[] =
                     42: "@(#) Copyright (c) 1989, 1993\n\
                     43:        The Regents of the University of California.  All rights reserved.\n";
                     44: #endif /* not lint */
                     45:
                     46: #ifndef lint
                     47: #if 0
                     48: static char sccsid[] = "@(#)cut.c      8.3 (Berkeley) 5/4/95";
                     49: #endif
1.6     ! aaron      50: static char rcsid[] = "$OpenBSD: cut.c,v 1.5 1997/11/05 00:18:44 deraadt Exp $";
1.1       deraadt    51: #endif /* not lint */
                     52:
                     53: #include <ctype.h>
                     54: #include <err.h>
                     55: #include <errno.h>
                     56: #include <limits.h>
                     57: #include <locale.h>
                     58: #include <stdio.h>
                     59: #include <stdlib.h>
                     60: #include <string.h>
                     61: #include <unistd.h>
                     62:
                     63: int    cflag;
                     64: char   dchar;
                     65: int    dflag;
                     66: int    fflag;
                     67: int    sflag;
                     68:
                     69: void   c_cut __P((FILE *, char *));
                     70: void   f_cut __P((FILE *, char *));
                     71: void   get_list __P((char *));
                     72: void   usage __P((void));
                     73:
                     74: int
                     75: main(argc, argv)
                     76:        int argc;
                     77:        char *argv[];
                     78: {
                     79:        FILE *fp;
                     80:        void (*fcn) __P((FILE *, char *));
                     81:        int ch;
                     82:
                     83:        setlocale (LC_ALL, "");
                     84:
                     85:        dchar = '\t';                   /* default delimiter is \t */
                     86:
                     87:        /* Since we don't support multi-byte characters, the -c and -b
                     88:           options are equivalent, and the -n option is meaningless. */
1.3       millert    89:        while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1)
1.1       deraadt    90:                switch(ch) {
                     91:                case 'b':
                     92:                case 'c':
                     93:                        fcn = c_cut;
                     94:                        get_list(optarg);
                     95:                        cflag = 1;
                     96:                        break;
                     97:                case 'd':
                     98:                        dchar = *optarg;
                     99:                        dflag = 1;
                    100:                        break;
                    101:                case 'f':
                    102:                        get_list(optarg);
                    103:                        fcn = f_cut;
                    104:                        fflag = 1;
                    105:                        break;
                    106:                case 's':
                    107:                        sflag = 1;
                    108:                        break;
                    109:                case 'n':
                    110:                        break;
                    111:                case '?':
                    112:                default:
                    113:                        usage();
                    114:                }
                    115:        argc -= optind;
                    116:        argv += optind;
                    117:
                    118:        if (fflag) {
                    119:                if (cflag)
                    120:                        usage();
                    121:        } else if (!cflag || dflag || sflag)
                    122:                usage();
                    123:
                    124:        if (*argv)
                    125:                for (; *argv; ++argv) {
                    126:                        if (!(fp = fopen(*argv, "r")))
                    127:                                err(1, "%s", *argv);
                    128:                        fcn(fp, *argv);
                    129:                        (void)fclose(fp);
                    130:                }
                    131:        else
                    132:                fcn(stdin, "stdin");
                    133:        exit(0);
                    134: }
                    135:
                    136: int autostart, autostop, maxval;
                    137:
                    138: char positions[_POSIX2_LINE_MAX + 1];
                    139:
                    140: void
                    141: get_list(list)
                    142:        char *list;
                    143: {
                    144:        register int setautostart, start, stop;
                    145:        register char *pos;
                    146:        char *p;
                    147:
                    148:        /*
                    149:         * set a byte in the positions array to indicate if a field or
                    150:         * column is to be selected; use +1, it's 1-based, not 0-based.
                    151:         * This parser is less restrictive than the Draft 9 POSIX spec.
                    152:         * POSIX doesn't allow lists that aren't in increasing order or
                    153:         * overlapping lists.  We also handle "-3-5" although there's no
                    154:         * real reason too.
                    155:         */
1.6     ! aaron     156:        for (; p = strsep(&list, ", \t");) {
1.1       deraadt   157:                setautostart = start = stop = 0;
                    158:                if (*p == '-') {
                    159:                        ++p;
                    160:                        setautostart = 1;
                    161:                }
                    162:                if (isdigit(*p)) {
                    163:                        start = stop = strtol(p, &p, 10);
                    164:                        if (setautostart && start > autostart)
                    165:                                autostart = start;
                    166:                }
                    167:                if (*p == '-') {
                    168:                        if (isdigit(p[1]))
                    169:                                stop = strtol(p + 1, &p, 10);
                    170:                        if (*p == '-') {
                    171:                                ++p;
                    172:                                if (!autostop || autostop > stop)
                    173:                                        autostop = stop;
                    174:                        }
                    175:                }
                    176:                if (*p)
1.4       millert   177:                        errx(1, "[-cf] list: illegal list value");
1.1       deraadt   178:                if (!stop || !start)
1.4       millert   179:                        errx(1, "[-cf] list: values may not include zero");
1.1       deraadt   180:                if (stop > _POSIX2_LINE_MAX)
1.4       millert   181:                        errx(1, "[-cf] list: %d too large (max %d)",
1.1       deraadt   182:                            stop, _POSIX2_LINE_MAX);
                    183:                if (maxval < stop)
                    184:                        maxval = stop;
                    185:                for (pos = positions + start; start++ <= stop; *pos++ = 1);
                    186:        }
                    187:
                    188:        /* overlapping ranges */
                    189:        if (autostop && maxval > autostop)
                    190:                maxval = autostop;
                    191:
                    192:        /* set autostart */
                    193:        if (autostart)
                    194:                memset(positions + 1, '1', autostart);
                    195: }
                    196:
                    197: /* ARGSUSED */
                    198: void
                    199: c_cut(fp, fname)
                    200:        FILE *fp;
                    201:        char *fname;
                    202: {
                    203:        register int ch, col;
                    204:        register char *pos;
                    205:
                    206:        for (;;) {
                    207:                pos = positions + 1;
                    208:                for (col = maxval; col; --col) {
                    209:                        if ((ch = getc(fp)) == EOF)
                    210:                                return;
                    211:                        if (ch == '\n')
                    212:                                break;
                    213:                        if (*pos++)
                    214:                                (void)putchar(ch);
                    215:                }
                    216:                if (ch != '\n')
                    217:                        if (autostop)
                    218:                                while ((ch = getc(fp)) != EOF && ch != '\n')
                    219:                                        (void)putchar(ch);
                    220:                        else
                    221:                                while ((ch = getc(fp)) != EOF && ch != '\n');
                    222:                (void)putchar('\n');
                    223:        }
                    224: }
                    225:
                    226: void
                    227: f_cut(fp, fname)
                    228:        FILE *fp;
                    229:        char *fname;
                    230: {
                    231:        register int ch, field, isdelim;
                    232:        register char *pos, *p, sep;
                    233:        int output;
                    234:        char lbuf[_POSIX2_LINE_MAX + 1];
                    235:
                    236:        for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) {
                    237:                output = 0;
                    238:                for (isdelim = 0, p = lbuf;; ++p) {
                    239:                        if (!(ch = *p))
1.4       millert   240:                                errx(1, "%s: line too long.", fname);
1.1       deraadt   241:                        /* this should work if newline is delimiter */
                    242:                        if (ch == sep)
                    243:                                isdelim = 1;
                    244:                        if (ch == '\n') {
                    245:                                if (!isdelim && !sflag)
                    246:                                        (void)printf("%s", lbuf);
                    247:                                break;
                    248:                        }
                    249:                }
                    250:                if (!isdelim)
                    251:                        continue;
                    252:
                    253:                pos = positions + 1;
                    254:                for (field = maxval, p = lbuf; field; --field, ++pos) {
                    255:                        if (*pos) {
                    256:                                if (output++)
                    257:                                        (void)putchar(sep);
                    258:                                while ((ch = *p++) != '\n' && ch != sep)
                    259:                                        (void)putchar(ch);
                    260:                        } else
                    261:                                while ((ch = *p++) != '\n' && ch != sep);
                    262:                        if (ch == '\n')
                    263:                                break;
                    264:                }
                    265:                if (ch != '\n')
                    266:                        if (autostop) {
                    267:                                if (output)
                    268:                                        (void)putchar(sep);
                    269:                                for (; (ch = *p) != '\n'; ++p)
                    270:                                        (void)putchar(ch);
                    271:                        } else
                    272:                                for (; (ch = *p) != '\n'; ++p);
                    273:                (void)putchar('\n');
                    274:        }
                    275: }
                    276:
                    277: void
                    278: usage()
                    279: {
                    280:        (void)fprintf(stderr,
1.5       deraadt   281:                "usage:\tcut -c list [file1 ...]\n"
                    282:                "\tcut -f list [-s] [-d delim] [file ...]\n"
                    283:                "\tcut -b list [-n] [file ...]\n");
1.1       deraadt   284:        exit(1);
                    285: }