fold.c revision 94978
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 94978 2002-04-18 03:33:51Z tjr $"); 5187751Scharnier 5294978Stjr#include <ctype.h> 5327270Scharnier#include <err.h> 5494978Stjr#include <limits.h> 551590Srgrimes#include <stdio.h> 5627270Scharnier#include <stdlib.h> 5794978Stjr#include <string.h> 5827270Scharnier#include <unistd.h> 591590Srgrimes 601590Srgrimes#define DEFLINEWIDTH 80 611590Srgrimes 6292920Simpvoid fold(int); 6394978Stjrstatic int newpos(int, int); 6492920Simpstatic void usage(void); 6527270Scharnier 6694978Stjrint bflag; /* Count bytes, not columns */ 6794978Stjrint sflag; /* Split on word boundaries */ 6894978Stjr 6927270Scharnierint 701590Srgrimesmain(argc, argv) 711590Srgrimes int argc; 721590Srgrimes char **argv; 731590Srgrimes{ 741590Srgrimes register int ch; 751590Srgrimes int width; 761590Srgrimes char *p; 771590Srgrimes 781590Srgrimes width = -1; 7994978Stjr while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 801590Srgrimes switch (ch) { 8194978Stjr case 'b': 8294978Stjr bflag = 1; 8394978Stjr break; 8494978Stjr case 's': 8594978Stjr sflag = 1; 8694978Stjr break; 871590Srgrimes case 'w': 881590Srgrimes if ((width = atoi(optarg)) <= 0) { 8927270Scharnier errx(1, "illegal width value"); 901590Srgrimes } 911590Srgrimes break; 921590Srgrimes case '0': case '1': case '2': case '3': case '4': 931590Srgrimes case '5': case '6': case '7': case '8': case '9': 941590Srgrimes if (width == -1) { 951590Srgrimes p = argv[optind - 1]; 961590Srgrimes if (p[0] == '-' && p[1] == ch && !p[2]) 971590Srgrimes width = atoi(++p); 981590Srgrimes else 991590Srgrimes width = atoi(argv[optind] + 1); 1001590Srgrimes } 1011590Srgrimes break; 1021590Srgrimes default: 10327270Scharnier usage(); 1041590Srgrimes } 1051590Srgrimes argv += optind; 1061590Srgrimes argc -= optind; 1071590Srgrimes 1081590Srgrimes if (width == -1) 1091590Srgrimes width = DEFLINEWIDTH; 1101590Srgrimes if (!*argv) 1111590Srgrimes fold(width); 1121590Srgrimes else for (; *argv; ++argv) 1131590Srgrimes if (!freopen(*argv, "r", stdin)) { 11427270Scharnier err(1, "%s", *argv); 1151590Srgrimes } else 1161590Srgrimes fold(width); 1171590Srgrimes exit(0); 1181590Srgrimes} 1191590Srgrimes 12027270Scharnierstatic void 12127270Scharnierusage() 12227270Scharnier{ 12394978Stjr (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 12427270Scharnier exit(1); 12527270Scharnier} 12627270Scharnier 12794978Stjr/* 12894978Stjr * Fold the contents of standard input to fit within WIDTH columns (or bytes) 12994978Stjr * and write to standard output. 13094978Stjr * 13194978Stjr * If sflag is set, split the line at the last space character on the line. 13294978Stjr * This flag necessitates storing the line in a buffer until the current 13394978Stjr * column > width, or a newline or EOF is read. 13494978Stjr * 13594978Stjr * The buffer can grow larger than WIDTH due to backspaces and carriage 13694978Stjr * returns embedded in the input stream. 13794978Stjr */ 13827270Scharniervoid 1391590Srgrimesfold(width) 1401590Srgrimes register int width; 1411590Srgrimes{ 14294978Stjr static char *buf; 14394978Stjr static int buf_max; 14494978Stjr int ch, col, i, indx, space; 1451590Srgrimes 14694978Stjr col = indx = 0; 14794978Stjr while ((ch = getchar()) != EOF) { 14894978Stjr if (ch == '\n') { 14994978Stjr if (indx != 0) 15094978Stjr fwrite(buf, 1, indx, stdout); 15194978Stjr putchar('\n'); 15294978Stjr col = indx = 0; 15394978Stjr continue; 1541590Srgrimes } 15594978Stjr if ((col = newpos(col, ch)) > width) { 15694978Stjr if (sflag) { 15794978Stjr i = indx; 15894978Stjr while (--i >= 0 && !isblank(buf[i])) 15994978Stjr ; 16094978Stjr space = i; 16194978Stjr } 16294978Stjr if (sflag && space != -1) { 16394978Stjr space++; 16494978Stjr fwrite(buf, 1, space, stdout); 16594978Stjr memmove(buf, buf + space, indx - space); 16694978Stjr indx -= space; 16794978Stjr col = 0; 16894978Stjr for (i = 0; i < indx; i++) 16994978Stjr col = newpos(col, buf[i]); 17094978Stjr } else { 17194978Stjr fwrite(buf, 1, indx, stdout); 17294978Stjr col = indx = 0; 17394978Stjr } 1741590Srgrimes putchar('\n'); 17594978Stjr col = newpos(col, ch); 1761590Srgrimes } 17794978Stjr if (indx + 1 > buf_max) { 17894978Stjr buf_max += LINE_MAX; 17994978Stjr if ((buf = realloc(buf, buf_max)) == NULL) 18094978Stjr err(1, "realloc()"); 18194978Stjr } 18294978Stjr buf[indx++] = ch; 18394978Stjr } 1841590Srgrimes 18594978Stjr if (indx != 0) 18694978Stjr fwrite(buf, 1, indx, stdout); 18794978Stjr} 18894978Stjr 18994978Stjr/* 19094978Stjr * Update the current column position for a character. 19194978Stjr */ 19294978Stjrstatic int 19394978Stjrnewpos(col, ch) 19494978Stjr int col, ch; 19594978Stjr{ 19694978Stjr 19794978Stjr if (bflag) 19894978Stjr ++col; 19994978Stjr else 2001590Srgrimes switch (ch) { 2011590Srgrimes case '\b': 2021590Srgrimes if (col > 0) 2031590Srgrimes --col; 2041590Srgrimes break; 2051590Srgrimes case '\r': 2061590Srgrimes col = 0; 2071590Srgrimes break; 2081590Srgrimes case '\t': 20994978Stjr col = (col + 8) & ~7; 2101590Srgrimes break; 2111590Srgrimes default: 2121590Srgrimes ++col; 2131590Srgrimes break; 2141590Srgrimes } 21594978Stjr 21694978Stjr return (col); 2171590Srgrimes} 218