19b50d902SRodney W. Grimes /* 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 89b50d902SRodney W. Grimes * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue. 99b50d902SRodney W. Grimes * 109b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 119b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 129b50d902SRodney W. Grimes * are met: 139b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 159b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 169b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 179b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 199b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 209b50d902SRodney W. Grimes * without specific prior written permission. 219b50d902SRodney W. Grimes * 229b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 239b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 249b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 259b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 269b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 279b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 289b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 299b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 309b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 319b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 329b50d902SRodney W. Grimes * SUCH DAMAGE. 339b50d902SRodney W. Grimes */ 349b50d902SRodney W. Grimes 359b50d902SRodney W. Grimes #include <ctype.h> 36812bff99SPhilippe Charnier #include <err.h> 37a5c4bafcSTim J. Robbins #include <errno.h> 389b50d902SRodney W. Grimes #include <limits.h> 39d51c6625SEivind Eklund #include <locale.h> 409b50d902SRodney W. Grimes #include <stdio.h> 419b50d902SRodney W. Grimes #include <stdlib.h> 429b50d902SRodney W. Grimes #include <string.h> 43df3f5d9dSPeter Wemm #include <unistd.h> 44d900c384STim J. Robbins #include <wchar.h> 459b50d902SRodney W. Grimes 4641b662c5SEd Schouten static int bflag; 4741b662c5SEd Schouten static int cflag; 4841b662c5SEd Schouten static wchar_t dchar; 4941b662c5SEd Schouten static char dcharmb[MB_LEN_MAX + 1]; 5041b662c5SEd Schouten static int dflag; 5141b662c5SEd Schouten static int fflag; 5241b662c5SEd Schouten static int nflag; 5341b662c5SEd Schouten static int sflag; 5418ba28c8SEitan Adler static int wflag; 559b50d902SRodney W. Grimes 5641b662c5SEd Schouten static size_t autostart, autostop, maxval; 5741b662c5SEd Schouten static char * positions; 583b90bf79STim J. Robbins 5941b662c5SEd Schouten static int b_cut(FILE *, const char *); 6041b662c5SEd Schouten static int b_n_cut(FILE *, const char *); 6141b662c5SEd Schouten static int c_cut(FILE *, const char *); 6241b662c5SEd Schouten static int f_cut(FILE *, const char *); 6341b662c5SEd Schouten static void get_list(char *); 64bd9dd0c6SAndrew Turner static int is_delim(wchar_t); 6541b662c5SEd Schouten static void needpos(size_t); 6699557a79SWill Andrews static void usage(void); 679b50d902SRodney W. Grimes 689b50d902SRodney W. Grimes int 69f4ac32deSDavid Malone main(int argc, char *argv[]) 709b50d902SRodney W. Grimes { 719b50d902SRodney W. Grimes FILE *fp; 72364d0a91STim J. Robbins int (*fcn)(FILE *, const char *); 73a6ea32c3STim J. Robbins int ch, rval; 74a5c4bafcSTim J. Robbins size_t n; 759b50d902SRodney W. Grimes 76d51c6625SEivind Eklund setlocale(LC_ALL, ""); 77d51c6625SEivind Eklund 7893738f50STim J. Robbins fcn = NULL; 799b50d902SRodney W. Grimes dchar = '\t'; /* default delimiter is \t */ 80a5c4bafcSTim J. Robbins strcpy(dcharmb, "\t"); 819b50d902SRodney W. Grimes 8218ba28c8SEitan Adler while ((ch = getopt(argc, argv, "b:c:d:f:snw")) != -1) 839b50d902SRodney W. Grimes switch(ch) { 84d51c6625SEivind Eklund case 'b': 85393cf508STim J. Robbins get_list(optarg); 86393cf508STim J. Robbins bflag = 1; 87393cf508STim J. Robbins break; 889b50d902SRodney W. Grimes case 'c': 899b50d902SRodney W. Grimes get_list(optarg); 909b50d902SRodney W. Grimes cflag = 1; 919b50d902SRodney W. Grimes break; 929b50d902SRodney W. Grimes case 'd': 93a5c4bafcSTim J. Robbins n = mbrtowc(&dchar, optarg, MB_LEN_MAX, NULL); 94a5c4bafcSTim J. Robbins if (dchar == '\0' || n != strlen(optarg)) 95a5c4bafcSTim J. Robbins errx(1, "bad delimiter"); 96a5c4bafcSTim J. Robbins strcpy(dcharmb, optarg); 979b50d902SRodney W. Grimes dflag = 1; 989b50d902SRodney W. Grimes break; 999b50d902SRodney W. Grimes case 'f': 1009b50d902SRodney W. Grimes get_list(optarg); 1019b50d902SRodney W. Grimes fflag = 1; 1029b50d902SRodney W. Grimes break; 1039b50d902SRodney W. Grimes case 's': 1049b50d902SRodney W. Grimes sflag = 1; 1059b50d902SRodney W. Grimes break; 106d51c6625SEivind Eklund case 'n': 107393cf508STim J. Robbins nflag = 1; 108d51c6625SEivind Eklund break; 10918ba28c8SEitan Adler case 'w': 11018ba28c8SEitan Adler wflag = 1; 11118ba28c8SEitan Adler break; 1129b50d902SRodney W. Grimes case '?': 1139b50d902SRodney W. Grimes default: 1149b50d902SRodney W. Grimes usage(); 1159b50d902SRodney W. Grimes } 1169b50d902SRodney W. Grimes argc -= optind; 1179b50d902SRodney W. Grimes argv += optind; 1189b50d902SRodney W. Grimes 1199b50d902SRodney W. Grimes if (fflag) { 12018ba28c8SEitan Adler if (bflag || cflag || nflag || (wflag && dflag)) 1219b50d902SRodney W. Grimes usage(); 12218ba28c8SEitan Adler } else if (!(bflag || cflag) || dflag || sflag || wflag) 1239b50d902SRodney W. Grimes usage(); 124393cf508STim J. Robbins else if (!bflag && nflag) 125393cf508STim J. Robbins usage(); 126393cf508STim J. Robbins 127364d0a91STim J. Robbins if (fflag) 128364d0a91STim J. Robbins fcn = f_cut; 129364d0a91STim J. Robbins else if (cflag) 130364d0a91STim J. Robbins fcn = MB_CUR_MAX > 1 ? c_cut : b_cut; 131364d0a91STim J. Robbins else if (bflag) 132364d0a91STim J. Robbins fcn = nflag && MB_CUR_MAX > 1 ? b_n_cut : b_cut; 1339b50d902SRodney W. Grimes 134a6ea32c3STim J. Robbins rval = 0; 1359b50d902SRodney W. Grimes if (*argv) 1369b50d902SRodney W. Grimes for (; *argv; ++argv) { 137204c78a1STim J. Robbins if (strcmp(*argv, "-") == 0) 138364d0a91STim J. Robbins rval |= fcn(stdin, "stdin"); 139204c78a1STim J. Robbins else { 140a6ea32c3STim J. Robbins if (!(fp = fopen(*argv, "r"))) { 141a6ea32c3STim J. Robbins warn("%s", *argv); 142a6ea32c3STim J. Robbins rval = 1; 143a6ea32c3STim J. Robbins continue; 144a6ea32c3STim J. Robbins } 1459b50d902SRodney W. Grimes fcn(fp, *argv); 1469b50d902SRodney W. Grimes (void)fclose(fp); 1479b50d902SRodney W. Grimes } 148204c78a1STim J. Robbins } 1499b50d902SRodney W. Grimes else 150364d0a91STim J. Robbins rval = fcn(stdin, "stdin"); 151a6ea32c3STim J. Robbins exit(rval); 1529b50d902SRodney W. Grimes } 1539b50d902SRodney W. Grimes 15441b662c5SEd Schouten static void 155f4ac32deSDavid Malone get_list(char *list) 1569b50d902SRodney W. Grimes { 157d8a3fbd5SWill Andrews size_t setautostart, start, stop; 1582c39ae65SEivind Eklund char *pos; 1599b50d902SRodney W. Grimes char *p; 1609b50d902SRodney W. Grimes 1619b50d902SRodney W. Grimes /* 1629b50d902SRodney W. Grimes * set a byte in the positions array to indicate if a field or 1639b50d902SRodney W. Grimes * column is to be selected; use +1, it's 1-based, not 0-based. 1640dcb7b75STim J. Robbins * Numbers and number ranges may be overlapping, repeated, and in 165d334b286SKevin Lo * any order. We handle "-3-5" although there's no real reason to. 1669b50d902SRodney W. Grimes */ 1672c39ae65SEivind Eklund for (; (p = strsep(&list, ", \t")) != NULL;) { 1689b50d902SRodney W. Grimes setautostart = start = stop = 0; 1699b50d902SRodney W. Grimes if (*p == '-') { 1709b50d902SRodney W. Grimes ++p; 1719b50d902SRodney W. Grimes setautostart = 1; 1729b50d902SRodney W. Grimes } 1732c39ae65SEivind Eklund if (isdigit((unsigned char)*p)) { 1749b50d902SRodney W. Grimes start = stop = strtol(p, &p, 10); 1759b50d902SRodney W. Grimes if (setautostart && start > autostart) 1769b50d902SRodney W. Grimes autostart = start; 1779b50d902SRodney W. Grimes } 1789b50d902SRodney W. Grimes if (*p == '-') { 1792c39ae65SEivind Eklund if (isdigit((unsigned char)p[1])) 1809b50d902SRodney W. Grimes stop = strtol(p + 1, &p, 10); 1819b50d902SRodney W. Grimes if (*p == '-') { 1829b50d902SRodney W. Grimes ++p; 1839b50d902SRodney W. Grimes if (!autostop || autostop > stop) 1849b50d902SRodney W. Grimes autostop = stop; 1859b50d902SRodney W. Grimes } 1869b50d902SRodney W. Grimes } 1879b50d902SRodney W. Grimes if (*p) 188d334b286SKevin Lo errx(1, "[-bcf] list: illegal list value"); 1899b50d902SRodney W. Grimes if (!stop || !start) 190d334b286SKevin Lo errx(1, "[-bcf] list: values may not include zero"); 191a8522a9bSTim J. Robbins if (maxval < stop) { 1929b50d902SRodney W. Grimes maxval = stop; 193a8522a9bSTim J. Robbins needpos(maxval + 1); 194a8522a9bSTim J. Robbins } 1959b50d902SRodney W. Grimes for (pos = positions + start; start++ <= stop; *pos++ = 1); 1969b50d902SRodney W. Grimes } 1979b50d902SRodney W. Grimes 1989b50d902SRodney W. Grimes /* overlapping ranges */ 199a8522a9bSTim J. Robbins if (autostop && maxval > autostop) { 2009b50d902SRodney W. Grimes maxval = autostop; 201a8522a9bSTim J. Robbins needpos(maxval + 1); 202a8522a9bSTim J. Robbins } 2039b50d902SRodney W. Grimes 2046872fd3cSEitan Adler /* reversed range with autostart */ 2056872fd3cSEitan Adler if (maxval < autostart) { 2066872fd3cSEitan Adler maxval = autostart; 2076872fd3cSEitan Adler needpos(maxval + 1); 2086872fd3cSEitan Adler } 2096872fd3cSEitan Adler 2109b50d902SRodney W. Grimes /* set autostart */ 2119b50d902SRodney W. Grimes if (autostart) 2129b50d902SRodney W. Grimes memset(positions + 1, '1', autostart); 2139b50d902SRodney W. Grimes } 2149b50d902SRodney W. Grimes 21541b662c5SEd Schouten static void 216a8522a9bSTim J. Robbins needpos(size_t n) 217a8522a9bSTim J. Robbins { 218a8522a9bSTim J. Robbins static size_t npos; 219f457179aSTim J. Robbins size_t oldnpos; 220a8522a9bSTim J. Robbins 221a8522a9bSTim J. Robbins /* Grow the positions array to at least the specified size. */ 222a8522a9bSTim J. Robbins if (n > npos) { 223f457179aSTim J. Robbins oldnpos = npos; 224a8522a9bSTim J. Robbins if (npos == 0) 225a8522a9bSTim J. Robbins npos = n; 226a8522a9bSTim J. Robbins while (n > npos) 227a8522a9bSTim J. Robbins npos *= 2; 228a8522a9bSTim J. Robbins if ((positions = realloc(positions, npos)) == NULL) 229a8522a9bSTim J. Robbins err(1, "realloc"); 230f457179aSTim J. Robbins memset((char *)positions + oldnpos, 0, npos - oldnpos); 231a8522a9bSTim J. Robbins } 232a8522a9bSTim J. Robbins } 233a8522a9bSTim J. Robbins 23441b662c5SEd Schouten static int 235f0b4606fSTim J. Robbins b_cut(FILE *fp, const char *fname __unused) 236364d0a91STim J. Robbins { 237364d0a91STim J. Robbins int ch, col; 238364d0a91STim J. Robbins char *pos; 239364d0a91STim J. Robbins 240364d0a91STim J. Robbins ch = 0; 241364d0a91STim J. Robbins for (;;) { 242364d0a91STim J. Robbins pos = positions + 1; 243364d0a91STim J. Robbins for (col = maxval; col; --col) { 244364d0a91STim J. Robbins if ((ch = getc(fp)) == EOF) 245364d0a91STim J. Robbins return (0); 246364d0a91STim J. Robbins if (ch == '\n') 247364d0a91STim J. Robbins break; 248364d0a91STim J. Robbins if (*pos++) 249364d0a91STim J. Robbins (void)putchar(ch); 250364d0a91STim J. Robbins } 251364d0a91STim J. Robbins if (ch != '\n') { 252364d0a91STim J. Robbins if (autostop) 253364d0a91STim J. Robbins while ((ch = getc(fp)) != EOF && ch != '\n') 254364d0a91STim J. Robbins (void)putchar(ch); 255364d0a91STim J. Robbins else 256364d0a91STim J. Robbins while ((ch = getc(fp)) != EOF && ch != '\n'); 257364d0a91STim J. Robbins } 258364d0a91STim J. Robbins (void)putchar('\n'); 259364d0a91STim J. Robbins } 260364d0a91STim J. Robbins return (0); 261364d0a91STim J. Robbins } 262364d0a91STim J. Robbins 263393cf508STim J. Robbins /* 264393cf508STim J. Robbins * Cut based on byte positions, taking care not to split multibyte characters. 265393cf508STim J. Robbins * Although this function also handles the case where -n is not specified, 266364d0a91STim J. Robbins * b_cut() ought to be much faster. 267393cf508STim J. Robbins */ 26841b662c5SEd Schouten static int 269f4ac32deSDavid Malone b_n_cut(FILE *fp, const char *fname) 270393cf508STim J. Robbins { 271*b0578595SMartin Tournoij size_t col, i, bufsize = 0; 272*b0578595SMartin Tournoij ssize_t lbuflen; 273*b0578595SMartin Tournoij char *lbuf = NULL; 274393cf508STim J. Robbins int canwrite, clen, warned; 275d900c384STim J. Robbins mbstate_t mbs; 276393cf508STim J. Robbins 277d900c384STim J. Robbins memset(&mbs, 0, sizeof(mbs)); 278393cf508STim J. Robbins warned = 0; 279*b0578595SMartin Tournoij while ((lbuflen = getline(&lbuf, &bufsize, fp)) >= 0) { 280393cf508STim J. Robbins for (col = 0; lbuflen > 0; col += clen) { 281d900c384STim J. Robbins if ((clen = mbrlen(lbuf, lbuflen, &mbs)) < 0) { 282393cf508STim J. Robbins if (!warned) { 283393cf508STim J. Robbins warn("%s", fname); 284393cf508STim J. Robbins warned = 1; 285393cf508STim J. Robbins } 286d900c384STim J. Robbins memset(&mbs, 0, sizeof(mbs)); 287393cf508STim J. Robbins clen = 1; 288393cf508STim J. Robbins } 289393cf508STim J. Robbins if (clen == 0 || *lbuf == '\n') 290393cf508STim J. Robbins break; 291393cf508STim J. Robbins if (col < maxval && !positions[1 + col]) { 292393cf508STim J. Robbins /* 293393cf508STim J. Robbins * Print the character if (1) after an initial 294393cf508STim J. Robbins * segment of un-selected bytes, the rest of 295393cf508STim J. Robbins * it is selected, and (2) the last byte is 296393cf508STim J. Robbins * selected. 297393cf508STim J. Robbins */ 298393cf508STim J. Robbins i = col; 299393cf508STim J. Robbins while (i < col + clen && i < maxval && 300393cf508STim J. Robbins !positions[1 + i]) 301393cf508STim J. Robbins i++; 302393cf508STim J. Robbins canwrite = i < col + clen; 303393cf508STim J. Robbins for (; i < col + clen && i < maxval; i++) 304393cf508STim J. Robbins canwrite &= positions[1 + i]; 305393cf508STim J. Robbins if (canwrite) 306393cf508STim J. Robbins fwrite(lbuf, 1, clen, stdout); 307393cf508STim J. Robbins } else { 308393cf508STim J. Robbins /* 309393cf508STim J. Robbins * Print the character if all of it has 310393cf508STim J. Robbins * been selected. 311393cf508STim J. Robbins */ 312393cf508STim J. Robbins canwrite = 1; 313393cf508STim J. Robbins for (i = col; i < col + clen; i++) 314393cf508STim J. Robbins if ((i >= maxval && !autostop) || 315393cf508STim J. Robbins (i < maxval && !positions[1 + i])) { 316393cf508STim J. Robbins canwrite = 0; 317393cf508STim J. Robbins break; 318393cf508STim J. Robbins } 319393cf508STim J. Robbins if (canwrite) 320393cf508STim J. Robbins fwrite(lbuf, 1, clen, stdout); 321393cf508STim J. Robbins } 322393cf508STim J. Robbins lbuf += clen; 323393cf508STim J. Robbins lbuflen -= clen; 324393cf508STim J. Robbins } 325393cf508STim J. Robbins if (lbuflen > 0) 326393cf508STim J. Robbins putchar('\n'); 327393cf508STim J. Robbins } 328*b0578595SMartin Tournoij free(lbuf); 329364d0a91STim J. Robbins return (warned); 330393cf508STim J. Robbins } 331393cf508STim J. Robbins 33241b662c5SEd Schouten static int 333364d0a91STim J. Robbins c_cut(FILE *fp, const char *fname) 3349b50d902SRodney W. Grimes { 335364d0a91STim J. Robbins wint_t ch; 336364d0a91STim J. Robbins int col; 3372c39ae65SEivind Eklund char *pos; 3389b50d902SRodney W. Grimes 3392c39ae65SEivind Eklund ch = 0; 3409b50d902SRodney W. Grimes for (;;) { 3419b50d902SRodney W. Grimes pos = positions + 1; 3429b50d902SRodney W. Grimes for (col = maxval; col; --col) { 343364d0a91STim J. Robbins if ((ch = getwc(fp)) == WEOF) 344364d0a91STim J. Robbins goto out; 3459b50d902SRodney W. Grimes if (ch == '\n') 3469b50d902SRodney W. Grimes break; 3479b50d902SRodney W. Grimes if (*pos++) 348364d0a91STim J. Robbins (void)putwchar(ch); 3499b50d902SRodney W. Grimes } 3502c39ae65SEivind Eklund if (ch != '\n') { 3519b50d902SRodney W. Grimes if (autostop) 352364d0a91STim J. Robbins while ((ch = getwc(fp)) != WEOF && ch != '\n') 353364d0a91STim J. Robbins (void)putwchar(ch); 3549b50d902SRodney W. Grimes else 355364d0a91STim J. Robbins while ((ch = getwc(fp)) != WEOF && ch != '\n'); 3562c39ae65SEivind Eklund } 357364d0a91STim J. Robbins (void)putwchar('\n'); 3589b50d902SRodney W. Grimes } 359364d0a91STim J. Robbins out: 360364d0a91STim J. Robbins if (ferror(fp)) { 361364d0a91STim J. Robbins warn("%s", fname); 362364d0a91STim J. Robbins return (1); 363364d0a91STim J. Robbins } 364364d0a91STim J. Robbins return (0); 3659b50d902SRodney W. Grimes } 3669b50d902SRodney W. Grimes 36741b662c5SEd Schouten static int 368bd9dd0c6SAndrew Turner is_delim(wchar_t ch) 36918ba28c8SEitan Adler { 37018ba28c8SEitan Adler if (wflag) { 37118ba28c8SEitan Adler if (ch == ' ' || ch == '\t') 37218ba28c8SEitan Adler return 1; 37318ba28c8SEitan Adler } else { 37418ba28c8SEitan Adler if (ch == dchar) 37518ba28c8SEitan Adler return 1; 37618ba28c8SEitan Adler } 37718ba28c8SEitan Adler return 0; 37818ba28c8SEitan Adler } 37918ba28c8SEitan Adler 38018ba28c8SEitan Adler static int 381a5c4bafcSTim J. Robbins f_cut(FILE *fp, const char *fname) 3829b50d902SRodney W. Grimes { 383a5c4bafcSTim J. Robbins wchar_t ch; 384a5c4bafcSTim J. Robbins int field, i, isdelim; 385a5c4bafcSTim J. Robbins char *pos, *p; 3869b50d902SRodney W. Grimes int output; 387*b0578595SMartin Tournoij char *lbuf = NULL; 388*b0578595SMartin Tournoij size_t clen, bufsize = 0, reallen; 389*b0578595SMartin Tournoij ssize_t lbuflen; 3909b50d902SRodney W. Grimes 391*b0578595SMartin Tournoij while ((lbuflen = getline(&lbuf, &bufsize, fp)) >= 0) { 392a2222839STim J. Robbins reallen = lbuflen; 3931928e20eSDima Dorfman /* Assert EOL has a newline. */ 394*b0578595SMartin Tournoij if (lbuflen > 0 && *(lbuf + lbuflen - 1) != '\n') { 3951928e20eSDima Dorfman /* Can't have > 1 line with no trailing newline. */ 396*b0578595SMartin Tournoij if ((ssize_t)bufsize < (lbuflen + 1)) { 397*b0578595SMartin Tournoij bufsize = lbuflen + 1; 398*b0578595SMartin Tournoij lbuf = realloc(lbuf, bufsize); 399*b0578595SMartin Tournoij } 400*b0578595SMartin Tournoij if (lbuf == NULL) 401*b0578595SMartin Tournoij err(1, "realloc"); 402*b0578595SMartin Tournoij lbuf[lbuflen] = '\n'; 403a2222839STim J. Robbins reallen++; 4041928e20eSDima Dorfman } 405eaf92380SAndrey A. Chernov output = 0; 406a5c4bafcSTim J. Robbins for (isdelim = 0, p = lbuf;; p += clen) { 407a2222839STim J. Robbins clen = mbrtowc(&ch, p, lbuf + reallen - p, NULL); 408a5c4bafcSTim J. Robbins if (clen == (size_t)-1 || clen == (size_t)-2) { 409a5c4bafcSTim J. Robbins warnc(EILSEQ, "%s", fname); 410*b0578595SMartin Tournoij free(lbuf); 411a5c4bafcSTim J. Robbins return (1); 412a5c4bafcSTim J. Robbins } 413a5c4bafcSTim J. Robbins if (clen == 0) 414a5c4bafcSTim J. Robbins clen = 1; 4159b50d902SRodney W. Grimes /* this should work if newline is delimiter */ 41618ba28c8SEitan Adler if (is_delim(ch)) 4179b50d902SRodney W. Grimes isdelim = 1; 4189b50d902SRodney W. Grimes if (ch == '\n') { 4199b50d902SRodney W. Grimes if (!isdelim && !sflag) 4201928e20eSDima Dorfman (void)fwrite(lbuf, lbuflen, 1, stdout); 4219b50d902SRodney W. Grimes break; 4229b50d902SRodney W. Grimes } 4239b50d902SRodney W. Grimes } 4249b50d902SRodney W. Grimes if (!isdelim) 4259b50d902SRodney W. Grimes continue; 4269b50d902SRodney W. Grimes 4279b50d902SRodney W. Grimes pos = positions + 1; 4289b50d902SRodney W. Grimes for (field = maxval, p = lbuf; field; --field, ++pos) { 429a5c4bafcSTim J. Robbins if (*pos && output++) 430a5c4bafcSTim J. Robbins for (i = 0; dcharmb[i] != '\0'; i++) 431a5c4bafcSTim J. Robbins putchar(dcharmb[i]); 432a5c4bafcSTim J. Robbins for (;;) { 433a2222839STim J. Robbins clen = mbrtowc(&ch, p, lbuf + reallen - p, 434a5c4bafcSTim J. Robbins NULL); 435a5c4bafcSTim J. Robbins if (clen == (size_t)-1 || clen == (size_t)-2) { 436a5c4bafcSTim J. Robbins warnc(EILSEQ, "%s", fname); 437*b0578595SMartin Tournoij free(lbuf); 438a5c4bafcSTim J. Robbins return (1); 439a5c4bafcSTim J. Robbins } 440a5c4bafcSTim J. Robbins if (clen == 0) 441a5c4bafcSTim J. Robbins clen = 1; 442a5c4bafcSTim J. Robbins p += clen; 44318ba28c8SEitan Adler if (ch == '\n' || is_delim(ch)) { 44418ba28c8SEitan Adler /* compress whitespace */ 44518ba28c8SEitan Adler if (wflag && ch != '\n') 44618ba28c8SEitan Adler while (is_delim(*p)) 44718ba28c8SEitan Adler p++; 448a5c4bafcSTim J. Robbins break; 44918ba28c8SEitan Adler } 450a5c4bafcSTim J. Robbins if (*pos) 451a5c4bafcSTim J. Robbins for (i = 0; i < (int)clen; i++) 452a5c4bafcSTim J. Robbins putchar(p[i - clen]); 4532c39ae65SEivind Eklund } 4549b50d902SRodney W. Grimes if (ch == '\n') 4559b50d902SRodney W. Grimes break; 4569b50d902SRodney W. Grimes } 4572c39ae65SEivind Eklund if (ch != '\n') { 4589b50d902SRodney W. Grimes if (autostop) { 4599b50d902SRodney W. Grimes if (output) 460a5c4bafcSTim J. Robbins for (i = 0; dcharmb[i] != '\0'; i++) 461a5c4bafcSTim J. Robbins putchar(dcharmb[i]); 4629b50d902SRodney W. Grimes for (; (ch = *p) != '\n'; ++p) 4639b50d902SRodney W. Grimes (void)putchar(ch); 4649b50d902SRodney W. Grimes } else 4659b50d902SRodney W. Grimes for (; (ch = *p) != '\n'; ++p); 4662c39ae65SEivind Eklund } 4679b50d902SRodney W. Grimes (void)putchar('\n'); 4689b50d902SRodney W. Grimes } 469*b0578595SMartin Tournoij free(lbuf); 470364d0a91STim J. Robbins return (0); 4719b50d902SRodney W. Grimes } 4729b50d902SRodney W. Grimes 473812bff99SPhilippe Charnier static void 474f4ac32deSDavid Malone usage(void) 4759b50d902SRodney W. Grimes { 476d51c6625SEivind Eklund (void)fprintf(stderr, "%s\n%s\n%s\n", 477d51c6625SEivind Eklund "usage: cut -b list [-n] [file ...]", 478d51c6625SEivind Eklund " cut -c list [file ...]", 47918ba28c8SEitan Adler " cut -f list [-s] [-w | -d delim] [file ...]"); 4809b50d902SRodney W. Grimes exit(1); 4819b50d902SRodney W. Grimes } 482