From owner-freebsd-standards Sat Mar 23 18:40:19 2002 Delivered-To: freebsd-standards@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 0376637B419 for ; Sat, 23 Mar 2002 18:40:01 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g2O2e0w70144; Sat, 23 Mar 2002 18:40:00 -0800 (PST) (envelope-from gnats) Received: from descent.robbins.dropbear.id.au (126.b.008.mel.iprimus.net.au [210.50.87.126]) by hub.freebsd.org (Postfix) with ESMTP id 8330837B439 for ; Sat, 23 Mar 2002 18:33:26 -0800 (PST) Received: (from tim@localhost) by descent.robbins.dropbear.id.au (8.11.6/8.11.6) id g2O2Pn114298; Sun, 24 Mar 2002 13:25:49 +1100 (EST) (envelope-from tim) Message-Id: <200203240225.g2O2Pn114298@descent.robbins.dropbear.id.au> Date: Sun, 24 Mar 2002 13:25:49 +1100 (EST) From: "Tim J. Robbins" Reply-To: "Tim J. Robbins" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: standards/36245: Missing P1003.1-2001 fold -b and -s options Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG >Number: 36245 >Category: standards >Synopsis: Missing P1003.1-2001 fold -b and -s options >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sat Mar 23 18:40:00 PST 2002 >Closed-Date: >Last-Modified: >Originator: Tim J. Robbins >Release: FreeBSD 4.5-STABLE i386 >Organization: >Environment: System: FreeBSD descent.robbins.dropbear.id.au 4.5-STABLE FreeBSD 4.5-STABLE #17: Thu Mar 21 19:48:18 EST 2002 tim@descent.robbins.dropbear.id.au:/usr/obj/usr/src/sys/DESCENT i386 >Description: FreeBSD's fold(1) utility is missing the -b and -s options mandated by P1003.1-2001. >How-To-Repeat: fold -s >Fix: This patch is based on NetBSD's fold utility, with some style changes. Index: fold.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/fold/fold.1,v retrieving revision 1.7 diff -u -r1.7 fold.1 --- fold.1 2001/12/12 18:25:53 1.7 +++ fold.1 2002/03/24 02:31:02 @@ -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.c =================================================================== RCS file: /home/ncvs/src/usr.bin/fold/fold.c,v retrieving revision 1.7 diff -u -r1.7 fold.c --- fold.c 2002/03/22 01:22:35 1.7 +++ fold.c 2002/03/24 02:31:03 @@ -52,13 +52,18 @@ #include #include #include +#include #include #define DEFLINEWIDTH 80 void fold(int); +static int new_column_position(int, int); static void usage(void); +int count_bytes = 0; +int split_words = 0; + int main(argc, argv) int argc; @@ -69,8 +74,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"); @@ -107,57 +118,110 @@ 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; } - if (new > width) { + col = new_column_position(col, ch); + if (col > width) { + int i, last_space; + + 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++; + + 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); } - putchar(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 */ + } + } + 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; } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message