docs/cut

changeset 14:21ad1c1548c4

Code ausgewaehlter Implementierungen eingefuegt Das Datum entspricht dem Dateiaenderungsdatum.
author markus schnalke <meillo@marmaro.de>
date Tue, 12 May 2015 06:46:59 +0200
parents bf5e41260f89
children 77d1f55bba08
files code/cut.c__4.3bsd-reno.1990-06-25 code/cut.c__4.3bsd-uwisc.1986-11-07 code/cut.c__freebsd.1994-05-27 code/cut.c__freebsd.2012-11-24 code/cut.c__gnu.1992-11-08 code/cut.c__gnu.2015-05-01 code/cut.c__heirloom.2012-05-20 code/cut.c__netbsd.1993-03-21 code/cut.c__netbsd.2014-02-03 code/cut.c__openbsd.2008-06-27 code/cut.c__system_iii.1980-04-11
diffstat 11 files changed, 3966 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/code/cut.c__4.3bsd-reno.1990-06-25	Tue May 12 06:46:59 2015 +0200
     1.3 @@ -0,0 +1,256 @@
     1.4 +/*
     1.5 + * Copyright (c) 1989 The Regents of the University of California.
     1.6 + * All rights reserved.
     1.7 + *
     1.8 + * This code is derived from software contributed to Berkeley by
     1.9 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
    1.10 + *
    1.11 + * Redistribution and use in source and binary forms are permitted provided
    1.12 + * that: (1) source distributions retain this entire copyright notice and
    1.13 + * comment, and (2) distributions including binaries display the following
    1.14 + * acknowledgement:  ``This product includes software developed by the
    1.15 + * University of California, Berkeley and its contributors'' in the
    1.16 + * documentation or other materials provided with the distribution and in
    1.17 + * all advertising materials mentioning features or use of this software.
    1.18 + * Neither the name of the University nor the names of its contributors may
    1.19 + * be used to endorse or promote products derived from this software without
    1.20 + * specific prior written permission.
    1.21 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
    1.22 + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    1.23 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    1.24 + */
    1.25 +
    1.26 +#ifndef lint
    1.27 +char copyright[] =
    1.28 +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
    1.29 + All rights reserved.\n";
    1.30 +#endif /* not lint */
    1.31 +
    1.32 +#ifndef lint
    1.33 +static char sccsid[] = "@(#)cut.c	5.3 (Berkeley) 6/24/90";
    1.34 +#endif /* not lint */
    1.35 +
    1.36 +#include <limits.h>
    1.37 +#include <stdio.h>
    1.38 +#include <ctype.h>
    1.39 +
    1.40 +int	cflag;
    1.41 +char	dchar;
    1.42 +int	dflag;
    1.43 +int	fflag;
    1.44 +int	sflag;
    1.45 +
    1.46 +main(argc, argv)
    1.47 +	int argc;
    1.48 +	char **argv;
    1.49 +{
    1.50 +	extern char *optarg;
    1.51 +	extern int errno, optind;
    1.52 +	FILE *fp;
    1.53 +	int ch, (*fcn)(), c_cut(), f_cut();
    1.54 +	char *strerror();
    1.55 +
    1.56 +	dchar = '\t';			/* default delimiter is \t */
    1.57 +
    1.58 +	while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF)
    1.59 +		switch(ch) {
    1.60 +		case 'c':
    1.61 +			fcn = c_cut;
    1.62 +			get_list(optarg);
    1.63 +			cflag = 1;
    1.64 +			break;
    1.65 +		case 'd':
    1.66 +			dchar = *optarg;
    1.67 +			dflag = 1;
    1.68 +			break;
    1.69 +		case 'f':
    1.70 +			get_list(optarg);
    1.71 +			fcn = f_cut;
    1.72 +			fflag = 1;
    1.73 +			break;
    1.74 +		case 's':
    1.75 +			sflag = 1;
    1.76 +			break;
    1.77 +		case '?':
    1.78 +		default:
    1.79 +			usage();
    1.80 +		}
    1.81 +	argc -= optind;
    1.82 +	argv += optind;
    1.83 +
    1.84 +	if (fflag) {
    1.85 +		if (cflag)
    1.86 +			usage();
    1.87 +	} else if (!cflag || dflag || sflag)
    1.88 +		usage();
    1.89 +
    1.90 +	if (*argv)
    1.91 +		for (; *argv; ++argv) {
    1.92 +			if (!(fp = fopen(*argv, "r"))) {
    1.93 +				(void)fprintf(stderr,
    1.94 +				    "cut: %s: %s\n", *argv, strerror(errno));
    1.95 +				exit(1);
    1.96 +			}
    1.97 +			fcn(fp, *argv);
    1.98 +		}
    1.99 +	else
   1.100 +		fcn(stdin, "stdin");
   1.101 +	exit(0);
   1.102 +}
   1.103 +
   1.104 +int autostart, autostop, maxval;
   1.105 +
   1.106 +char positions[_BSD_LINE_MAX + 1];
   1.107 +
   1.108 +get_list(list)
   1.109 +	char *list;
   1.110 +{
   1.111 +	register char *pos;
   1.112 +	register int setautostart, start, stop;
   1.113 +	char *p, *strtok();
   1.114 +
   1.115 +	/*
   1.116 +	 * set a byte in the positions array to indicate if a field or
   1.117 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
   1.118 +	 * This parser is less restrictive than the Draft 9 POSIX spec.
   1.119 +	 * POSIX doesn't allow lists that aren't in increasing order or
   1.120 +	 * overlapping lists.  We also handle "-3-5" although there's no
   1.121 +	 * real reason too.
   1.122 +	 */
   1.123 +	for (; p = strtok(list, ", \t"); list = NULL) {
   1.124 +		setautostart = start = stop = 0;
   1.125 +		if (*p == '-') {
   1.126 +			++p;
   1.127 +			setautostart = 1;
   1.128 +		}
   1.129 +		if (isdigit(*p)) {
   1.130 +			start = stop = strtol(p, &p, 10);
   1.131 +			if (setautostart && start > autostart)
   1.132 +				autostart = start;
   1.133 +		}
   1.134 +		if (*p == '-') {
   1.135 +			if (isdigit(p[1]))
   1.136 +				stop = strtol(p + 1, &p, 10);
   1.137 +			if (*p == '-') {
   1.138 +				++p;
   1.139 +				if (!autostop || autostop > stop)
   1.140 +					autostop = stop;
   1.141 +			}
   1.142 +		}
   1.143 +		if (*p)
   1.144 +			badlist("illegal list value");
   1.145 +		if (!stop || !start)
   1.146 +			badlist("values may not include zero");
   1.147 +		if (stop > _BSD_LINE_MAX) {
   1.148 +			/* positions used rather than allocate a new buffer */
   1.149 +			(void)sprintf(positions, "%d too large (max %d)",
   1.150 +			    stop, _BSD_LINE_MAX);
   1.151 +			badlist(positions);
   1.152 +		}
   1.153 +		if (maxval < stop)
   1.154 +			maxval = stop;
   1.155 +		for (pos = positions + start; start++ <= stop; *pos++ = 1);
   1.156 +	}
   1.157 +
   1.158 +	/* overlapping ranges */
   1.159 +	if (autostop && maxval > autostop)
   1.160 +		maxval = autostop;
   1.161 +
   1.162 +	/* set autostart */
   1.163 +	if (autostart)
   1.164 +		memset(positions + 1, '1', autostart);
   1.165 +}
   1.166 +
   1.167 +/* ARGSUSED */
   1.168 +c_cut(fp, fname)
   1.169 +	FILE *fp;
   1.170 +	char *fname;
   1.171 +{
   1.172 +	register int ch, col;
   1.173 +	register char *pos;
   1.174 +
   1.175 +	for (;;) {
   1.176 +		pos = positions + 1;
   1.177 +		for (col = maxval; col; --col) {
   1.178 +			if ((ch = getc(fp)) == EOF)
   1.179 +				return;
   1.180 +			if (ch == '\n')
   1.181 +				break;
   1.182 +			if (*pos++)
   1.183 +				putchar(ch);
   1.184 +		}
   1.185 +		if (ch != '\n')
   1.186 +			if (autostop)
   1.187 +				while ((ch = getc(fp)) != EOF && ch != '\n')
   1.188 +					putchar(ch);
   1.189 +			else
   1.190 +				while ((ch = getc(fp)) != EOF && ch != '\n');
   1.191 +		putchar('\n');
   1.192 +	}
   1.193 +}
   1.194 +
   1.195 +f_cut(fp, fname)
   1.196 +	FILE *fp;
   1.197 +	char *fname;
   1.198 +{
   1.199 +	register int ch, field, isdelim;
   1.200 +	register char *pos, *p, sep;
   1.201 +	int output;
   1.202 +	char lbuf[_BSD_LINE_MAX + 1];
   1.203 +
   1.204 +	for (sep = dchar, output = 0; fgets(lbuf, sizeof(lbuf), fp);) {
   1.205 +		for (isdelim = 0, p = lbuf;; ++p) {
   1.206 +			if (!(ch = *p)) {
   1.207 +				(void)fprintf(stderr,
   1.208 +				    "cut: %s: line too long.\n", fname);
   1.209 +				exit(1);
   1.210 +			}
   1.211 +			/* this should work if newline is delimiter */
   1.212 +			if (ch == sep)
   1.213 +				isdelim = 1;
   1.214 +			if (ch == '\n') {
   1.215 +				if (!isdelim && !sflag)
   1.216 +					(void)printf("%s", lbuf);
   1.217 +				break;
   1.218 +			}
   1.219 +		}
   1.220 +		if (!isdelim)
   1.221 +			continue;
   1.222 +
   1.223 +		pos = positions + 1;
   1.224 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
   1.225 +			if (*pos) {
   1.226 +				if (output++)
   1.227 +					putchar(sep);
   1.228 +				while ((ch = *p++) != '\n' && ch != sep)
   1.229 +					putchar(ch);
   1.230 +			} else
   1.231 +				while ((ch = *p++) != '\n' && ch != sep);
   1.232 +			if (ch == '\n')
   1.233 +				break;
   1.234 +		}
   1.235 +		if (ch != '\n')
   1.236 +			if (autostop) {
   1.237 +				if (output)
   1.238 +					putchar(sep);
   1.239 +				for (; (ch = *p) != '\n'; ++p)
   1.240 +					putchar(ch);
   1.241 +			} else
   1.242 +				for (; (ch = *p) != '\n'; ++p);
   1.243 +		putchar('\n');
   1.244 +	}
   1.245 +}
   1.246 +
   1.247 +badlist(msg)
   1.248 +	char *msg;
   1.249 +{
   1.250 +	(void)fprintf(stderr, "cut: [-cf] list: %s.\n", msg);
   1.251 +	exit(1);
   1.252 +}
   1.253 +
   1.254 +usage()
   1.255 +{
   1.256 +	(void)fprintf(stderr,
   1.257 +"usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n");
   1.258 +	exit(1);
   1.259 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/code/cut.c__4.3bsd-uwisc.1986-11-07	Tue May 12 06:46:59 2015 +0200
     2.3 @@ -0,0 +1,125 @@
     2.4 +static char sccsid[] = "@(#)cut.c	1.3";
     2.5 +#
     2.6 +/* cut : cut and paste columns of a table (projection of a relation) */
     2.7 +/* Release 1.5; handles single backspaces as produced by nroff    */
     2.8 +# include <stdio.h>	/* make: cc cut.c */
     2.9 +# define NFIELDS 512	/* max no of fields or resulting line length */
    2.10 +# define BACKSPACE 8
    2.11 +main(argc, argv)
    2.12 +int argc; char **argv;
    2.13 +{
    2.14 +	int del = '\t';
    2.15 +	int i, j, count, poscnt, r, s, t;
    2.16 +	int endflag, supflag, cflag, fflag, backflag, filenr;
    2.17 +	int sel[NFIELDS];
    2.18 +	register int c;
    2.19 +	register char *p1;
    2.20 +	char *p2, outbuf[NFIELDS];
    2.21 +	FILE *inptr;
    2.22 +	endflag = supflag = cflag = fflag = 0;
    2.23 + 
    2.24 + 
    2.25 +while (argc > 1 && argv[1][0] == '-'){
    2.26 +	for (i = 1; (c = argv[1][i]) != '\0'; i++) {
    2.27 +		switch(c) {
    2.28 +			case 'd' : del = argv[1][++i];
    2.29 +				if (del == '\0') diag("no delimiter\n");
    2.30 +				break;
    2.31 +			case 's': supflag++ ;
    2.32 +				break;
    2.33 +			case 'c': cflag++ ;
    2.34 +				break;
    2.35 +			case 'f': fflag++ ;
    2.36 +				break;
    2.37 +			default : diag("Usage: cut [-s] [-d<char>] {-c<list> | -f<list>} file ...\n");
    2.38 +				break;
    2.39 +		}
    2.40 +		if (!endflag && (cflag || fflag)) {
    2.41 +			endflag = 1;
    2.42 +			r = s = t = 0;
    2.43 +			do {	c = argv[1][++i];
    2.44 +				switch(c) {
    2.45 +					case '-' : if (r) diagl();
    2.46 +						r = 1;
    2.47 +						if (t == 0)  s = 1;
    2.48 +						else {s = t; t = 0;}
    2.49 +						continue;
    2.50 +					case '\0' :
    2.51 +					case ','  : if (t >= NFIELDS) diagl();
    2.52 +						if (r) { if (t == 0) t = NFIELDS - 1;
    2.53 +							if (t<s) diagl();
    2.54 +							for(j = s; j <= t; j++) sel[j] = 1;
    2.55 +							}
    2.56 +						else sel[t] = (t > 0 ? 1 : 0);
    2.57 +						r = s = t = 0;
    2.58 +						if (c == '\0') {i--; break;}
    2.59 +						continue;
    2.60 +					default :
    2.61 +						if (c< '0' || c> '9') diagl();
    2.62 +						t = 10*t + c - '0';
    2.63 +						continue;
    2.64 +				}
    2.65 +				for (j = t = 0; j < NFIELDS; j++) t += sel[j];
    2.66 +				if (t == 0) diag("no fields\n");
    2.67 +			} while (c != '\0');
    2.68 +		}
    2.69 +	}
    2.70 +	--argc;
    2.71 +	++argv;
    2.72 +} /* end options */
    2.73 +if (!(cflag || fflag)) diagl();
    2.74 +
    2.75 +--argc;
    2.76 +filenr = 1;
    2.77 +do {	/* for all input files */
    2.78 +	if (argc > 0) inptr = fopen(argv[filenr], "r");
    2.79 +	else inptr = stdin;
    2.80 +  
    2.81 +	if (inptr == NULL) {
    2.82 +		write(2,"Cannot open :",14);
    2.83 +		diag(argv[filenr]);
    2.84 +	}
    2.85 +	endflag = 0;
    2.86 +	do {	/* for all lines of a file */
    2.87 +		count = poscnt = backflag = 0;
    2.88 +		p1 = &outbuf[0] - 1 ;
    2.89 +		p2 = p1;
    2.90 +		do { 	/* for all char of the line */
    2.91 +			c = fgetc(inptr);
    2.92 +			if (c == EOF) {
    2.93 +				endflag = 1;
    2.94 +				break;
    2.95 +				}
    2.96 +			if (count == NFIELDS - 1) diag("line too long\n");
    2.97 +			if (c != '\n') *++p1 = c;
    2.98 +			if (cflag && (c == BACKSPACE)) backflag++ ; else 
    2.99 +				{ if ( !backflag ) poscnt += 1 ; else backflag-- ;}
   2.100 +			if ( backflag > 1 ) diag("cannot handle multiple adjacent backspaces\n");
   2.101 +			if ( ((c == '\n') && count > 0)  || c == del || cflag) {
   2.102 +				count += 1;
   2.103 +				if (fflag) poscnt = count  ;
   2.104 +				if (sel[poscnt]) p2 = p1; else p1 = p2;
   2.105 +			}
   2.106 +		}while (c != '\n');
   2.107 +		if ( !endflag && (count > 0 || !supflag)) {
   2.108 +			if (*p1 == del) *p1 = '\0';
   2.109 +				else *++p1 = '\0'; /*suppress trailing delimiter*/
   2.110 +			puts(outbuf);
   2.111 +			}
   2.112 +	} while (!endflag) ;
   2.113 +fclose(inptr);
   2.114 +} while(++filenr <= argc);
   2.115 +}
   2.116 +
   2.117 +diag(s)
   2.118 +char *s;
   2.119 +{
   2.120 +	write(2, "cut : ", 6);
   2.121 +	while(*s)
   2.122 +		write(2,s++,1);
   2.123 +	exit(2);
   2.124 +}
   2.125 +diagl()
   2.126 +{
   2.127 +diag("bad list for c/f option\n");
   2.128 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/code/cut.c__freebsd.1994-05-27	Tue May 12 06:46:59 2015 +0200
     3.3 @@ -0,0 +1,296 @@
     3.4 +/*
     3.5 + * Copyright (c) 1989, 1993
     3.6 + *	The Regents of the University of California.  All rights reserved.
     3.7 + *
     3.8 + * This code is derived from software contributed to Berkeley by
     3.9 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
    3.10 + *
    3.11 + * Redistribution and use in source and binary forms, with or without
    3.12 + * modification, are permitted provided that the following conditions
    3.13 + * are met:
    3.14 + * 1. Redistributions of source code must retain the above copyright
    3.15 + *    notice, this list of conditions and the following disclaimer.
    3.16 + * 2. Redistributions in binary form must reproduce the above copyright
    3.17 + *    notice, this list of conditions and the following disclaimer in the
    3.18 + *    documentation and/or other materials provided with the distribution.
    3.19 + * 3. All advertising materials mentioning features or use of this software
    3.20 + *    must display the following acknowledgement:
    3.21 + *	This product includes software developed by the University of
    3.22 + *	California, Berkeley and its contributors.
    3.23 + * 4. Neither the name of the University nor the names of its contributors
    3.24 + *    may be used to endorse or promote products derived from this software
    3.25 + *    without specific prior written permission.
    3.26 + *
    3.27 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    3.28 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.30 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    3.31 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    3.32 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    3.33 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    3.34 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    3.35 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    3.36 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    3.37 + * SUCH DAMAGE.
    3.38 + */
    3.39 +
    3.40 +#ifndef lint
    3.41 +static char copyright[] =
    3.42 +"@(#) Copyright (c) 1989, 1993\n\
    3.43 +	The Regents of the University of California.  All rights reserved.\n";
    3.44 +#endif /* not lint */
    3.45 +
    3.46 +#ifndef lint
    3.47 +static char sccsid[] = "@(#)cut.c	8.1 (Berkeley) 6/6/93";
    3.48 +#endif /* not lint */
    3.49 +
    3.50 +#include <ctype.h>
    3.51 +#include <errno.h>
    3.52 +#include <limits.h>
    3.53 +#include <stdio.h>
    3.54 +#include <stdlib.h>
    3.55 +#include <string.h>
    3.56 +
    3.57 +int	cflag;
    3.58 +char	dchar;
    3.59 +int	dflag;
    3.60 +int	fflag;
    3.61 +int	sflag;
    3.62 +
    3.63 +void	c_cut __P((FILE *, char *));
    3.64 +void	err __P((const char *, ...));
    3.65 +void	f_cut __P((FILE *, char *));
    3.66 +void	get_list __P((char *));
    3.67 +void	usage __P((void));
    3.68 +
    3.69 +int
    3.70 +main(argc, argv)
    3.71 +	int argc;
    3.72 +	char *argv[];
    3.73 +{
    3.74 +	FILE *fp;
    3.75 +	void (*fcn) __P((FILE *, char *));
    3.76 +	int ch;
    3.77 +
    3.78 +	dchar = '\t';			/* default delimiter is \t */
    3.79 +
    3.80 +	while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF)
    3.81 +		switch(ch) {
    3.82 +		case 'c':
    3.83 +			fcn = c_cut;
    3.84 +			get_list(optarg);
    3.85 +			cflag = 1;
    3.86 +			break;
    3.87 +		case 'd':
    3.88 +			dchar = *optarg;
    3.89 +			dflag = 1;
    3.90 +			break;
    3.91 +		case 'f':
    3.92 +			get_list(optarg);
    3.93 +			fcn = f_cut;
    3.94 +			fflag = 1;
    3.95 +			break;
    3.96 +		case 's':
    3.97 +			sflag = 1;
    3.98 +			break;
    3.99 +		case '?':
   3.100 +		default:
   3.101 +			usage();
   3.102 +		}
   3.103 +	argc -= optind;
   3.104 +	argv += optind;
   3.105 +
   3.106 +	if (fflag) {
   3.107 +		if (cflag)
   3.108 +			usage();
   3.109 +	} else if (!cflag || dflag || sflag)
   3.110 +		usage();
   3.111 +
   3.112 +	if (*argv)
   3.113 +		for (; *argv; ++argv) {
   3.114 +			if (!(fp = fopen(*argv, "r")))
   3.115 +				err("%s: %s\n", *argv, strerror(errno));
   3.116 +			fcn(fp, *argv);
   3.117 +			(void)fclose(fp);
   3.118 +		}
   3.119 +	else
   3.120 +		fcn(stdin, "stdin");
   3.121 +	exit(0);
   3.122 +}
   3.123 +
   3.124 +int autostart, autostop, maxval;
   3.125 +
   3.126 +char positions[_POSIX2_LINE_MAX + 1];
   3.127 +
   3.128 +void
   3.129 +get_list(list)
   3.130 +	char *list;
   3.131 +{
   3.132 +	register int setautostart, start, stop;
   3.133 +	register char *pos;
   3.134 +	char *p;
   3.135 +
   3.136 +	/*
   3.137 +	 * set a byte in the positions array to indicate if a field or
   3.138 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
   3.139 +	 * This parser is less restrictive than the Draft 9 POSIX spec.
   3.140 +	 * POSIX doesn't allow lists that aren't in increasing order or
   3.141 +	 * overlapping lists.  We also handle "-3-5" although there's no
   3.142 +	 * real reason too.
   3.143 +	 */
   3.144 +	for (; p = strtok(list, ", \t"); list = NULL) {
   3.145 +		setautostart = start = stop = 0;
   3.146 +		if (*p == '-') {
   3.147 +			++p;
   3.148 +			setautostart = 1;
   3.149 +		}
   3.150 +		if (isdigit(*p)) {
   3.151 +			start = stop = strtol(p, &p, 10);
   3.152 +			if (setautostart && start > autostart)
   3.153 +				autostart = start;
   3.154 +		}
   3.155 +		if (*p == '-') {
   3.156 +			if (isdigit(p[1]))
   3.157 +				stop = strtol(p + 1, &p, 10);
   3.158 +			if (*p == '-') {
   3.159 +				++p;
   3.160 +				if (!autostop || autostop > stop)
   3.161 +					autostop = stop;
   3.162 +			}
   3.163 +		}
   3.164 +		if (*p)
   3.165 +			err("[-cf] list: illegal list value\n");
   3.166 +		if (!stop || !start)
   3.167 +			err("[-cf] list: values may not include zero\n");
   3.168 +		if (stop > _POSIX2_LINE_MAX)
   3.169 +			err("[-cf] list: %d too large (max %d)\n",
   3.170 +			    stop, _POSIX2_LINE_MAX);
   3.171 +		if (maxval < stop)
   3.172 +			maxval = stop;
   3.173 +		for (pos = positions + start; start++ <= stop; *pos++ = 1);
   3.174 +	}
   3.175 +
   3.176 +	/* overlapping ranges */
   3.177 +	if (autostop && maxval > autostop)
   3.178 +		maxval = autostop;
   3.179 +
   3.180 +	/* set autostart */
   3.181 +	if (autostart)
   3.182 +		memset(positions + 1, '1', autostart);
   3.183 +}
   3.184 +
   3.185 +/* ARGSUSED */
   3.186 +void
   3.187 +c_cut(fp, fname)
   3.188 +	FILE *fp;
   3.189 +	char *fname;
   3.190 +{
   3.191 +	register int ch, col;
   3.192 +	register char *pos;
   3.193 +
   3.194 +	for (;;) {
   3.195 +		pos = positions + 1;
   3.196 +		for (col = maxval; col; --col) {
   3.197 +			if ((ch = getc(fp)) == EOF)
   3.198 +				return;
   3.199 +			if (ch == '\n')
   3.200 +				break;
   3.201 +			if (*pos++)
   3.202 +				(void)putchar(ch);
   3.203 +		}
   3.204 +		if (ch != '\n')
   3.205 +			if (autostop)
   3.206 +				while ((ch = getc(fp)) != EOF && ch != '\n')
   3.207 +					(void)putchar(ch);
   3.208 +			else
   3.209 +				while ((ch = getc(fp)) != EOF && ch != '\n');
   3.210 +		(void)putchar('\n');
   3.211 +	}
   3.212 +}
   3.213 +
   3.214 +void
   3.215 +f_cut(fp, fname)
   3.216 +	FILE *fp;
   3.217 +	char *fname;
   3.218 +{
   3.219 +	register int ch, field, isdelim;
   3.220 +	register char *pos, *p, sep;
   3.221 +	int output;
   3.222 +	char lbuf[_POSIX2_LINE_MAX + 1];
   3.223 +
   3.224 +	for (sep = dchar, output = 0; fgets(lbuf, sizeof(lbuf), fp);) {
   3.225 +		for (isdelim = 0, p = lbuf;; ++p) {
   3.226 +			if (!(ch = *p))
   3.227 +				err("%s: line too long.\n", fname);
   3.228 +			/* this should work if newline is delimiter */
   3.229 +			if (ch == sep)
   3.230 +				isdelim = 1;
   3.231 +			if (ch == '\n') {
   3.232 +				if (!isdelim && !sflag)
   3.233 +					(void)printf("%s", lbuf);
   3.234 +				break;
   3.235 +			}
   3.236 +		}
   3.237 +		if (!isdelim)
   3.238 +			continue;
   3.239 +
   3.240 +		pos = positions + 1;
   3.241 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
   3.242 +			if (*pos) {
   3.243 +				if (output++)
   3.244 +					(void)putchar(sep);
   3.245 +				while ((ch = *p++) != '\n' && ch != sep)
   3.246 +					(void)putchar(ch);
   3.247 +			} else
   3.248 +				while ((ch = *p++) != '\n' && ch != sep);
   3.249 +			if (ch == '\n')
   3.250 +				break;
   3.251 +		}
   3.252 +		if (ch != '\n')
   3.253 +			if (autostop) {
   3.254 +				if (output)
   3.255 +					(void)putchar(sep);
   3.256 +				for (; (ch = *p) != '\n'; ++p)
   3.257 +					(void)putchar(ch);
   3.258 +			} else
   3.259 +				for (; (ch = *p) != '\n'; ++p);
   3.260 +		(void)putchar('\n');
   3.261 +	}
   3.262 +}
   3.263 +
   3.264 +void
   3.265 +usage()
   3.266 +{
   3.267 +	(void)fprintf(stderr,
   3.268 +"usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n");
   3.269 +	exit(1);
   3.270 +}
   3.271 +
   3.272 +#if __STDC__
   3.273 +#include <stdarg.h>
   3.274 +#else
   3.275 +#include <varargs.h>
   3.276 +#endif
   3.277 +
   3.278 +void
   3.279 +#if __STDC__
   3.280 +err(const char *fmt, ...)
   3.281 +#else
   3.282 +err(fmt, va_alist)
   3.283 +	char *fmt;
   3.284 +        va_dcl
   3.285 +#endif
   3.286 +{
   3.287 +	va_list ap;
   3.288 +#if __STDC__
   3.289 +	va_start(ap, fmt);
   3.290 +#else
   3.291 +	va_start(ap);
   3.292 +#endif
   3.293 +	(void)fprintf(stderr, "cut: ");
   3.294 +	(void)vfprintf(stderr, fmt, ap);
   3.295 +	va_end(ap);
   3.296 +	(void)fprintf(stderr, "\n");
   3.297 +	exit(1);
   3.298 +	/* NOTREACHED */
   3.299 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/code/cut.c__freebsd.2012-11-24	Tue May 12 06:46:59 2015 +0200
     4.3 @@ -0,0 +1,479 @@
     4.4 +/*
     4.5 + * Copyright (c) 1989, 1993
     4.6 + *	The Regents of the University of California.  All rights reserved.
     4.7 + *
     4.8 + * This code is derived from software contributed to Berkeley by
     4.9 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
    4.10 + *
    4.11 + * Redistribution and use in source and binary forms, with or without
    4.12 + * modification, are permitted provided that the following conditions
    4.13 + * are met:
    4.14 + * 1. Redistributions of source code must retain the above copyright
    4.15 + *    notice, this list of conditions and the following disclaimer.
    4.16 + * 2. Redistributions in binary form must reproduce the above copyright
    4.17 + *    notice, this list of conditions and the following disclaimer in the
    4.18 + *    documentation and/or other materials provided with the distribution.
    4.19 + * 4. Neither the name of the University nor the names of its contributors
    4.20 + *    may be used to endorse or promote products derived from this software
    4.21 + *    without specific prior written permission.
    4.22 + *
    4.23 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    4.24 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    4.25 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    4.26 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    4.27 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    4.28 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    4.29 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    4.30 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    4.31 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    4.32 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    4.33 + * SUCH DAMAGE.
    4.34 + */
    4.35 +
    4.36 +#ifndef lint
    4.37 +static const char copyright[] =
    4.38 +"@(#) Copyright (c) 1989, 1993\n\
    4.39 +	The Regents of the University of California.  All rights reserved.\n";
    4.40 +static const char sccsid[] = "@(#)cut.c	8.3 (Berkeley) 5/4/95";
    4.41 +#endif /* not lint */
    4.42 +#include <sys/cdefs.h>
    4.43 +__FBSDID("$FreeBSD$");
    4.44 +
    4.45 +#include <ctype.h>
    4.46 +#include <err.h>
    4.47 +#include <errno.h>
    4.48 +#include <limits.h>
    4.49 +#include <locale.h>
    4.50 +#include <stdio.h>
    4.51 +#include <stdlib.h>
    4.52 +#include <string.h>
    4.53 +#include <unistd.h>
    4.54 +#include <wchar.h>
    4.55 +
    4.56 +static int	bflag;
    4.57 +static int	cflag;
    4.58 +static wchar_t	dchar;
    4.59 +static char	dcharmb[MB_LEN_MAX + 1];
    4.60 +static int	dflag;
    4.61 +static int	fflag;
    4.62 +static int	nflag;
    4.63 +static int	sflag;
    4.64 +static int	wflag;
    4.65 +
    4.66 +static size_t	autostart, autostop, maxval;
    4.67 +static char *	positions;
    4.68 +
    4.69 +static int	b_cut(FILE *, const char *);
    4.70 +static int	b_n_cut(FILE *, const char *);
    4.71 +static int	c_cut(FILE *, const char *);
    4.72 +static int	f_cut(FILE *, const char *);
    4.73 +static void	get_list(char *);
    4.74 +static int	is_delim(wchar_t);
    4.75 +static void	needpos(size_t);
    4.76 +static void	usage(void);
    4.77 +
    4.78 +int
    4.79 +main(int argc, char *argv[])
    4.80 +{
    4.81 +	FILE *fp;
    4.82 +	int (*fcn)(FILE *, const char *);
    4.83 +	int ch, rval;
    4.84 +	size_t n;
    4.85 +
    4.86 +	setlocale(LC_ALL, "");
    4.87 +
    4.88 +	fcn = NULL;
    4.89 +	dchar = '\t';			/* default delimiter is \t */
    4.90 +	strcpy(dcharmb, "\t");
    4.91 +
    4.92 +	while ((ch = getopt(argc, argv, "b:c:d:f:snw")) != -1)
    4.93 +		switch(ch) {
    4.94 +		case 'b':
    4.95 +			get_list(optarg);
    4.96 +			bflag = 1;
    4.97 +			break;
    4.98 +		case 'c':
    4.99 +			get_list(optarg);
   4.100 +			cflag = 1;
   4.101 +			break;
   4.102 +		case 'd':
   4.103 +			n = mbrtowc(&dchar, optarg, MB_LEN_MAX, NULL);
   4.104 +			if (dchar == '\0' || n != strlen(optarg))
   4.105 +				errx(1, "bad delimiter");
   4.106 +			strcpy(dcharmb, optarg);
   4.107 +			dflag = 1;
   4.108 +			break;
   4.109 +		case 'f':
   4.110 +			get_list(optarg);
   4.111 +			fflag = 1;
   4.112 +			break;
   4.113 +		case 's':
   4.114 +			sflag = 1;
   4.115 +			break;
   4.116 +		case 'n':
   4.117 +			nflag = 1;
   4.118 +			break;
   4.119 +		case 'w':
   4.120 +			wflag = 1;
   4.121 +			break;
   4.122 +		case '?':
   4.123 +		default:
   4.124 +			usage();
   4.125 +		}
   4.126 +	argc -= optind;
   4.127 +	argv += optind;
   4.128 +
   4.129 +	if (fflag) {
   4.130 +		if (bflag || cflag || nflag || (wflag && dflag))
   4.131 +			usage();
   4.132 +	} else if (!(bflag || cflag) || dflag || sflag || wflag)
   4.133 +		usage();
   4.134 +	else if (!bflag && nflag)
   4.135 +		usage();
   4.136 +
   4.137 +	if (fflag)
   4.138 +		fcn = f_cut;
   4.139 +	else if (cflag)
   4.140 +		fcn = MB_CUR_MAX > 1 ? c_cut : b_cut;
   4.141 +	else if (bflag)
   4.142 +		fcn = nflag && MB_CUR_MAX > 1 ? b_n_cut : b_cut;
   4.143 +
   4.144 +	rval = 0;
   4.145 +	if (*argv)
   4.146 +		for (; *argv; ++argv) {
   4.147 +			if (strcmp(*argv, "-") == 0)
   4.148 +				rval |= fcn(stdin, "stdin");
   4.149 +			else {
   4.150 +				if (!(fp = fopen(*argv, "r"))) {
   4.151 +					warn("%s", *argv);
   4.152 +					rval = 1;
   4.153 +					continue;
   4.154 +				}
   4.155 +				fcn(fp, *argv);
   4.156 +				(void)fclose(fp);
   4.157 +			}
   4.158 +		}
   4.159 +	else
   4.160 +		rval = fcn(stdin, "stdin");
   4.161 +	exit(rval);
   4.162 +}
   4.163 +
   4.164 +static void
   4.165 +get_list(char *list)
   4.166 +{
   4.167 +	size_t setautostart, start, stop;
   4.168 +	char *pos;
   4.169 +	char *p;
   4.170 +
   4.171 +	/*
   4.172 +	 * set a byte in the positions array to indicate if a field or
   4.173 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
   4.174 +	 * Numbers and number ranges may be overlapping, repeated, and in
   4.175 +	 * any order. We handle "-3-5" although there's no real reason to.
   4.176 +	 */
   4.177 +	for (; (p = strsep(&list, ", \t")) != NULL;) {
   4.178 +		setautostart = start = stop = 0;
   4.179 +		if (*p == '-') {
   4.180 +			++p;
   4.181 +			setautostart = 1;
   4.182 +		}
   4.183 +		if (isdigit((unsigned char)*p)) {
   4.184 +			start = stop = strtol(p, &p, 10);
   4.185 +			if (setautostart && start > autostart)
   4.186 +				autostart = start;
   4.187 +		}
   4.188 +		if (*p == '-') {
   4.189 +			if (isdigit((unsigned char)p[1]))
   4.190 +				stop = strtol(p + 1, &p, 10);
   4.191 +			if (*p == '-') {
   4.192 +				++p;
   4.193 +				if (!autostop || autostop > stop)
   4.194 +					autostop = stop;
   4.195 +			}
   4.196 +		}
   4.197 +		if (*p)
   4.198 +			errx(1, "[-bcf] list: illegal list value");
   4.199 +		if (!stop || !start)
   4.200 +			errx(1, "[-bcf] list: values may not include zero");
   4.201 +		if (maxval < stop) {
   4.202 +			maxval = stop;
   4.203 +			needpos(maxval + 1);
   4.204 +		}
   4.205 +		for (pos = positions + start; start++ <= stop; *pos++ = 1);
   4.206 +	}
   4.207 +
   4.208 +	/* overlapping ranges */
   4.209 +	if (autostop && maxval > autostop) {
   4.210 +		maxval = autostop;
   4.211 +		needpos(maxval + 1);
   4.212 +	}
   4.213 +
   4.214 +	/* set autostart */
   4.215 +	if (autostart)
   4.216 +		memset(positions + 1, '1', autostart);
   4.217 +}
   4.218 +
   4.219 +static void
   4.220 +needpos(size_t n)
   4.221 +{
   4.222 +	static size_t npos;
   4.223 +	size_t oldnpos;
   4.224 +
   4.225 +	/* Grow the positions array to at least the specified size. */
   4.226 +	if (n > npos) {
   4.227 +		oldnpos = npos;
   4.228 +		if (npos == 0)
   4.229 +			npos = n;
   4.230 +		while (n > npos)
   4.231 +			npos *= 2;
   4.232 +		if ((positions = realloc(positions, npos)) == NULL)
   4.233 +			err(1, "realloc");
   4.234 +		memset((char *)positions + oldnpos, 0, npos - oldnpos);
   4.235 +	}
   4.236 +}
   4.237 +
   4.238 +static int
   4.239 +b_cut(FILE *fp, const char *fname __unused)
   4.240 +{
   4.241 +	int ch, col;
   4.242 +	char *pos;
   4.243 +
   4.244 +	ch = 0;
   4.245 +	for (;;) {
   4.246 +		pos = positions + 1;
   4.247 +		for (col = maxval; col; --col) {
   4.248 +			if ((ch = getc(fp)) == EOF)
   4.249 +				return (0);
   4.250 +			if (ch == '\n')
   4.251 +				break;
   4.252 +			if (*pos++)
   4.253 +				(void)putchar(ch);
   4.254 +		}
   4.255 +		if (ch != '\n') {
   4.256 +			if (autostop)
   4.257 +				while ((ch = getc(fp)) != EOF && ch != '\n')
   4.258 +					(void)putchar(ch);
   4.259 +			else
   4.260 +				while ((ch = getc(fp)) != EOF && ch != '\n');
   4.261 +		}
   4.262 +		(void)putchar('\n');
   4.263 +	}
   4.264 +	return (0);
   4.265 +}
   4.266 +
   4.267 +/*
   4.268 + * Cut based on byte positions, taking care not to split multibyte characters.
   4.269 + * Although this function also handles the case where -n is not specified,
   4.270 + * b_cut() ought to be much faster.
   4.271 + */
   4.272 +static int
   4.273 +b_n_cut(FILE *fp, const char *fname)
   4.274 +{
   4.275 +	size_t col, i, lbuflen;
   4.276 +	char *lbuf;
   4.277 +	int canwrite, clen, warned;
   4.278 +	mbstate_t mbs;
   4.279 +
   4.280 +	memset(&mbs, 0, sizeof(mbs));
   4.281 +	warned = 0;
   4.282 +	while ((lbuf = fgetln(fp, &lbuflen)) != NULL) {
   4.283 +		for (col = 0; lbuflen > 0; col += clen) {
   4.284 +			if ((clen = mbrlen(lbuf, lbuflen, &mbs)) < 0) {
   4.285 +				if (!warned) {
   4.286 +					warn("%s", fname);
   4.287 +					warned = 1;
   4.288 +				}
   4.289 +				memset(&mbs, 0, sizeof(mbs));
   4.290 +				clen = 1;
   4.291 +			}
   4.292 +			if (clen == 0 || *lbuf == '\n')
   4.293 +				break;
   4.294 +			if (col < maxval && !positions[1 + col]) {
   4.295 +				/*
   4.296 +				 * Print the character if (1) after an initial
   4.297 +				 * segment of un-selected bytes, the rest of
   4.298 +				 * it is selected, and (2) the last byte is
   4.299 +				 * selected.
   4.300 +				 */
   4.301 +				i = col;
   4.302 +				while (i < col + clen && i < maxval &&
   4.303 +				    !positions[1 + i])
   4.304 +					i++;
   4.305 +				canwrite = i < col + clen;
   4.306 +				for (; i < col + clen && i < maxval; i++)
   4.307 +					canwrite &= positions[1 + i];
   4.308 +				if (canwrite)
   4.309 +					fwrite(lbuf, 1, clen, stdout);
   4.310 +			} else {
   4.311 +				/*
   4.312 +				 * Print the character if all of it has
   4.313 +				 * been selected.
   4.314 +				 */
   4.315 +				canwrite = 1;
   4.316 +				for (i = col; i < col + clen; i++)
   4.317 +					if ((i >= maxval && !autostop) ||
   4.318 +					    (i < maxval && !positions[1 + i])) {
   4.319 +						canwrite = 0;
   4.320 +						break;
   4.321 +					}
   4.322 +				if (canwrite)
   4.323 +					fwrite(lbuf, 1, clen, stdout);
   4.324 +			}
   4.325 +			lbuf += clen;
   4.326 +			lbuflen -= clen;
   4.327 +		}
   4.328 +		if (lbuflen > 0)
   4.329 +			putchar('\n');
   4.330 +	}
   4.331 +	return (warned);
   4.332 +}
   4.333 +
   4.334 +static int
   4.335 +c_cut(FILE *fp, const char *fname)
   4.336 +{
   4.337 +	wint_t ch;
   4.338 +	int col;
   4.339 +	char *pos;
   4.340 +
   4.341 +	ch = 0;
   4.342 +	for (;;) {
   4.343 +		pos = positions + 1;
   4.344 +		for (col = maxval; col; --col) {
   4.345 +			if ((ch = getwc(fp)) == WEOF)
   4.346 +				goto out;
   4.347 +			if (ch == '\n')
   4.348 +				break;
   4.349 +			if (*pos++)
   4.350 +				(void)putwchar(ch);
   4.351 +		}
   4.352 +		if (ch != '\n') {
   4.353 +			if (autostop)
   4.354 +				while ((ch = getwc(fp)) != WEOF && ch != '\n')
   4.355 +					(void)putwchar(ch);
   4.356 +			else
   4.357 +				while ((ch = getwc(fp)) != WEOF && ch != '\n');
   4.358 +		}
   4.359 +		(void)putwchar('\n');
   4.360 +	}
   4.361 +out:
   4.362 +	if (ferror(fp)) {
   4.363 +		warn("%s", fname);
   4.364 +		return (1);
   4.365 +	}
   4.366 +	return (0);
   4.367 +}
   4.368 +
   4.369 +static int
   4.370 +is_delim(wchar_t ch)
   4.371 +{
   4.372 +	if (wflag) {
   4.373 +		if (ch == ' ' || ch == '\t')
   4.374 +			return 1;
   4.375 +	} else {
   4.376 +		if (ch == dchar)
   4.377 +			return 1;
   4.378 +	}
   4.379 +	return 0;
   4.380 +}
   4.381 +
   4.382 +static int
   4.383 +f_cut(FILE *fp, const char *fname)
   4.384 +{
   4.385 +	wchar_t ch;
   4.386 +	int field, i, isdelim;
   4.387 +	char *pos, *p;
   4.388 +	int output;
   4.389 +	char *lbuf, *mlbuf;
   4.390 +	size_t clen, lbuflen, reallen;
   4.391 +
   4.392 +	mlbuf = NULL;
   4.393 +	while ((lbuf = fgetln(fp, &lbuflen)) != NULL) {
   4.394 +		reallen = lbuflen;
   4.395 +		/* Assert EOL has a newline. */
   4.396 +		if (*(lbuf + lbuflen - 1) != '\n') {
   4.397 +			/* Can't have > 1 line with no trailing newline. */
   4.398 +			mlbuf = malloc(lbuflen + 1);
   4.399 +			if (mlbuf == NULL)
   4.400 +				err(1, "malloc");
   4.401 +			memcpy(mlbuf, lbuf, lbuflen);
   4.402 +			*(mlbuf + lbuflen) = '\n';
   4.403 +			lbuf = mlbuf;
   4.404 +			reallen++;
   4.405 +		}
   4.406 +		output = 0;
   4.407 +		for (isdelim = 0, p = lbuf;; p += clen) {
   4.408 +			clen = mbrtowc(&ch, p, lbuf + reallen - p, NULL);
   4.409 +			if (clen == (size_t)-1 || clen == (size_t)-2) {
   4.410 +				warnc(EILSEQ, "%s", fname);
   4.411 +				free(mlbuf);
   4.412 +				return (1);
   4.413 +			}
   4.414 +			if (clen == 0)
   4.415 +				clen = 1;
   4.416 +			/* this should work if newline is delimiter */
   4.417 +			if (is_delim(ch))
   4.418 +				isdelim = 1;
   4.419 +			if (ch == '\n') {
   4.420 +				if (!isdelim && !sflag)
   4.421 +					(void)fwrite(lbuf, lbuflen, 1, stdout);
   4.422 +				break;
   4.423 +			}
   4.424 +		}
   4.425 +		if (!isdelim)
   4.426 +			continue;
   4.427 +
   4.428 +		pos = positions + 1;
   4.429 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
   4.430 +			if (*pos && output++)
   4.431 +				for (i = 0; dcharmb[i] != '\0'; i++)
   4.432 +					putchar(dcharmb[i]);
   4.433 +			for (;;) {
   4.434 +				clen = mbrtowc(&ch, p, lbuf + reallen - p,
   4.435 +				    NULL);
   4.436 +				if (clen == (size_t)-1 || clen == (size_t)-2) {
   4.437 +					warnc(EILSEQ, "%s", fname);
   4.438 +					free(mlbuf);
   4.439 +					return (1);
   4.440 +				}
   4.441 +				if (clen == 0)
   4.442 +					clen = 1;
   4.443 +				p += clen;
   4.444 +				if (ch == '\n' || is_delim(ch)) {
   4.445 +					/* compress whitespace */
   4.446 +					if (wflag && ch != '\n')
   4.447 +						while (is_delim(*p))
   4.448 +							p++;
   4.449 +					break;
   4.450 +				}
   4.451 +				if (*pos)
   4.452 +					for (i = 0; i < (int)clen; i++)
   4.453 +						putchar(p[i - clen]);
   4.454 +			}
   4.455 +			if (ch == '\n')
   4.456 +				break;
   4.457 +		}
   4.458 +		if (ch != '\n') {
   4.459 +			if (autostop) {
   4.460 +				if (output)
   4.461 +					for (i = 0; dcharmb[i] != '\0'; i++)
   4.462 +						putchar(dcharmb[i]);
   4.463 +				for (; (ch = *p) != '\n'; ++p)
   4.464 +					(void)putchar(ch);
   4.465 +			} else
   4.466 +				for (; (ch = *p) != '\n'; ++p);
   4.467 +		}
   4.468 +		(void)putchar('\n');
   4.469 +	}
   4.470 +	free(mlbuf);
   4.471 +	return (0);
   4.472 +}
   4.473 +
   4.474 +static void
   4.475 +usage(void)
   4.476 +{
   4.477 +	(void)fprintf(stderr, "%s\n%s\n%s\n",
   4.478 +		"usage: cut -b list [-n] [file ...]",
   4.479 +		"       cut -c list [file ...]",
   4.480 +		"       cut -f list [-s] [-w | -d delim] [file ...]");
   4.481 +	exit(1);
   4.482 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/code/cut.c__gnu.1992-11-08	Tue May 12 06:46:59 2015 +0200
     5.3 @@ -0,0 +1,586 @@
     5.4 +/* cut - remove parts of lines of files
     5.5 +   Copyright (C) 1984 by David M. Ihnat
     5.6 + 
     5.7 +   This program is a total rewrite of the Bell Laboratories Unix(Tm)
     5.8 +   command of the same name, as of System V.  It contains no proprietary
     5.9 +   code, and therefore may be used without violation of any proprietary
    5.10 +   agreements whatsoever.  However, you will notice that the program is
    5.11 +   copyrighted by me.  This is to assure the program does *not* fall
    5.12 +   into the public domain.  Thus, I may specify just what I am now:
    5.13 +   This program may be freely copied and distributed, provided this notice
    5.14 +   remains; it may not be sold for profit without express written consent of
    5.15 +   the author.
    5.16 +   Please note that I recreated the behavior of the Unix(Tm) 'cut' command
    5.17 +   as faithfully as possible; however, I haven't run a full set of regression
    5.18 +   tests.  Thus, the user of this program accepts full responsibility for any
    5.19 +   effects or loss; in particular, the author is not responsible for any losses,
    5.20 +   explicit or incidental, that may be incurred through use of this program.
    5.21 +
    5.22 +   I ask that any bugs (and, if possible, fixes) be reported to me when
    5.23 +   possible.  -David Ihnat (312) 784-4544 ignatz@homebru.chi.il.us
    5.24 +
    5.25 +   POSIX changes, bug fixes, long-named options, and cleanup
    5.26 +   by David MacKenzie <djm@ai.mit.edu>.
    5.27 +
    5.28 +   Options:
    5.29 +   --bytes=byte-list
    5.30 +   -b byte-list			Print only the bytes in positions listed
    5.31 +				in BYTE-LIST.
    5.32 +				Tabs and backspaces are treated like any
    5.33 +				other character; they take up 1 byte.
    5.34 +
    5.35 +   --characters=character-list
    5.36 +   -c character-list		Print only characters in positions listed
    5.37 +				in CHARACTER-LIST.
    5.38 +				The same as -b for now, but
    5.39 +				internationalization will change that.
    5.40 +				Tabs and backspaces are treated like any
    5.41 +				other character; they take up 1 character.
    5.42 +
    5.43 +   --fields=field-list
    5.44 +   -f field-list		Print only the fields listed in FIELD-LIST.
    5.45 +				Fields are separated by a TAB by default.
    5.46 +
    5.47 +   --delimiter=delim
    5.48 +   -d delim			For -f, fields are separated by the first
    5.49 +				character in DELIM instead of TAB.
    5.50 +
    5.51 +   -n				Do not split multibyte chars (no-op for now).
    5.52 +
    5.53 +   --only-delimited
    5.54 +   -s				For -f, do not print lines that do not contain
    5.55 +				the field separator character.
    5.56 +
    5.57 +   The BYTE-LIST, CHARACTER-LIST, and FIELD-LIST are one or more numbers
    5.58 +   or ranges separated by commas.  The first byte, character, and field
    5.59 +   are numbered 1.
    5.60 +
    5.61 +   A FILE of `-' means standard input. */
    5.62 +
    5.63 +#define _GNU_SOURCE
    5.64 +#include <ctype.h>
    5.65 +#ifndef isblank
    5.66 +#define isblank(c) ((c) == ' ' || (c) == '\t')
    5.67 +#endif
    5.68 +#include <stdio.h>
    5.69 +#include <getopt.h>
    5.70 +#include <sys/types.h>
    5.71 +#include "system.h"
    5.72 +
    5.73 +#ifdef isascii
    5.74 +#define ISDIGIT(c) (isascii ((c)) && isdigit ((c)))
    5.75 +#else
    5.76 +#define ISDIGIT(c) (isdigit ((c)))
    5.77 +#endif
    5.78 +
    5.79 +char *xmalloc ();
    5.80 +char *xrealloc ();
    5.81 +int set_fields ();
    5.82 +int cut_file ();
    5.83 +void cut_stream ();
    5.84 +void cut_bytes ();
    5.85 +void cut_fields ();
    5.86 +void enlarge_line ();
    5.87 +void error ();
    5.88 +void invalid_list ();
    5.89 +void usage ();
    5.90 +
    5.91 +/* The number of elements allocated for the input line
    5.92 +   and the byte or field number.
    5.93 +   Enlarged as necessary. */
    5.94 +int line_size;
    5.95 +
    5.96 +/* Processed output buffer. */
    5.97 +char *outbuf;
    5.98 +
    5.99 +/* Where to save next char to output. */
   5.100 +char *outbufptr;
   5.101 +
   5.102 +/* Raw line buffer for field mode. */
   5.103 +char *inbuf;
   5.104 +
   5.105 +/* Where to save next input char. */
   5.106 +char *inbufptr;
   5.107 +
   5.108 +/* What can be done about a byte or field. */
   5.109 +enum field_action
   5.110 +{
   5.111 +  field_omit,
   5.112 +  field_output
   5.113 +};
   5.114 +
   5.115 +/* In byte mode, which bytes to output.
   5.116 +   In field mode, which `delim'-separated fields to output.
   5.117 +   Both bytes and fields are numbered starting with 1,
   5.118 +   so the first element of `fields' is unused. */
   5.119 +enum field_action *fields;
   5.120 +
   5.121 +enum operating_mode
   5.122 +{
   5.123 +  undefined_mode,
   5.124 +
   5.125 +  /* Output characters that are in the given bytes. */
   5.126 +  byte_mode,
   5.127 +
   5.128 +  /* Output the given delimeter-separated fields. */
   5.129 +  field_mode
   5.130 +};
   5.131 +
   5.132 +enum operating_mode operating_mode;
   5.133 +
   5.134 +/* If nonzero,
   5.135 +   for field mode, do not output lines containing no delimeter characters. */
   5.136 +int delimited_lines_only;
   5.137 +
   5.138 +/* The delimeter character for field mode. */
   5.139 +unsigned char delim;
   5.140 +
   5.141 +/* Nonzero if we have ever read standard input. */
   5.142 +int have_read_stdin;
   5.143 +
   5.144 +/* The name this program was run with. */
   5.145 +char *program_name;
   5.146 +
   5.147 +struct option longopts[] =
   5.148 +{
   5.149 +  {"bytes", 1, 0, 'b'},
   5.150 +  {"characters", 1, 0, 'c'},
   5.151 +  {"fields", 1, 0, 'f'},
   5.152 +  {"delimiter", 1, 0, 'd'},
   5.153 +  {"only-delimited", 0, 0, 's'},
   5.154 +  {0, 0, 0, 0}
   5.155 +};
   5.156 +
   5.157 +void
   5.158 +main (argc, argv)
   5.159 +     int argc;
   5.160 +     char **argv;
   5.161 +{
   5.162 +  int optc, exit_status = 0;
   5.163 +
   5.164 +  program_name = argv[0];
   5.165 +
   5.166 +  line_size = 512;
   5.167 +  operating_mode = undefined_mode;
   5.168 +  delimited_lines_only = 0;
   5.169 +  delim = '\0';
   5.170 +  have_read_stdin = 0;
   5.171 +
   5.172 +  fields = (enum field_action *)
   5.173 +    xmalloc (line_size * sizeof (enum field_action));
   5.174 +  outbuf = (char *) xmalloc (line_size);
   5.175 +  inbuf = (char *) xmalloc (line_size);
   5.176 +
   5.177 +  for (optc = 0; optc < line_size; optc++)
   5.178 +    fields[optc] = field_omit;
   5.179 +
   5.180 +  while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, (int *) 0))
   5.181 +	 != EOF)
   5.182 +    {
   5.183 +      switch (optc)
   5.184 +	{
   5.185 +	case 'b':
   5.186 +	case 'c':
   5.187 +	  /* Build the byte list. */
   5.188 +	  if (operating_mode != undefined_mode)
   5.189 +	    usage ();
   5.190 +	  operating_mode = byte_mode;
   5.191 +	  if (set_fields (optarg) == 0)
   5.192 +	    error (2, 0, "no fields given");
   5.193 +	  break;
   5.194 +
   5.195 +	case 'f':
   5.196 +	  /* Build the field list. */
   5.197 +	  if (operating_mode != undefined_mode)
   5.198 +	    usage ();
   5.199 +	  operating_mode = field_mode;
   5.200 +	  if (set_fields (optarg) == 0)
   5.201 +	    error (2, 0, "no fields given");
   5.202 +	  break;
   5.203 +
   5.204 +	case 'd':
   5.205 +	  /* New delimiter. */
   5.206 +	  if (optarg[0] == '\0')
   5.207 +	    error (2, 0, "no delimiter given");
   5.208 +	  if (optarg[1] != '\0')
   5.209 +	    error (2, 0, "delimiter must be a single character");
   5.210 +	  delim = optarg[0];
   5.211 +	  break;
   5.212 +
   5.213 +	case 'n':
   5.214 +	  break;
   5.215 +
   5.216 +	case 's':
   5.217 +	  delimited_lines_only++;
   5.218 +	  break;
   5.219 +
   5.220 +	default:
   5.221 +	  usage ();
   5.222 +	}
   5.223 +    }
   5.224 +
   5.225 +  if (operating_mode == undefined_mode)
   5.226 +    usage ();
   5.227 +
   5.228 +  if ((delimited_lines_only || delim != '\0') && operating_mode != field_mode)
   5.229 +    usage ();
   5.230 +
   5.231 +  if (delim == '\0')
   5.232 +    delim = '\t';
   5.233 +
   5.234 +  if (optind == argc)
   5.235 +    exit_status |= cut_file ("-");
   5.236 +  else
   5.237 +    for (; optind < argc; optind++)
   5.238 +      exit_status |= cut_file (argv[optind]);
   5.239 +
   5.240 +  if (have_read_stdin && fclose (stdin) == EOF)
   5.241 +    {
   5.242 +      error (0, errno, "-");
   5.243 +      exit_status = 1;
   5.244 +    }
   5.245 +  if (ferror (stdout) || fclose (stdout) == EOF)
   5.246 +    error (1, 0, "write error");
   5.247 +
   5.248 +  exit (exit_status);
   5.249 +}
   5.250 +
   5.251 +/* Select for printing the positions in `fields' that are listed in
   5.252 +   byte or field specification FIELDSTR.  FIELDSTR should be
   5.253 +   composed of one or more numbers or ranges of numbers, separated by
   5.254 +   blanks or commas.  Incomplete ranges may be given: `-m' means
   5.255 +   `1-m'; `n-' means `n' through end of line or last field.
   5.256 +
   5.257 +   Return the number of fields selected. */
   5.258 +
   5.259 +int
   5.260 +set_fields (fieldstr)
   5.261 +     char *fieldstr;
   5.262 +{
   5.263 +  int initial = 1;		/* Value of first number in a range. */
   5.264 +  int dash_found = 0;		/* Nonzero if a '-' is found in this field. */
   5.265 +  int value = 0;		/* If nonzero, a number being accumulated. */
   5.266 +  int fields_selected = 0;	/* Number of fields selected so far. */
   5.267 +  /* If nonzero, index of first field in a range that goes to end of line. */
   5.268 +  int eol_range_start = 0;
   5.269 +
   5.270 +  for (;;)
   5.271 +    {
   5.272 +      if (*fieldstr == '-')
   5.273 +	{
   5.274 +	  /* Starting a range. */
   5.275 +	  if (dash_found)
   5.276 +	    invalid_list ();
   5.277 +	  dash_found++;
   5.278 +	  fieldstr++;
   5.279 +
   5.280 +	  if (value)
   5.281 +	    {
   5.282 +	      if (value >= line_size)
   5.283 +		enlarge_line (value);
   5.284 +	      initial = value;
   5.285 +	      value = 0;
   5.286 +	    }
   5.287 +	  else
   5.288 +	    initial = 1;
   5.289 +	}
   5.290 +      else if (*fieldstr == ',' || isblank (*fieldstr) || *fieldstr == '\0')
   5.291 +	{
   5.292 +	  /* Ending the string, or this field/byte sublist. */
   5.293 +	  if (dash_found)
   5.294 +	    {
   5.295 +	      dash_found = 0;
   5.296 +
   5.297 +	      /* A range.  Possibilites: -n, m-n, n-.
   5.298 +		 In any case, `initial' contains the start of the range. */
   5.299 +	      if (value == 0)
   5.300 +		{
   5.301 +		  /* `n-'.  From `initial' to end of line. */
   5.302 +		  eol_range_start = initial;
   5.303 +		  fields_selected++;
   5.304 +		}
   5.305 +	      else
   5.306 +		{
   5.307 +		  /* `m-n' or `-n' (1-n). */
   5.308 +		  if (value < initial)
   5.309 +		    invalid_list ();
   5.310 +
   5.311 +		  if (value >= line_size)
   5.312 +		    enlarge_line (value);
   5.313 +
   5.314 +		  /* Is there already a range going to end of line? */
   5.315 +		  if (eol_range_start != 0)
   5.316 +		    {
   5.317 +		      /* Yes.  Is the new sequence already contained
   5.318 +			 in the old one?  If so, no processing is
   5.319 +			 necessary. */
   5.320 +		      if (initial < eol_range_start)
   5.321 +			{
   5.322 +			  /* No, the new sequence starts before the
   5.323 +			     old.  Does the old range going to end of line
   5.324 +			     extend into the new range?  */
   5.325 +			  if (eol_range_start < value)
   5.326 +			    /* Yes.  Simply move the end of line marker. */
   5.327 +			    eol_range_start = initial;
   5.328 +			  else
   5.329 +			    {
   5.330 +			      /* No.  A simple range, before and disjoint from
   5.331 +				 the range going to end of line.  Fill it. */
   5.332 +			      for (; initial <= value; initial++)
   5.333 +				fields[initial] = field_output;
   5.334 +			    }
   5.335 +
   5.336 +			  /* In any case, some fields were selected. */
   5.337 +			  fields_selected++;
   5.338 +			}
   5.339 +		    }
   5.340 +		  else
   5.341 +		    {
   5.342 +		      /* There is no range going to end of line. */
   5.343 +		      for (; initial <= value; initial++)
   5.344 +			fields[initial] = field_output;
   5.345 +		      fields_selected++;
   5.346 +		    }
   5.347 +		  value = 0;
   5.348 +		}
   5.349 +	    }
   5.350 +	  else if (value != 0)
   5.351 +	    {
   5.352 +	      /* A simple field number, not a range. */
   5.353 +	      if (value >= line_size)
   5.354 +		enlarge_line (value);
   5.355 +
   5.356 +	      fields[value] = field_output;
   5.357 +	      value = 0;
   5.358 +	      fields_selected++;
   5.359 +	    }
   5.360 +
   5.361 +	  if (*fieldstr == '\0')
   5.362 +	    {
   5.363 +	      /* If there was a range going to end of line, fill the
   5.364 +		 array from the end of line point.  */
   5.365 +	      if (eol_range_start)
   5.366 +		for (initial = eol_range_start; initial < line_size; initial++)
   5.367 +		  fields[initial] = field_output;
   5.368 +
   5.369 +	      return fields_selected;
   5.370 +	    }
   5.371 +
   5.372 +	  fieldstr++;
   5.373 +	}
   5.374 +      else if (ISDIGIT (*fieldstr))
   5.375 +	{
   5.376 +	  value = 10 * value + *fieldstr - '0';
   5.377 +	  fieldstr++;
   5.378 +	}
   5.379 +      else
   5.380 +	invalid_list ();
   5.381 +    }
   5.382 +}
   5.383 +
   5.384 +/* Process file FILE to standard output.
   5.385 +   Return 0 if successful, 1 if not. */
   5.386 +
   5.387 +int
   5.388 +cut_file (file)
   5.389 +     char *file;
   5.390 +{
   5.391 +  FILE *stream;
   5.392 +
   5.393 +  if (!strcmp (file, "-"))
   5.394 +    {
   5.395 +      have_read_stdin = 1;
   5.396 +      stream = stdin;
   5.397 +    }
   5.398 +  else
   5.399 +    {
   5.400 +      stream = fopen (file, "r");
   5.401 +      if (stream == NULL)
   5.402 +	{
   5.403 +	  error (0, errno, "%s", file);
   5.404 +	  return 1;
   5.405 +	}
   5.406 +    }
   5.407 +
   5.408 +  cut_stream (stream);
   5.409 +
   5.410 +  if (ferror (stream))
   5.411 +    {
   5.412 +      error (0, errno, "%s", file);
   5.413 +      return 1;
   5.414 +    }
   5.415 +  if (!strcmp (file, "-"))
   5.416 +    clearerr (stream);		/* Also clear EOF. */
   5.417 +  else if (fclose (stream) == EOF)
   5.418 +    {
   5.419 +      error (0, errno, "%s", file);
   5.420 +      return 1;
   5.421 +    }
   5.422 +  return 0;
   5.423 +}
   5.424 +
   5.425 +void
   5.426 +cut_stream (stream)
   5.427 +     FILE *stream;
   5.428 +{
   5.429 +  if (operating_mode == byte_mode)
   5.430 +    cut_bytes (stream);
   5.431 +  else
   5.432 +    cut_fields (stream);
   5.433 +}
   5.434 +
   5.435 +/* Print the file open for reading on stream STREAM
   5.436 +   with the bytes marked `field_omit' in `fields' removed from each line. */
   5.437 +
   5.438 +void
   5.439 +cut_bytes (stream)
   5.440 +     FILE *stream;
   5.441 +{
   5.442 +  register int c;		/* Each character from the file. */
   5.443 +  int doneflag = 0;		/* Nonzero if EOF reached. */
   5.444 +  int char_count;		/* Number of chars in the line so far. */
   5.445 +
   5.446 +  while (doneflag == 0)
   5.447 +    {
   5.448 +      /* Start processing a line. */
   5.449 +      outbufptr = outbuf;
   5.450 +      char_count = 0;
   5.451 +
   5.452 +      do
   5.453 +	{
   5.454 +	  c = getc (stream);
   5.455 +	  if (c == EOF)
   5.456 +	    {
   5.457 +	      doneflag++;
   5.458 +	      break;
   5.459 +	    }
   5.460 +
   5.461 +	  /* If this character is to be sent, stow it in the outbuffer. */
   5.462 +
   5.463 +	  if (++char_count == line_size - 1)
   5.464 +	    enlarge_line (char_count);
   5.465 +
   5.466 +	  if (fields[char_count] == field_output || c == '\n')
   5.467 +	    *outbufptr++ = c;
   5.468 +	}
   5.469 +      while (c != '\n');
   5.470 +
   5.471 +      if (char_count)
   5.472 +	fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout);
   5.473 +    }
   5.474 +}
   5.475 +
   5.476 +/* Print the file open for reading on stream STREAM
   5.477 +   with the fields marked `field_omit' in `fields' removed from each line.
   5.478 +   All characters are initially stowed in the raw input buffer, until
   5.479 +   at least one field has been found. */
   5.480 +
   5.481 +void
   5.482 +cut_fields (stream)
   5.483 +     FILE *stream;
   5.484 +{
   5.485 +  register int c;		/* Each character from the file. */
   5.486 +  int doneflag = 0;		/* Nonzero if EOF reached. */
   5.487 +  int char_count;		/* Number of chars in line before any delim. */
   5.488 +  int fieldfound;		/* Nonzero if any fields to print found. */
   5.489 +  int curr_field;		/* Current index in `fields'. */
   5.490 +
   5.491 +  while (doneflag == 0)
   5.492 +    {
   5.493 +      char_count = 0;
   5.494 +      fieldfound = 0;
   5.495 +      curr_field = 1;
   5.496 +      outbufptr = outbuf;
   5.497 +      inbufptr = inbuf;
   5.498 +
   5.499 +      do
   5.500 +	{
   5.501 +	  c = getc (stream);
   5.502 +	  if (c == EOF)
   5.503 +	    {
   5.504 +	      doneflag++;
   5.505 +	      break;
   5.506 +	    }
   5.507 +
   5.508 +	  if (fields[curr_field] == field_output && c != '\n')
   5.509 +	    {
   5.510 +	      /* Working on a field.  It, and its terminating
   5.511 +		 delimiter, go only into the processed buffer. */
   5.512 +	      fieldfound = 1;
   5.513 +	      if (outbufptr - outbuf == line_size - 2)
   5.514 +		enlarge_line (outbufptr - outbuf);
   5.515 +	      *outbufptr++ = c;
   5.516 +	    }
   5.517 +	  else if (fieldfound == 0)
   5.518 +	    {
   5.519 +	      if (++char_count == line_size - 1)
   5.520 +		enlarge_line (char_count);
   5.521 +	      *inbufptr++ = c;
   5.522 +	    }
   5.523 +
   5.524 +	  if (c == delim && ++curr_field == line_size - 1)
   5.525 +	    enlarge_line (curr_field);
   5.526 +	}
   5.527 +      while (c != '\n');
   5.528 +
   5.529 +      if (fieldfound)
   5.530 +	{
   5.531 +	  /* Something was found. Print it. */
   5.532 +	  if (outbufptr[-1] == delim)
   5.533 +	    --outbufptr;	/* Suppress trailing delimiter. */
   5.534 +
   5.535 +	  fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout);
   5.536 +	  if (c == '\n')
   5.537 +	    putc (c, stdout);
   5.538 +	}
   5.539 +      else if (!delimited_lines_only && char_count)
   5.540 +	/* A line with some characters, no delimiters, and no
   5.541 +	   suppression.  Print it. */
   5.542 +	fwrite (inbuf, sizeof (char), inbufptr - inbuf, stdout);
   5.543 +    }
   5.544 +}
   5.545 +
   5.546 +/* Extend the buffers to accomodate at least NEW_SIZE characters. */
   5.547 +
   5.548 +void
   5.549 +enlarge_line (new_size)
   5.550 +     int new_size;
   5.551 +{
   5.552 +  char *newp;
   5.553 +  int i;
   5.554 +
   5.555 +  new_size += 256;		/* Leave some room to grow. */
   5.556 +
   5.557 +  fields = (enum field_action *)
   5.558 +    xrealloc (fields, new_size * sizeof (enum field_action));
   5.559 +
   5.560 +  newp = (char *) xrealloc (outbuf, new_size);
   5.561 +  outbufptr += newp - outbuf;
   5.562 +  outbuf = newp;
   5.563 +
   5.564 +  newp = (char *) xrealloc (inbuf, new_size);
   5.565 +  inbufptr += newp - inbuf;
   5.566 +  inbuf = newp;
   5.567 +
   5.568 +  for (i = line_size; i < new_size; i++)
   5.569 +    fields[i] = field_omit;
   5.570 +  line_size = new_size;
   5.571 +}
   5.572 +
   5.573 +void
   5.574 +invalid_list ()
   5.575 +{
   5.576 +  error (2, 0, "invalid byte or field list");
   5.577 +}
   5.578 +
   5.579 +void
   5.580 +usage ()
   5.581 +{
   5.582 +  fprintf (stderr, "\
   5.583 +Usage: %s {-b byte-list,--bytes=byte-list} [-n] [file...]\n\
   5.584 +       %s {-c character-list,--characters=character-list} [file...]\n\
   5.585 +       %s {-f field-list,--fields=field-list} [-d delim] [-s]\n\
   5.586 +       [--delimiter=delim] [--only-delimited] [file...]\n",
   5.587 +	   program_name, program_name, program_name);
   5.588 +  exit (2);
   5.589 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/code/cut.c__gnu.2015-05-01	Tue May 12 06:46:59 2015 +0200
     6.3 @@ -0,0 +1,830 @@
     6.4 +/* cut - remove parts of lines of files
     6.5 +   Copyright (C) 1997-2015 Free Software Foundation, Inc.
     6.6 +   Copyright (C) 1984 David M. Ihnat
     6.7 +
     6.8 +   This program is free software: you can redistribute it and/or modify
     6.9 +   it under the terms of the GNU General Public License as published by
    6.10 +   the Free Software Foundation, either version 3 of the License, or
    6.11 +   (at your option) any later version.
    6.12 +
    6.13 +   This program is distributed in the hope that it will be useful,
    6.14 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 +   GNU General Public License for more details.
    6.17 +
    6.18 +   You should have received a copy of the GNU General Public License
    6.19 +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
    6.20 +
    6.21 +/* Written by David Ihnat.  */
    6.22 +
    6.23 +/* POSIX changes, bug fixes, long-named options, and cleanup
    6.24 +   by David MacKenzie <djm@gnu.ai.mit.edu>.
    6.25 +
    6.26 +   Rewrite cut_fields and cut_bytes -- Jim Meyering.  */
    6.27 +
    6.28 +#include <config.h>
    6.29 +
    6.30 +#include <stdio.h>
    6.31 +#include <assert.h>
    6.32 +#include <getopt.h>
    6.33 +#include <sys/types.h>
    6.34 +#include "system.h"
    6.35 +
    6.36 +#include "error.h"
    6.37 +#include "fadvise.h"
    6.38 +#include "getndelim2.h"
    6.39 +#include "hash.h"
    6.40 +#include "quote.h"
    6.41 +#include "xstrndup.h"
    6.42 +
    6.43 +/* The official name of this program (e.g., no 'g' prefix).  */
    6.44 +#define PROGRAM_NAME "cut"
    6.45 +
    6.46 +#define AUTHORS \
    6.47 +  proper_name ("David M. Ihnat"), \
    6.48 +  proper_name ("David MacKenzie"), \
    6.49 +  proper_name ("Jim Meyering")
    6.50 +
    6.51 +#define FATAL_ERROR(Message)						\
    6.52 +  do									\
    6.53 +    {									\
    6.54 +      error (0, 0, (Message));						\
    6.55 +      usage (EXIT_FAILURE);						\
    6.56 +    }									\
    6.57 +  while (0)
    6.58 +
    6.59 +
    6.60 +struct range_pair
    6.61 +  {
    6.62 +    size_t lo;
    6.63 +    size_t hi;
    6.64 +  };
    6.65 +
    6.66 +/* Array of `struct range_pair' holding all the finite ranges. */
    6.67 +static struct range_pair *rp;
    6.68 +
    6.69 +/* Pointer inside RP.  When checking if a byte or field is selected
    6.70 +   by a finite range, we check if it is between CURRENT_RP.LO
    6.71 +   and CURRENT_RP.HI.  If the byte or field index is greater than
    6.72 +   CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */
    6.73 +static struct range_pair *current_rp;
    6.74 +
    6.75 +/* Number of finite ranges specified by the user. */
    6.76 +static size_t n_rp;
    6.77 +
    6.78 +/* Number of `struct range_pair's allocated. */
    6.79 +static size_t n_rp_allocated;
    6.80 +
    6.81 +
    6.82 +/* Append LOW, HIGH to the list RP of range pairs, allocating additional
    6.83 +   space if necessary.  Update global variable N_RP.  When allocating,
    6.84 +   update global variable N_RP_ALLOCATED.  */
    6.85 +
    6.86 +static void
    6.87 +add_range_pair (size_t lo, size_t hi)
    6.88 +{
    6.89 +  if (n_rp == n_rp_allocated)
    6.90 +    rp = X2NREALLOC (rp, &n_rp_allocated);
    6.91 +  rp[n_rp].lo = lo;
    6.92 +  rp[n_rp].hi = hi;
    6.93 +  ++n_rp;
    6.94 +}
    6.95 +
    6.96 +/* This buffer is used to support the semantics of the -s option
    6.97 +   (or lack of same) when the specified field list includes (does
    6.98 +   not include) the first field.  In both of those cases, the entire
    6.99 +   first field must be read into this buffer to determine whether it
   6.100 +   is followed by a delimiter or a newline before any of it may be
   6.101 +   output.  Otherwise, cut_fields can do the job without using this
   6.102 +   buffer.  */
   6.103 +static char *field_1_buffer;
   6.104 +
   6.105 +/* The number of bytes allocated for FIELD_1_BUFFER.  */
   6.106 +static size_t field_1_bufsize;
   6.107 +
   6.108 +enum operating_mode
   6.109 +  {
   6.110 +    undefined_mode,
   6.111 +
   6.112 +    /* Output characters that are in the given bytes. */
   6.113 +    byte_mode,
   6.114 +
   6.115 +    /* Output the given delimiter-separated fields. */
   6.116 +    field_mode
   6.117 +  };
   6.118 +
   6.119 +static enum operating_mode operating_mode;
   6.120 +
   6.121 +/* If true do not output lines containing no delimiter characters.
   6.122 +   Otherwise, all such lines are printed.  This option is valid only
   6.123 +   with field mode.  */
   6.124 +static bool suppress_non_delimited;
   6.125 +
   6.126 +/* If true, print all bytes, characters, or fields _except_
   6.127 +   those that were specified.  */
   6.128 +static bool complement;
   6.129 +
   6.130 +/* The delimiter character for field mode. */
   6.131 +static unsigned char delim;
   6.132 +
   6.133 +/* True if the --output-delimiter=STRING option was specified.  */
   6.134 +static bool output_delimiter_specified;
   6.135 +
   6.136 +/* The length of output_delimiter_string.  */
   6.137 +static size_t output_delimiter_length;
   6.138 +
   6.139 +/* The output field separator string.  Defaults to the 1-character
   6.140 +   string consisting of the input delimiter.  */
   6.141 +static char *output_delimiter_string;
   6.142 +
   6.143 +/* True if we have ever read standard input. */
   6.144 +static bool have_read_stdin;
   6.145 +
   6.146 +/* For long options that have no equivalent short option, use a
   6.147 +   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
   6.148 +enum
   6.149 +{
   6.150 +  OUTPUT_DELIMITER_OPTION = CHAR_MAX + 1,
   6.151 +  COMPLEMENT_OPTION
   6.152 +};
   6.153 +
   6.154 +static struct option const longopts[] =
   6.155 +{
   6.156 +  {"bytes", required_argument, NULL, 'b'},
   6.157 +  {"characters", required_argument, NULL, 'c'},
   6.158 +  {"fields", required_argument, NULL, 'f'},
   6.159 +  {"delimiter", required_argument, NULL, 'd'},
   6.160 +  {"only-delimited", no_argument, NULL, 's'},
   6.161 +  {"output-delimiter", required_argument, NULL, OUTPUT_DELIMITER_OPTION},
   6.162 +  {"complement", no_argument, NULL, COMPLEMENT_OPTION},
   6.163 +  {GETOPT_HELP_OPTION_DECL},
   6.164 +  {GETOPT_VERSION_OPTION_DECL},
   6.165 +  {NULL, 0, NULL, 0}
   6.166 +};
   6.167 +
   6.168 +void
   6.169 +usage (int status)
   6.170 +{
   6.171 +  if (status != EXIT_SUCCESS)
   6.172 +    emit_try_help ();
   6.173 +  else
   6.174 +    {
   6.175 +      printf (_("\
   6.176 +Usage: %s OPTION... [FILE]...\n\
   6.177 +"),
   6.178 +              program_name);
   6.179 +      fputs (_("\
   6.180 +Print selected parts of lines from each FILE to standard output.\n\
   6.181 +"), stdout);
   6.182 +
   6.183 +      emit_stdin_note ();
   6.184 +      emit_mandatory_arg_note ();
   6.185 +
   6.186 +      fputs (_("\
   6.187 +  -b, --bytes=LIST        select only these bytes\n\
   6.188 +  -c, --characters=LIST   select only these characters\n\
   6.189 +  -d, --delimiter=DELIM   use DELIM instead of TAB for field delimiter\n\
   6.190 +"), stdout);
   6.191 +      fputs (_("\
   6.192 +  -f, --fields=LIST       select only these fields;  also print any line\n\
   6.193 +                            that contains no delimiter character, unless\n\
   6.194 +                            the -s option is specified\n\
   6.195 +  -n                      (ignored)\n\
   6.196 +"), stdout);
   6.197 +      fputs (_("\
   6.198 +      --complement        complement the set of selected bytes, characters\n\
   6.199 +                            or fields\n\
   6.200 +"), stdout);
   6.201 +      fputs (_("\
   6.202 +  -s, --only-delimited    do not print lines not containing delimiters\n\
   6.203 +      --output-delimiter=STRING  use STRING as the output delimiter\n\
   6.204 +                            the default is to use the input delimiter\n\
   6.205 +"), stdout);
   6.206 +      fputs (HELP_OPTION_DESCRIPTION, stdout);
   6.207 +      fputs (VERSION_OPTION_DESCRIPTION, stdout);
   6.208 +      fputs (_("\
   6.209 +\n\
   6.210 +Use one, and only one of -b, -c or -f.  Each LIST is made up of one\n\
   6.211 +range, or many ranges separated by commas.  Selected input is written\n\
   6.212 +in the same order that it is read, and is written exactly once.\n\
   6.213 +"), stdout);
   6.214 +      fputs (_("\
   6.215 +Each range is one of:\n\
   6.216 +\n\
   6.217 +  N     N'th byte, character or field, counted from 1\n\
   6.218 +  N-    from N'th byte, character or field, to end of line\n\
   6.219 +  N-M   from N'th to M'th (included) byte, character or field\n\
   6.220 +  -M    from first to M'th (included) byte, character or field\n\
   6.221 +"), stdout);
   6.222 +      emit_ancillary_info (PROGRAM_NAME);
   6.223 +    }
   6.224 +  exit (status);
   6.225 +}
   6.226 +
   6.227 +/* Comparison function for qsort to order the list of
   6.228 +   struct range_pairs.  */
   6.229 +static int
   6.230 +compare_ranges (const void *a, const void *b)
   6.231 +{
   6.232 +  int a_start = ((const struct range_pair *) a)->lo;
   6.233 +  int b_start = ((const struct range_pair *) b)->lo;
   6.234 +  return a_start < b_start ? -1 : a_start > b_start;
   6.235 +}
   6.236 +
   6.237 +/* Reallocate Range Pair entries, with corresponding
   6.238 +   entries outside the range of each specified entry.  */
   6.239 +
   6.240 +static void
   6.241 +complement_rp (void)
   6.242 +{
   6.243 +  if (complement)
   6.244 +    {
   6.245 +      struct range_pair *c = rp;
   6.246 +      size_t n = n_rp;
   6.247 +      size_t i;
   6.248 +
   6.249 +      rp = NULL;
   6.250 +      n_rp = 0;
   6.251 +      n_rp_allocated = 0;
   6.252 +
   6.253 +      if (c[0].lo > 1)
   6.254 +        add_range_pair (1, c[0].lo - 1);
   6.255 +
   6.256 +      for (i = 1; i < n; ++i)
   6.257 +        {
   6.258 +          if (c[i-1].hi + 1 == c[i].lo)
   6.259 +            continue;
   6.260 +
   6.261 +          add_range_pair (c[i-1].hi + 1, c[i].lo - 1);
   6.262 +        }
   6.263 +
   6.264 +      if (c[n-1].hi < SIZE_MAX)
   6.265 +        add_range_pair (c[n-1].hi + 1, SIZE_MAX);
   6.266 +
   6.267 +      free (c);
   6.268 +    }
   6.269 +}
   6.270 +
   6.271 +/* Given the list of field or byte range specifications FIELDSTR,
   6.272 +   allocate and initialize the RP array. FIELDSTR should
   6.273 +   be composed of one or more numbers or ranges of numbers, separated
   6.274 +   by blanks or commas.  Incomplete ranges may be given: '-m' means '1-m';
   6.275 +   'n-' means 'n' through end of line.
   6.276 +   Return true if FIELDSTR contains at least one field specification,
   6.277 +   false otherwise.  */
   6.278 +
   6.279 +static bool
   6.280 +set_fields (const char *fieldstr)
   6.281 +{
   6.282 +  size_t initial = 1;		/* Value of first number in a range.  */
   6.283 +  size_t value = 0;		/* If nonzero, a number being accumulated.  */
   6.284 +  bool lhs_specified = false;
   6.285 +  bool rhs_specified = false;
   6.286 +  bool dash_found = false;	/* True if a '-' is found in this field.  */
   6.287 +  bool field_found = false;	/* True if at least one field spec
   6.288 +                                   has been processed.  */
   6.289 +
   6.290 +  size_t i;
   6.291 +  bool in_digits = false;
   6.292 +
   6.293 +  /* Collect and store in RP the range end points. */
   6.294 +
   6.295 +  while (true)
   6.296 +    {
   6.297 +      if (*fieldstr == '-')
   6.298 +        {
   6.299 +          in_digits = false;
   6.300 +          /* Starting a range. */
   6.301 +          if (dash_found)
   6.302 +            FATAL_ERROR (_("invalid byte, character or field list"));
   6.303 +          dash_found = true;
   6.304 +          fieldstr++;
   6.305 +
   6.306 +          if (lhs_specified && !value)
   6.307 +            FATAL_ERROR (_("fields and positions are numbered from 1"));
   6.308 +
   6.309 +          initial = (lhs_specified ? value : 1);
   6.310 +          value = 0;
   6.311 +        }
   6.312 +      else if (*fieldstr == ','
   6.313 +               || isblank (to_uchar (*fieldstr)) || *fieldstr == '\0')
   6.314 +        {
   6.315 +          in_digits = false;
   6.316 +          /* Ending the string, or this field/byte sublist. */
   6.317 +          if (dash_found)
   6.318 +            {
   6.319 +              dash_found = false;
   6.320 +
   6.321 +              if (!lhs_specified && !rhs_specified)
   6.322 +                FATAL_ERROR (_("invalid range with no endpoint: -"));
   6.323 +
   6.324 +              /* A range.  Possibilities: -n, m-n, n-.
   6.325 +                 In any case, 'initial' contains the start of the range. */
   6.326 +              if (!rhs_specified)
   6.327 +                {
   6.328 +                  /* 'n-'.  From 'initial' to end of line. */
   6.329 +                  add_range_pair (initial, SIZE_MAX);
   6.330 +                  field_found = true;
   6.331 +                }
   6.332 +              else
   6.333 +                {
   6.334 +                  /* 'm-n' or '-n' (1-n). */
   6.335 +                  if (value < initial)
   6.336 +                    FATAL_ERROR (_("invalid decreasing range"));
   6.337 +
   6.338 +                  add_range_pair (initial, value);
   6.339 +                  field_found = true;
   6.340 +                }
   6.341 +              value = 0;
   6.342 +            }
   6.343 +          else
   6.344 +            {
   6.345 +              /* A simple field number, not a range. */
   6.346 +              if (value == 0)
   6.347 +                FATAL_ERROR (_("fields and positions are numbered from 1"));
   6.348 +              add_range_pair (value, value);
   6.349 +              value = 0;
   6.350 +              field_found = true;
   6.351 +            }
   6.352 +
   6.353 +          if (*fieldstr == '\0')
   6.354 +            break;
   6.355 +
   6.356 +          fieldstr++;
   6.357 +          lhs_specified = false;
   6.358 +          rhs_specified = false;
   6.359 +        }
   6.360 +      else if (ISDIGIT (*fieldstr))
   6.361 +        {
   6.362 +          /* Record beginning of digit string, in case we have to
   6.363 +             complain about it.  */
   6.364 +          static char const *num_start;
   6.365 +          if (!in_digits || !num_start)
   6.366 +            num_start = fieldstr;
   6.367 +          in_digits = true;
   6.368 +
   6.369 +          if (dash_found)
   6.370 +            rhs_specified = 1;
   6.371 +          else
   6.372 +            lhs_specified = 1;
   6.373 +
   6.374 +          /* Detect overflow.  */
   6.375 +          if (!DECIMAL_DIGIT_ACCUMULATE (value, *fieldstr - '0', size_t)
   6.376 +              || value == SIZE_MAX)
   6.377 +            {
   6.378 +              /* In case the user specified -c$(echo 2^64|bc),22,
   6.379 +                 complain only about the first number.  */
   6.380 +              /* Determine the length of the offending number.  */
   6.381 +              size_t len = strspn (num_start, "0123456789");
   6.382 +              char *bad_num = xstrndup (num_start, len);
   6.383 +              if (operating_mode == byte_mode)
   6.384 +                error (0, 0,
   6.385 +                       _("byte offset %s is too large"), quote (bad_num));
   6.386 +              else
   6.387 +                error (0, 0,
   6.388 +                       _("field number %s is too large"), quote (bad_num));
   6.389 +              free (bad_num);
   6.390 +              exit (EXIT_FAILURE);
   6.391 +            }
   6.392 +
   6.393 +          fieldstr++;
   6.394 +        }
   6.395 +      else
   6.396 +        FATAL_ERROR (_("invalid byte, character or field list"));
   6.397 +    }
   6.398 +
   6.399 +  qsort (rp, n_rp, sizeof (rp[0]), compare_ranges);
   6.400 +
   6.401 +  /* Merge range pairs (e.g. `2-5,3-4' becomes `2-5'). */
   6.402 +  for (i = 0; i < n_rp; ++i)
   6.403 +    {
   6.404 +      for (size_t j = i + 1; j < n_rp; ++j)
   6.405 +        {
   6.406 +          if (rp[j].lo <= rp[i].hi)
   6.407 +            {
   6.408 +              rp[i].hi = MAX (rp[j].hi, rp[i].hi);
   6.409 +              memmove (rp + j, rp + j + 1, (n_rp - j - 1) * sizeof *rp);
   6.410 +              n_rp--;
   6.411 +              j--;
   6.412 +            }
   6.413 +          else
   6.414 +            break;
   6.415 +        }
   6.416 +    }
   6.417 +
   6.418 +  complement_rp ();
   6.419 +
   6.420 +  /* After merging, reallocate RP so we release memory to the system.
   6.421 +     Also add a sentinel at the end of RP, to avoid out of bounds access
   6.422 +     and for performance reasons.  */
   6.423 +  ++n_rp;
   6.424 +  rp = xrealloc (rp, n_rp * sizeof (struct range_pair));
   6.425 +  rp[n_rp - 1].lo = rp[n_rp - 1].hi = SIZE_MAX;
   6.426 +
   6.427 +  return field_found;
   6.428 +}
   6.429 +
   6.430 +/* Increment *ITEM_IDX (i.e., a field or byte index),
   6.431 +   and if required CURRENT_RP.  */
   6.432 +
   6.433 +static inline void
   6.434 +next_item (size_t *item_idx)
   6.435 +{
   6.436 +  (*item_idx)++;
   6.437 +  if ((*item_idx) > current_rp->hi)
   6.438 +    current_rp++;
   6.439 +}
   6.440 +
   6.441 +/* Return nonzero if the K'th field or byte is printable. */
   6.442 +
   6.443 +static inline bool
   6.444 +print_kth (size_t k)
   6.445 +{
   6.446 +  return current_rp->lo <= k;
   6.447 +}
   6.448 +
   6.449 +/* Return nonzero if K'th byte is the beginning of a range. */
   6.450 +
   6.451 +static inline bool
   6.452 +is_range_start_index (size_t k)
   6.453 +{
   6.454 +  return k == current_rp->lo;
   6.455 +}
   6.456 +
   6.457 +/* Read from stream STREAM, printing to standard output any selected bytes.  */
   6.458 +
   6.459 +static void
   6.460 +cut_bytes (FILE *stream)
   6.461 +{
   6.462 +  size_t byte_idx;	/* Number of bytes in the line so far. */
   6.463 +  /* Whether to begin printing delimiters between ranges for the current line.
   6.464 +     Set after we've begun printing data corresponding to the first range.  */
   6.465 +  bool print_delimiter;
   6.466 +
   6.467 +  byte_idx = 0;
   6.468 +  print_delimiter = false;
   6.469 +  current_rp = rp;
   6.470 +  while (true)
   6.471 +    {
   6.472 +      int c;		/* Each character from the file. */
   6.473 +
   6.474 +      c = getc (stream);
   6.475 +
   6.476 +      if (c == '\n')
   6.477 +        {
   6.478 +          putchar ('\n');
   6.479 +          byte_idx = 0;
   6.480 +          print_delimiter = false;
   6.481 +          current_rp = rp;
   6.482 +        }
   6.483 +      else if (c == EOF)
   6.484 +        {
   6.485 +          if (byte_idx > 0)
   6.486 +            putchar ('\n');
   6.487 +          break;
   6.488 +        }
   6.489 +      else
   6.490 +        {
   6.491 +          next_item (&byte_idx);
   6.492 +          if (print_kth (byte_idx))
   6.493 +            {
   6.494 +              if (output_delimiter_specified)
   6.495 +                {
   6.496 +                  if (print_delimiter && is_range_start_index (byte_idx))
   6.497 +                    {
   6.498 +                      fwrite (output_delimiter_string, sizeof (char),
   6.499 +                              output_delimiter_length, stdout);
   6.500 +                    }
   6.501 +                  print_delimiter = true;
   6.502 +                }
   6.503 +
   6.504 +              putchar (c);
   6.505 +            }
   6.506 +        }
   6.507 +    }
   6.508 +}
   6.509 +
   6.510 +/* Read from stream STREAM, printing to standard output any selected fields.  */
   6.511 +
   6.512 +static void
   6.513 +cut_fields (FILE *stream)
   6.514 +{
   6.515 +  int c;
   6.516 +  size_t field_idx = 1;
   6.517 +  bool found_any_selected_field = false;
   6.518 +  bool buffer_first_field;
   6.519 +
   6.520 +  current_rp = rp;
   6.521 +
   6.522 +  c = getc (stream);
   6.523 +  if (c == EOF)
   6.524 +    return;
   6.525 +
   6.526 +  ungetc (c, stream);
   6.527 +  c = 0;
   6.528 +
   6.529 +  /* To support the semantics of the -s flag, we may have to buffer
   6.530 +     all of the first field to determine whether it is 'delimited.'
   6.531 +     But that is unnecessary if all non-delimited lines must be printed
   6.532 +     and the first field has been selected, or if non-delimited lines
   6.533 +     must be suppressed and the first field has *not* been selected.
   6.534 +     That is because a non-delimited line has exactly one field.  */
   6.535 +  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
   6.536 +
   6.537 +  while (1)
   6.538 +    {
   6.539 +      if (field_idx == 1 && buffer_first_field)
   6.540 +        {
   6.541 +          ssize_t len;
   6.542 +          size_t n_bytes;
   6.543 +
   6.544 +          len = getndelim2 (&field_1_buffer, &field_1_bufsize, 0,
   6.545 +                            GETNLINE_NO_LIMIT, delim, '\n', stream);
   6.546 +          if (len < 0)
   6.547 +            {
   6.548 +              free (field_1_buffer);
   6.549 +              field_1_buffer = NULL;
   6.550 +              if (ferror (stream) || feof (stream))
   6.551 +                break;
   6.552 +              xalloc_die ();
   6.553 +            }
   6.554 +
   6.555 +          n_bytes = len;
   6.556 +          assert (n_bytes != 0);
   6.557 +
   6.558 +          c = 0;
   6.559 +
   6.560 +          /* If the first field extends to the end of line (it is not
   6.561 +             delimited) and we are printing all non-delimited lines,
   6.562 +             print this one.  */
   6.563 +          if (to_uchar (field_1_buffer[n_bytes - 1]) != delim)
   6.564 +            {
   6.565 +              if (suppress_non_delimited)
   6.566 +                {
   6.567 +                  /* Empty.  */
   6.568 +                }
   6.569 +              else
   6.570 +                {
   6.571 +                  fwrite (field_1_buffer, sizeof (char), n_bytes, stdout);
   6.572 +                  /* Make sure the output line is newline terminated.  */
   6.573 +                  if (field_1_buffer[n_bytes - 1] != '\n')
   6.574 +                    putchar ('\n');
   6.575 +                  c = '\n';
   6.576 +                }
   6.577 +              continue;
   6.578 +            }
   6.579 +          if (print_kth (1))
   6.580 +            {
   6.581 +              /* Print the field, but not the trailing delimiter.  */
   6.582 +              fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout);
   6.583 +
   6.584 +              /* With -d$'\n' don't treat the last '\n' as a delimiter.  */
   6.585 +              if (delim == '\n')
   6.586 +                {
   6.587 +                  int last_c = getc (stream);
   6.588 +                  if (last_c != EOF)
   6.589 +                    {
   6.590 +                      ungetc (last_c, stream);
   6.591 +                      found_any_selected_field = true;
   6.592 +                    }
   6.593 +                }
   6.594 +              else
   6.595 +                found_any_selected_field = true;
   6.596 +            }
   6.597 +          next_item (&field_idx);
   6.598 +        }
   6.599 +
   6.600 +      int prev_c = c;
   6.601 +
   6.602 +      if (print_kth (field_idx))
   6.603 +        {
   6.604 +          if (found_any_selected_field)
   6.605 +            {
   6.606 +              fwrite (output_delimiter_string, sizeof (char),
   6.607 +                      output_delimiter_length, stdout);
   6.608 +            }
   6.609 +          found_any_selected_field = true;
   6.610 +
   6.611 +          while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
   6.612 +            {
   6.613 +              putchar (c);
   6.614 +              prev_c = c;
   6.615 +            }
   6.616 +        }
   6.617 +      else
   6.618 +        {
   6.619 +          while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
   6.620 +            {
   6.621 +              prev_c = c;
   6.622 +            }
   6.623 +        }
   6.624 +
   6.625 +      /* With -d$'\n' don't treat the last '\n' as a delimiter.  */
   6.626 +      if (delim == '\n' && c == delim)
   6.627 +        {
   6.628 +          int last_c = getc (stream);
   6.629 +          if (last_c != EOF)
   6.630 +            ungetc (last_c, stream);
   6.631 +          else
   6.632 +            c = last_c;
   6.633 +        }
   6.634 +
   6.635 +      if (c == delim)
   6.636 +        next_item (&field_idx);
   6.637 +      else if (c == '\n' || c == EOF)
   6.638 +        {
   6.639 +          if (found_any_selected_field
   6.640 +              || !(suppress_non_delimited && field_idx == 1))
   6.641 +            {
   6.642 +              if (c == '\n' || prev_c != '\n' || delim == '\n')
   6.643 +                putchar ('\n');
   6.644 +            }
   6.645 +          if (c == EOF)
   6.646 +            break;
   6.647 +          field_idx = 1;
   6.648 +          current_rp = rp;
   6.649 +          found_any_selected_field = false;
   6.650 +        }
   6.651 +    }
   6.652 +}
   6.653 +
   6.654 +static void
   6.655 +cut_stream (FILE *stream)
   6.656 +{
   6.657 +  if (operating_mode == byte_mode)
   6.658 +    cut_bytes (stream);
   6.659 +  else
   6.660 +    cut_fields (stream);
   6.661 +}
   6.662 +
   6.663 +/* Process file FILE to standard output.
   6.664 +   Return true if successful.  */
   6.665 +
   6.666 +static bool
   6.667 +cut_file (char const *file)
   6.668 +{
   6.669 +  FILE *stream;
   6.670 +
   6.671 +  if (STREQ (file, "-"))
   6.672 +    {
   6.673 +      have_read_stdin = true;
   6.674 +      stream = stdin;
   6.675 +    }
   6.676 +  else
   6.677 +    {
   6.678 +      stream = fopen (file, "r");
   6.679 +      if (stream == NULL)
   6.680 +        {
   6.681 +          error (0, errno, "%s", file);
   6.682 +          return false;
   6.683 +        }
   6.684 +    }
   6.685 +
   6.686 +  fadvise (stream, FADVISE_SEQUENTIAL);
   6.687 +
   6.688 +  cut_stream (stream);
   6.689 +
   6.690 +  if (ferror (stream))
   6.691 +    {
   6.692 +      error (0, errno, "%s", file);
   6.693 +      return false;
   6.694 +    }
   6.695 +  if (STREQ (file, "-"))
   6.696 +    clearerr (stream);		/* Also clear EOF. */
   6.697 +  else if (fclose (stream) == EOF)
   6.698 +    {
   6.699 +      error (0, errno, "%s", file);
   6.700 +      return false;
   6.701 +    }
   6.702 +  return true;
   6.703 +}
   6.704 +
   6.705 +int
   6.706 +main (int argc, char **argv)
   6.707 +{
   6.708 +  int optc;
   6.709 +  bool ok;
   6.710 +  bool delim_specified = false;
   6.711 +  char *spec_list_string IF_LINT ( = NULL);
   6.712 +
   6.713 +  initialize_main (&argc, &argv);
   6.714 +  set_program_name (argv[0]);
   6.715 +  setlocale (LC_ALL, "");
   6.716 +  bindtextdomain (PACKAGE, LOCALEDIR);
   6.717 +  textdomain (PACKAGE);
   6.718 +
   6.719 +  atexit (close_stdout);
   6.720 +
   6.721 +  operating_mode = undefined_mode;
   6.722 +
   6.723 +  /* By default, all non-delimited lines are printed.  */
   6.724 +  suppress_non_delimited = false;
   6.725 +
   6.726 +  delim = '\0';
   6.727 +  have_read_stdin = false;
   6.728 +
   6.729 +  while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, NULL)) != -1)
   6.730 +    {
   6.731 +      switch (optc)
   6.732 +        {
   6.733 +        case 'b':
   6.734 +        case 'c':
   6.735 +          /* Build the byte list. */
   6.736 +          if (operating_mode != undefined_mode)
   6.737 +            FATAL_ERROR (_("only one type of list may be specified"));
   6.738 +          operating_mode = byte_mode;
   6.739 +          spec_list_string = optarg;
   6.740 +          break;
   6.741 +
   6.742 +        case 'f':
   6.743 +          /* Build the field list. */
   6.744 +          if (operating_mode != undefined_mode)
   6.745 +            FATAL_ERROR (_("only one type of list may be specified"));
   6.746 +          operating_mode = field_mode;
   6.747 +          spec_list_string = optarg;
   6.748 +          break;
   6.749 +
   6.750 +        case 'd':
   6.751 +          /* New delimiter. */
   6.752 +          /* Interpret -d '' to mean 'use the NUL byte as the delimiter.'  */
   6.753 +          if (optarg[0] != '\0' && optarg[1] != '\0')
   6.754 +            FATAL_ERROR (_("the delimiter must be a single character"));
   6.755 +          delim = optarg[0];
   6.756 +          delim_specified = true;
   6.757 +          break;
   6.758 +
   6.759 +        case OUTPUT_DELIMITER_OPTION:
   6.760 +          output_delimiter_specified = true;
   6.761 +          /* Interpret --output-delimiter='' to mean
   6.762 +             'use the NUL byte as the delimiter.'  */
   6.763 +          output_delimiter_length = (optarg[0] == '\0'
   6.764 +                                     ? 1 : strlen (optarg));
   6.765 +          output_delimiter_string = xstrdup (optarg);
   6.766 +          break;
   6.767 +
   6.768 +        case 'n':
   6.769 +          break;
   6.770 +
   6.771 +        case 's':
   6.772 +          suppress_non_delimited = true;
   6.773 +          break;
   6.774 +
   6.775 +        case COMPLEMENT_OPTION:
   6.776 +          complement = true;
   6.777 +          break;
   6.778 +
   6.779 +        case_GETOPT_HELP_CHAR;
   6.780 +
   6.781 +        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
   6.782 +
   6.783 +        default:
   6.784 +          usage (EXIT_FAILURE);
   6.785 +        }
   6.786 +    }
   6.787 +
   6.788 +  if (operating_mode == undefined_mode)
   6.789 +    FATAL_ERROR (_("you must specify a list of bytes, characters, or fields"));
   6.790 +
   6.791 +  if (delim_specified && operating_mode != field_mode)
   6.792 +    FATAL_ERROR (_("an input delimiter may be specified only\
   6.793 + when operating on fields"));
   6.794 +
   6.795 +  if (suppress_non_delimited && operating_mode != field_mode)
   6.796 +    FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\
   6.797 +\tonly when operating on fields"));
   6.798 +
   6.799 +  if (! set_fields (spec_list_string))
   6.800 +    {
   6.801 +      if (operating_mode == field_mode)
   6.802 +        FATAL_ERROR (_("missing list of fields"));
   6.803 +      else
   6.804 +        FATAL_ERROR (_("missing list of positions"));
   6.805 +    }
   6.806 +
   6.807 +  if (!delim_specified)
   6.808 +    delim = '\t';
   6.809 +
   6.810 +  if (output_delimiter_string == NULL)
   6.811 +    {
   6.812 +      static char dummy[2];
   6.813 +      dummy[0] = delim;
   6.814 +      dummy[1] = '\0';
   6.815 +      output_delimiter_string = dummy;
   6.816 +      output_delimiter_length = 1;
   6.817 +    }
   6.818 +
   6.819 +  if (optind == argc)
   6.820 +    ok = cut_file ("-");
   6.821 +  else
   6.822 +    for (ok = true; optind < argc; optind++)
   6.823 +      ok &= cut_file (argv[optind]);
   6.824 +
   6.825 +
   6.826 +  if (have_read_stdin && fclose (stdin) == EOF)
   6.827 +    {
   6.828 +      error (0, errno, "-");
   6.829 +      ok = false;
   6.830 +    }
   6.831 +
   6.832 +  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
   6.833 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/code/cut.c__heirloom.2012-05-20	Tue May 12 06:46:59 2015 +0200
     7.3 @@ -0,0 +1,405 @@
     7.4 +/*
     7.5 + * cut - cut out fields of lines of files
     7.6 + *
     7.7 + * Gunnar Ritter, Freiburg i. Br., Germany, December 2002.
     7.8 + */
     7.9 +/*
    7.10 + * Copyright (c) 2003 Gunnar Ritter
    7.11 + *
    7.12 + * This software is provided 'as-is', without any express or implied
    7.13 + * warranty. In no event will the authors be held liable for any damages
    7.14 + * arising from the use of this software.
    7.15 + *
    7.16 + * Permission is granted to anyone to use this software for any purpose,
    7.17 + * including commercial applications, and to alter it and redistribute
    7.18 + * it freely, subject to the following restrictions:
    7.19 + *
    7.20 + * 1. The origin of this software must not be misrepresented; you must not
    7.21 + *    claim that you wrote the original software. If you use this software
    7.22 + *    in a product, an acknowledgment in the product documentation would be
    7.23 + *    appreciated but is not required.
    7.24 + *
    7.25 + * 2. Altered source versions must be plainly marked as such, and must not be
    7.26 + *    misrepresented as being the original software.
    7.27 + *
    7.28 + * 3. This notice may not be removed or altered from any source distribution.
    7.29 + */
    7.30 +
    7.31 +#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
    7.32 +#define	USED	__attribute__ ((used))
    7.33 +#elif defined __GNUC__
    7.34 +#define	USED	__attribute__ ((unused))
    7.35 +#else
    7.36 +#define	USED
    7.37 +#endif
    7.38 +static const char sccsid[] USED = "@(#)cut.sl	1.20 (gritter) 5/29/05";
    7.39 +
    7.40 +#include	<sys/types.h>
    7.41 +#include	<sys/stat.h>
    7.42 +#include	<fcntl.h>
    7.43 +#include	<unistd.h>
    7.44 +#include	<stdio.h>
    7.45 +#include	<string.h>
    7.46 +#include	<stdlib.h>
    7.47 +#include	<errno.h>
    7.48 +#include	<libgen.h>
    7.49 +#include	<limits.h>
    7.50 +#include	<wchar.h>
    7.51 +#include	<ctype.h>
    7.52 +#include	<locale.h>
    7.53 +
    7.54 +#include	"iblok.h"
    7.55 +
    7.56 +#if defined (__GLIBC__) && defined (_IO_putc_unlocked)
    7.57 +#undef	putc
    7.58 +#define	putc(c, f)	_IO_putc_unlocked(c, f)
    7.59 +#endif
    7.60 +
    7.61 +struct	range {
    7.62 +	struct range	*r_nxt;
    7.63 +	long	r_min;
    7.64 +	long	r_max;
    7.65 +};
    7.66 +
    7.67 +static unsigned	errcnt;			/* count of errors */
    7.68 +static int	method;			/* one of b, c, f */
    7.69 +static int	nflag;			/* character boundary bytes */
    7.70 +static int	sflag;			/* suppress lines w/o delimiters */
    7.71 +static char	*progname;		/* argv[0] to main() */
    7.72 +static wchar_t	wcdelim = '\t';		/* delimiter character */
    7.73 +static const char	*mbdelim = "\t";/* delimiter character */
    7.74 +struct range	*fields;		/* range list */
    7.75 +static int	multibyte;		/* multibyte LC_CTYPE */
    7.76 +
    7.77 +#define	next(wc, s)	(multibyte ? mbtowc(&(wc), s, MB_LEN_MAX) :\
    7.78 +				((wc) = *(s) & 0377, (wc) != 0))
    7.79 +
    7.80 +void *
    7.81 +lrealloc(void *vp, size_t nbytes)
    7.82 +{
    7.83 +	void	*p;
    7.84 +
    7.85 +	if ((p = realloc(vp, nbytes)) == NULL) {
    7.86 +		write(2, "line too long\n", 14);
    7.87 +		exit(076);
    7.88 +	}
    7.89 +	return p;
    7.90 +}
    7.91 +
    7.92 +void *
    7.93 +smalloc(size_t nbytes)
    7.94 +{
    7.95 +	void	*p;
    7.96 +
    7.97 +	if ((p = malloc(nbytes)) == NULL) {
    7.98 +		write(2, "no memory\n", 11);
    7.99 +		exit(077);
   7.100 +	}
   7.101 +	return p;
   7.102 +}
   7.103 +
   7.104 +static void
   7.105 +error(const char *s)
   7.106 +{
   7.107 +	fprintf(stderr, "%s: ERROR: %s\n", progname, s);
   7.108 +	exit(2);
   7.109 +}
   7.110 +
   7.111 +static void
   7.112 +usage(void)
   7.113 +{
   7.114 +	error("Usage: cut [-s] [-d<char>] {-c<list> | -f<list>} file ...");
   7.115 +}
   7.116 +
   7.117 +static void
   7.118 +badlist(void)
   7.119 +{
   7.120 +	error(method == 'b' ? "bad list for b/c/f option" : 
   7.121 +			"bad list for c/f option");
   7.122 +}
   7.123 +
   7.124 +static void
   7.125 +setdelim(const char *s)
   7.126 +{
   7.127 +	int	n;
   7.128 +
   7.129 +	if ((n = next(wcdelim, s)) < 0 || (n > 0 && s[n] != '\0'))
   7.130 +		error("no delimiter");
   7.131 +	mbdelim = s;
   7.132 +}
   7.133 +
   7.134 +static void
   7.135 +addrange(long m, long n)
   7.136 +{
   7.137 +	struct range	*rp, *rq;
   7.138 +
   7.139 +	rp = smalloc(sizeof *rp);
   7.140 +	rp->r_nxt = NULL;
   7.141 +	rp->r_min = m;
   7.142 +	rp->r_max = n ? n : m;
   7.143 +	if (fields) {
   7.144 +		for (rq = fields; rq->r_nxt; rq = rq->r_nxt);
   7.145 +		rq->r_nxt = rp;
   7.146 +	} else
   7.147 +		fields = rp;
   7.148 +}
   7.149 +
   7.150 +static int
   7.151 +have(long i)
   7.152 +{
   7.153 +	struct range	*rp;
   7.154 +
   7.155 +	for (rp = fields; rp; rp = rp->r_nxt)
   7.156 +		if (i >= rp->r_min && i <= rp->r_max)
   7.157 +			return 1;
   7.158 +	return 0;
   7.159 +}
   7.160 +
   7.161 +#define	mnreset()	m = 0, n = 0, lp = &m
   7.162 +
   7.163 +static void
   7.164 +setlist(const char *s)
   7.165 +{
   7.166 +	char	*cbuf, *cp;
   7.167 +	long	m, n;
   7.168 +	long	*lp;
   7.169 +
   7.170 +	fields = NULL;
   7.171 +	cbuf = smalloc(strlen(s) + 1);
   7.172 +	mnreset();
   7.173 +	for (;;) {
   7.174 +		if (*s == '-') {
   7.175 +			if (m == 0)
   7.176 +				m = 1;
   7.177 +			n = LONG_MAX;
   7.178 +			lp = &n;
   7.179 +			s++;
   7.180 +		} else if (*s == ',' || *s == ' ' || *s == '\t' || *s == '\0') {
   7.181 +			if (m)
   7.182 +				addrange(m, n);
   7.183 +			mnreset();
   7.184 +			if (*s == '\0')
   7.185 +				break;
   7.186 +			s++;
   7.187 +		} else if (isdigit(*s & 0377)) {
   7.188 +			cp = cbuf;
   7.189 +			do
   7.190 +				*cp++ = *s++;
   7.191 +			while (isdigit(*s & 0377));
   7.192 +			*cp = '\0';
   7.193 +			*lp = strtol(cbuf, NULL, 10);
   7.194 +		} else
   7.195 +			badlist();
   7.196 +	}
   7.197 +	if (fields == NULL)
   7.198 +		error("no fields");
   7.199 +	free(cbuf);
   7.200 +}
   7.201 +
   7.202 +static void
   7.203 +cutb(struct iblok *ip)
   7.204 +{
   7.205 +	int	c, i;
   7.206 +
   7.207 +	i = 1;
   7.208 +	while ((c = ib_get(ip)) != EOF) {
   7.209 +		if (c == '\n') {
   7.210 +			i = 1;
   7.211 +			putc(c, stdout);
   7.212 +		} else if (have(i++))
   7.213 +			putc(c, stdout);
   7.214 +	}
   7.215 +}
   7.216 +
   7.217 +static void
   7.218 +cutbn(struct iblok *ip)
   7.219 +{
   7.220 +	char	*cp;
   7.221 +	int	i, m, n;
   7.222 +	wint_t	wc;
   7.223 +
   7.224 +	i = 1;
   7.225 +	while ((cp = ib_getw(ip, &wc, &n)) != NULL) {
   7.226 +		if (wc == '\n') {
   7.227 +			i = 1;
   7.228 +			putc('\n', stdout);
   7.229 +		} else {
   7.230 +			if (have(i + n - 1))
   7.231 +				for (m = 0; m < n; m++)
   7.232 +					putc(cp[m], stdout);
   7.233 +			i += n;
   7.234 +		}
   7.235 +	}
   7.236 +}
   7.237 +
   7.238 +static void
   7.239 +cutc(struct iblok *ip)
   7.240 +{
   7.241 +	char	*cp;
   7.242 +	int	i, n, m;
   7.243 +	wint_t	wc;
   7.244 +
   7.245 +	i = 1;
   7.246 +	while ((cp = ib_getw(ip, &wc, &n)) != NULL) {
   7.247 +		if (wc == '\n') {
   7.248 +			i = 1;
   7.249 +			putc('\n', stdout);
   7.250 +		} else if (wc != WEOF && have(i++)) {
   7.251 +			for (m = 0; m < n; m++)
   7.252 +				putc(cp[m], stdout);
   7.253 +		}
   7.254 +	}
   7.255 +}
   7.256 +
   7.257 +static void
   7.258 +cutf(struct iblok *ip)
   7.259 +{
   7.260 +	static char	*line;
   7.261 +	static size_t	linesize;
   7.262 +	char	*cp, *lp, *lq;
   7.263 +	int	c, i, n, m, gotcha;
   7.264 +	char	b;
   7.265 +	wint_t	wc;
   7.266 +	const int	incr = 128;
   7.267 +
   7.268 +	if (linesize == 0)
   7.269 +		line = smalloc(linesize = incr);
   7.270 +	lp = line;
   7.271 +	gotcha = 0;
   7.272 +	i = 1;
   7.273 +	do {
   7.274 +		if (multibyte)
   7.275 +			cp = ib_getw(ip, &wc, &n);
   7.276 +		else {
   7.277 +			if ((c = ib_get(ip)) != EOF) {
   7.278 +				wc = c;
   7.279 +				b = (char)c;
   7.280 +				cp = &b;
   7.281 +			} else {
   7.282 +				wc = WEOF;
   7.283 +				cp = NULL;
   7.284 +			}
   7.285 +			n = 1;
   7.286 +		}
   7.287 +		if (cp == NULL || wc == '\n' || wc == wcdelim) {
   7.288 +			if (have(i) && (!sflag || gotcha || wc == wcdelim) ||
   7.289 +					(!sflag && i == 1 &&
   7.290 +						(cp == NULL || wc == '\n'))) {
   7.291 +				if (gotcha)
   7.292 +					for (m = 0; mbdelim[m]; m++)
   7.293 +						putc(mbdelim[m], stdout);
   7.294 +				for (lq = line; lq < lp; lq++)
   7.295 +					putc(*lq, stdout);
   7.296 +				gotcha = 1;
   7.297 +			}
   7.298 +			if (wc == '\n') {
   7.299 +				if (gotcha)
   7.300 +					putc('\n', stdout);
   7.301 +				i = 1;
   7.302 +				gotcha = 0;
   7.303 +			} else
   7.304 +				i++;
   7.305 +			lp = line;
   7.306 +		} else {
   7.307 +			for (m = 0; m < n; m++) {
   7.308 +				if (lp >= &line[linesize]) {
   7.309 +					size_t	diff = lp - line;
   7.310 +					line = lrealloc(line, linesize += incr);
   7.311 +					lp = &line[diff];
   7.312 +				}
   7.313 +				*lp++ = cp[m];
   7.314 +			}
   7.315 +		}
   7.316 +	} while (cp != NULL);
   7.317 +}
   7.318 +
   7.319 +static int
   7.320 +fdcut(int fd)
   7.321 +{
   7.322 +	struct iblok	*ip;
   7.323 +
   7.324 +	ip = ib_alloc(fd, 0);
   7.325 +	switch (method) {
   7.326 +	case 'b':
   7.327 +		if (nflag && multibyte)
   7.328 +			cutbn(ip);
   7.329 +		else
   7.330 +			cutb(ip);
   7.331 +		break;
   7.332 +	case 'c':
   7.333 +		if (multibyte)
   7.334 +			cutc(ip);
   7.335 +		else
   7.336 +			cutb(ip);
   7.337 +		break;
   7.338 +	case 'f':
   7.339 +		cutf(ip);
   7.340 +		break;
   7.341 +	}
   7.342 +	ib_free(ip);
   7.343 +	return 0;
   7.344 +}
   7.345 +
   7.346 +static int
   7.347 +fncut(const char *fn)
   7.348 +{
   7.349 +	int	fd, res;
   7.350 +
   7.351 +	if (fn[0] == '-' && fn[1] == '\0')
   7.352 +		fd = 0;
   7.353 +	else if ((fd = open(fn, O_RDONLY)) < 0) {
   7.354 +		fprintf(stderr, "%s: WARNING: cannot open %s\n", progname, fn);
   7.355 +		return 1;
   7.356 +	}
   7.357 +	res = fdcut(fd);
   7.358 +	if (fd)
   7.359 +		close(fd);
   7.360 +	return res;
   7.361 +}
   7.362 +
   7.363 +int
   7.364 +main(int argc, char **argv)
   7.365 +{
   7.366 +	const char	optstring[] = "b:c:d:f:ns";
   7.367 +	int	i;
   7.368 +
   7.369 +	progname = basename(argv[0]);
   7.370 +	setlocale(LC_CTYPE, "");
   7.371 +	multibyte = MB_CUR_MAX > 1;
   7.372 +#ifdef	__GLIBC__
   7.373 +	putenv("POSIXLY_CORRECT=1");
   7.374 +#endif
   7.375 +	while ((i = getopt(argc, argv, optstring)) != EOF) {
   7.376 +		switch (i) {
   7.377 +		case 'b':
   7.378 +		case 'c':
   7.379 +		case 'f':
   7.380 +			if (method && method != i)
   7.381 +				usage();
   7.382 +			method = i;
   7.383 +			setlist(optarg);
   7.384 +			break;
   7.385 +		case 'd':
   7.386 +			setdelim(optarg);
   7.387 +			break;
   7.388 +		case 'n':
   7.389 +			nflag = 1;
   7.390 +			break;
   7.391 +		case 's':
   7.392 +			sflag = 1;
   7.393 +			break;
   7.394 +		default:
   7.395 +			usage();
   7.396 +		}
   7.397 +	}
   7.398 +	/*if ((sflag && method != 'f') || (nflag && method != 'b'))
   7.399 +		usage();*/
   7.400 +	if (method == 0)
   7.401 +		badlist();
   7.402 +	if (argv[optind]) {
   7.403 +		for (i = optind; argv[i]; i++)
   7.404 +			errcnt |= fncut(argv[i]);
   7.405 +	} else
   7.406 +		errcnt |= fdcut(0);
   7.407 +	return errcnt;
   7.408 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/code/cut.c__netbsd.1993-03-21	Tue May 12 06:46:59 2015 +0200
     8.3 @@ -0,0 +1,270 @@
     8.4 +/*
     8.5 + * Copyright (c) 1989 The Regents of the University of California.
     8.6 + * All rights reserved.
     8.7 + *
     8.8 + * This code is derived from software contributed to Berkeley by
     8.9 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
    8.10 + *
    8.11 + * Redistribution and use in source and binary forms, with or without
    8.12 + * modification, are permitted provided that the following conditions
    8.13 + * are met:
    8.14 + * 1. Redistributions of source code must retain the above copyright
    8.15 + *    notice, this list of conditions and the following disclaimer.
    8.16 + * 2. Redistributions in binary form must reproduce the above copyright
    8.17 + *    notice, this list of conditions and the following disclaimer in the
    8.18 + *    documentation and/or other materials provided with the distribution.
    8.19 + * 3. All advertising materials mentioning features or use of this software
    8.20 + *    must display the following acknowledgement:
    8.21 + *	This product includes software developed by the University of
    8.22 + *	California, Berkeley and its contributors.
    8.23 + * 4. Neither the name of the University nor the names of its contributors
    8.24 + *    may be used to endorse or promote products derived from this software
    8.25 + *    without specific prior written permission.
    8.26 + *
    8.27 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    8.28 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    8.29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    8.30 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    8.31 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    8.32 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    8.33 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    8.34 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    8.35 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    8.36 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    8.37 + * SUCH DAMAGE.
    8.38 + */
    8.39 +
    8.40 +#ifndef lint
    8.41 +char copyright[] =
    8.42 +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
    8.43 + All rights reserved.\n";
    8.44 +#endif /* not lint */
    8.45 +
    8.46 +#ifndef lint
    8.47 +static char sccsid[] = "@(#)cut.c	5.4 (Berkeley) 10/30/90";
    8.48 +#endif /* not lint */
    8.49 +
    8.50 +#include <limits.h>
    8.51 +#include <stdio.h>
    8.52 +#include <ctype.h>
    8.53 +
    8.54 +int	cflag;
    8.55 +char	dchar;
    8.56 +int	dflag;
    8.57 +int	fflag;
    8.58 +int	sflag;
    8.59 +
    8.60 +main(argc, argv)
    8.61 +	int argc;
    8.62 +	char **argv;
    8.63 +{
    8.64 +	extern char *optarg;
    8.65 +	extern int errno, optind;
    8.66 +	FILE *fp;
    8.67 +	int ch, (*fcn)(), c_cut(), f_cut();
    8.68 +	char *strerror();
    8.69 +
    8.70 +	dchar = '\t';			/* default delimiter is \t */
    8.71 +
    8.72 +	while ((ch = getopt(argc, argv, "c:d:f:s")) != EOF)
    8.73 +		switch(ch) {
    8.74 +		case 'c':
    8.75 +			fcn = c_cut;
    8.76 +			get_list(optarg);
    8.77 +			cflag = 1;
    8.78 +			break;
    8.79 +		case 'd':
    8.80 +			dchar = *optarg;
    8.81 +			dflag = 1;
    8.82 +			break;
    8.83 +		case 'f':
    8.84 +			get_list(optarg);
    8.85 +			fcn = f_cut;
    8.86 +			fflag = 1;
    8.87 +			break;
    8.88 +		case 's':
    8.89 +			sflag = 1;
    8.90 +			break;
    8.91 +		case '?':
    8.92 +		default:
    8.93 +			usage();
    8.94 +		}
    8.95 +	argc -= optind;
    8.96 +	argv += optind;
    8.97 +
    8.98 +	if (fflag) {
    8.99 +		if (cflag)
   8.100 +			usage();
   8.101 +	} else if (!cflag || dflag || sflag)
   8.102 +		usage();
   8.103 +
   8.104 +	if (*argv)
   8.105 +		for (; *argv; ++argv) {
   8.106 +			if (!(fp = fopen(*argv, "r"))) {
   8.107 +				(void)fprintf(stderr,
   8.108 +				    "cut: %s: %s\n", *argv, strerror(errno));
   8.109 +				exit(1);
   8.110 +			}
   8.111 +			fcn(fp, *argv);
   8.112 +		}
   8.113 +	else
   8.114 +		fcn(stdin, "stdin");
   8.115 +	exit(0);
   8.116 +}
   8.117 +
   8.118 +int autostart, autostop, maxval;
   8.119 +
   8.120 +char positions[_POSIX2_LINE_MAX + 1];
   8.121 +
   8.122 +get_list(list)
   8.123 +	char *list;
   8.124 +{
   8.125 +	register char *pos;
   8.126 +	register int setautostart, start, stop;
   8.127 +	char *p, *strtok();
   8.128 +
   8.129 +	/*
   8.130 +	 * set a byte in the positions array to indicate if a field or
   8.131 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
   8.132 +	 * This parser is less restrictive than the Draft 9 POSIX spec.
   8.133 +	 * POSIX doesn't allow lists that aren't in increasing order or
   8.134 +	 * overlapping lists.  We also handle "-3-5" although there's no
   8.135 +	 * real reason too.
   8.136 +	 */
   8.137 +	for (; p = strtok(list, ", \t"); list = NULL) {
   8.138 +		setautostart = start = stop = 0;
   8.139 +		if (*p == '-') {
   8.140 +			++p;
   8.141 +			setautostart = 1;
   8.142 +		}
   8.143 +		if (isdigit(*p)) {
   8.144 +			start = stop = strtol(p, &p, 10);
   8.145 +			if (setautostart && start > autostart)
   8.146 +				autostart = start;
   8.147 +		}
   8.148 +		if (*p == '-') {
   8.149 +			if (isdigit(p[1]))
   8.150 +				stop = strtol(p + 1, &p, 10);
   8.151 +			if (*p == '-') {
   8.152 +				++p;
   8.153 +				if (!autostop || autostop > stop)
   8.154 +					autostop = stop;
   8.155 +			}
   8.156 +		}
   8.157 +		if (*p)
   8.158 +			badlist("illegal list value");
   8.159 +		if (!stop || !start)
   8.160 +			badlist("values may not include zero");
   8.161 +		if (stop > _POSIX2_LINE_MAX) {
   8.162 +			/* positions used rather than allocate a new buffer */
   8.163 +			(void)sprintf(positions, "%d too large (max %d)",
   8.164 +			    stop, _POSIX2_LINE_MAX);
   8.165 +			badlist(positions);
   8.166 +		}
   8.167 +		if (maxval < stop)
   8.168 +			maxval = stop;
   8.169 +		for (pos = positions + start; start++ <= stop; *pos++ = 1);
   8.170 +	}
   8.171 +
   8.172 +	/* overlapping ranges */
   8.173 +	if (autostop && maxval > autostop)
   8.174 +		maxval = autostop;
   8.175 +
   8.176 +	/* set autostart */
   8.177 +	if (autostart)
   8.178 +		memset(positions + 1, '1', autostart);
   8.179 +}
   8.180 +
   8.181 +/* ARGSUSED */
   8.182 +c_cut(fp, fname)
   8.183 +	FILE *fp;
   8.184 +	char *fname;
   8.185 +{
   8.186 +	register int ch, col;
   8.187 +	register char *pos;
   8.188 +
   8.189 +	for (;;) {
   8.190 +		pos = positions + 1;
   8.191 +		for (col = maxval; col; --col) {
   8.192 +			if ((ch = getc(fp)) == EOF)
   8.193 +				return;
   8.194 +			if (ch == '\n')
   8.195 +				break;
   8.196 +			if (*pos++)
   8.197 +				putchar(ch);
   8.198 +		}
   8.199 +		if (ch != '\n')
   8.200 +			if (autostop)
   8.201 +				while ((ch = getc(fp)) != EOF && ch != '\n')
   8.202 +					putchar(ch);
   8.203 +			else
   8.204 +				while ((ch = getc(fp)) != EOF && ch != '\n');
   8.205 +		putchar('\n');
   8.206 +	}
   8.207 +}
   8.208 +
   8.209 +f_cut(fp, fname)
   8.210 +	FILE *fp;
   8.211 +	char *fname;
   8.212 +{
   8.213 +	register int ch, field, isdelim;
   8.214 +	register char *pos, *p, sep;
   8.215 +	int output;
   8.216 +	char lbuf[_POSIX2_LINE_MAX + 1];
   8.217 +
   8.218 +	for (sep = dchar, output = 0; fgets(lbuf, sizeof(lbuf), fp);) {
   8.219 +		for (isdelim = 0, p = lbuf;; ++p) {
   8.220 +			if (!(ch = *p)) {
   8.221 +				(void)fprintf(stderr,
   8.222 +				    "cut: %s: line too long.\n", fname);
   8.223 +				exit(1);
   8.224 +			}
   8.225 +			/* this should work if newline is delimiter */
   8.226 +			if (ch == sep)
   8.227 +				isdelim = 1;
   8.228 +			if (ch == '\n') {
   8.229 +				if (!isdelim && !sflag)
   8.230 +					(void)printf("%s", lbuf);
   8.231 +				break;
   8.232 +			}
   8.233 +		}
   8.234 +		if (!isdelim)
   8.235 +			continue;
   8.236 +
   8.237 +		pos = positions + 1;
   8.238 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
   8.239 +			if (*pos) {
   8.240 +				if (output++)
   8.241 +					putchar(sep);
   8.242 +				while ((ch = *p++) != '\n' && ch != sep)
   8.243 +					putchar(ch);
   8.244 +			} else
   8.245 +				while ((ch = *p++) != '\n' && ch != sep);
   8.246 +			if (ch == '\n')
   8.247 +				break;
   8.248 +		}
   8.249 +		if (ch != '\n')
   8.250 +			if (autostop) {
   8.251 +				if (output)
   8.252 +					putchar(sep);
   8.253 +				for (; (ch = *p) != '\n'; ++p)
   8.254 +					putchar(ch);
   8.255 +			} else
   8.256 +				for (; (ch = *p) != '\n'; ++p);
   8.257 +		putchar('\n');
   8.258 +	}
   8.259 +}
   8.260 +
   8.261 +badlist(msg)
   8.262 +	char *msg;
   8.263 +{
   8.264 +	(void)fprintf(stderr, "cut: [-cf] list: %s.\n", msg);
   8.265 +	exit(1);
   8.266 +}
   8.267 +
   8.268 +usage()
   8.269 +{
   8.270 +	(void)fprintf(stderr,
   8.271 +"usage:\tcut -c list [file1 ...]\n\tcut -f list [-s] [-d delim] [file ...]\n");
   8.272 +	exit(1);
   8.273 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/code/cut.c__netbsd.2014-02-03	Tue May 12 06:46:59 2015 +0200
     9.3 @@ -0,0 +1,306 @@
     9.4 +/*	$NetBSD: cut.c,v 1.29 2014/02/03 20:22:19 wiz Exp $	*/
     9.5 +
     9.6 +/*
     9.7 + * Copyright (c) 1989, 1993
     9.8 + *	The Regents of the University of California.  All rights reserved.
     9.9 + *
    9.10 + * This code is derived from software contributed to Berkeley by
    9.11 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
    9.12 + *
    9.13 + * Redistribution and use in source and binary forms, with or without
    9.14 + * modification, are permitted provided that the following conditions
    9.15 + * are met:
    9.16 + * 1. Redistributions of source code must retain the above copyright
    9.17 + *    notice, this list of conditions and the following disclaimer.
    9.18 + * 2. Redistributions in binary form must reproduce the above copyright
    9.19 + *    notice, this list of conditions and the following disclaimer in the
    9.20 + *    documentation and/or other materials provided with the distribution.
    9.21 + * 3. Neither the name of the University nor the names of its contributors
    9.22 + *    may be used to endorse or promote products derived from this software
    9.23 + *    without specific prior written permission.
    9.24 + *
    9.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    9.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    9.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    9.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    9.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    9.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    9.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    9.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    9.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    9.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    9.35 + * SUCH DAMAGE.
    9.36 + */
    9.37 +
    9.38 +#include <sys/cdefs.h>
    9.39 +#ifndef lint
    9.40 +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
    9.41 + The Regents of the University of California.  All rights reserved.");
    9.42 +#endif /* not lint */
    9.43 +
    9.44 +#ifndef lint
    9.45 +#if 0
    9.46 +static char sccsid[] = "@(#)cut.c	8.3 (Berkeley) 5/4/95";
    9.47 +#endif
    9.48 +__RCSID("$NetBSD: cut.c,v 1.29 2014/02/03 20:22:19 wiz Exp $");
    9.49 +#endif /* not lint */
    9.50 +
    9.51 +#include <ctype.h>
    9.52 +#include <err.h>
    9.53 +#include <errno.h>
    9.54 +#include <limits.h>
    9.55 +#include <locale.h>
    9.56 +#include <stdio.h>
    9.57 +#include <stdlib.h>
    9.58 +#include <string.h>
    9.59 +#include <unistd.h>
    9.60 +#include <util.h>
    9.61 +#include <wchar.h>
    9.62 +#include <sys/param.h>
    9.63 +
    9.64 +static int bflag;
    9.65 +static int	cflag;
    9.66 +static char	dchar;
    9.67 +static int	dflag;
    9.68 +static int	fflag;
    9.69 +static int	sflag;
    9.70 +
    9.71 +static void	b_cut(FILE *, const char *);
    9.72 +static void	c_cut(FILE *, const char *);
    9.73 +static void	f_cut(FILE *, const char *);
    9.74 +static void	get_list(char *);
    9.75 +static void	usage(void) __dead;
    9.76 +
    9.77 +int
    9.78 +main(int argc, char *argv[])
    9.79 +{
    9.80 +	FILE *fp;
    9.81 +	void (*fcn)(FILE *, const char *);
    9.82 +	int ch, rval;
    9.83 +
    9.84 +	fcn = NULL;
    9.85 +	(void)setlocale(LC_ALL, "");
    9.86 +
    9.87 +	dchar = '\t';			/* default delimiter is \t */
    9.88 +
    9.89 +	/* Since we don't support multi-byte characters, the -c and -b
    9.90 +	   options are equivalent, and the -n option is meaningless. */
    9.91 +	while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1)
    9.92 +		switch(ch) {
    9.93 +		case 'b':
    9.94 +			fcn = b_cut;
    9.95 +			get_list(optarg);
    9.96 +			bflag = 1;
    9.97 +			break;
    9.98 +		case 'c':
    9.99 +			fcn = c_cut;
   9.100 +			get_list(optarg);
   9.101 +			cflag = 1;
   9.102 +			break;
   9.103 +		case 'd':
   9.104 +			dchar = *optarg;
   9.105 +			dflag = 1;
   9.106 +			break;
   9.107 +		case 'f':
   9.108 +			get_list(optarg);
   9.109 +			fcn = f_cut;
   9.110 +			fflag = 1;
   9.111 +			break;
   9.112 +		case 's':
   9.113 +			sflag = 1;
   9.114 +			break;
   9.115 +		case 'n':
   9.116 +			break;
   9.117 +		case '?':
   9.118 +		default:
   9.119 +			usage();
   9.120 +		}
   9.121 +	argc -= optind;
   9.122 +	argv += optind;
   9.123 +
   9.124 +	if (fflag) {
   9.125 +		if (cflag || bflag)
   9.126 +			usage();
   9.127 +	} else if ((!cflag && !bflag) || dflag || sflag)
   9.128 +		usage();
   9.129 +	else if (bflag && cflag)
   9.130 +		usage();
   9.131 +
   9.132 +	rval = 0;
   9.133 +	if (*argv)
   9.134 +		for (; *argv; ++argv) {
   9.135 +			if (strcmp(*argv, "-") == 0)
   9.136 +				fcn(stdin, "stdin");
   9.137 +			else {
   9.138 +				if ((fp = fopen(*argv, "r"))) {
   9.139 +					fcn(fp, *argv);
   9.140 +					(void)fclose(fp);
   9.141 +				} else {
   9.142 +					rval = 1;
   9.143 +					warn("%s", *argv);
   9.144 +				}
   9.145 +			}
   9.146 +		}
   9.147 +	else
   9.148 +		fcn(stdin, "stdin");
   9.149 +	return(rval);
   9.150 +}
   9.151 +
   9.152 +static size_t autostart, autostop, maxval;
   9.153 +
   9.154 +static char *positions = NULL;
   9.155 +static size_t numpositions = 0;
   9.156 +#define ALLOC_CHUNK	_POSIX2_LINE_MAX	/* malloc granularity */
   9.157 +
   9.158 +static void
   9.159 +get_list(char *list)
   9.160 +{
   9.161 +	size_t setautostart, start, stop;
   9.162 +	char *pos;
   9.163 +	char *p;
   9.164 +
   9.165 +	if (positions == NULL) {
   9.166 +		numpositions = ALLOC_CHUNK;
   9.167 +		positions = ecalloc(numpositions, sizeof(*positions));
   9.168 +	}
   9.169 +
   9.170 +	/*
   9.171 +	 * set a byte in the positions array to indicate if a field or
   9.172 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
   9.173 +	 * This parser is less restrictive than the Draft 9 POSIX spec.
   9.174 +	 * POSIX doesn't allow lists that aren't in increasing order or
   9.175 +	 * overlapping lists.  We also handle "-3-5" although there's no
   9.176 +	 * real reason to.
   9.177 +	 */
   9.178 +	for (; (p = strtok(list, ", \t")) != NULL; list = NULL) {
   9.179 +		setautostart = start = stop = 0;
   9.180 +		if (*p == '-') {
   9.181 +			++p;
   9.182 +			setautostart = 1;
   9.183 +		}
   9.184 +		if (isdigit((unsigned char)*p)) {
   9.185 +			start = stop = strtol(p, &p, 10);
   9.186 +			if (setautostart && start > autostart)
   9.187 +				autostart = start;
   9.188 +		}
   9.189 +		if (*p == '-') {
   9.190 +			if (isdigit((unsigned char)p[1]))
   9.191 +				stop = strtol(p + 1, &p, 10);
   9.192 +			if (*p == '-') {
   9.193 +				++p;
   9.194 +				if (!autostop || autostop > stop)
   9.195 +					autostop = stop;
   9.196 +			}
   9.197 +		}
   9.198 +		if (*p)
   9.199 +			errx(1, "[-bcf] list: illegal list value");
   9.200 +		if (!stop || !start)
   9.201 +			errx(1, "[-bcf] list: values may not include zero");
   9.202 +		if (stop + 1 > numpositions) {
   9.203 +			size_t newsize;
   9.204 +			newsize = roundup(stop + 1, ALLOC_CHUNK);
   9.205 +			positions = erealloc(positions, newsize);
   9.206 +			(void)memset(positions + numpositions, 0,
   9.207 +			    newsize - numpositions);
   9.208 +			numpositions = newsize;
   9.209 +		}
   9.210 +		if (maxval < stop)
   9.211 +			maxval = stop;
   9.212 +		for (pos = positions + start; start++ <= stop; pos++)
   9.213 +			*pos = 1;
   9.214 +	}
   9.215 +
   9.216 +	/* overlapping ranges */
   9.217 +	if (autostop && maxval > autostop)
   9.218 +		maxval = autostop;
   9.219 +
   9.220 +	/* set autostart */
   9.221 +	if (autostart)
   9.222 +		(void)memset(positions + 1, '1', autostart);
   9.223 +}
   9.224 +
   9.225 +static void
   9.226 +/*ARGSUSED*/
   9.227 +f_cut(FILE *fp, const char *fname __unused)
   9.228 +{
   9.229 +	int ch, field, isdelim;
   9.230 +	char *pos, *p, sep;
   9.231 +	int output;
   9.232 +	size_t len;
   9.233 +	char *lbuf, *tbuf;
   9.234 +
   9.235 +	for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len)) != NULL;) {
   9.236 +		output = 0;
   9.237 +		if (lbuf[len - 1] != '\n') {
   9.238 +			/* no newline at the end of the last line so add one */
   9.239 +			if ((tbuf = (char *)malloc(len + 1)) == NULL)
   9.240 +				err(1, NULL);
   9.241 +			(void)memcpy(tbuf, lbuf, len);
   9.242 +			tbuf[len++] = '\n';
   9.243 +			lbuf = tbuf;
   9.244 +		}
   9.245 +		for (isdelim = 0, p = lbuf;; ++p) {
   9.246 +			ch = *p;
   9.247 +			/* this should work if newline is delimiter */
   9.248 +			if (ch == sep)
   9.249 +				isdelim = 1;
   9.250 +			if (ch == '\n') {
   9.251 +				if (!isdelim && !sflag)
   9.252 +					(void)fwrite(lbuf, len, 1, stdout);
   9.253 +				break;
   9.254 +			}
   9.255 +		}
   9.256 +		if (!isdelim)
   9.257 +			continue;
   9.258 +
   9.259 +		pos = positions + 1;
   9.260 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
   9.261 +			if (*pos) {
   9.262 +				if (output++)
   9.263 +					(void)putchar(sep);
   9.264 +				while ((ch = *p++) != '\n' && ch != sep)
   9.265 +					(void)putchar(ch);
   9.266 +			} else {
   9.267 +				while ((ch = *p++) != '\n' && ch != sep)
   9.268 +					continue;
   9.269 +			}
   9.270 +			if (ch == '\n')
   9.271 +				break;
   9.272 +		}
   9.273 +		if (ch != '\n') {
   9.274 +			if (autostop) {
   9.275 +				if (output)
   9.276 +					(void)putchar(sep);
   9.277 +				for (; (ch = *p) != '\n'; ++p)
   9.278 +					(void)putchar(ch);
   9.279 +			} else
   9.280 +				for (; (ch = *p) != '\n'; ++p);
   9.281 +		}
   9.282 +		(void)putchar('\n');
   9.283 +		if (tbuf) {
   9.284 +			free(tbuf);
   9.285 +			tbuf = NULL;
   9.286 +		}
   9.287 +	}
   9.288 +	if (tbuf)
   9.289 +		free(tbuf);
   9.290 +}
   9.291 +
   9.292 +static void
   9.293 +usage(void)
   9.294 +{
   9.295 +	(void)fprintf(stderr, "usage:\tcut -b list [-n] [file ...]\n"
   9.296 +	    "\tcut -c list [file ...]\n"
   9.297 +	    "\tcut -f list [-d string] [-s] [file ...]\n");
   9.298 +	exit(1);
   9.299 +}
   9.300 +
   9.301 +/* make b_put(): */
   9.302 +#define CUT_BYTE 1
   9.303 +#include "x_cut.c"
   9.304 +#undef CUT_BYTE
   9.305 +
   9.306 +/* make c_put(): */
   9.307 +#define CUT_BYTE 0
   9.308 +#include "x_cut.c"
   9.309 +#undef CUT_BYTE
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/code/cut.c__openbsd.2008-06-27	Tue May 12 06:46:59 2015 +0200
    10.3 @@ -0,0 +1,290 @@
    10.4 +/*	$OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $	*/
    10.5 +/*	$NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $	*/
    10.6 +
    10.7 +/*
    10.8 + * Copyright (c) 1989, 1993
    10.9 + *	The Regents of the University of California.  All rights reserved.
   10.10 + *
   10.11 + * This code is derived from software contributed to Berkeley by
   10.12 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
   10.13 + *
   10.14 + * Redistribution and use in source and binary forms, with or without
   10.15 + * modification, are permitted provided that the following conditions
   10.16 + * are met:
   10.17 + * 1. Redistributions of source code must retain the above copyright
   10.18 + *    notice, this list of conditions and the following disclaimer.
   10.19 + * 2. Redistributions in binary form must reproduce the above copyright
   10.20 + *    notice, this list of conditions and the following disclaimer in the
   10.21 + *    documentation and/or other materials provided with the distribution.
   10.22 + * 3. Neither the name of the University nor the names of its contributors
   10.23 + *    may be used to endorse or promote products derived from this software
   10.24 + *    without specific prior written permission.
   10.25 + *
   10.26 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   10.27 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   10.28 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   10.29 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   10.30 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   10.31 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   10.32 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   10.33 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   10.34 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   10.35 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   10.36 + * SUCH DAMAGE.
   10.37 + */
   10.38 +
   10.39 +#ifndef lint
   10.40 +static char copyright[] =
   10.41 +"@(#) Copyright (c) 1989, 1993\n\
   10.42 +	The Regents of the University of California.  All rights reserved.\n";
   10.43 +#endif /* not lint */
   10.44 +
   10.45 +#ifndef lint
   10.46 +#if 0
   10.47 +static char sccsid[] = "@(#)cut.c	8.3 (Berkeley) 5/4/95";
   10.48 +#endif
   10.49 +static char rcsid[] = "$OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $";
   10.50 +#endif /* not lint */
   10.51 +
   10.52 +#include <ctype.h>
   10.53 +#include <err.h>
   10.54 +#include <errno.h>
   10.55 +#include <limits.h>
   10.56 +#include <locale.h>
   10.57 +#include <stdio.h>
   10.58 +#include <stdlib.h>
   10.59 +#include <string.h>
   10.60 +#include <unistd.h>
   10.61 +
   10.62 +int	cflag;
   10.63 +char	dchar;
   10.64 +int	dflag;
   10.65 +int	fflag;
   10.66 +int	sflag;
   10.67 +
   10.68 +void	c_cut(FILE *, char *);
   10.69 +void	f_cut(FILE *, char *);
   10.70 +void	get_list(char *);
   10.71 +void	usage(void);
   10.72 +
   10.73 +int
   10.74 +main(int argc, char *argv[])
   10.75 +{
   10.76 +	FILE *fp;
   10.77 +	void (*fcn)(FILE *, char *);
   10.78 +	int ch;
   10.79 +
   10.80 +	setlocale (LC_ALL, "");
   10.81 +
   10.82 +	dchar = '\t';			/* default delimiter is \t */
   10.83 +
   10.84 +	/* Since we don't support multi-byte characters, the -c and -b 
   10.85 +	   options are equivalent, and the -n option is meaningless. */
   10.86 +	while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1)
   10.87 +		switch(ch) {
   10.88 +		case 'b':
   10.89 +		case 'c':
   10.90 +			fcn = c_cut;
   10.91 +			get_list(optarg);
   10.92 +			cflag = 1;
   10.93 +			break;
   10.94 +		case 'd':
   10.95 +			dchar = *optarg;
   10.96 +			dflag = 1;
   10.97 +			break;
   10.98 +		case 'f':
   10.99 +			get_list(optarg);
  10.100 +			fcn = f_cut;
  10.101 +			fflag = 1;
  10.102 +			break;
  10.103 +		case 's':
  10.104 +			sflag = 1;
  10.105 +			break;
  10.106 +		case 'n':
  10.107 +			break;
  10.108 +		case '?':
  10.109 +		default:
  10.110 +			usage();
  10.111 +		}
  10.112 +	argc -= optind;
  10.113 +	argv += optind;
  10.114 +
  10.115 +	if (fflag) {
  10.116 +		if (cflag)
  10.117 +			usage();
  10.118 +	} else if (!cflag || dflag || sflag)
  10.119 +		usage();
  10.120 +
  10.121 +	if (*argv)
  10.122 +		for (; *argv; ++argv) {
  10.123 +			if (!(fp = fopen(*argv, "r")))
  10.124 +				err(1, "%s", *argv);
  10.125 +			fcn(fp, *argv);
  10.126 +			(void)fclose(fp);
  10.127 +		}
  10.128 +	else
  10.129 +		fcn(stdin, "stdin");
  10.130 +	exit(0);
  10.131 +}
  10.132 +
  10.133 +int autostart, autostop, maxval;
  10.134 +
  10.135 +char positions[_POSIX2_LINE_MAX + 1];
  10.136 +
  10.137 +void
  10.138 +get_list(char *list)
  10.139 +{
  10.140 +	int setautostart, start, stop;
  10.141 +	char *pos;
  10.142 +	char *p;
  10.143 +
  10.144 +	/*
  10.145 +	 * set a byte in the positions array to indicate if a field or
  10.146 +	 * column is to be selected; use +1, it's 1-based, not 0-based.
  10.147 +	 * This parser is less restrictive than the Draft 9 POSIX spec.
  10.148 +	 * POSIX doesn't allow lists that aren't in increasing order or
  10.149 +	 * overlapping lists.  We also handle "-3-5" although there's no
  10.150 +	 * real reason too.
  10.151 +	 */
  10.152 +	while ((p = strsep(&list, ", \t"))) {
  10.153 +		setautostart = start = stop = 0;
  10.154 +		if (*p == '-') {
  10.155 +			++p;
  10.156 +			setautostart = 1;
  10.157 +		}
  10.158 +		if (isdigit(*p)) {
  10.159 +			start = stop = strtol(p, &p, 10);
  10.160 +			if (setautostart && start > autostart)
  10.161 +				autostart = start;
  10.162 +		}
  10.163 +		if (*p == '-') {
  10.164 +			if (isdigit(p[1]))
  10.165 +				stop = strtol(p + 1, &p, 10);
  10.166 +			if (*p == '-') {
  10.167 +				++p;
  10.168 +				if (!autostop || autostop > stop)
  10.169 +					autostop = stop;
  10.170 +			}
  10.171 +		}
  10.172 +		if (*p)
  10.173 +			errx(1, "[-cf] list: illegal list value");
  10.174 +		if (!stop || !start)
  10.175 +			errx(1, "[-cf] list: values may not include zero");
  10.176 +		if (stop > _POSIX2_LINE_MAX)
  10.177 +			errx(1, "[-cf] list: %d too large (max %d)",
  10.178 +			    stop, _POSIX2_LINE_MAX);
  10.179 +		if (maxval < stop)
  10.180 +			maxval = stop;
  10.181 +		for (pos = positions + start; start++ <= stop; *pos++ = 1)
  10.182 +			;
  10.183 +	}
  10.184 +
  10.185 +	/* overlapping ranges */
  10.186 +	if (autostop && maxval > autostop)
  10.187 +		maxval = autostop;
  10.188 +
  10.189 +	/* set autostart */
  10.190 +	if (autostart)
  10.191 +		memset(positions + 1, '1', autostart);
  10.192 +}
  10.193 +
  10.194 +/* ARGSUSED */
  10.195 +void
  10.196 +c_cut(FILE *fp, char *fname)
  10.197 +{
  10.198 +	int ch, col;
  10.199 +	char *pos;
  10.200 +
  10.201 +	for (;;) {
  10.202 +		pos = positions + 1;
  10.203 +		for (col = maxval; col; --col) {
  10.204 +			if ((ch = getc(fp)) == EOF)
  10.205 +				return;
  10.206 +			if (ch == '\n')
  10.207 +				break;
  10.208 +			if (*pos++)
  10.209 +				(void)putchar(ch);
  10.210 +		}
  10.211 +		if (ch != '\n') {
  10.212 +			if (autostop)
  10.213 +				while ((ch = getc(fp)) != EOF && ch != '\n')
  10.214 +					(void)putchar(ch);
  10.215 +			else
  10.216 +				while ((ch = getc(fp)) != EOF && ch != '\n')
  10.217 +					;
  10.218 +		}
  10.219 +		(void)putchar('\n');
  10.220 +	}
  10.221 +}
  10.222 +
  10.223 +void
  10.224 +f_cut(FILE *fp, char *fname)
  10.225 +{
  10.226 +	int ch, field, isdelim;
  10.227 +	char *pos, *p, sep;
  10.228 +	int output;
  10.229 +	size_t len;
  10.230 +	char *lbuf, *tbuf;
  10.231 +
  10.232 +	for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len));) {
  10.233 +		output = 0;
  10.234 +		if (lbuf[len - 1] != '\n') {
  10.235 +			/* no newline at the end of the last line so add one */
  10.236 +			if ((tbuf = (char *)malloc(len + 1)) == NULL)
  10.237 +				err(1, NULL);
  10.238 +			memcpy(tbuf, lbuf, len);
  10.239 +			tbuf[len] = '\n';
  10.240 +			lbuf = tbuf;
  10.241 +		}
  10.242 +		for (isdelim = 0, p = lbuf;; ++p) {
  10.243 +			ch = *p;
  10.244 +			/* this should work if newline is delimiter */
  10.245 +			if (ch == sep)
  10.246 +				isdelim = 1;
  10.247 +			if (ch == '\n') {
  10.248 +				if (!isdelim && !sflag)
  10.249 +					(void)fwrite(lbuf, len, 1, stdout);
  10.250 +				break;
  10.251 +			}
  10.252 +		}
  10.253 +		if (!isdelim)
  10.254 +			continue;
  10.255 +
  10.256 +		pos = positions + 1;
  10.257 +		for (field = maxval, p = lbuf; field; --field, ++pos) {
  10.258 +			if (*pos) {
  10.259 +				if (output++)
  10.260 +					(void)putchar(sep);
  10.261 +				while ((ch = *p++) != '\n' && ch != sep)
  10.262 +					(void)putchar(ch);
  10.263 +			} else
  10.264 +				while ((ch = *p++) != '\n' && ch != sep)
  10.265 +					;
  10.266 +			if (ch == '\n')
  10.267 +				break;
  10.268 +		}
  10.269 +		if (ch != '\n') {
  10.270 +			if (autostop) {
  10.271 +				if (output)
  10.272 +					(void)putchar(sep);
  10.273 +				for (; (ch = *p) != '\n'; ++p)
  10.274 +					(void)putchar(ch);
  10.275 +			} else
  10.276 +				for (; (ch = *p) != '\n'; ++p)
  10.277 +					;
  10.278 +		}
  10.279 +		(void)putchar('\n');
  10.280 +	}
  10.281 +	if (tbuf)
  10.282 +		free(tbuf);
  10.283 +}
  10.284 +
  10.285 +void
  10.286 +usage(void)
  10.287 +{
  10.288 +	(void)fprintf(stderr,
  10.289 +	    "usage: cut -b list [-n] [file ...]\n"
  10.290 +	    "       cut -c list [file ...]\n"
  10.291 +	    "       cut -f list [-s] [-d delim] [file ...]\n");
  10.292 +	exit(1);
  10.293 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/code/cut.c__system_iii.1980-04-11	Tue May 12 06:46:59 2015 +0200
    11.3 @@ -0,0 +1,123 @@
    11.4 +#
    11.5 +/* cut : cut and paste columns of a table (projection of a relation)  (GWRL) */
    11.6 +/* Release 1.5; handles single backspaces as produced by nroff    */
    11.7 +# include <stdio.h>	/* make: cc cut.c */
    11.8 +# define NFIELDS 512	/* max no of fields or resulting line length */
    11.9 +# define BACKSPACE 8
   11.10 +main(argc, argv)
   11.11 +int argc; char **argv;
   11.12 +{
   11.13 +	int del = '\t';
   11.14 +	int i, j, count, poscnt, r, s, t;
   11.15 +	int endflag, supflag, cflag, fflag, backflag, filenr;
   11.16 +	int sel[NFIELDS];
   11.17 +	register int c;
   11.18 +	register char *p1;
   11.19 +	char *p2, outbuf[NFIELDS];
   11.20 +	FILE *inptr;
   11.21 + 
   11.22 + 
   11.23 +while (argc > 1 && argv[1][0] == '-'){
   11.24 +	for (i = 1; (c = argv[1][i]) != '\0'; i++) {
   11.25 +		switch(c) {
   11.26 +			case 'd' : del = argv[1][++i];
   11.27 +				if (del == '\0') diag("no delimiter\n");
   11.28 +				break;
   11.29 +			case 's': supflag++ ;
   11.30 +				break;
   11.31 +			case 'c': cflag++ ;
   11.32 +				break;
   11.33 +			case 'f': fflag++ ;
   11.34 +				break;
   11.35 +			default : diag("Usage: cut [-s] [-d<char>] {-c<list> | -f<list>} file ...\n");
   11.36 +				break;
   11.37 +		}
   11.38 +		if (!endflag && (cflag || fflag)) {
   11.39 +			endflag = 1;
   11.40 +			r = s = t = 0;
   11.41 +			do {	c = argv[1][++i];
   11.42 +				switch(c) {
   11.43 +					case '-' : if (r) diagl();
   11.44 +						r = 1;
   11.45 +						if (t == 0)  s = 1;
   11.46 +						else {s = t; t = 0;}
   11.47 +						continue;
   11.48 +					case '\0' :
   11.49 +					case ','  : if (t >= NFIELDS) diagl();
   11.50 +						if (r) { if (t == 0) t = NFIELDS - 1;
   11.51 +							if (t<s) diagl();
   11.52 +							for(j = s; j <= t; j++) sel[j] = 1;
   11.53 +							}
   11.54 +						else sel[t] = (t > 0 ? 1 : 0);
   11.55 +						r = s = t = 0;
   11.56 +						if (c == '\0') {i--; break;}
   11.57 +						continue;
   11.58 +					default :
   11.59 +						if (c< '0' || c> '9') diagl();
   11.60 +						t = 10*t + c - '0';
   11.61 +						continue;
   11.62 +				}
   11.63 +				for (j = t = 0; j < NFIELDS; j++) t += sel[j];
   11.64 +				if (t == 0) diag("no fields\n");
   11.65 +			} while (c != '\0');
   11.66 +		}
   11.67 +	}
   11.68 +	--argc;
   11.69 +	++argv;
   11.70 +} /* end options */
   11.71 +if (!(cflag || fflag)) diagl();
   11.72 +
   11.73 +--argc;
   11.74 +filenr = 1;
   11.75 +do {	/* for all input files */
   11.76 +	if (argc > 0) inptr = fopen(argv[filenr], "r");
   11.77 +	else inptr = stdin;
   11.78 +  
   11.79 +	if (inptr == NULL) {
   11.80 +		write(2,"Cannot open :",14);
   11.81 +		diag(argv[filenr]);
   11.82 +	}
   11.83 +	endflag = 0;
   11.84 +	do {	/* for all lines of a file */
   11.85 +		count = poscnt = backflag = 0;
   11.86 +		p1 = &outbuf[0] - 1 ;
   11.87 +		p2 = p1;
   11.88 +		do { 	/* for all char of the line */
   11.89 +			c = fgetc(inptr);
   11.90 +			if (c == EOF) {
   11.91 +				endflag = 1;
   11.92 +				break;
   11.93 +				}
   11.94 +			if (count == NFIELDS - 1) diag("line too long\n");
   11.95 +			if (c != '\n') *++p1 = c;
   11.96 +			if (cflag && (c == BACKSPACE)) backflag++ ; else 
   11.97 +				{ if ( !backflag ) poscnt += 1 ; else backflag-- ;}
   11.98 +			if ( backflag > 1 ) diag("cannot handle multiple adjacent backspaces\n");
   11.99 +			if ( ((c == '\n') && count > 0)  || c == del || cflag) {
  11.100 +				count += 1;
  11.101 +				if (fflag) poscnt = count  ;
  11.102 +				if (sel[poscnt]) p2 = p1; else p1 = p2;
  11.103 +			}
  11.104 +		}while (c != '\n');
  11.105 +		if ( !endflag && (count > 0 || !supflag)) {
  11.106 +			if (*p1 == del) *p1 = '\0';
  11.107 +				else *++p1 = '\0'; /*suppress trailing delimiter*/
  11.108 +			puts(outbuf);
  11.109 +			}
  11.110 +	} while (!endflag) ;
  11.111 +fclose(inptr);
  11.112 +} while(++filenr <= argc);
  11.113 +}
  11.114 +
  11.115 +diag(s)
  11.116 +char *s;
  11.117 +{
  11.118 +	write(2, "cut : ", 6);
  11.119 +	while(*s)
  11.120 +		write(2,s++,1);
  11.121 +	exit(2);
  11.122 +}
  11.123 +diagl()
  11.124 +{
  11.125 +diag("bad list for c/f option\n");
  11.126 +}