From 44d32288394b3cd46366fbc10752a10f99a01d56 Mon Sep 17 00:00:00 2001 From: stateless Date: Mon, 17 Jun 2013 12:00:36 +0100 Subject: [PATCH] Add primitive expand(1) --- Makefile | 1 + expand.1 | 13 +++++++++ expand.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 expand.1 create mode 100644 expand.c diff --git a/Makefile b/Makefile index d567b1f..4c45ff6 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,7 @@ SRC = \ dirname.c \ echo.c \ env.c \ + expand.c \ false.c \ fold.c \ grep.c \ diff --git a/expand.1 b/expand.1 new file mode 100644 index 0000000..6798a47 --- /dev/null +++ b/expand.1 @@ -0,0 +1,13 @@ +.TH EXPAND 1 sbase\-VERSION +.SH NAME +expand \- expand tabs to spaces +.SH SYNOPSIS +.B expand +.IR [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 SEE ALSO +.IR fold (1) diff --git a/expand.c b/expand.c new file mode 100644 index 0000000..77b1802 --- /dev/null +++ b/expand.c @@ -0,0 +1,99 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include "util.h" + +typedef struct { + FILE *fp; + const char *name; +} Fdescr; + +static int expand(Fdescr *f); + +int +main(int argc, char *argv[]) +{ + Fdescr dsc; + FILE *fp; + + ARGBEGIN { + case 't': + eprintf("not yet implemented\n"); + default: + eprintf("usage: %s [file...]\n", argv0); + } ARGEND; + + if (argc == 0) { + dsc.name = ""; + dsc.fp = stdin; + expand(&dsc); + } else { + for (; argc > 0; argc--) { + if (!(fp = fopen(*argv, "r"))) { + eprintf("fopen %s:", *argv); + } + dsc.name = *argv; + dsc.fp = fp; + expand(&dsc); + 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 col = 0; + wint_t c; + + for (;;) { + c = in(dsc); + if (c == WEOF) + break; + + switch (c) { + case '\t': + do { + col++; + out(' '); + } while (col & 0x7); + break; + case '\b': + if (col) + col--; + out(c); + break; + case '\n': + col = 0; + out(c); + break; + default: + col++; + out(c); + break; + } + } + + return 0; +} -- 1.7.10.4