Date: Wed, 30 Jan 2002 20:16:15 +1100 From: "Tim J. Robbins" <tim@robbins.dropbear.id.au> To: freebsd-standards@FreeBSD.ORG Subject: fold -b and -s options patch Message-ID: <20020130201615.A9151@descent.robbins.dropbear.id.au>
next in thread | raw e-mail | index | archive | help
--T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: inline This patch adds the -b and -s options to fold. It's mostly taken from NetBSD but I've hopefully kept it compilable by K&R compilers. Tim --T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="fold.diff" Index: fold/fold.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/fold/fold.1,v retrieving revision 1.7 diff -u -r1.7 fold.1 --- fold/fold.1 2001/12/12 18:25:53 1.7 +++ fold/fold.1 2002/01/30 09:16:34 @@ -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 @@ .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 Index: fold/fold.c =================================================================== RCS file: /home/ncvs/src/usr.bin/fold/fold.c,v retrieving revision 1.6 diff -u -r1.6 fold.c --- fold/fold.c 2001/12/12 18:25:53 1.6 +++ fold/fold.c 2002/01/30 09:16:35 @@ -52,13 +52,19 @@ #include <err.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <sysexits.h> #include <unistd.h> #define DEFLINEWIDTH 80 void fold __P((int)); +static int new_column_position __P((int, int)); static void usage __P((void)); +int count_bytes = 0; +int split_words = 0; + int main(argc, argv) int argc; @@ -69,8 +75,14 @@ char *p; width = -1; - while ((ch = getopt(argc, argv, "0123456789w:")) != -1) + while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) switch (ch) { + case 'b': + count_bytes = 1; + break; + case 's': + split_words = 1; + break; case 'w': if ((width = atoi(optarg)) <= 0) { errx(1, "illegal width value"); @@ -98,7 +110,7 @@ fold(width); else for (; *argv; ++argv) if (!freopen(*argv, "r", stdin)) { - err(1, "%s", *argv); + err(EX_NOINPUT, "%s", *argv); } else fold(width); exit(0); @@ -107,57 +119,115 @@ 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 split_words 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; - - 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; + static char *buf = NULL; + static int buf_max = 0; + register int ch, col; + int indx; + + col = indx = 0; + while ((ch = getchar()) != EOF) { + if (ch == '\n') { + if (indx != 0) + fwrite (buf, 1, indx, stdout); + putchar('\n'); + col = indx = 0; + continue; } + + col = new_column_position (col, ch); + if (col > width) { + int i, last_space; + +#ifdef __GNUC__ + last_space = 0; /* XXX gcc */ +#endif + if (split_words) { + for (i = 0, last_space = -1; i < indx; i++) + if (buf[i] == ' ') + last_space = i; + } + + if (split_words && last_space != -1) { + last_space++; - if (new > width) { + fwrite (buf, 1, last_space, stdout); + memmove (buf, buf+last_space, indx-last_space); + + indx -= last_space; + col = 0; + for (i = 0; i < indx; i++) { + col = new_column_position (col, buf[i]); + } + } else { + fwrite (buf, 1, indx, stdout); + col = indx = 0; + } putchar('\n'); - col = 0; + + /* calculate the column position for the next line. */ + col = new_column_position (col, ch); + } + + if (indx + 1 > buf_max) { + /* Allocate buffer in LINE_MAX increments */ + buf_max += 2048; + if((buf = realloc (buf, buf_max)) == NULL) { + err (1, "realloc"); + /* NOTREACHED */ + } } - putchar(ch); + buf[indx++] = ch; + } + if (indx != 0) + fwrite (buf, 1, indx, stdout); +} + +/* + * calculate the column position + */ +static int +new_column_position (col, ch) + int col, ch; +{ + if (!count_bytes) { 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; } + } else { + ++col; } + + return col; } --T4sUOijqQbZv57TR-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020130201615.A9151>