Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Mar 2002 18:12:20 +1100 (EST)
From:      "Tim J. Robbins" <tim@robbins.dropbear.id.au>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/35621: Patch to add P1003.1-2001 -t option to unexpand(1)
Message-ID:  <200203070712.g277CKs46132@descent.robbins.dropbear.id.au>

next in thread | raw e-mail | index | archive | help

>Number:         35621
>Category:       bin
>Synopsis:       Patch to add P1003.1-2001 -t option to unexpand(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 06 23:20:01 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 #5: Sat Feb 16 18:56:18 EST 2002 tim@descent.robbins.dropbear.id.au:/usr/obj/usr/src/sys/DESCENT i386


	
>Description:
This patch adds the -t option to unexpand(1), which is specified by
P1003.1-2001. It also removes the artifical line length limits imposed
by buffering the file line-by-line. The getstops() function in this
patch is taken from expand.c.
>How-To-Repeat:
$ unexpand -t4 
usage: unexpand [-a] file ...
>Fix:

Index: expand/expand.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/expand/expand.1,v
retrieving revision 1.7
diff -u -r1.7 expand.1
--- expand/expand.1	2001/07/10 14:15:57	1.7
+++ expand/expand.1	2002/03/07 07:11:46
@@ -51,6 +51,12 @@
 .Op Ar
 .Nm unexpand
 .Op Fl a
+.Oo
+.Fl t
+.Sm off
+.Ar tab1 , tab2 , ... , tabn
+.Sm on
+.Oc
 .Op Ar
 .Sh DESCRIPTION
 .Nm Expand
@@ -86,6 +92,13 @@
 option is given, then tabs are inserted whenever they would compress the
 resultant file by replacing two or more characters.
 .El
+.Sh STANDARDS
+The
+.Nm expand
+and
+.Nm unexpand
+utilities are expected to conform to
+.St -p1003.1-2001 .
 .Sh HISTORY
 The
 .Nm

Index: unexpand/unexpand.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/unexpand/unexpand.c,v
retrieving revision 1.7
diff -u -r1.7 unexpand.c
--- unexpand/unexpand.c	2001/12/11 23:18:25	1.7
+++ unexpand/unexpand.c	2002/03/07 07:05:27
@@ -52,13 +52,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
 
-char	genbuf[BUFSIZ];
-char	linebuf[BUFSIZ];
 int	all;
+int	nstops;
+int	tabstops[100];
 
+static void getstops __P((char *));
 static void usage __P((void));
-void tabify __P((char));
+void tabify __P((void));
 
 int
 main(argc, argv)
@@ -66,28 +69,34 @@
 	char *argv[];
 {
 	register char *cp;
+	int ch;
 
-	argc--, argv++;
-	if (argc > 0 && argv[0][0] == '-') {
-		if (strcmp(argv[0], "-a") != 0)
+	nstops = 1;
+	tabstops[0] = 8;
+	while ((ch = getopt(argc, argv, "at:")) != -1) {
+		switch (ch) {
+		case 'a':
+			all = 1;
+			break;
+		case 't':
+			getstops(optarg);
+			all = 1;
+			break;
+		default:
 			usage();
-		all++;
-		argc--, argv++;
+			/*NOTREACHED*/
+		}
 	}
+	argc -= optind;
+	argv += optind;
+
 	do {
 		if (argc > 0) {
 			if (freopen(argv[0], "r", stdin) == NULL)
-				err(1, "%s", argv[0]);
+				err(EX_NOINPUT, "%s", argv[0]);
 			argc--, argv++;
 		}
-		while (fgets(genbuf, BUFSIZ, stdin) != NULL) {
-			for (cp = linebuf; *cp; cp++)
-				continue;
-			if (cp > linebuf)
-				cp[-1] = 0;
-			tabify(all);
-			printf("%s", linebuf);
-		}
+		tabify();
 	} while (argc > 0);
 	exit(0);
 }
@@ -95,52 +104,97 @@
 static void
 usage()
 {
-	fprintf(stderr, "usage: unexpand [-a] file ...\n");
-	exit(1);
+	fprintf(stderr, "usage: unexpand [-a] [-t tablist] [file ...]\n");
+	exit(EX_USAGE);
 }
 
 void
-tabify(c)
-	char c;
+tabify()
 {
-	register char *cp, *dp;
 	register int dcol;
-	int ocol;
+	int ch, n, ocol;
 
 	ocol = 0;
 	dcol = 0;
-	cp = genbuf, dp = linebuf;
-	for (;;) {
-		switch (*cp) {
-
+	while ((ch = getchar()) != EOF) {
+		switch (ch) {
+		case EOF:
+			return;
+		case '\n':
+			putchar('\n');
+			ocol = dcol = 0;
+			break;
 		case ' ':
 			dcol++;
 			break;
-
 		case '\t':
 			dcol += 8;
 			dcol &= ~07;
 			break;
-
+		case '\b':
+			if (dcol > 0)
+				dcol--;
+			/*FALLTHROUGH*/
 		default:
-			while (((ocol + 8) &~ 07) <= dcol) {
-				if (ocol + 1 == dcol)
-					break;
-				*dp++ = '\t';
-				ocol += 8;
-				ocol &= ~07;
+			if (nstops == 1) {
+				while (((ocol + tabstops[0]) / tabstops[0])
+				    <= (dcol / tabstops[0])) {
+					if (dcol - ocol < 2)
+						break;
+					putchar('\t');
+					ocol = (1 + ocol / tabstops[0]) *
+						tabstops[0];
+				}
+			} else {
+				for (n = 0; n < nstops; n++)
+					if (tabstops[n] > ocol)
+						break;
+				while (n < nstops && tabstops[n] <= dcol) {
+					if (dcol - ocol < 2)
+						break;
+					putchar('\t');
+					ocol = tabstops[n++];
+				}
 			}
 			while (ocol < dcol) {
-				*dp++ = ' ';
+				putchar(' ');
 				ocol++;
 			}
-			if (*cp == 0 || c == 0) {
-				strcpy(dp, cp);
-				return;
+			putchar(ch);
+			if (!all) {
+				while ((ch = getchar()) != EOF && ch != '\n')
+					putchar(ch);
+				putchar('\n');
+				ocol = dcol = 0;
+				break;
 			}
-			*dp++ = *cp;
 			ocol++, dcol++;
 		}
+	}
+}
+
+static void
+getstops(cp)
+	register char *cp;
+{
+	register int i;
+
+	nstops = 0;
+	for (;;) {
+		i = 0;
+		while (*cp >= '0' && *cp <= '9')
+			i = i * 10 + *cp++ - '0';
+		if (i <= 0)
+			errx(1, "bad tab stop spec");
+		if (nstops > 0 && i <= tabstops[nstops-1])
+			errx(1, "bad tab stop spec");
+		if (nstops == sizeof(tabstops) / sizeof(*tabstops))
+			errx(1, "too many tabstops");
+		tabstops[nstops++] = i;
+		if (*cp == 0)
+			break;
+		if (*cp != ',' && *cp != ' ')
+			errx(1, "bad tab stop spec");
 		cp++;
 	}
 }
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203070712.g277CKs46132>