source: trunk/essentials/sys-libs/ncurses/tack/sync.c

Last change on this file was 2621, checked in by bird, 19 years ago

GNU ncurses 5.5

File size: 9.8 KB
Line 
1/*
2** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3**
4** This file is part of TACK.
5**
6** TACK is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2, or (at your option)
9** any later version.
10**
11** TACK is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with TACK; see the file COPYING. If not, write to
18** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19** Boston, MA 02110-1301, USA
20*/
21
22#include <tack.h>
23#include <time.h>
24
25MODULE_ID("$Id: sync.c,v 1.8 2005/09/17 19:49:16 tom Exp $")
26
27/* terminal-synchronization and performance tests */
28
29static void sync_home(struct test_list *, int *, int *);
30static void sync_lines(struct test_list *, int *, int *);
31static void sync_clear(struct test_list *, int *, int *);
32static void sync_summary(struct test_list *, int *, int *);
33
34static struct test_list sync_test_list[] = {
35 {MENU_NEXT, 0, 0, 0, "b) baud rate test", sync_home, 0},
36 {MENU_NEXT, 0, 0, 0, "l) scroll performance", sync_lines, 0},
37 {MENU_NEXT, 0, 0, 0, "c) clear screen performance", sync_clear, 0},
38 {MENU_NEXT, 0, 0, 0, "p) summary of results", sync_summary, 0},
39 {0, 0, 0, 0, txt_longer_test_time, longer_test_time, 0},
40 {0, 0, 0, 0, txt_shorter_test_time, shorter_test_time, 0},
41 {MENU_LAST, 0, 0, 0, 0, 0, 0}
42};
43
44struct test_menu sync_menu = {
45 0, 'n', 0,
46 "Performance tests", "perf", "n) run standard tests",
47 sync_test, sync_test_list, 0, 0, 0
48};
49
50int tty_can_sync; /* TRUE if tty_sync_error() returned FALSE */
51static int tty_newline_rate; /* The number of newlines per second */
52static int tty_clear_rate; /* The number of clear-screens per second */
53unsigned long tty_cps; /* The number of characters per second */
54
55#define TTY_ACK_SIZE 64
56
57static int ACK_terminator; /* terminating ACK character */
58static int ACK_length; /* length of ACK string */
59static const char *tty_ENQ; /* enquire string */
60static char tty_ACK[TTY_ACK_SIZE]; /* ACK response, set by tty_sync_error() */
61
62/*****************************************************************************
63 *
64 * Terminal synchronization.
65 *
66 * These functions handle the messy business of enq-ack handshaking
67 * for timing purposes.
68 *
69 *****************************************************************************/
70
71int
72tty_sync_error(void)
73{
74 int ch, trouble, ack;
75
76 trouble = FALSE;
77 for (;;) {
78 tt_putp(tty_ENQ); /* send ENQ */
79 ch = getnext(STRIP_PARITY);
80 event_start(TIME_SYNC); /* start the timer */
81
82 /*
83 The timer doesn't start until we get the first character.
84 After that I expect to get the remaining characters of
85 the acknowledge string in a short period of time. If
86 that is not true then these characters are coming from
87 the user and we need to send the ENQ sequence out again.
88 */
89 for (ack = 0; ; ) {
90 if (ack < TTY_ACK_SIZE - 2) {
91 tty_ACK[ack] = ch;
92 tty_ACK[ack + 1] = '\0';
93 }
94 if (ch == ACK_terminator) {
95 return trouble;
96 }
97 if (++ack >= ACK_length) {
98 return trouble;
99 }
100 ch = getnext(STRIP_PARITY);
101 if (event_time(TIME_SYNC) > 400000) {
102 break;
103 }
104 }
105
106 set_attr(0); /* just in case */
107 put_crlf();
108 if (trouble) {
109 /* The terminal won't sync. Life is not good. */
110 return TRUE;
111 }
112 put_str(" -- sync -- ");
113 trouble = TRUE;
114 }
115}
116
117/*
118** flush_input()
119**
120** Throw away any output.
121*/
122void
123flush_input(void)
124{
125 if (tty_can_sync == SYNC_TESTED && ACK_terminator >= 0) {
126 (void) tty_sync_error();
127 } else {
128 spin_flush();
129 }
130}
131
132/*
133** probe_enq_ok()
134**
135** does the terminal do enq/ack handshaking?
136*/
137static void
138probe_enq_ok(void)
139{
140 int tc, len, ulen;
141
142 put_str("Testing ENQ/ACK, standby...");
143 fflush(stdout);
144 can_test("u8 u9", FLAG_TESTED);
145
146#ifdef user9
147 tty_ENQ = user9 ? user9 : "\005";
148#else
149 tty_ENQ = "\005";
150#endif
151 tc_putp(tty_ENQ);
152 event_start(TIME_SYNC); /* start the timer */
153 read_key(tty_ACK, TTY_ACK_SIZE - 1);
154
155 if (event_time(TIME_SYNC) > 400000 || tty_ACK[0] == '\0') {
156 /* These characters came from the user. Sigh. */
157 tty_can_sync = SYNC_FAILED;
158 ptext("\nThis program expects the ENQ sequence to be");
159 ptext(" answered with the ACK character. This will help");
160 ptext(" the program reestablish synchronization when");
161 ptextln(" the terminal is overrun with data.");
162 ptext("\nENQ sequence from (u9): ");
163 putln(expand(tty_ENQ));
164 ptext("ACK received: ");
165 putln(expand(tty_ACK));
166#ifdef user8
167 len = user8 ? strlen(user8) : 0;
168#else
169 len = 0;
170#endif
171 sprintf(temp, "Length of ACK %d. Expected length of ACK %d.",
172 (int) strlen(tty_ACK), len);
173 ptextln(temp);
174#ifdef user8
175 if (len) {
176 temp[0] = user8[len - 1];
177 temp[1] = '\0';
178 ptext("Terminating character found in (u8): ");
179 putln(expand(temp));
180 }
181#endif
182 return;
183 }
184
185 tty_can_sync = SYNC_TESTED;
186 if ((len = strlen(tty_ACK)) == 1) {
187 /* single character acknowledge string */
188 ACK_terminator = tty_ACK[0];
189 ACK_length = 4096;
190 return;
191 }
192 tc = tty_ACK[len - 1];
193#ifdef user8
194 if (user8) {
195 ulen = strlen(user8);
196 if (tc == user8[ulen - 1]) {
197 /* ANSI style acknowledge string */
198 ACK_terminator = tc;
199 ACK_length = 4096;
200 return;
201 }
202 }
203#endif
204 /* fixed length acknowledge string */
205 ACK_length = len;
206 ACK_terminator = -2;
207}
208
209/*
210** verify_time()
211**
212** verify that the time tests are ready to run.
213** If the baud rate is not set then compute it.
214*/
215void
216verify_time(void)
217{
218 int status, ch;
219
220 if (tty_can_sync == SYNC_FAILED) {
221 return;
222 }
223 probe_enq_ok();
224 put_crlf();
225 if (tty_can_sync == SYNC_TESTED) {
226 put_crlf();
227 if (ACK_terminator >= 0) {
228 ptext("ACK terminating character: ");
229 temp[0] = ACK_terminator;
230 temp[1] = '\0';
231 ptextln(expand(temp));
232 } else {
233 sprintf(temp, "Fixed length ACK, %d characters",
234 ACK_length);
235 ptextln(temp);
236 }
237 }
238 if (tty_baud_rate == 0) {
239 sync_home(&sync_test_list[0], &status, &ch);
240 }
241}
242
243/*****************************************************************************
244 *
245 * Terminal performance tests
246 *
247 * Find out how fast the terminal can:
248 * 1) accept characters
249 * 2) scroll the screen
250 * 3) clear the screen
251 *
252 *****************************************************************************/
253
254/*
255** sync_home(test_list, status, ch)
256**
257** Baudrate test
258*/
259void
260sync_home(
261 struct test_list *t,
262 int *state,
263 int *ch)
264{
265 int j, k;
266 unsigned long rate;
267
268 if (!cursor_home && !cursor_address && !row_address) {
269 ptext("Terminal can not home cursor. ");
270 generic_done_message(t, state, ch);
271 return;
272 }
273 if (skip_pad_test(t, state, ch,
274 "(home) Start baudrate search")) {
275 return;
276 }
277 pad_test_startup(1);
278 do {
279 go_home();
280 for (j = 1; j < lines; j++) {
281 for (k = 0; k < columns; k++) {
282 if (k & 0xF) {
283 put_this(letter);
284 } else {
285 put_this('.');
286 }
287 }
288 SLOW_TERMINAL_EXIT;
289 }
290 NEXT_LETTER;
291 } while(still_testing());
292 pad_test_shutdown(t, auto_right_margin == 0);
293 /* note: tty_frame_size is the real framesize times two.
294 This takes care of half bits. */
295 rate = (tx_cps * tty_frame_size) >> 1;
296 if (rate > tty_baud_rate) {
297 tty_baud_rate = rate;
298 }
299 if (tx_cps > tty_cps) {
300 tty_cps = tx_cps;
301 }
302 sprintf(temp, "%lu characters per second. Baudrate %d ", tx_cps, j);
303 ptext(temp);
304 generic_done_message(t, state, ch);
305}
306
307/*
308** sync_lines(test_list, status, ch)
309**
310** How many newlines/second?
311*/
312static void
313sync_lines(
314 struct test_list *t,
315 int *state,
316 int *ch)
317{
318 int j;
319
320 if (skip_pad_test(t, state, ch,
321 "(nel) Start scroll performance test")) {
322 return;
323 }
324 pad_test_startup(0);
325 repeats = 100;
326 do {
327 sprintf(temp, "%d", test_complete);
328 put_str(temp);
329 put_newlines(repeats);
330 } while(still_testing());
331 pad_test_shutdown(t, 0);
332 j = sliding_scale(tx_count[0], 1000000, usec_run_time);
333 if (j > tty_newline_rate) {
334 tty_newline_rate = j;
335 }
336 sprintf(temp, "%d linefeeds per second. ", j);
337 ptext(temp);
338 generic_done_message(t, state, ch);
339}
340
341/*
342** sync_clear(test_list, status, ch)
343**
344** How many clear-screens/second?
345*/
346static void
347sync_clear(
348 struct test_list *t,
349 int *state,
350 int *ch)
351{
352 int j;
353
354 if (!clear_screen) {
355 ptext("Terminal can not clear-screen. ");
356 generic_done_message(t, state, ch);
357 return;
358 }
359 if (skip_pad_test(t, state, ch,
360 "(clear) Start clear-screen performance test")) {
361 return;
362 }
363 pad_test_startup(0);
364 repeats = 20;
365 do {
366 sprintf(temp, "%d", test_complete);
367 put_str(temp);
368 for (j = 0; j < repeats; j++) {
369 put_clear();
370 }
371 } while(still_testing());
372 pad_test_shutdown(t, 0);
373 j = sliding_scale(tx_count[0], 1000000, usec_run_time);
374 if (j > tty_clear_rate) {
375 tty_clear_rate = j;
376 }
377 sprintf(temp, "%d clear-screens per second. ", j);
378 ptext(temp);
379 generic_done_message(t, state, ch);
380}
381
382/*
383** sync_summary(test_list, status, ch)
384**
385** Print out the test results.
386*/
387static void
388sync_summary(
389 struct test_list *t,
390 int *state,
391 int *ch)
392{
393 char size[32];
394
395 put_crlf();
396 ptextln("Terminal size characters/sec linefeeds/sec clears/sec");
397 sprintf(size, "%dx%d", columns, lines);
398 sprintf(temp, "%-10s%-11s%11lu %11d %11d", tty_basename, size,
399 tty_cps, tty_newline_rate, tty_clear_rate);
400 ptextln(temp);
401 generic_done_message(t, state, ch);
402}
403
404/*
405** sync_test(menu)
406**
407** Run at the beginning of the pad tests and function key tests
408*/
409void
410sync_test(
411 struct test_menu *menu)
412{
413 control_init();
414 if (tty_can_sync == SYNC_NOT_TESTED) {
415 verify_time();
416 }
417 if (menu->menu_title) {
418 put_crlf();
419 ptextln(menu->menu_title);
420 }
421}
422
423/*
424** sync_handshake(test_list, status, ch)
425**
426** Test or retest the ENQ/ACK handshake
427*/
428void
429sync_handshake(
430 struct test_list *t GCC_UNUSED,
431 int *state GCC_UNUSED,
432 int *ch GCC_UNUSED)
433{
434 tty_can_sync = SYNC_NOT_TESTED;
435 verify_time();
436}
Note: See TracBrowser for help on using the repository browser.