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

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