19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 69b50d902SRodney W. Grimes * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 99b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 109b50d902SRodney W. Grimes * are met: 119b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 129b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 139b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 159b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 169b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 179b50d902SRodney W. Grimes * must display the following acknowledgement: 189b50d902SRodney W. Grimes * This product includes software developed by the University of 199b50d902SRodney W. Grimes * California, Berkeley and its contributors. 209b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 219b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 229b50d902SRodney W. Grimes * without specific prior written permission. 239b50d902SRodney W. Grimes * 249b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 259b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 269b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 279b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 289b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 299b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 309b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 319b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 329b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 339b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 349b50d902SRodney W. Grimes * SUCH DAMAGE. 359b50d902SRodney W. Grimes */ 369b50d902SRodney W. Grimes 379b50d902SRodney W. Grimes #ifndef lint 38fa146c53SArchie Cobbs static const char copyright[] = 399b50d902SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 409b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 41fa146c53SArchie Cobbs static const char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95"; 429b50d902SRodney W. Grimes #endif /* not lint */ 4377c8bf7cSDavid E. O'Brien #include <sys/cdefs.h> 4477c8bf7cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 459b50d902SRodney W. Grimes 469b50d902SRodney W. Grimes #include <ctype.h> 47812bff99SPhilippe Charnier #include <err.h> 48a5c4bafcSTim J. Robbins #include <errno.h> 499b50d902SRodney W. Grimes #include <limits.h> 50d51c6625SEivind Eklund #include <locale.h> 519b50d902SRodney W. Grimes #include <stdio.h> 529b50d902SRodney W. Grimes #include <stdlib.h> 539b50d902SRodney W. Grimes #include <string.h> 54df3f5d9dSPeter Wemm #include <unistd.h> 55d900c384STim J. Robbins #include <wchar.h> 569b50d902SRodney W. Grimes 57393cf508STim J. Robbins int bflag; 589b50d902SRodney W. Grimes int cflag; 59a5c4bafcSTim J. Robbins wchar_t dchar; 60a5c4bafcSTim J. Robbins char dcharmb[MB_LEN_MAX + 1]; 619b50d902SRodney W. Grimes int dflag; 629b50d902SRodney W. Grimes int fflag; 63393cf508STim J. Robbins int nflag; 649b50d902SRodney W. Grimes int sflag; 659b50d902SRodney W. Grimes 663b90bf79STim J. Robbins size_t autostart, autostop, maxval; 673b90bf79STim J. Robbins char * positions; 683b90bf79STim J. Robbins 69364d0a91STim J. Robbins int b_cut(FILE *, const char *); 70364d0a91STim J. Robbins int b_n_cut(FILE *, const char *); 71364d0a91STim J. Robbins int c_cut(FILE *, const char *); 72364d0a91STim J. Robbins int f_cut(FILE *, const char *); 7399557a79SWill Andrews void get_list(char *); 74a8522a9bSTim J. Robbins void needpos(size_t); 7599557a79SWill Andrews static void usage(void); 769b50d902SRodney W. Grimes 779b50d902SRodney W. Grimes int 78f4ac32deSDavid Malone main(int argc, char *argv[]) 799b50d902SRodney W. Grimes { 809b50d902SRodney W. Grimes FILE *fp; 81364d0a91STim J. Robbins int (*fcn)(FILE *, const char *); 82a6ea32c3STim J. Robbins int ch, rval; 83a5c4bafcSTim J. Robbins size_t n; 849b50d902SRodney W. Grimes 85d51c6625SEivind Eklund setlocale(LC_ALL, ""); 86d51c6625SEivind Eklund 8793738f50STim J. Robbins fcn = NULL; 889b50d902SRodney W. Grimes dchar = '\t'; /* default delimiter is \t */ 89a5c4bafcSTim J. Robbins strcpy(dcharmb, "\t"); 909b50d902SRodney W. Grimes 915183fb53SEivind Eklund while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1) 929b50d902SRodney W. Grimes switch(ch) { 93d51c6625SEivind Eklund case 'b': 94393cf508STim J. Robbins get_list(optarg); 95393cf508STim J. Robbins bflag = 1; 96393cf508STim J. Robbins break; 979b50d902SRodney W. Grimes case 'c': 989b50d902SRodney W. Grimes get_list(optarg); 999b50d902SRodney W. Grimes cflag = 1; 1009b50d902SRodney W. Grimes break; 1019b50d902SRodney W. Grimes case 'd': 102a5c4bafcSTim J. Robbins n = mbrtowc(&dchar, optarg, MB_LEN_MAX, NULL); 103a5c4bafcSTim J. Robbins if (dchar == '\0' || n != strlen(optarg)) 104a5c4bafcSTim J. Robbins errx(1, "bad delimiter"); 105a5c4bafcSTim J. Robbins strcpy(dcharmb, optarg); 1069b50d902SRodney W. Grimes dflag = 1; 1079b50d902SRodney W. Grimes break; 1089b50d902SRodney W. Grimes case 'f': 1099b50d902SRodney W. Grimes get_list(optarg); 1109b50d902SRodney W. Grimes fflag = 1; 1119b50d902SRodney W. Grimes break; 1129b50d902SRodney W. Grimes case 's': 1139b50d902SRodney W. Grimes sflag = 1; 1149b50d902SRodney W. Grimes break; 115d51c6625SEivind Eklund case 'n': 116393cf508STim J. Robbins nflag = 1; 117d51c6625SEivind Eklund break; 1189b50d902SRodney W. Grimes case '?': 1199b50d902SRodney W. Grimes default: 1209b50d902SRodney W. Grimes usage(); 1219b50d902SRodney W. Grimes } 1229b50d902SRodney W. Grimes argc -= optind; 1239b50d902SRodney W. Grimes argv += optind; 1249b50d902SRodney W. Grimes 1259b50d902SRodney W. Grimes if (fflag) { 126393cf508STim J. Robbins if (bflag || cflag || nflag) 1279b50d902SRodney W. Grimes usage(); 128393cf508STim J. Robbins } else if (!(bflag || cflag) || dflag || sflag) 1299b50d902SRodney W. Grimes usage(); 130393cf508STim J. Robbins else if (!bflag && nflag) 131393cf508STim J. Robbins usage(); 132393cf508STim J. Robbins 133364d0a91STim J. Robbins if (fflag) 134364d0a91STim J. Robbins fcn = f_cut; 135364d0a91STim J. Robbins else if (cflag) 136364d0a91STim J. Robbins fcn = MB_CUR_MAX > 1 ? c_cut : b_cut; 137364d0a91STim J. Robbins else if (bflag) 138364d0a91STim J. Robbins fcn = nflag && MB_CUR_MAX > 1 ? b_n_cut : b_cut; 1399b50d902SRodney W. Grimes 140a6ea32c3STim J. Robbins rval = 0; 1419b50d902SRodney W. Grimes if (*argv) 1429b50d902SRodney W. Grimes for (; *argv; ++argv) { 143204c78a1STim J. Robbins if (strcmp(*argv, "-") == 0) 144364d0a91STim J. Robbins rval |= fcn(stdin, "stdin"); 145204c78a1STim J. Robbins else { 146a6ea32c3STim J. Robbins if (!(fp = fopen(*argv, "r"))) { 147a6ea32c3STim J. Robbins warn("%s", *argv); 148a6ea32c3STim J. Robbins rval = 1; 149a6ea32c3STim J. Robbins continue; 150a6ea32c3STim J. Robbins } 1519b50d902SRodney W. Grimes fcn(fp, *argv); 1529b50d902SRodney W. Grimes (void)fclose(fp); 1539b50d902SRodney W. Grimes } 154204c78a1STim J. Robbins } 1559b50d902SRodney W. Grimes else 156364d0a91STim J. Robbins rval = fcn(stdin, "stdin"); 157a6ea32c3STim J. Robbins exit(rval); 1589b50d902SRodney W. Grimes } 1599b50d902SRodney W. Grimes 1609b50d902SRodney W. Grimes void 161f4ac32deSDavid Malone get_list(char *list) 1629b50d902SRodney W. Grimes { 163d8a3fbd5SWill Andrews size_t setautostart, start, stop; 1642c39ae65SEivind Eklund char *pos; 1659b50d902SRodney W. Grimes char *p; 1669b50d902SRodney W. Grimes 1679b50d902SRodney W. Grimes /* 1689b50d902SRodney W. Grimes * set a byte in the positions array to indicate if a field or 1699b50d902SRodney W. Grimes * column is to be selected; use +1, it's 1-based, not 0-based. 1700dcb7b75STim J. Robbins * Numbers and number ranges may be overlapping, repeated, and in 1710dcb7b75STim J. Robbins * any order. We handle "-3-5" although there's no real reason too. 1729b50d902SRodney W. Grimes */ 1732c39ae65SEivind Eklund for (; (p = strsep(&list, ", \t")) != NULL;) { 1749b50d902SRodney W. Grimes setautostart = start = stop = 0; 1759b50d902SRodney W. Grimes if (*p == '-') { 1769b50d902SRodney W. Grimes ++p; 1779b50d902SRodney W. Grimes setautostart = 1; 1789b50d902SRodney W. Grimes } 1792c39ae65SEivind Eklund if (isdigit((unsigned char)*p)) { 1809b50d902SRodney W. Grimes start = stop = strtol(p, &p, 10); 1819b50d902SRodney W. Grimes if (setautostart && start > autostart) 1829b50d902SRodney W. Grimes autostart = start; 1839b50d902SRodney W. Grimes } 1849b50d902SRodney W. Grimes if (*p == '-') { 1852c39ae65SEivind Eklund if (isdigit((unsigned char)p[1])) 1869b50d902SRodney W. Grimes stop = strtol(p + 1, &p, 10); 1879b50d902SRodney W. Grimes if (*p == '-') { 1889b50d902SRodney W. Grimes ++p; 1899b50d902SRodney W. Grimes if (!autostop || autostop > stop) 1909b50d902SRodney W. Grimes autostop = stop; 1919b50d902SRodney W. Grimes } 1929b50d902SRodney W. Grimes } 1939b50d902SRodney W. Grimes if (*p) 194812bff99SPhilippe Charnier errx(1, "[-cf] list: illegal list value"); 1959b50d902SRodney W. Grimes if (!stop || !start) 196812bff99SPhilippe Charnier errx(1, "[-cf] list: values may not include zero"); 197a8522a9bSTim J. Robbins if (maxval < stop) { 1989b50d902SRodney W. Grimes maxval = stop; 199a8522a9bSTim J. Robbins needpos(maxval + 1); 200a8522a9bSTim J. Robbins } 2019b50d902SRodney W. Grimes for (pos = positions + start; start++ <= stop; *pos++ = 1); 2029b50d902SRodney W. Grimes } 2039b50d902SRodney W. Grimes 2049b50d902SRodney W. Grimes /* overlapping ranges */ 205a8522a9bSTim J. Robbins if (autostop && maxval > autostop) { 2069b50d902SRodney W. Grimes maxval = autostop; 207a8522a9bSTim J. Robbins needpos(maxval + 1); 208a8522a9bSTim J. Robbins } 2099b50d902SRodney W. Grimes 2109b50d902SRodney W. Grimes /* set autostart */ 2119b50d902SRodney W. Grimes if (autostart) 2129b50d902SRodney W. Grimes memset(positions + 1, '1', autostart); 2139b50d902SRodney W. Grimes } 2149b50d902SRodney W. Grimes 215a8522a9bSTim J. Robbins 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 234364d0a91STim J. Robbins 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 */ 268364d0a91STim J. Robbins int 269f4ac32deSDavid Malone b_n_cut(FILE *fp, const char *fname) 270393cf508STim J. Robbins { 271393cf508STim J. Robbins size_t col, i, lbuflen; 272393cf508STim J. Robbins char *lbuf; 273393cf508STim J. Robbins int canwrite, clen, warned; 274d900c384STim J. Robbins mbstate_t mbs; 275393cf508STim J. Robbins 276d900c384STim J. Robbins memset(&mbs, 0, sizeof(mbs)); 277393cf508STim J. Robbins warned = 0; 278393cf508STim J. Robbins while ((lbuf = fgetln(fp, &lbuflen)) != NULL) { 279393cf508STim J. Robbins for (col = 0; lbuflen > 0; col += clen) { 280d900c384STim J. Robbins if ((clen = mbrlen(lbuf, lbuflen, &mbs)) < 0) { 281393cf508STim J. Robbins if (!warned) { 282393cf508STim J. Robbins warn("%s", fname); 283393cf508STim J. Robbins warned = 1; 284393cf508STim J. Robbins } 285d900c384STim J. Robbins memset(&mbs, 0, sizeof(mbs)); 286393cf508STim J. Robbins clen = 1; 287393cf508STim J. Robbins } 288393cf508STim J. Robbins if (clen == 0 || *lbuf == '\n') 289393cf508STim J. Robbins break; 290393cf508STim J. Robbins if (col < maxval && !positions[1 + col]) { 291393cf508STim J. Robbins /* 292393cf508STim J. Robbins * Print the character if (1) after an initial 293393cf508STim J. Robbins * segment of un-selected bytes, the rest of 294393cf508STim J. Robbins * it is selected, and (2) the last byte is 295393cf508STim J. Robbins * selected. 296393cf508STim J. Robbins */ 297393cf508STim J. Robbins i = col; 298393cf508STim J. Robbins while (i < col + clen && i < maxval && 299393cf508STim J. Robbins !positions[1 + i]) 300393cf508STim J. Robbins i++; 301393cf508STim J. Robbins canwrite = i < col + clen; 302393cf508STim J. Robbins for (; i < col + clen && i < maxval; i++) 303393cf508STim J. Robbins canwrite &= positions[1 + i]; 304393cf508STim J. Robbins if (canwrite) 305393cf508STim J. Robbins fwrite(lbuf, 1, clen, stdout); 306393cf508STim J. Robbins } else { 307393cf508STim J. Robbins /* 308393cf508STim J. Robbins * Print the character if all of it has 309393cf508STim J. Robbins * been selected. 310393cf508STim J. Robbins */ 311393cf508STim J. Robbins canwrite = 1; 312393cf508STim J. Robbins for (i = col; i < col + clen; i++) 313393cf508STim J. Robbins if ((i >= maxval && !autostop) || 314393cf508STim J. Robbins (i < maxval && !positions[1 + i])) { 315393cf508STim J. Robbins canwrite = 0; 316393cf508STim J. Robbins break; 317393cf508STim J. Robbins } 318393cf508STim J. Robbins if (canwrite) 319393cf508STim J. Robbins fwrite(lbuf, 1, clen, stdout); 320393cf508STim J. Robbins } 321393cf508STim J. Robbins lbuf += clen; 322393cf508STim J. Robbins lbuflen -= clen; 323393cf508STim J. Robbins } 324393cf508STim J. Robbins if (lbuflen > 0) 325393cf508STim J. Robbins putchar('\n'); 326393cf508STim J. Robbins } 327364d0a91STim J. Robbins return (warned); 328393cf508STim J. Robbins } 329393cf508STim J. Robbins 330364d0a91STim J. Robbins int 331364d0a91STim J. Robbins c_cut(FILE *fp, const char *fname) 3329b50d902SRodney W. Grimes { 333364d0a91STim J. Robbins wint_t ch; 334364d0a91STim J. Robbins int col; 3352c39ae65SEivind Eklund char *pos; 3369b50d902SRodney W. Grimes 3372c39ae65SEivind Eklund ch = 0; 3389b50d902SRodney W. Grimes for (;;) { 3399b50d902SRodney W. Grimes pos = positions + 1; 3409b50d902SRodney W. Grimes for (col = maxval; col; --col) { 341364d0a91STim J. Robbins if ((ch = getwc(fp)) == WEOF) 342364d0a91STim J. Robbins goto out; 3439b50d902SRodney W. Grimes if (ch == '\n') 3449b50d902SRodney W. Grimes break; 3459b50d902SRodney W. Grimes if (*pos++) 346364d0a91STim J. Robbins (void)putwchar(ch); 3479b50d902SRodney W. Grimes } 3482c39ae65SEivind Eklund if (ch != '\n') { 3499b50d902SRodney W. Grimes if (autostop) 350364d0a91STim J. Robbins while ((ch = getwc(fp)) != WEOF && ch != '\n') 351364d0a91STim J. Robbins (void)putwchar(ch); 3529b50d902SRodney W. Grimes else 353364d0a91STim J. Robbins while ((ch = getwc(fp)) != WEOF && ch != '\n'); 3542c39ae65SEivind Eklund } 355364d0a91STim J. Robbins (void)putwchar('\n'); 3569b50d902SRodney W. Grimes } 357364d0a91STim J. Robbins out: 358364d0a91STim J. Robbins if (ferror(fp)) { 359364d0a91STim J. Robbins warn("%s", fname); 360364d0a91STim J. Robbins return (1); 361364d0a91STim J. Robbins } 362364d0a91STim J. Robbins return (0); 3639b50d902SRodney W. Grimes } 3649b50d902SRodney W. Grimes 365364d0a91STim J. Robbins int 366a5c4bafcSTim J. Robbins f_cut(FILE *fp, const char *fname) 3679b50d902SRodney W. Grimes { 368a5c4bafcSTim J. Robbins wchar_t ch; 369a5c4bafcSTim J. Robbins int field, i, isdelim; 370a5c4bafcSTim J. Robbins char *pos, *p; 371a5c4bafcSTim J. Robbins wchar_t sep; 3729b50d902SRodney W. Grimes int output; 37393738f50STim J. Robbins char *lbuf, *mlbuf; 374a5c4bafcSTim J. Robbins size_t clen, lbuflen; 3759b50d902SRodney W. Grimes 37693738f50STim J. Robbins mlbuf = NULL; 3771928e20eSDima Dorfman for (sep = dchar; (lbuf = fgetln(fp, &lbuflen)) != NULL;) { 3781928e20eSDima Dorfman /* Assert EOL has a newline. */ 3791928e20eSDima Dorfman if (*(lbuf + lbuflen - 1) != '\n') { 3801928e20eSDima Dorfman /* Can't have > 1 line with no trailing newline. */ 3811928e20eSDima Dorfman mlbuf = malloc(lbuflen + 1); 3821928e20eSDima Dorfman if (mlbuf == NULL) 3831928e20eSDima Dorfman err(1, "malloc"); 3841928e20eSDima Dorfman memcpy(mlbuf, lbuf, lbuflen); 3851928e20eSDima Dorfman *(mlbuf + lbuflen) = '\n'; 3861928e20eSDima Dorfman lbuf = mlbuf; 3871928e20eSDima Dorfman } 388eaf92380SAndrey A. Chernov output = 0; 389a5c4bafcSTim J. Robbins for (isdelim = 0, p = lbuf;; p += clen) { 390a5c4bafcSTim J. Robbins clen = mbrtowc(&ch, p, lbuf + lbuflen - p, NULL); 391a5c4bafcSTim J. Robbins if (clen == (size_t)-1 || clen == (size_t)-2) { 392a5c4bafcSTim J. Robbins warnc(EILSEQ, "%s", fname); 393a5c4bafcSTim J. Robbins free(mlbuf); 394a5c4bafcSTim J. Robbins return (1); 395a5c4bafcSTim J. Robbins } 396a5c4bafcSTim J. Robbins if (clen == 0) 397a5c4bafcSTim J. Robbins clen = 1; 3989b50d902SRodney W. Grimes /* this should work if newline is delimiter */ 3999b50d902SRodney W. Grimes if (ch == sep) 4009b50d902SRodney W. Grimes isdelim = 1; 4019b50d902SRodney W. Grimes if (ch == '\n') { 4029b50d902SRodney W. Grimes if (!isdelim && !sflag) 4031928e20eSDima Dorfman (void)fwrite(lbuf, lbuflen, 1, stdout); 4049b50d902SRodney W. Grimes break; 4059b50d902SRodney W. Grimes } 4069b50d902SRodney W. Grimes } 4079b50d902SRodney W. Grimes if (!isdelim) 4089b50d902SRodney W. Grimes continue; 4099b50d902SRodney W. Grimes 4109b50d902SRodney W. Grimes pos = positions + 1; 4119b50d902SRodney W. Grimes for (field = maxval, p = lbuf; field; --field, ++pos) { 412a5c4bafcSTim J. Robbins if (*pos && output++) 413a5c4bafcSTim J. Robbins for (i = 0; dcharmb[i] != '\0'; i++) 414a5c4bafcSTim J. Robbins putchar(dcharmb[i]); 415a5c4bafcSTim J. Robbins for (;;) { 416a5c4bafcSTim J. Robbins clen = mbrtowc(&ch, p, lbuf + lbuflen - p, 417a5c4bafcSTim J. Robbins NULL); 418a5c4bafcSTim J. Robbins if (clen == (size_t)-1 || clen == (size_t)-2) { 419a5c4bafcSTim J. Robbins warnc(EILSEQ, "%s", fname); 420a5c4bafcSTim J. Robbins free(mlbuf); 421a5c4bafcSTim J. Robbins return (1); 422a5c4bafcSTim J. Robbins } 423a5c4bafcSTim J. Robbins if (clen == 0) 424a5c4bafcSTim J. Robbins clen = 1; 425a5c4bafcSTim J. Robbins p += clen; 426a5c4bafcSTim J. Robbins if (ch == '\n' || ch == sep) 427a5c4bafcSTim J. Robbins break; 428a5c4bafcSTim J. Robbins if (*pos) 429a5c4bafcSTim J. Robbins for (i = 0; i < (int)clen; i++) 430a5c4bafcSTim J. Robbins putchar(p[i - clen]); 4312c39ae65SEivind Eklund } 4329b50d902SRodney W. Grimes if (ch == '\n') 4339b50d902SRodney W. Grimes break; 4349b50d902SRodney W. Grimes } 4352c39ae65SEivind Eklund if (ch != '\n') { 4369b50d902SRodney W. Grimes if (autostop) { 4379b50d902SRodney W. Grimes if (output) 438a5c4bafcSTim J. Robbins for (i = 0; dcharmb[i] != '\0'; i++) 439a5c4bafcSTim J. Robbins putchar(dcharmb[i]); 4409b50d902SRodney W. Grimes for (; (ch = *p) != '\n'; ++p) 4419b50d902SRodney W. Grimes (void)putchar(ch); 4429b50d902SRodney W. Grimes } else 4439b50d902SRodney W. Grimes for (; (ch = *p) != '\n'; ++p); 4442c39ae65SEivind Eklund } 4459b50d902SRodney W. Grimes (void)putchar('\n'); 4469b50d902SRodney W. Grimes } 4471928e20eSDima Dorfman free(mlbuf); 448364d0a91STim J. Robbins return (0); 4499b50d902SRodney W. Grimes } 4509b50d902SRodney W. Grimes 451812bff99SPhilippe Charnier static void 452f4ac32deSDavid Malone usage(void) 4539b50d902SRodney W. Grimes { 454d51c6625SEivind Eklund (void)fprintf(stderr, "%s\n%s\n%s\n", 455d51c6625SEivind Eklund "usage: cut -b list [-n] [file ...]", 456d51c6625SEivind Eklund " cut -c list [file ...]", 457812bff99SPhilippe Charnier " cut -f list [-s] [-d delim] [file ...]"); 4589b50d902SRodney W. Grimes exit(1); 4599b50d902SRodney W. Grimes } 460