home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sys / next / misc / 22969 < prev    next >
Encoding:
Text File  |  1992-12-12  |  6.9 KB  |  282 lines

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