fold.c revision 97266
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 97266 2002-05-25 03:04:28Z tjr $"); 5187751Scharnier 5294978Stjr#include <ctype.h> 5327270Scharnier#include <err.h> 5494978Stjr#include <limits.h> 5595033Sache#include <locale.h> 561590Srgrimes#include <stdio.h> 5727270Scharnier#include <stdlib.h> 5894978Stjr#include <string.h> 5927270Scharnier#include <unistd.h> 601590Srgrimes 611590Srgrimes#define DEFLINEWIDTH 80 621590Srgrimes 6392920Simpvoid fold(int); 6494978Stjrstatic int newpos(int, int); 6592920Simpstatic void usage(void); 6627270Scharnier 6794978Stjrint bflag; /* Count bytes, not columns */ 6894978Stjrint sflag; /* Split on word boundaries */ 6994978Stjr 7027270Scharnierint 711590Srgrimesmain(argc, argv) 721590Srgrimes int argc; 731590Srgrimes char **argv; 741590Srgrimes{ 751590Srgrimes register int ch; 7697266Stjr int rval, width; 771590Srgrimes char *p; 781590Srgrimes 7995033Sache (void) setlocale(LC_CTYPE, ""); 8095033Sache 811590Srgrimes width = -1; 8294978Stjr while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 831590Srgrimes switch (ch) { 8494978Stjr case 'b': 8594978Stjr bflag = 1; 8694978Stjr break; 8794978Stjr case 's': 8894978Stjr sflag = 1; 8994978Stjr break; 901590Srgrimes case 'w': 911590Srgrimes if ((width = atoi(optarg)) <= 0) { 9227270Scharnier errx(1, "illegal width value"); 931590Srgrimes } 941590Srgrimes break; 951590Srgrimes case '0': case '1': case '2': case '3': case '4': 961590Srgrimes case '5': case '6': case '7': case '8': case '9': 971590Srgrimes if (width == -1) { 981590Srgrimes p = argv[optind - 1]; 991590Srgrimes if (p[0] == '-' && p[1] == ch && !p[2]) 1001590Srgrimes width = atoi(++p); 1011590Srgrimes else 1021590Srgrimes width = atoi(argv[optind] + 1); 1031590Srgrimes } 1041590Srgrimes break; 1051590Srgrimes default: 10627270Scharnier usage(); 1071590Srgrimes } 1081590Srgrimes argv += optind; 1091590Srgrimes argc -= optind; 1101590Srgrimes 1111590Srgrimes if (width == -1) 1121590Srgrimes width = DEFLINEWIDTH; 11397266Stjr rval = 0; 1141590Srgrimes if (!*argv) 1151590Srgrimes fold(width); 1161590Srgrimes else for (; *argv; ++argv) 1171590Srgrimes if (!freopen(*argv, "r", stdin)) { 11897266Stjr warn("%s", *argv); 11997266Stjr rval = 1; 1201590Srgrimes } else 1211590Srgrimes fold(width); 12297266Stjr exit(rval); 1231590Srgrimes} 1241590Srgrimes 12527270Scharnierstatic void 12627270Scharnierusage() 12727270Scharnier{ 12894978Stjr (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 12927270Scharnier exit(1); 13027270Scharnier} 13127270Scharnier 13294978Stjr/* 13394978Stjr * Fold the contents of standard input to fit within WIDTH columns (or bytes) 13494978Stjr * and write to standard output. 13594978Stjr * 13694978Stjr * If sflag is set, split the line at the last space character on the line. 13794978Stjr * This flag necessitates storing the line in a buffer until the current 13894978Stjr * column > width, or a newline or EOF is read. 13994978Stjr * 14094978Stjr * The buffer can grow larger than WIDTH due to backspaces and carriage 14194978Stjr * returns embedded in the input stream. 14294978Stjr */ 14327270Scharniervoid 1441590Srgrimesfold(width) 1451590Srgrimes register int width; 1461590Srgrimes{ 14794978Stjr static char *buf; 14894978Stjr static int buf_max; 14994978Stjr int ch, col, i, indx, space; 1501590Srgrimes 15194978Stjr col = indx = 0; 15294978Stjr while ((ch = getchar()) != EOF) { 15394978Stjr if (ch == '\n') { 15494978Stjr if (indx != 0) 15594978Stjr fwrite(buf, 1, indx, stdout); 15694978Stjr putchar('\n'); 15794978Stjr col = indx = 0; 15894978Stjr continue; 1591590Srgrimes } 16094978Stjr if ((col = newpos(col, ch)) > width) { 16194978Stjr if (sflag) { 16294978Stjr i = indx; 16395033Sache while (--i >= 0 && !isblank((unsigned char)buf[i])) 16494978Stjr ; 16594978Stjr space = i; 16694978Stjr } 16794978Stjr if (sflag && space != -1) { 16894978Stjr space++; 16994978Stjr fwrite(buf, 1, space, stdout); 17094978Stjr memmove(buf, buf + space, indx - space); 17194978Stjr indx -= space; 17294978Stjr col = 0; 17394978Stjr for (i = 0; i < indx; i++) 17494978Stjr col = newpos(col, buf[i]); 17594978Stjr } else { 17694978Stjr fwrite(buf, 1, indx, stdout); 17794978Stjr col = indx = 0; 17894978Stjr } 1791590Srgrimes putchar('\n'); 18094978Stjr col = newpos(col, ch); 1811590Srgrimes } 18294978Stjr if (indx + 1 > buf_max) { 18394978Stjr buf_max += LINE_MAX; 18494978Stjr if ((buf = realloc(buf, buf_max)) == NULL) 18594978Stjr err(1, "realloc()"); 18694978Stjr } 18794978Stjr buf[indx++] = ch; 18894978Stjr } 1891590Srgrimes 19094978Stjr if (indx != 0) 19194978Stjr fwrite(buf, 1, indx, stdout); 19294978Stjr} 19394978Stjr 19494978Stjr/* 19594978Stjr * Update the current column position for a character. 19694978Stjr */ 19794978Stjrstatic int 19894978Stjrnewpos(col, ch) 19994978Stjr int col, ch; 20094978Stjr{ 20194978Stjr 20294978Stjr if (bflag) 20394978Stjr ++col; 20494978Stjr 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: 2171590Srgrimes ++col; 2181590Srgrimes break; 2191590Srgrimes } 22094978Stjr 22194978Stjr return (col); 2221590Srgrimes} 223