Introduction
Introduction Statistics Contact Development Disclaimer Help
unexpand.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
unexpand.c (3318B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "utf.h"
7 #include "util.h"
8
9 static int aflag = 0;
10 static size_t *tablist = NULL;
11 static size_t tablistlen = 8;
12
13 static size_t
14 parselist(const char *s)
15 {
16 size_t i;
17 char *p, *tmp;
18
19 tmp = estrdup(s);
20 for (i = 0; (p = strsep(&tmp, " ,")); i++) {
21 if (*p == '\0')
22 eprintf("empty field in tablist\n");
23 tablist = ereallocarray(tablist, i + 1, sizeof(*tablist)…
24 tablist[i] = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
25 if (i > 0 && tablist[i - 1] >= tablist[i])
26 eprintf("tablist must be ascending\n");
27 }
28 tablist = ereallocarray(tablist, i + 1, sizeof(*tablist));
29
30 return i;
31 }
32
33 static void
34 unexpandspan(size_t last, size_t col)
35 {
36 size_t off, i, j;
37 Rune r;
38
39 if (tablistlen == 1) {
40 i = 0;
41 off = last % tablist[i];
42
43 if ((col - last) + off >= tablist[i] && last < col)
44 last -= off;
45
46 r = '\t';
47 for (; last + tablist[i] <= col; last += tablist[i])
48 efputrune(&r, stdout, "<stdout>");
49 r = ' ';
50 for (; last < col; last++)
51 efputrune(&r, stdout, "<stdout>");
52 } else {
53 for (i = 0; i < tablistlen; i++)
54 if (col < tablist[i])
55 break;
56 for (j = 0; j < tablistlen; j++)
57 if (last < tablist[j])
58 break;
59 r = '\t';
60 for (; j < i; j++) {
61 efputrune(&r, stdout, "<stdout>");
62 last = tablist[j];
63 }
64 r = ' ';
65 for (; last < col; last++)
66 efputrune(&r, stdout, "<stdout>");
67 }
68 }
69
70 static void
71 unexpand(const char *file, FILE *fp)
72 {
73 Rune r;
74 size_t last = 0, col = 0, i;
75 int bol = 1;
76
77 while (efgetrune(&r, fp, file)) {
78 switch (r) {
79 case ' ':
80 if (!bol && !aflag)
81 last++;
82 col++;
83 break;
84 case '\t':
85 if (tablistlen == 1) {
86 if (!bol && !aflag)
87 last += tablist[0] - col % tabli…
88 col += tablist[0] - col % tablist[0];
89 } else {
90 for (i = 0; i < tablistlen; i++)
91 if (col < tablist[i])
92 break;
93 if (!bol && !aflag)
94 last = tablist[i];
95 col = tablist[i];
96 }
97 break;
98 case '\b':
99 if (bol || aflag)
100 unexpandspan(last, col);
101 col -= (col > 0);
102 last = col;
103 bol = 0;
104 break;
105 case '\n':
106 if (bol || aflag)
107 unexpandspan(last, col);
108 last = col = 0;
109 bol = 1;
110 break;
111 default:
112 if (bol || aflag)
113 unexpandspan(last, col);
114 last = ++col;
115 bol = 0;
116 break;
117 }
118 if ((r != ' ' && r != '\t') || (!aflag && !bol))
119 efputrune(&r, stdout, "<stdout>");
120 }
121 if (last < col && (bol || aflag))
122 unexpandspan(last, col);
123 }
124
125 static void
126 usage(void)
127 {
128 eprintf("usage: %s [-a] [-t tablist] [file ...]\n", argv0);
129 }
130
131 int
132 main(int argc, char *argv[])
133 {
134 FILE *fp;
135 int ret = 0;
136 char *tl = "8";
137
138 ARGBEGIN {
139 case 't':
140 tl = EARGF(usage());
141 if (!*tl)
142 eprintf("tablist cannot be empty\n");
143 /* Fallthrough: -t implies -a */
144 case 'a':
145 aflag = 1;
146 break;
147 default:
148 usage();
149 } ARGEND
150
151 tablistlen = parselist(tl);
152
153 if (!argc) {
154 unexpand("<stdin>", stdin);
155 } else {
156 for (; *argv; argc--, argv++) {
157 if (!strcmp(*argv, "-")) {
158 *argv = "<stdin>";
159 fp = stdin;
160 } else if (!(fp = fopen(*argv, "r"))) {
161 weprintf("fopen %s:", *argv);
162 ret = 1;
163 continue;
164 }
165 unexpand(*argv, fp);
166 if (fp != stdin && fshut(fp, *argv))
167 ret = 1;
168 }
169 }
170
171 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
172
173 return ret;
174 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.