19b50d902SRodney W. Grimes /*- 29b50d902SRodney W. Grimes * Copyright (c) 1990, 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 * Kevin Ruddy. 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 38f589c9aaSPhilippe Charnier static const char copyright[] = 399b50d902SRodney W. Grimes "@(#) Copyright (c) 1990, 1993\n\ 409b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 419b50d902SRodney W. Grimes #endif /* not lint */ 429b50d902SRodney W. Grimes 439b50d902SRodney W. Grimes #ifndef lint 44f589c9aaSPhilippe Charnier #if 0 459b50d902SRodney W. Grimes static char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93"; 46f589c9aaSPhilippe Charnier #endif 479b50d902SRodney W. Grimes #endif /* not lint */ 489b50d902SRodney W. Grimes 49a9c9a0d1SPhilippe Charnier #include <sys/cdefs.h> 50a9c9a0d1SPhilippe Charnier __FBSDID("$FreeBSD$"); 51a9c9a0d1SPhilippe Charnier 52f589c9aaSPhilippe Charnier #include <err.h> 5313e06695STim J. Robbins #include <limits.h> 54a243305fSAndrey A. Chernov #include <locale.h> 559b50d902SRodney W. Grimes #include <stdio.h> 56f589c9aaSPhilippe Charnier #include <stdlib.h> 5713e06695STim J. Robbins #include <string.h> 58f589c9aaSPhilippe Charnier #include <unistd.h> 5919657ec3STim J. Robbins #include <wchar.h> 6019657ec3STim J. Robbins #include <wctype.h> 619b50d902SRodney W. Grimes 629b50d902SRodney W. Grimes #define DEFLINEWIDTH 80 639b50d902SRodney W. Grimes 64f1bb2cd2SWarner Losh void fold(int); 6519657ec3STim J. Robbins static int newpos(int, wint_t); 66f1bb2cd2SWarner Losh static void usage(void); 67f589c9aaSPhilippe Charnier 6813e06695STim J. Robbins int bflag; /* Count bytes, not columns */ 6913e06695STim J. Robbins int sflag; /* Split on word boundaries */ 7013e06695STim J. Robbins 71f589c9aaSPhilippe Charnier int 72f4ac32deSDavid Malone main(int argc, char **argv) 739b50d902SRodney W. Grimes { 74f4ac32deSDavid Malone int ch; 75fb2582c0STim J. Robbins int rval, width; 769b50d902SRodney W. Grimes char *p; 779b50d902SRodney W. Grimes 78a243305fSAndrey A. Chernov (void) setlocale(LC_CTYPE, ""); 79a243305fSAndrey A. Chernov 809b50d902SRodney W. Grimes width = -1; 8113e06695STim J. Robbins while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 829b50d902SRodney W. Grimes switch (ch) { 8313e06695STim J. Robbins case 'b': 8413e06695STim J. Robbins bflag = 1; 8513e06695STim J. Robbins break; 8613e06695STim J. Robbins case 's': 8713e06695STim J. Robbins sflag = 1; 8813e06695STim J. Robbins break; 899b50d902SRodney W. Grimes case 'w': 909b50d902SRodney W. Grimes if ((width = atoi(optarg)) <= 0) { 91f589c9aaSPhilippe Charnier errx(1, "illegal width value"); 929b50d902SRodney W. Grimes } 939b50d902SRodney W. Grimes break; 949b50d902SRodney W. Grimes case '0': case '1': case '2': case '3': case '4': 959b50d902SRodney W. Grimes case '5': case '6': case '7': case '8': case '9': 969b50d902SRodney W. Grimes if (width == -1) { 979b50d902SRodney W. Grimes p = argv[optind - 1]; 989b50d902SRodney W. Grimes if (p[0] == '-' && p[1] == ch && !p[2]) 999b50d902SRodney W. Grimes width = atoi(++p); 1009b50d902SRodney W. Grimes else 1019b50d902SRodney W. Grimes width = atoi(argv[optind] + 1); 1029b50d902SRodney W. Grimes } 1039b50d902SRodney W. Grimes break; 1049b50d902SRodney W. Grimes default: 105f589c9aaSPhilippe Charnier usage(); 1069b50d902SRodney W. Grimes } 1079b50d902SRodney W. Grimes argv += optind; 1089b50d902SRodney W. Grimes argc -= optind; 1099b50d902SRodney W. Grimes 1109b50d902SRodney W. Grimes if (width == -1) 1119b50d902SRodney W. Grimes width = DEFLINEWIDTH; 112fb2582c0STim J. Robbins rval = 0; 1139b50d902SRodney W. Grimes if (!*argv) 1149b50d902SRodney W. Grimes fold(width); 1159b50d902SRodney W. Grimes else for (; *argv; ++argv) 1169b50d902SRodney W. Grimes if (!freopen(*argv, "r", stdin)) { 117fb2582c0STim J. Robbins warn("%s", *argv); 118fb2582c0STim J. Robbins rval = 1; 1199b50d902SRodney W. Grimes } else 1209b50d902SRodney W. Grimes fold(width); 121fb2582c0STim J. Robbins exit(rval); 1229b50d902SRodney W. Grimes } 1239b50d902SRodney W. Grimes 124f589c9aaSPhilippe Charnier static void 125f4ac32deSDavid Malone usage(void) 126f589c9aaSPhilippe Charnier { 12713e06695STim J. Robbins (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 128f589c9aaSPhilippe Charnier exit(1); 129f589c9aaSPhilippe Charnier } 130f589c9aaSPhilippe Charnier 13113e06695STim J. Robbins /* 13213e06695STim J. Robbins * Fold the contents of standard input to fit within WIDTH columns (or bytes) 13313e06695STim J. Robbins * and write to standard output. 13413e06695STim J. Robbins * 13513e06695STim J. Robbins * If sflag is set, split the line at the last space character on the line. 13613e06695STim J. Robbins * This flag necessitates storing the line in a buffer until the current 13713e06695STim J. Robbins * column > width, or a newline or EOF is read. 13813e06695STim J. Robbins * 13913e06695STim J. Robbins * The buffer can grow larger than WIDTH due to backspaces and carriage 14013e06695STim J. Robbins * returns embedded in the input stream. 14113e06695STim J. Robbins */ 142f589c9aaSPhilippe Charnier void 143f4ac32deSDavid Malone fold(int width) 1449b50d902SRodney W. Grimes { 14519657ec3STim J. Robbins static wchar_t *buf; 14613e06695STim J. Robbins static int buf_max; 14719657ec3STim J. Robbins int col, i, indx, space; 14819657ec3STim J. Robbins wint_t ch; 1499b50d902SRodney W. Grimes 15013e06695STim J. Robbins col = indx = 0; 15119657ec3STim J. Robbins while ((ch = getwchar()) != WEOF) { 15213e06695STim J. Robbins if (ch == '\n') { 15319657ec3STim J. Robbins wprintf(L"%.*ls\n", indx, buf); 15413e06695STim J. Robbins col = indx = 0; 15513e06695STim J. Robbins continue; 1569b50d902SRodney W. Grimes } 15713e06695STim J. Robbins if ((col = newpos(col, ch)) > width) { 15813e06695STim J. Robbins if (sflag) { 15913e06695STim J. Robbins i = indx; 16019657ec3STim J. Robbins while (--i >= 0 && !iswblank(buf[i])) 16113e06695STim J. Robbins ; 16213e06695STim J. Robbins space = i; 16313e06695STim J. Robbins } 16413e06695STim J. Robbins if (sflag && space != -1) { 16513e06695STim J. Robbins space++; 16619657ec3STim J. Robbins wprintf(L"%.*ls\n", space, buf); 16719657ec3STim J. Robbins wmemmove(buf, buf + space, indx - space); 16813e06695STim J. Robbins indx -= space; 16913e06695STim J. Robbins col = 0; 17013e06695STim J. Robbins for (i = 0; i < indx; i++) 17119657ec3STim J. Robbins col = newpos(col, buf[i]); 17213e06695STim J. Robbins } else { 17319657ec3STim J. Robbins wprintf(L"%.*ls\n", indx, buf); 17413e06695STim J. Robbins col = indx = 0; 17513e06695STim J. Robbins } 17613e06695STim J. Robbins col = newpos(col, ch); 17713e06695STim J. Robbins } 17813e06695STim J. Robbins if (indx + 1 > buf_max) { 17913e06695STim J. Robbins buf_max += LINE_MAX; 18019657ec3STim J. Robbins buf = realloc(buf, sizeof(*buf) * buf_max); 18119657ec3STim J. Robbins if (buf == NULL) 18213e06695STim J. Robbins err(1, "realloc()"); 18313e06695STim J. Robbins } 18413e06695STim J. Robbins buf[indx++] = ch; 18513e06695STim J. Robbins } 1869b50d902SRodney W. Grimes 18713e06695STim J. Robbins if (indx != 0) 18819657ec3STim J. Robbins wprintf(L"%.*ls", indx, buf); 18913e06695STim J. Robbins } 19013e06695STim J. Robbins 19113e06695STim J. Robbins /* 19213e06695STim J. Robbins * Update the current column position for a character. 19313e06695STim J. Robbins */ 19413e06695STim J. Robbins static int 19519657ec3STim J. Robbins newpos(int col, wint_t ch) 19613e06695STim J. Robbins { 19719657ec3STim J. Robbins char buf[MB_LEN_MAX]; 19819657ec3STim J. Robbins size_t len; 19919657ec3STim J. Robbins int w; 20013e06695STim J. Robbins 20119657ec3STim J. Robbins if (bflag) { 20219657ec3STim J. Robbins len = wcrtomb(buf, ch, NULL); 20319657ec3STim J. Robbins col += len; 20419657ec3STim J. Robbins } else 2059b50d902SRodney W. Grimes switch (ch) { 2069b50d902SRodney W. Grimes case '\b': 2079b50d902SRodney W. Grimes if (col > 0) 2089b50d902SRodney W. Grimes --col; 2099b50d902SRodney W. Grimes break; 2109b50d902SRodney W. Grimes case '\r': 2119b50d902SRodney W. Grimes col = 0; 2129b50d902SRodney W. Grimes break; 2139b50d902SRodney W. Grimes case '\t': 21413e06695STim J. Robbins col = (col + 8) & ~7; 2159b50d902SRodney W. Grimes break; 2169b50d902SRodney W. Grimes default: 21719657ec3STim J. Robbins if ((w = wcwidth(ch)) > 0) 21819657ec3STim J. Robbins col += w; 2199b50d902SRodney W. Grimes break; 2209b50d902SRodney W. Grimes } 22113e06695STim J. Robbins 22213e06695STim J. Robbins return (col); 2239b50d902SRodney W. Grimes } 224