1
0
mirror of git://git.suckless.org/sbase synced 2024-12-28 10:02:26 +00:00
sbase/expand.c
FRIGN ec8246bbc6 Un-boolify sbase
It actually makes the binaries smaller, the code easier to read
(gems like "val == true", "val == false" are gone) and actually
predictable in the sense of that we actually know what we're
working with (one bitwise operator was quite adventurous and
should now be fixed).

This is also more consistent with the other suckless projects
around which don't use boolean types.
2014-11-14 10:54:20 +00:00

125 lines
1.6 KiB
C

/* 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 int iflag = 0;
static void
usage(void)
{
eprintf("usage: %s [-i] [-t n] [file...]\n", argv0);
}
int
main(int argc, char *argv[])
{
Fdescr dsc;
FILE *fp;
int tabstop = 8;
ARGBEGIN {
case 'i':
iflag = 1;
break;
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--, argv++) {
if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv);
continue;
}
dsc.name = *argv;
dsc.fp = fp;
expand(&dsc, tabstop);
fclose(fp);
}
}
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;
int bol = 1;
for (;;) {
c = in(dsc);
if (c == WEOF)
break;
switch (c) {
case '\t':
if (bol || !iflag) {
do {
col++;
out(' ');
} while (col & (tabstop - 1));
} else {
out('\t');
col += tabstop - col % tabstop;
}
break;
case '\b':
if (col)
col--;
bol = 0;
out(c);
break;
case '\n':
col = 0;
bol = 1;
out(c);
break;
default:
col++;
if (c != ' ')
bol = 0;
out(c);
break;
}
}
return 0;
}