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