Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/disc/sfdcmore.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#include "sfdchdr.h"
23
24
#if _PACKAGE_ast
25
#include <ast_tty.h>
26
#include <signal.h>
27
#endif
28
29
/*
30
* a simple but fast more style pager discipline
31
* if on sfstdout then sfstdin ops reset the page state
32
*
33
* Glenn Fowler
34
* AT&T Research
35
*
36
* @(#)$Id: sfdcmore (AT&T Research) 1998-06-25 $
37
*/
38
39
typedef struct
40
{
41
Sfdisc_t disc; /* sfio discipline */
42
Sfio_t* input; /* tied with this input stream */
43
Sfio_t* error; /* tied with this error stream */
44
int rows; /* max rows */
45
int cols; /* max cols */
46
int row; /* current row */
47
int col; /* current col */
48
int match; /* match length, 0 if none */
49
char pattern[128]; /* match pattern */
50
char prompt[1]; /* prompt string */
51
} More_t;
52
53
/*
54
* more read
55
* we assume line-at-a-time input
56
*/
57
58
#if __STD_C
59
static ssize_t moreread(Sfio_t* f, void* buf, size_t n, Sfdisc_t* dp)
60
#else
61
static ssize_t moreread(f, buf, n, dp)
62
Sfio_t* f;
63
void* buf;
64
size_t n;
65
Sfdisc_t* dp;
66
#endif
67
{
68
register More_t* more = (More_t*)dp;
69
70
more->match = 0;
71
more->row = 2;
72
more->col = 1;
73
return sfrd(f, buf, n, dp);
74
}
75
76
/*
77
* output label on wfd and return next char on rfd with no echo
78
* return < -1 is -(signal + 1)
79
*/
80
81
#if __STD_C
82
static int ttyquery(Sfio_t* rp, Sfio_t* wp, const char* label, Sfdisc_t* dp)
83
#else
84
static int ttyquery(rp, wp, label, dp)
85
Sfio_t* rp;
86
Sfio_t* wp;
87
char* label;
88
Sfdisc_t* dp;
89
#endif
90
{
91
register int r;
92
int n;
93
94
#ifdef TCSADRAIN
95
unsigned char c;
96
struct termios old;
97
struct termios tty;
98
int rfd = sffileno(rp);
99
int wfd = sffileno(rp);
100
101
if (!label)
102
n = 0;
103
else if (n = strlen(label))
104
write(wfd, label, n);
105
tcgetattr(rfd, &old);
106
tty = old;
107
tty.c_cc[VTIME] = 0;
108
tty.c_cc[VMIN] = 1;
109
tty.c_lflag &= ~(ICANON|ECHO|ECHOK|ISIG);
110
tcsetattr(rfd, TCSADRAIN, &tty);
111
if ((r = read(rfd, &c, 1)) == 1)
112
{
113
if (c == old.c_cc[VEOF])
114
r = -1;
115
else if (c == old.c_cc[VINTR])
116
r = -(SIGINT + 1);
117
else if (c == old.c_cc[VQUIT])
118
r = -(SIGQUIT + 1);
119
else if (c == '\r')
120
r = '\n';
121
else
122
r = c;
123
}
124
tcsetattr(rfd, TCSADRAIN, &old);
125
if (n)
126
{
127
write(wfd, "\r", 1);
128
while (n-- > 0)
129
write(wfd, " ", 1);
130
write(wfd, "\r", 1);
131
}
132
#else
133
register char* s;
134
135
if (label && (n = strlen(label)))
136
sfwr(wp, label, n, dp);
137
r = (s = sfgetr(rp, '\n', 0)) ? *s : -1;
138
#endif
139
return r;
140
}
141
142
/*
143
* more write
144
*/
145
146
#if __STD_C
147
static ssize_t morewrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
148
#else
149
static ssize_t morewrite(f, buf, n, dp)
150
Sfio_t* f;
151
Void_t* buf;
152
register size_t n;
153
Sfdisc_t* dp;
154
#endif
155
{
156
register More_t* more = (More_t*)dp;
157
register char* b;
158
register char* s;
159
register char* e;
160
register ssize_t w;
161
register int r;
162
163
if (!more->row)
164
return n;
165
if (!more->col)
166
return sfwr(f, buf, n, dp);
167
w = 0;
168
b = (char*)buf;
169
s = b;
170
e = s + n;
171
if (more->match)
172
{
173
match:
174
for (r = more->pattern[0];; s++)
175
{
176
if (s >= e)
177
return n;
178
if (*s == '\n')
179
b = s + 1;
180
else if (*s == r && (e - s) >= more->match && !strncmp(s, more->pattern, more->match))
181
break;
182
}
183
s = b;
184
w += b - (char*)buf;
185
more->match = 0;
186
}
187
while (s < e)
188
{
189
switch (*s++)
190
{
191
case '\t':
192
more->col = ((more->col + 8) & ~7) - 1;
193
/*FALLTHROUGH*/
194
default:
195
if (++more->col <= more->cols || s < e && *s == '\n')
196
continue;
197
/*FALLTHROUGH*/
198
case '\n':
199
more->col = 1;
200
if (++more->row < more->rows)
201
continue;
202
break;
203
case '\b':
204
if (more->col > 1)
205
more->col--;
206
continue;
207
case '\r':
208
more->col = 1;
209
continue;
210
}
211
w += sfwr(f, b, s - b, dp);
212
b = s;
213
r = ttyquery(sfstdin, f, more->prompt, dp);
214
if (r == '/' || r == 'n')
215
{
216
if (r == '/')
217
{
218
sfwr(f, "/", 1, dp);
219
if ((s = sfgetr(sfstdin, '\n', 1)) && (n = sfvalue(sfstdin) - 1) > 0)
220
{
221
if (n >= sizeof(more->pattern))
222
n = sizeof(more->pattern) - 1;
223
memcpy(more->pattern, s, n);
224
more->pattern[n] = 0;
225
}
226
}
227
if (more->match = strlen(more->pattern))
228
{
229
more->row = 1;
230
more->col = 1;
231
goto match;
232
}
233
}
234
switch (r)
235
{
236
case '\n':
237
case '\r':
238
more->row--;
239
more->col = 1;
240
break;
241
case ' ':
242
more->row = 2;
243
more->col = 1;
244
break;
245
default:
246
more->row = 0;
247
return n;
248
}
249
}
250
if (s > b)
251
w += sfwr(f, b, s - b, dp);
252
return w;
253
}
254
255
/*
256
* remove the discipline on close
257
*/
258
259
#if __STD_C
260
static int moreexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
261
#else
262
static int moreexcept(f, type, data, dp)
263
Sfio_t* f;
264
int type;
265
Void_t* data;
266
Sfdisc_t* dp;
267
#endif
268
{
269
register More_t* more = (More_t*)dp;
270
271
if (type == SF_FINAL || type == SF_DPOP)
272
{
273
if (f = more->input)
274
{
275
more->input = 0;
276
sfdisc(f, SF_POPDISC);
277
}
278
else if (f = more->error)
279
{
280
more->error = 0;
281
sfdisc(f, SF_POPDISC);
282
}
283
else
284
free(dp);
285
}
286
else if (type == SF_SYNC)
287
{
288
more->match = 0;
289
more->row = 1;
290
more->col = 1;
291
}
292
return 0;
293
}
294
295
/*
296
* push the more discipline on f
297
* if prompt==0 then a default ansi prompt is used
298
* if rows==0 or cols==0 then they are deterimined from the tty
299
* if f==sfstdout then input on sfstdin also resets the state
300
*/
301
302
#if __STD_C
303
int sfdcmore(Sfio_t* f, const char* prompt, int rows, int cols)
304
#else
305
int sfdcmore(f, prompt, rows, cols)
306
Sfio_t* f;
307
char* prompt;
308
int rows;
309
int cols;
310
#endif
311
{
312
register More_t* more;
313
size_t n;
314
315
/*
316
* this is a writeonly discipline for interactive io
317
*/
318
319
if (!(sfset(f, 0, 0) & SF_WRITE) || !isatty(sffileno(sfstdin)) || !isatty(sffileno(sfstdout)))
320
return -1;
321
if (!prompt)
322
prompt = "\033[7m More\033[m";
323
n = strlen(prompt) + 1;
324
if (!(more = (More_t*)malloc(sizeof(More_t) + n)))
325
return -1;
326
memset(more, 0, sizeof(*more));
327
328
more->disc.readf = moreread;
329
more->disc.writef = morewrite;
330
more->disc.exceptf = moreexcept;
331
memcpy(more->prompt, prompt, n);
332
if (!rows || !cols)
333
{
334
#if _PACKAGE_ast
335
astwinsize(sffileno(sfstdin), &rows, &cols);
336
#endif
337
if (!rows)
338
rows = 24;
339
if (!cols)
340
cols = 80;
341
}
342
more->rows = rows;
343
more->cols = cols;
344
more->row = 1;
345
more->col = 1;
346
347
if (sfdisc(f, &more->disc) != &more->disc)
348
{
349
free(more);
350
return -1;
351
}
352
if (f == sfstdout)
353
{
354
if (sfdisc(sfstdin, &more->disc) != &more->disc)
355
{
356
sfdisc(f, SF_POPDISC);
357
return -1;
358
}
359
more->input = sfstdin;
360
if (sfdisc(sfstderr, &more->disc) != &more->disc)
361
{
362
sfdisc(f, SF_POPDISC);
363
return -1;
364
}
365
more->error = sfstdin;
366
}
367
368
return 0;
369
}
370
371