docs/cut
diff code/cut.c__openbsd.2008-06-27 @ 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 | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/code/cut.c__openbsd.2008-06-27 Tue May 12 06:46:59 2015 +0200 1.3 @@ -0,0 +1,290 @@ 1.4 +/* $OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $ */ 1.5 +/* $NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $ */ 1.6 + 1.7 +/* 1.8 + * Copyright (c) 1989, 1993 1.9 + * The Regents of the University of California. All rights reserved. 1.10 + * 1.11 + * This code is derived from software contributed to Berkeley by 1.12 + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue. 1.13 + * 1.14 + * Redistribution and use in source and binary forms, with or without 1.15 + * modification, are permitted provided that the following conditions 1.16 + * are met: 1.17 + * 1. Redistributions of source code must retain the above copyright 1.18 + * notice, this list of conditions and the following disclaimer. 1.19 + * 2. Redistributions in binary form must reproduce the above copyright 1.20 + * notice, this list of conditions and the following disclaimer in the 1.21 + * documentation and/or other materials provided with the distribution. 1.22 + * 3. Neither the name of the University nor the names of its contributors 1.23 + * may be used to endorse or promote products derived from this software 1.24 + * without specific prior written permission. 1.25 + * 1.26 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1.27 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.28 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.29 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1.30 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1.31 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1.32 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1.33 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1.34 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1.35 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.36 + * SUCH DAMAGE. 1.37 + */ 1.38 + 1.39 +#ifndef lint 1.40 +static char copyright[] = 1.41 +"@(#) Copyright (c) 1989, 1993\n\ 1.42 + The Regents of the University of California. All rights reserved.\n"; 1.43 +#endif /* not lint */ 1.44 + 1.45 +#ifndef lint 1.46 +#if 0 1.47 +static char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95"; 1.48 +#endif 1.49 +static char rcsid[] = "$OpenBSD: cut.c,v 1.13 2008/06/27 08:02:13 sobrado Exp $"; 1.50 +#endif /* not lint */ 1.51 + 1.52 +#include <ctype.h> 1.53 +#include <err.h> 1.54 +#include <errno.h> 1.55 +#include <limits.h> 1.56 +#include <locale.h> 1.57 +#include <stdio.h> 1.58 +#include <stdlib.h> 1.59 +#include <string.h> 1.60 +#include <unistd.h> 1.61 + 1.62 +int cflag; 1.63 +char dchar; 1.64 +int dflag; 1.65 +int fflag; 1.66 +int sflag; 1.67 + 1.68 +void c_cut(FILE *, char *); 1.69 +void f_cut(FILE *, char *); 1.70 +void get_list(char *); 1.71 +void usage(void); 1.72 + 1.73 +int 1.74 +main(int argc, char *argv[]) 1.75 +{ 1.76 + FILE *fp; 1.77 + void (*fcn)(FILE *, char *); 1.78 + int ch; 1.79 + 1.80 + setlocale (LC_ALL, ""); 1.81 + 1.82 + dchar = '\t'; /* default delimiter is \t */ 1.83 + 1.84 + /* Since we don't support multi-byte characters, the -c and -b 1.85 + options are equivalent, and the -n option is meaningless. */ 1.86 + while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1) 1.87 + switch(ch) { 1.88 + case 'b': 1.89 + case 'c': 1.90 + fcn = c_cut; 1.91 + get_list(optarg); 1.92 + cflag = 1; 1.93 + break; 1.94 + case 'd': 1.95 + dchar = *optarg; 1.96 + dflag = 1; 1.97 + break; 1.98 + case 'f': 1.99 + get_list(optarg); 1.100 + fcn = f_cut; 1.101 + fflag = 1; 1.102 + break; 1.103 + case 's': 1.104 + sflag = 1; 1.105 + break; 1.106 + case 'n': 1.107 + break; 1.108 + case '?': 1.109 + default: 1.110 + usage(); 1.111 + } 1.112 + argc -= optind; 1.113 + argv += optind; 1.114 + 1.115 + if (fflag) { 1.116 + if (cflag) 1.117 + usage(); 1.118 + } else if (!cflag || dflag || sflag) 1.119 + usage(); 1.120 + 1.121 + if (*argv) 1.122 + for (; *argv; ++argv) { 1.123 + if (!(fp = fopen(*argv, "r"))) 1.124 + err(1, "%s", *argv); 1.125 + fcn(fp, *argv); 1.126 + (void)fclose(fp); 1.127 + } 1.128 + else 1.129 + fcn(stdin, "stdin"); 1.130 + exit(0); 1.131 +} 1.132 + 1.133 +int autostart, autostop, maxval; 1.134 + 1.135 +char positions[_POSIX2_LINE_MAX + 1]; 1.136 + 1.137 +void 1.138 +get_list(char *list) 1.139 +{ 1.140 + int setautostart, start, stop; 1.141 + char *pos; 1.142 + char *p; 1.143 + 1.144 + /* 1.145 + * set a byte in the positions array to indicate if a field or 1.146 + * column is to be selected; use +1, it's 1-based, not 0-based. 1.147 + * This parser is less restrictive than the Draft 9 POSIX spec. 1.148 + * POSIX doesn't allow lists that aren't in increasing order or 1.149 + * overlapping lists. We also handle "-3-5" although there's no 1.150 + * real reason too. 1.151 + */ 1.152 + while ((p = strsep(&list, ", \t"))) { 1.153 + setautostart = start = stop = 0; 1.154 + if (*p == '-') { 1.155 + ++p; 1.156 + setautostart = 1; 1.157 + } 1.158 + if (isdigit(*p)) { 1.159 + start = stop = strtol(p, &p, 10); 1.160 + if (setautostart && start > autostart) 1.161 + autostart = start; 1.162 + } 1.163 + if (*p == '-') { 1.164 + if (isdigit(p[1])) 1.165 + stop = strtol(p + 1, &p, 10); 1.166 + if (*p == '-') { 1.167 + ++p; 1.168 + if (!autostop || autostop > stop) 1.169 + autostop = stop; 1.170 + } 1.171 + } 1.172 + if (*p) 1.173 + errx(1, "[-cf] list: illegal list value"); 1.174 + if (!stop || !start) 1.175 + errx(1, "[-cf] list: values may not include zero"); 1.176 + if (stop > _POSIX2_LINE_MAX) 1.177 + errx(1, "[-cf] list: %d too large (max %d)", 1.178 + stop, _POSIX2_LINE_MAX); 1.179 + if (maxval < stop) 1.180 + maxval = stop; 1.181 + for (pos = positions + start; start++ <= stop; *pos++ = 1) 1.182 + ; 1.183 + } 1.184 + 1.185 + /* overlapping ranges */ 1.186 + if (autostop && maxval > autostop) 1.187 + maxval = autostop; 1.188 + 1.189 + /* set autostart */ 1.190 + if (autostart) 1.191 + memset(positions + 1, '1', autostart); 1.192 +} 1.193 + 1.194 +/* ARGSUSED */ 1.195 +void 1.196 +c_cut(FILE *fp, char *fname) 1.197 +{ 1.198 + int ch, col; 1.199 + char *pos; 1.200 + 1.201 + for (;;) { 1.202 + pos = positions + 1; 1.203 + for (col = maxval; col; --col) { 1.204 + if ((ch = getc(fp)) == EOF) 1.205 + return; 1.206 + if (ch == '\n') 1.207 + break; 1.208 + if (*pos++) 1.209 + (void)putchar(ch); 1.210 + } 1.211 + if (ch != '\n') { 1.212 + if (autostop) 1.213 + while ((ch = getc(fp)) != EOF && ch != '\n') 1.214 + (void)putchar(ch); 1.215 + else 1.216 + while ((ch = getc(fp)) != EOF && ch != '\n') 1.217 + ; 1.218 + } 1.219 + (void)putchar('\n'); 1.220 + } 1.221 +} 1.222 + 1.223 +void 1.224 +f_cut(FILE *fp, char *fname) 1.225 +{ 1.226 + int ch, field, isdelim; 1.227 + char *pos, *p, sep; 1.228 + int output; 1.229 + size_t len; 1.230 + char *lbuf, *tbuf; 1.231 + 1.232 + for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len));) { 1.233 + output = 0; 1.234 + if (lbuf[len - 1] != '\n') { 1.235 + /* no newline at the end of the last line so add one */ 1.236 + if ((tbuf = (char *)malloc(len + 1)) == NULL) 1.237 + err(1, NULL); 1.238 + memcpy(tbuf, lbuf, len); 1.239 + tbuf[len] = '\n'; 1.240 + lbuf = tbuf; 1.241 + } 1.242 + for (isdelim = 0, p = lbuf;; ++p) { 1.243 + ch = *p; 1.244 + /* this should work if newline is delimiter */ 1.245 + if (ch == sep) 1.246 + isdelim = 1; 1.247 + if (ch == '\n') { 1.248 + if (!isdelim && !sflag) 1.249 + (void)fwrite(lbuf, len, 1, stdout); 1.250 + break; 1.251 + } 1.252 + } 1.253 + if (!isdelim) 1.254 + continue; 1.255 + 1.256 + pos = positions + 1; 1.257 + for (field = maxval, p = lbuf; field; --field, ++pos) { 1.258 + if (*pos) { 1.259 + if (output++) 1.260 + (void)putchar(sep); 1.261 + while ((ch = *p++) != '\n' && ch != sep) 1.262 + (void)putchar(ch); 1.263 + } else 1.264 + while ((ch = *p++) != '\n' && ch != sep) 1.265 + ; 1.266 + if (ch == '\n') 1.267 + break; 1.268 + } 1.269 + if (ch != '\n') { 1.270 + if (autostop) { 1.271 + if (output) 1.272 + (void)putchar(sep); 1.273 + for (; (ch = *p) != '\n'; ++p) 1.274 + (void)putchar(ch); 1.275 + } else 1.276 + for (; (ch = *p) != '\n'; ++p) 1.277 + ; 1.278 + } 1.279 + (void)putchar('\n'); 1.280 + } 1.281 + if (tbuf) 1.282 + free(tbuf); 1.283 +} 1.284 + 1.285 +void 1.286 +usage(void) 1.287 +{ 1.288 + (void)fprintf(stderr, 1.289 + "usage: cut -b list [-n] [file ...]\n" 1.290 + " cut -c list [file ...]\n" 1.291 + " cut -f list [-s] [-d delim] [file ...]\n"); 1.292 + exit(1); 1.293 +}