Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/col.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* col - eliminate reverse line feeds */
2
#include <u.h>
3
#include <libc.h>
4
#include <ctype.h>
5
#include <bio.h>
6
 
7
enum {
8
	ESC	= '\033',
9
	RLF	= '\013',
10
 
11
	PL	= 256,
12
	LINELN	= 800,
13
 
14
	Tabstop	= 8,		/* must be power of 2 */
15
};
16
 
17
static int bflag, xflag, fflag;
18
static int cp, lp;
19
static int half;
20
static int ll, llh, mustwr;
21
static int pcp = 0;
22
 
23
static char *page[PL];
24
static char *line;
25
static char lbuff[LINELN];
26
static Biobuf bin, bout;
27
 
28
void	emit(char *s, int lineno);
29
void	incr(void), decr(void);
30
void	outc(Rune);
31
 
32
static void
33
usage(void)
34
{
35
	fprint(2, "usage: %s [-bfx]\n", argv0);
36
	exits("usage");
37
}
38
 
39
void
40
main(int argc, char **argv)
41
{
42
	int i, lno;
43
	long ch;
44
	Rune c;
45
 
46
	ARGBEGIN{
47
	case 'b':
48
		bflag++;
49
		break;
50
	case 'f':
51
		fflag++;
52
		break;
53
	case 'x':
54
		xflag++;
55
		break;
56
	default:
57
		usage();
58
	}ARGEND;
59
 
60
	for (ll=0; ll < PL; ll++)
61
		page[ll] = nil;
62
 
63
	cp = 0;
64
	ll = 0;
65
	mustwr = PL;
66
	line = lbuff;
67
 
68
	Binit(&bin, 0, OREAD);
69
	Binit(&bout, 1, OWRITE);
70
	while ((ch = Bgetrune(&bin)) != Beof) {
71
		c = ch;
72
		switch (c) {
73
		case '\n':
74
			incr();
75
			incr();
76
			cp = 0;
77
			break;
78
 
79
		case '\0':
80
			break;
81
 
82
		case ESC:
83
			c = Bgetrune(&bin);
84
			switch (c) {
85
			case '7':	/* reverse full line feed */
86
				decr();
87
				decr();
88
				break;
89
 
90
			case '8':	/* reverse half line feed */
91
				if (fflag)
92
					decr();
93
				else
94
					if (--half < -1) {
95
						decr();
96
						decr();
97
						half += 2;
98
					}
99
				break;
100
 
101
			case '9':	/* forward half line feed */
102
				if (fflag)
103
					incr();
104
				else
105
					if (++half > 0) {
106
						incr();
107
						incr();
108
						half -= 2;
109
					}
110
				break;
111
			}
112
			break;
113
 
114
		case RLF:
115
			decr();
116
			decr();
117
			break;
118
 
119
		case '\r':
120
			cp = 0;
121
			break;
122
 
123
		case '\t':
124
			cp = (cp + Tabstop) & -Tabstop;
125
			break;
126
 
127
		case '\b':
128
			if (cp > 0)
129
				cp--;
130
			break;
131
 
132
		case ' ':
133
			cp++;
134
			break;
135
 
136
		default:
137
			if (!isascii(c) || isprint(c)) {
138
				outc(c);
139
				cp++;
140
			}
141
			break;
142
		}
143
	}
144
 
145
	for (i=0; i < PL; i++) {
146
		lno = (mustwr+i) % PL;
147
		if (page[lno] != 0)
148
			emit(page[lno], mustwr+i-PL);
149
	}
150
	emit(" ", (llh + 1) & -2);
151
	exits(0);
152
}
153
 
154
void
155
outc(Rune c)
156
{
157
	if (lp > cp) {
158
		line = lbuff;
159
		lp = 0;
160
	}
161
 
162
	while (lp < cp) {
163
		switch (*line) {
164
		case '\0':
165
			*line = ' ';
166
			lp++;
167
			break;
168
		case '\b':
169
			lp--;
170
			break;
171
		default:
172
			lp++;
173
			break;
174
		}
175
		line++;
176
	}
177
	while (*line == '\b')
178
		line += 2;
179
	if (bflag || *line == '\0' || *line == ' ')
180
		cp += runetochar(line, &c) - 1;
181
	else {
182
		char c1, c2, c3;
183
 
184
		c1 = *++line;
185
		*line++ = '\b';
186
		c2 = *line;
187
		*line++ = c;
188
		while (c1) {
189
			c3 = *line;
190
			*line++ = c1;
191
			c1 = c2;
192
			c2 = c3;
193
		}
194
		lp = 0;
195
		line = lbuff;
196
	}
197
}
198
 
199
void
200
store(int lno)
201
{
202
	lno %= PL;
203
	if (page[lno] != nil)
204
		free(page[lno]);
205
	page[lno] = malloc((unsigned)strlen(lbuff) + 2);
206
	if (page[lno] == nil)
207
		sysfatal("out of memory");
208
	strcpy(page[lno], lbuff);
209
}
210
 
211
void
212
fetch(int lno)
213
{
214
	char *p;
215
 
216
	lno %= PL;
217
	p = lbuff;
218
	while (*p)
219
		*p++ = '\0';
220
	line = lbuff;
221
	lp = 0;
222
	if (page[lno])
223
		strcpy(line, page[lno]);
224
}
225
 
226
void
227
emit(char *s, int lineno)
228
{
229
	int ncp;
230
	char *p;
231
	static int cline = 0;
232
 
233
	if (*s) {
234
		while (cline < lineno - 1) {
235
			Bputc(&bout, '\n');
236
			pcp = 0;
237
			cline += 2;
238
		}
239
		if (cline != lineno) {
240
			Bputc(&bout, ESC);
241
			Bputc(&bout, '9');
242
			cline++;
243
		}
244
		if (pcp)
245
			Bputc(&bout, '\r');
246
		pcp = 0;
247
		p = s;
248
		while (*p) {
249
			ncp = pcp;
250
			while (*p++ == ' ')
251
				if ((++ncp & 7) == 0 && !xflag) {
252
					pcp = ncp;
253
					Bputc(&bout, '\t');
254
				}
255
			if (!*--p)
256
				break;
257
			while (pcp < ncp) {
258
				Bputc(&bout, ' ');
259
				pcp++;
260
			}
261
			Bputc(&bout, *p);
262
			if (*p++ == '\b')
263
				pcp--;
264
			else
265
				pcp++;
266
		}
267
	}
268
}
269
 
270
void
271
incr(void)
272
{
273
	int lno;
274
 
275
	store(ll++);
276
	if (ll > llh)
277
		llh = ll;
278
	lno = ll % PL;
279
	if (ll >= mustwr && page[lno]) {
280
		emit(page[lno], ll - PL);
281
		mustwr++;
282
		free(page[lno]);
283
		page[lno] = nil;
284
	}
285
	fetch(ll);
286
}
287
 
288
void
289
decr(void)
290
{
291
	if (ll > mustwr - PL) {
292
		store(ll--);
293
		fetch(ll);
294
	}
295
}