commit e28c17c7cc4955dd0a4b1b2d9f17faa05f9b238e
parent 12116cccc40df6b04edb57bb3e74ef12204aad80
Author: stateless <stateless@archlinux.us>
Date: Mon, 17 Jun 2013 12:00:36 +0100
Add expand(1)
Signed-off-by: Christoph Lohmann <20h@r-36.net>
Diffstat:
M | Makefile | | | 1 | + |
A | expand.1 | | | 21 | +++++++++++++++++++++ |
A | expand.c | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 130 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -35,6 +35,7 @@ SRC = \
dirname.c \
echo.c \
env.c \
+ expand.c \
false.c \
fold.c \
grep.c \
diff --git a/expand.1 b/expand.1
@@ -0,0 +1,21 @@
+.TH EXPAND 1 sbase\-VERSION
+.SH NAME
+expand \- expand tabs to spaces
+.SH SYNOPSIS
+.B expand
+.RB [ \-t
+.IR n ]
+.RI [ file ...]
+.SH DESCRIPTION
+expand processes the named files or the standard input, writing the
+standard output with tabs changed into spaces. Backspace characters
+are preserved into the output and decrement the column count for tab
+calculations.
+.SH OPTIONS
+.TP
+.BI \-t " n"
+Expand tabs to
+.I n
+spaces. We currently support only a single numerical argument.
+.SH SEE ALSO
+.IR fold (1)
diff --git a/expand.c b/expand.c
@@ -0,0 +1,108 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "util.h"
+
+typedef struct {
+ FILE *fp;
+ const char *name;
+} Fdescr;
+
+static int expand(Fdescr *f, int tabstop);
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-t n] [file...]\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ Fdescr dsc;
+ FILE *fp;
+ int tabstop = 8;
+
+ ARGBEGIN {
+ case 't':
+ tabstop = estrtol(EARGF(usage()), 0);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc == 0) {
+ dsc.name = "<stdin>";
+ dsc.fp = stdin;
+ expand(&dsc, tabstop);
+ } else {
+ for (; argc > 0; argc--) {
+ if (!(fp = fopen(*argv, "r"))) {
+ eprintf("fopen %s:", *argv);
+ }
+ dsc.name = *argv;
+ dsc.fp = fp;
+ expand(&dsc, tabstop);
+ fclose(fp);
+ argv++;
+ }
+ }
+ return 0;
+}
+
+static wint_t
+in(Fdescr *f)
+{
+ wint_t c = fgetwc(f->fp);
+
+ if (c == WEOF && ferror(f->fp))
+ eprintf("'%s' read error:", f->name);
+
+ return c;
+}
+
+static void
+out(wint_t c)
+{
+ putwchar(c);
+ if (ferror(stdout))
+ eprintf("write error:");
+}
+
+static int
+expand(Fdescr *dsc, int tabstop)
+{
+ int col = 0;
+ wint_t c;
+
+ for (;;) {
+ c = in(dsc);
+ if (c == WEOF)
+ break;
+
+ switch (c) {
+ case '\t':
+ do {
+ col++;
+ out(' ');
+ } while (col & (tabstop - 1));
+ break;
+ case '\b':
+ if (col)
+ col--;
+ out(c);
+ break;
+ case '\n':
+ col = 0;
+ out(c);
+ break;
+ default:
+ col++;
+ out(c);
+ break;
+ }
+ }
+
+ return 0;
+}