fold.c revision 97266
1177633Sdfr/*- 2177633Sdfr * Copyright (c) 1990, 1993 3177633Sdfr * The Regents of the University of California. All rights reserved. 4177633Sdfr * 5177633Sdfr * This code is derived from software contributed to Berkeley by 6177633Sdfr * Kevin Ruddy. 7177633Sdfr * 8177633Sdfr * Redistribution and use in source and binary forms, with or without 9177633Sdfr * modification, are permitted provided that the following conditions 10177633Sdfr * are met: 11177633Sdfr * 1. Redistributions of source code must retain the above copyright 12177633Sdfr * notice, this list of conditions and the following disclaimer. 13177633Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14177633Sdfr * notice, this list of conditions and the following disclaimer in the 15177633Sdfr * documentation and/or other materials provided with the distribution. 16177633Sdfr * 3. All advertising materials mentioning features or use of this software 17177633Sdfr * must display the following acknowledgement: 18177633Sdfr * This product includes software developed by the University of 19177633Sdfr * California, Berkeley and its contributors. 20177633Sdfr * 4. Neither the name of the University nor the names of its contributors 21177633Sdfr * may be used to endorse or promote products derived from this software 22177633Sdfr * without specific prior written permission. 23177633Sdfr * 24177633Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25177633Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26177633Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27177633Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28177633Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29177633Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30177633Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31177633Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32177633Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33177633Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34177633Sdfr * SUCH DAMAGE. 35177633Sdfr */ 36177633Sdfr 37177633Sdfr#ifndef lint 38177633Sdfrstatic const char copyright[] = 39177633Sdfr"@(#) Copyright (c) 1990, 1993\n\ 40177633Sdfr The Regents of the University of California. All rights reserved.\n"; 41177633Sdfr#endif /* not lint */ 42177633Sdfr 43177633Sdfr#ifndef lint 44177633Sdfr#if 0 45177633Sdfrstatic char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93"; 46177633Sdfr#endif 47177662Sdfr#endif /* not lint */ 48177633Sdfr 49184588Sdfr#include <sys/cdefs.h> 50177662Sdfr__FBSDID("$FreeBSD: head/usr.bin/fold/fold.c 97266 2002-05-25 03:04:28Z tjr $"); 51177633Sdfr 52177633Sdfr#include <ctype.h> 53177633Sdfr#include <err.h> 54177633Sdfr#include <limits.h> 55177633Sdfr#include <locale.h> 56177633Sdfr#include <stdio.h> 57177633Sdfr#include <stdlib.h> 58177633Sdfr#include <string.h> 59177633Sdfr#include <unistd.h> 60177633Sdfr 61177633Sdfr#define DEFLINEWIDTH 80 62177685Sdfr 63177633Sdfrvoid fold(int); 64177685Sdfrstatic int newpos(int, int); 65177685Sdfrstatic void usage(void); 66177685Sdfr 67177685Sdfrint bflag; /* Count bytes, not columns */ 68177633Sdfrint sflag; /* Split on word boundaries */ 69177633Sdfr 70177633Sdfrint 71177633Sdfrmain(argc, argv) 72177633Sdfr int argc; 73177633Sdfr char **argv; 74177633Sdfr{ 75177633Sdfr register int ch; 76177633Sdfr int rval, width; 77177633Sdfr char *p; 78177633Sdfr 79177633Sdfr (void) setlocale(LC_CTYPE, ""); 80177633Sdfr 81177633Sdfr width = -1; 82177633Sdfr while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 83177633Sdfr switch (ch) { 84177633Sdfr case 'b': 85177633Sdfr bflag = 1; 86177633Sdfr break; 87177633Sdfr case 's': 88177633Sdfr sflag = 1; 89177633Sdfr break; 90177633Sdfr case 'w': 91177633Sdfr if ((width = atoi(optarg)) <= 0) { 92177633Sdfr errx(1, "illegal width value"); 93177633Sdfr } 94177633Sdfr break; 95177633Sdfr case '0': case '1': case '2': case '3': case '4': 96177633Sdfr case '5': case '6': case '7': case '8': case '9': 97177633Sdfr if (width == -1) { 98177633Sdfr p = argv[optind - 1]; 99177633Sdfr if (p[0] == '-' && p[1] == ch && !p[2]) 100177633Sdfr width = atoi(++p); 101177633Sdfr else 102177633Sdfr width = atoi(argv[optind] + 1); 103177633Sdfr } 104177633Sdfr break; 105177633Sdfr default: 106177633Sdfr usage(); 107177633Sdfr } 108177633Sdfr argv += optind; 109177633Sdfr argc -= optind; 110177633Sdfr 111177633Sdfr if (width == -1) 112177633Sdfr width = DEFLINEWIDTH; 113177633Sdfr rval = 0; 114177633Sdfr if (!*argv) 115177633Sdfr fold(width); 116177633Sdfr else for (; *argv; ++argv) 117177633Sdfr if (!freopen(*argv, "r", stdin)) { 118177633Sdfr warn("%s", *argv); 119177633Sdfr rval = 1; 120177633Sdfr } else 121177633Sdfr fold(width); 122177633Sdfr exit(rval); 123177633Sdfr} 124177633Sdfr 125177633Sdfrstatic void 126177633Sdfrusage() 127177633Sdfr{ 128177633Sdfr (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 129177633Sdfr exit(1); 130177633Sdfr} 131177633Sdfr 132177633Sdfr/* 133177633Sdfr * Fold the contents of standard input to fit within WIDTH columns (or bytes) 134177633Sdfr * and write to standard output. 135177633Sdfr * 136177633Sdfr * If sflag is set, split the line at the last space character on the line. 137177633Sdfr * This flag necessitates storing the line in a buffer until the current 138177633Sdfr * column > width, or a newline or EOF is read. 139177633Sdfr * 140177633Sdfr * The buffer can grow larger than WIDTH due to backspaces and carriage 141177633Sdfr * returns embedded in the input stream. 142177633Sdfr */ 143177633Sdfrvoid 144177633Sdfrfold(width) 145177633Sdfr register int width; 146177633Sdfr{ 147177633Sdfr static char *buf; 148177633Sdfr static int buf_max; 149177633Sdfr int ch, col, i, indx, space; 150177633Sdfr 151177633Sdfr col = indx = 0; 152177633Sdfr while ((ch = getchar()) != EOF) { 153177633Sdfr if (ch == '\n') { 154177633Sdfr if (indx != 0) 155177633Sdfr fwrite(buf, 1, indx, stdout); 156177633Sdfr putchar('\n'); 157177633Sdfr col = indx = 0; 158177633Sdfr continue; 159177633Sdfr } 160177633Sdfr if ((col = newpos(col, ch)) > width) { 161177633Sdfr if (sflag) { 162177633Sdfr i = indx; 163177633Sdfr while (--i >= 0 && !isblank((unsigned char)buf[i])) 164177633Sdfr ; 165177633Sdfr space = i; 166177633Sdfr } 167177633Sdfr if (sflag && space != -1) { 168177633Sdfr space++; 169177633Sdfr fwrite(buf, 1, space, stdout); 170177633Sdfr memmove(buf, buf + space, indx - space); 171177633Sdfr indx -= space; 172177633Sdfr col = 0; 173177633Sdfr for (i = 0; i < indx; i++) 174177633Sdfr col = newpos(col, buf[i]); 175177633Sdfr } else { 176177633Sdfr fwrite(buf, 1, indx, stdout); 177177633Sdfr col = indx = 0; 178177633Sdfr } 179177633Sdfr putchar('\n'); 180177633Sdfr col = newpos(col, ch); 181177633Sdfr } 182177633Sdfr if (indx + 1 > buf_max) { 183177633Sdfr buf_max += LINE_MAX; 184177633Sdfr if ((buf = realloc(buf, buf_max)) == NULL) 185177633Sdfr err(1, "realloc()"); 186177633Sdfr } 187177633Sdfr buf[indx++] = ch; 188177633Sdfr } 189177633Sdfr 190177633Sdfr if (indx != 0) 191177633Sdfr fwrite(buf, 1, indx, stdout); 192177633Sdfr} 193177633Sdfr 194177633Sdfr/* 195177633Sdfr * Update the current column position for a character. 196177633Sdfr */ 197177633Sdfrstatic int 198177633Sdfrnewpos(col, ch) 199177633Sdfr int col, ch; 200177633Sdfr{ 201177633Sdfr 202177633Sdfr if (bflag) 203177633Sdfr ++col; 204177633Sdfr else 205177633Sdfr switch (ch) { 206177633Sdfr case '\b': 207177633Sdfr if (col > 0) 208177633Sdfr --col; 209177633Sdfr break; 210177633Sdfr case '\r': 211177633Sdfr col = 0; 212177633Sdfr break; 213177633Sdfr case '\t': 214177633Sdfr col = (col + 8) & ~7; 215177633Sdfr break; 216177633Sdfr default: 217177633Sdfr ++col; 218177633Sdfr break; 219177633Sdfr } 220177633Sdfr 221177633Sdfr return (col); 222177633Sdfr} 223177633Sdfr