From 64999c33fd2eb5bed83a9fddd9facf9700207c05 Mon Sep 17 00:00:00 2001 From: stateless Date: Mon, 17 Jun 2013 12:00:36 +0100 Subject: [PATCH] Add expand(1) --- Makefile | 1 + expand.1 | 21 ++++++++++++ expand.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 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..82be286 --- /dev/null +++ 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 new file mode 100644 index 0000000..68336ec --- /dev/null +++ b/expand.c @@ -0,0 +1,108 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#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 = ""; + 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; +} -- 1.7.10.4