diff options
author | tjr <tjr@FreeBSD.org> | 2002-04-18 03:33:51 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2002-04-18 03:33:51 +0000 |
commit | b7829d60fef4ef94c68a4c95c5e46126cf910197 (patch) | |
tree | 7f6edeec0b2cf0aa105b07956f4009fa50afeefd /usr.bin | |
parent | 50de41829507706df2569f9a0e93027eeae643ba (diff) | |
download | FreeBSD-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')
-rw-r--r-- | usr.bin/fold/fold.1 | 16 | ||||
-rw-r--r-- | usr.bin/fold/fold.c | 110 |
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); } |