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