Skip site navigation (1)Skip section navigation (2)
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>