[dev] [sbase][PATCH] Add col command

From: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
Date: Tue, 3 Mar 2015 10:52:34 +0100

col is used to display troff documents in ttys, removing the reverse
line feeds generated by .2C in ms. This implementation keeps the limit
of 256 lines of 800 characteres of the original implementation.
---
 Makefile |   1 +
 README   |   1 +
 col.1    |  90 +++++++++++++++++++++++++
 col.c    | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 319 insertions(+)
 create mode 100644 col.1
 create mode 100644 col.c
diff --git a/Makefile b/Makefile
index 6efa7f0..42f723f 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -82,6 +82,7 @@ BIN =\
 	cksum\
 	cmp\
 	cols\
+	col\
 	comm\
 	cp\
 	cron\
diff --git a/README b/README
index 7bccbf6..3155c7f 100644
--- a/README
+++ b/README
_AT_@ -19,6 +19,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
 =*  cksum           yes                          none
 =*  cmp             yes                          none
 #*  cols            non-posix                    none
+    col             yes                          none
 =*  comm            yes                          none
 =   cp              yes                          none (-i)
 =*  cron            non-posix                    none
diff --git a/col.1 b/col.1
new file mode 100644
index 0000000..6b4dfba
--- /dev/null
+++ b/col.1
_AT_@ -0,0 +1,90 @@
+.TH COL 1  col
+.SH NAME
+col - filter reverse line-feeds
+.SH SYPNOSIS
+.B col
+.RB [ \-p ]
+.RB [ \-b ]
+.RB [ \-f ]
+.RB [ \-x ]
+.RB [ \-l
+.IR num ]
+.SH DESCRIPTION
+.PP
+The
+.B col
+utility filter all the reverse (and half reverse) line feeds,
+as they are produced by nroff with .2C of ms(6) or by tbl(1).
+.B col
+also replaces spaces by tabs when it is possible.
+The control sequences managed by
+.B col
+are:
+.TP
+.B ESC-7
+reverse line-feed
+.TP
+.B ESC-8
+reverse half-line-feed
+.TP
+.B ESC-9
+forward half-line-feed
+.TP
+.B VT
+vertical-tab
+.TP
+.B SP
+Space
+.TP
+.B TAB
+horizontal tab
+.TP
+.B RETURN
+Carriage return
+.TP
+.B NL
+New line
+.PP
+All the other control codes and escape sequences are removed.
+.B Col
+transform all the spaces into tabulators.
+.SH OPTIONS
+.TP
+.B \-p
+Print unknown escape sequences to the output.
+.TP
+.B \-b
+Do not print backspaces in output,
+and Print only the last overstriked character in the output.
+.TP
+.B \-f
+Allow forward half line feeds in the output.
+.TP
+.B \-x
+Do not convert spaces in tabulators.
+.TP
+.BI \-l " num"
+Increment to
+.I num
+the number of lines buffered for
+.B col.
+.SH BUGS
+.PP
+.B Col
+only process text with a maximum of 256 lines with 800 characteres per line,
+although the number of lines can be modified with
+.B \-l
+option.
+When the number of lines is bigger,
+the buffer is flushed to the output,
+so new reverse line feeds can not operate in the flushed  lines.
+This implementation ignores SI and SO selection character sets,
+because it is supposed it will work only with UTF-8 strings,
+although the UTF-8 support is missed.
+.SH SEE ALSO
+.BR nroff (1),
+.BR ms (6),
+.BR tbl(1).
+
+
+
diff --git a/col.c b/col.c
new file mode 100644
index 0000000..f7f24e4
--- /dev/null
+++ b/col.c
_AT_@ -0,0 +1,227 @@
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "util.h"
+
+#define NLINES 256
+#define NCOLS 800
+
+char **buff;
+
+int obackspace, onotabs, ohalfline, oescape;
+unsigned nline, ncol, nchar, nspaces, maxline, bs;
+size_t pagsize = NLINES;
+
+static void
+usage(void)
+{
+	enprintf(2, "usage: %s [-p][-l num][-b][-f][-x]\n", argv0);
+}
+
+static void
+flush(void)
+{
+	int c;
+	unsigned i, j;
+
+	for (i = 0; i < maxline; ++i) {
+		for (j = 0; j < NCOLS && (c = buff[i][j]) != '\0'; ++j)
+			putchar(c);
+		putchar('\n');
+	}
+	bs = nchar = nline = ncol = 0;
+}
+
+static void
+forward(unsigned n)
+{
+	unsigned lim;
+
+	for (lim = ncol + n; ncol != lim && nchar < NCOLS-1; ++nchar) {
+		switch (buff[nline][nchar]) {
+		case '\b':
+			--ncol;
+			break;
+		case '\0':
+			buff[nline][nchar] = ' ';
+			/* FALLTHROUGH */
+		default:
+			++ncol;
+			break;
+		}
+	}
+}
+
+static void
+linefeed(int up, int rcarriage)
+{
+	unsigned oncol = ncol;
+
+	nspaces = 0;
+	if (up > 0) {
+		if (nline == pagsize-1) {
+			flush();
+		}  else {
+			if (++nline > maxline)
+				maxline = nline;
+		}
+	} else {
+		if (nline > 0)
+			--nline;
+	}
+	bs = 0;
+	if (rcarriage) {
+		forward(oncol);
+		 nchar = ncol = 0;
+	}
+}
+
+static void
+newchar(int c)
+{
+	char *cp;
+
+	forward(nspaces);
+	nspaces = 0;
+
+	switch (c) {
+	case ' ':
+		forward(1);
+		break;
+	case '\r':
+		nchar = ncol = 0;
+		break;
+	case '\t':
+		forward(8 - ncol%8);
+		break;
+	case '\b':
+		if (ncol > 0)
+			--ncol;
+		if (nchar > 0)
+			--nchar;
+		bs = 1;
+		break;
+	default:
+		cp = &buff[nline][nchar];
+		if (*cp != '\0' && *cp != ' ' && bs && !obackspace) {
+			if (nchar != NCOLS-3) {
+				memmove(cp + 3, cp + 1, NCOLS - nchar - 2);
+				cp[1] = '\b';
+				nchar += 2;
+			}
+		}
+		if (nchar != NCOLS-1) {
+			for (cp = buff[nline]; cp < &buff[nline][nchar]; ++cp) {
+				if (*cp == '\0')
+					*cp = ' ';
+			}
+			buff[nline][nchar++] = c;
+			++ncol;
+		}
+		bs = 0;
+	}
+}
+
+static void
+col(void)
+{
+	int c;
+
+	while ((c = getchar()) != EOF) {
+		switch (c) {
+		case '\x1b':
+			switch (c = getchar()) {
+			case '8': /* reverse half-line-feed */
+			case '7': /* reverse line-feed */
+				linefeed(-1, 0);
+				continue;
+			case '9':  /* forward half-line-feed */
+				if (ohalfline)
+					break;
+				linefeed(1, 0);
+				continue;
+			}
+			if (!oescape)
+				continue;
+			newchar('\x1b');
+			if (c != EOF)
+				newchar(c);			
+			break;
+		case '\v':
+			linefeed(-1, 0);
+			break;
+		case ' ':
+			if (!onotabs) {
+				if (++nspaces != 8)
+					continue;
+				c = '\t';
+				nspaces = 0;
+			}
+			/* FALLTHROUGH */
+		case '\r':
+		case '\b':
+		case '\t':
+			newchar(c);
+			break;
+		case '\n':
+			linefeed(1, 1);
+			break;
+		default:
+			if (!iscntrl(c))
+				newchar(c);
+			break;
+		}
+	}
+}
+
+static void
+allocbuf(void)
+{
+	char **bp;
+
+	buff = emalloc(sizeof(*buff) * pagsize);
+	for (bp = buff; bp < &buff[pagsize]; ++bp)
+		*bp = emalloc(NCOLS);	
+}
+
+int
+main(int argc, char *argv[])
+{
+	ARGBEGIN {
+	case 'b':
+		obackspace = 1;
+		break;
+	case 'f':
+		ohalfline = 1;
+		break;
+	case 'l':
+		pagsize = estrtonum(EARGF(usage()), 0, SIZE_MAX);
+		break;
+	case 'p':
+		oescape = 1;
+		break;
+	case 'x':
+		onotabs = 1;
+		break;
+	default:
+		usage();
+	} ARGEND;
+
+	if (argc > 0)
+		usage();
+
+	allocbuf();
+	col();
+	flush();
+
+	if (ferror(stdin))
+		enprintf(1, "error reading input");
+	if (ferror(stdout))
+		enprintf(2, "error writing output");
+
+	return 0;
+}
-- 
2.1.2.532.g19b5d50
Received on Tue Mar 03 2015 - 10:52:34 CET

This archive was generated by hypermail 2.3.0 : Tue Mar 03 2015 - 11:00:08 CET