fold.c revision 200462
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Kevin Ruddy. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 3827270Scharnierstatic const char copyright[] = 391590Srgrimes"@(#) Copyright (c) 1990, 1993\n\ 401590Srgrimes The Regents of the University of California. All rights reserved.\n"; 411590Srgrimes#endif /* not lint */ 421590Srgrimes 431590Srgrimes#ifndef lint 4427270Scharnier#if 0 451590Srgrimesstatic char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93"; 4627270Scharnier#endif 471590Srgrimes#endif /* not lint */ 481590Srgrimes 4987751Scharnier#include <sys/cdefs.h> 5087751Scharnier__FBSDID("$FreeBSD: head/usr.bin/fold/fold.c 200462 2009-12-13 03:14:06Z delphij $"); 5187751Scharnier 5227270Scharnier#include <err.h> 5394978Stjr#include <limits.h> 5495033Sache#include <locale.h> 551590Srgrimes#include <stdio.h> 5627270Scharnier#include <stdlib.h> 57200462Sdelphij#include <string.h> 5827270Scharnier#include <unistd.h> 59131056Stjr#include <wchar.h> 60131056Stjr#include <wctype.h> 611590Srgrimes 621590Srgrimes#define DEFLINEWIDTH 80 631590Srgrimes 6492920Simpvoid fold(int); 65131056Stjrstatic int newpos(int, wint_t); 6692920Simpstatic void usage(void); 6727270Scharnier 6894978Stjrint bflag; /* Count bytes, not columns */ 6994978Stjrint sflag; /* Split on word boundaries */ 7094978Stjr 7127270Scharnierint 72102944Sdwmalonemain(int argc, char **argv) 731590Srgrimes{ 74102944Sdwmalone int ch; 7597266Stjr int rval, width; 761590Srgrimes char *p; 771590Srgrimes 7895033Sache (void) setlocale(LC_CTYPE, ""); 7995033Sache 801590Srgrimes width = -1; 8194978Stjr while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 821590Srgrimes switch (ch) { 8394978Stjr case 'b': 8494978Stjr bflag = 1; 8594978Stjr break; 8694978Stjr case 's': 8794978Stjr sflag = 1; 8894978Stjr break; 891590Srgrimes case 'w': 901590Srgrimes if ((width = atoi(optarg)) <= 0) { 9127270Scharnier errx(1, "illegal width value"); 921590Srgrimes } 931590Srgrimes break; 941590Srgrimes case '0': case '1': case '2': case '3': case '4': 951590Srgrimes case '5': case '6': case '7': case '8': case '9': 961590Srgrimes if (width == -1) { 971590Srgrimes p = argv[optind - 1]; 981590Srgrimes if (p[0] == '-' && p[1] == ch && !p[2]) 991590Srgrimes width = atoi(++p); 1001590Srgrimes else 1011590Srgrimes width = atoi(argv[optind] + 1); 1021590Srgrimes } 1031590Srgrimes break; 1041590Srgrimes default: 10527270Scharnier usage(); 1061590Srgrimes } 1071590Srgrimes argv += optind; 1081590Srgrimes argc -= optind; 1091590Srgrimes 1101590Srgrimes if (width == -1) 1111590Srgrimes width = DEFLINEWIDTH; 11297266Stjr rval = 0; 1131590Srgrimes if (!*argv) 1141590Srgrimes fold(width); 1151590Srgrimes else for (; *argv; ++argv) 1161590Srgrimes if (!freopen(*argv, "r", stdin)) { 11797266Stjr warn("%s", *argv); 11897266Stjr rval = 1; 1191590Srgrimes } else 1201590Srgrimes fold(width); 12197266Stjr exit(rval); 1221590Srgrimes} 1231590Srgrimes 12427270Scharnierstatic void 125102944Sdwmaloneusage(void) 12627270Scharnier{ 12794978Stjr (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 12827270Scharnier exit(1); 12927270Scharnier} 13027270Scharnier 13194978Stjr/* 13294978Stjr * Fold the contents of standard input to fit within WIDTH columns (or bytes) 13394978Stjr * and write to standard output. 13494978Stjr * 13594978Stjr * If sflag is set, split the line at the last space character on the line. 13694978Stjr * This flag necessitates storing the line in a buffer until the current 13794978Stjr * column > width, or a newline or EOF is read. 13894978Stjr * 13994978Stjr * The buffer can grow larger than WIDTH due to backspaces and carriage 14094978Stjr * returns embedded in the input stream. 14194978Stjr */ 14227270Scharniervoid 143102944Sdwmalonefold(int width) 1441590Srgrimes{ 145131056Stjr static wchar_t *buf; 14694978Stjr static int buf_max; 147131056Stjr int col, i, indx, space; 148131056Stjr wint_t ch; 1491590Srgrimes 15094978Stjr col = indx = 0; 151131056Stjr while ((ch = getwchar()) != WEOF) { 15294978Stjr if (ch == '\n') { 153131056Stjr wprintf(L"%.*ls\n", indx, buf); 15494978Stjr col = indx = 0; 15594978Stjr continue; 1561590Srgrimes } 15794978Stjr if ((col = newpos(col, ch)) > width) { 15894978Stjr if (sflag) { 15994978Stjr i = indx; 160131056Stjr while (--i >= 0 && !iswblank(buf[i])) 16194978Stjr ; 16294978Stjr space = i; 16394978Stjr } 16494978Stjr if (sflag && space != -1) { 16594978Stjr space++; 166131056Stjr wprintf(L"%.*ls\n", space, buf); 167131056Stjr wmemmove(buf, buf + space, indx - space); 16894978Stjr indx -= space; 16994978Stjr col = 0; 17094978Stjr for (i = 0; i < indx; i++) 171131056Stjr col = newpos(col, buf[i]); 17294978Stjr } else { 173131056Stjr wprintf(L"%.*ls\n", indx, buf); 17494978Stjr col = indx = 0; 17594978Stjr } 17694978Stjr col = newpos(col, ch); 1771590Srgrimes } 17894978Stjr if (indx + 1 > buf_max) { 17994978Stjr buf_max += LINE_MAX; 180131056Stjr buf = realloc(buf, sizeof(*buf) * buf_max); 181131056Stjr if (buf == NULL) 18294978Stjr err(1, "realloc()"); 18394978Stjr } 18494978Stjr buf[indx++] = ch; 18594978Stjr } 1861590Srgrimes 18794978Stjr if (indx != 0) 188131056Stjr wprintf(L"%.*ls", indx, buf); 18994978Stjr} 19094978Stjr 19194978Stjr/* 19294978Stjr * Update the current column position for a character. 19394978Stjr */ 19494978Stjrstatic int 195131056Stjrnewpos(int col, wint_t ch) 19694978Stjr{ 197131056Stjr char buf[MB_LEN_MAX]; 198131056Stjr size_t len; 199131056Stjr int w; 20094978Stjr 201131056Stjr if (bflag) { 202131056Stjr len = wcrtomb(buf, ch, NULL); 203131056Stjr col += len; 204131056Stjr } else 2051590Srgrimes switch (ch) { 2061590Srgrimes case '\b': 2071590Srgrimes if (col > 0) 2081590Srgrimes --col; 2091590Srgrimes break; 2101590Srgrimes case '\r': 2111590Srgrimes col = 0; 2121590Srgrimes break; 2131590Srgrimes case '\t': 21494978Stjr col = (col + 8) & ~7; 2151590Srgrimes break; 2161590Srgrimes default: 217131056Stjr if ((w = wcwidth(ch)) > 0) 218131056Stjr col += w; 2191590Srgrimes break; 2201590Srgrimes } 22194978Stjr 22294978Stjr return (col); 2231590Srgrimes} 224