summaryrefslogtreecommitdiffstats
path: root/usr.bin/fold
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2002-04-18 03:33:51 +0000
committertjr <tjr@FreeBSD.org>2002-04-18 03:33:51 +0000
commitb7829d60fef4ef94c68a4c95c5e46126cf910197 (patch)
tree7f6edeec0b2cf0aa105b07956f4009fa50afeefd /usr.bin/fold
parent50de41829507706df2569f9a0e93027eeae643ba (diff)
downloadFreeBSD-src-b7829d60fef4ef94c68a4c95c5e46126cf910197.zip
FreeBSD-src-b7829d60fef4ef94c68a4c95c5e46126cf910197.tar.gz
Add the -b option (break at byte position, not column number) and the -s
option (try to break at word bounaries) for SUSv3 conformance. Partially based on the NetBSD version, with the following changes: - style(9) - break on <blank>s, not spaces, per POSIX (and GNU) - when looking for last space on line, search backwards instead of forwards; less comparisons needed this way. - use LINE_MAX macro instead of a magic number and a comment saying it is LINE_MAX. PR: 36245 Reviewed by: mike Obtained from: NetBSD (partially)
Diffstat (limited to 'usr.bin/fold')
-rw-r--r--usr.bin/fold/fold.116
-rw-r--r--usr.bin/fold/fold.c110
2 files changed, 97 insertions, 29 deletions
diff --git a/usr.bin/fold/fold.1 b/usr.bin/fold/fold.1
index 63a52f2..071f39a 100644
--- a/usr.bin/fold/fold.1
+++ b/usr.bin/fold/fold.1
@@ -32,7 +32,7 @@
.\" @(#)fold.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd June 6, 1993
+.Dd April 17, 2002
.Dt FOLD 1
.Os
.Sh NAME
@@ -40,6 +40,7 @@
.Nd "fold long lines for finite width output device"
.Sh SYNOPSIS
.Nm
+.Op Fl bs
.Op Fl w Ar width
.Op Ar
.Sh DESCRIPTION
@@ -50,6 +51,14 @@ breaking the lines to have a maximum of 80 characters.
.Pp
The following option is available:
.Bl -tag -width indent
+.It Fl b
+Count
+.Ar width
+in bytes rather than column positions.
+.It Fl s
+Fold line after the last blank character within the first
+.Ar width
+column positions (or bytes).
.It Fl w Ar width
Specify a line width to use instead of the default 80 characters.
.Ar Width
@@ -61,5 +70,10 @@ before using
.El
.Sh SEE ALSO
.Xr expand 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
.Sh BUGS
If underlining is present it may be messed up by folding.
diff --git a/usr.bin/fold/fold.c b/usr.bin/fold/fold.c
index 33208ae..68a3ebe 100644
--- a/usr.bin/fold/fold.c
+++ b/usr.bin/fold/fold.c
@@ -49,16 +49,23 @@ static char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <ctype.h>
#include <err.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#define DEFLINEWIDTH 80
void fold(int);
+static int newpos(int, int);
static void usage(void);
+int bflag; /* Count bytes, not columns */
+int sflag; /* Split on word boundaries */
+
int
main(argc, argv)
int argc;
@@ -69,8 +76,14 @@ main(argc, argv)
char *p;
width = -1;
- while ((ch = getopt(argc, argv, "0123456789w:")) != -1)
+ while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1)
switch (ch) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
case 'w':
if ((width = atoi(optarg)) <= 0) {
errx(1, "illegal width value");
@@ -107,57 +120,98 @@ main(argc, argv)
static void
usage()
{
- (void)fprintf(stderr, "usage: fold [-w width] [file ...]\n");
+ (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n");
exit(1);
}
+/*
+ * Fold the contents of standard input to fit within WIDTH columns (or bytes)
+ * and write to standard output.
+ *
+ * If sflag is set, split the line at the last space character on the line.
+ * This flag necessitates storing the line in a buffer until the current
+ * column > width, or a newline or EOF is read.
+ *
+ * The buffer can grow larger than WIDTH due to backspaces and carriage
+ * returns embedded in the input stream.
+ */
void
fold(width)
register int width;
{
- register int ch, col, new;
+ static char *buf;
+ static int buf_max;
+ int ch, col, i, indx, space;
- for (col = 0;;) {
- switch (ch = getchar()) {
- case EOF:
- return;
- case '\b':
- new = col ? col - 1 : 0;
- break;
- case '\n':
- case '\r':
- new = 0;
- break;
- case '\t':
- new = (col + 8) & ~7;
- break;
- default:
- new = col + 1;
- break;
+ col = indx = 0;
+ while ((ch = getchar()) != EOF) {
+ if (ch == '\n') {
+ if (indx != 0)
+ fwrite(buf, 1, indx, stdout);
+ putchar('\n');
+ col = indx = 0;
+ continue;
}
-
- if (new > width) {
+ if ((col = newpos(col, ch)) > width) {
+ if (sflag) {
+ i = indx;
+ while (--i >= 0 && !isblank(buf[i]))
+ ;
+ space = i;
+ }
+ if (sflag && space != -1) {
+ space++;
+ fwrite(buf, 1, space, stdout);
+ memmove(buf, buf + space, indx - space);
+ indx -= space;
+ col = 0;
+ for (i = 0; i < indx; i++)
+ col = newpos(col, buf[i]);
+ } else {
+ fwrite(buf, 1, indx, stdout);
+ col = indx = 0;
+ }
putchar('\n');
- col = 0;
+ col = newpos(col, ch);
+ }
+ if (indx + 1 > buf_max) {
+ buf_max += LINE_MAX;
+ if ((buf = realloc(buf, buf_max)) == NULL)
+ err(1, "realloc()");
}
- putchar(ch);
+ buf[indx++] = ch;
+ }
+ if (indx != 0)
+ fwrite(buf, 1, indx, stdout);
+}
+
+/*
+ * Update the current column position for a character.
+ */
+static int
+newpos(col, ch)
+ int col, ch;
+{
+
+ if (bflag)
+ ++col;
+ else
switch (ch) {
case '\b':
if (col > 0)
--col;
break;
- case '\n':
case '\r':
col = 0;
break;
case '\t':
- col += 8;
- col &= ~7;
+ col = (col + 8) & ~7;
break;
default:
++col;
break;
}
- }
+
+ return (col);
}
OpenPOWER on IntegriCloud