fold.c revision 94978
1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kevin Ruddy. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#ifndef lint 38static const char copyright[] = 39"@(#) Copyright (c) 1990, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /* not lint */ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93"; 46#endif 47#endif /* not lint */ 48 49#include <sys/cdefs.h> 50__FBSDID("$FreeBSD: head/usr.bin/fold/fold.c 94978 2002-04-18 03:33:51Z tjr $"); 51 52#include <ctype.h> 53#include <err.h> 54#include <limits.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <string.h> 58#include <unistd.h> 59 60#define DEFLINEWIDTH 80 61 62void fold(int); 63static int newpos(int, int); 64static void usage(void); 65 66int bflag; /* Count bytes, not columns */ 67int sflag; /* Split on word boundaries */ 68 69int 70main(argc, argv) 71 int argc; 72 char **argv; 73{ 74 register int ch; 75 int width; 76 char *p; 77 78 width = -1; 79 while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) 80 switch (ch) { 81 case 'b': 82 bflag = 1; 83 break; 84 case 's': 85 sflag = 1; 86 break; 87 case 'w': 88 if ((width = atoi(optarg)) <= 0) { 89 errx(1, "illegal width value"); 90 } 91 break; 92 case '0': case '1': case '2': case '3': case '4': 93 case '5': case '6': case '7': case '8': case '9': 94 if (width == -1) { 95 p = argv[optind - 1]; 96 if (p[0] == '-' && p[1] == ch && !p[2]) 97 width = atoi(++p); 98 else 99 width = atoi(argv[optind] + 1); 100 } 101 break; 102 default: 103 usage(); 104 } 105 argv += optind; 106 argc -= optind; 107 108 if (width == -1) 109 width = DEFLINEWIDTH; 110 if (!*argv) 111 fold(width); 112 else for (; *argv; ++argv) 113 if (!freopen(*argv, "r", stdin)) { 114 err(1, "%s", *argv); 115 } else 116 fold(width); 117 exit(0); 118} 119 120static void 121usage() 122{ 123 (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n"); 124 exit(1); 125} 126 127/* 128 * Fold the contents of standard input to fit within WIDTH columns (or bytes) 129 * and write to standard output. 130 * 131 * If sflag is set, split the line at the last space character on the line. 132 * This flag necessitates storing the line in a buffer until the current 133 * column > width, or a newline or EOF is read. 134 * 135 * The buffer can grow larger than WIDTH due to backspaces and carriage 136 * returns embedded in the input stream. 137 */ 138void 139fold(width) 140 register int width; 141{ 142 static char *buf; 143 static int buf_max; 144 int ch, col, i, indx, space; 145 146 col = indx = 0; 147 while ((ch = getchar()) != EOF) { 148 if (ch == '\n') { 149 if (indx != 0) 150 fwrite(buf, 1, indx, stdout); 151 putchar('\n'); 152 col = indx = 0; 153 continue; 154 } 155 if ((col = newpos(col, ch)) > width) { 156 if (sflag) { 157 i = indx; 158 while (--i >= 0 && !isblank(buf[i])) 159 ; 160 space = i; 161 } 162 if (sflag && space != -1) { 163 space++; 164 fwrite(buf, 1, space, stdout); 165 memmove(buf, buf + space, indx - space); 166 indx -= space; 167 col = 0; 168 for (i = 0; i < indx; i++) 169 col = newpos(col, buf[i]); 170 } else { 171 fwrite(buf, 1, indx, stdout); 172 col = indx = 0; 173 } 174 putchar('\n'); 175 col = newpos(col, ch); 176 } 177 if (indx + 1 > buf_max) { 178 buf_max += LINE_MAX; 179 if ((buf = realloc(buf, buf_max)) == NULL) 180 err(1, "realloc()"); 181 } 182 buf[indx++] = ch; 183 } 184 185 if (indx != 0) 186 fwrite(buf, 1, indx, stdout); 187} 188 189/* 190 * Update the current column position for a character. 191 */ 192static int 193newpos(col, ch) 194 int col, ch; 195{ 196 197 if (bflag) 198 ++col; 199 else 200 switch (ch) { 201 case '\b': 202 if (col > 0) 203 --col; 204 break; 205 case '\r': 206 col = 0; 207 break; 208 case '\t': 209 col = (col + 8) & ~7; 210 break; 211 default: 212 ++col; 213 break; 214 } 215 216 return (col); 217} 218