kernel - Update swapcache manual page
[dragonfly.git] / contrib / ncurses / tack / control.c
blob4a85384b412543007dffffde9b3836574671a47b
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., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, USA.
22 #include <tack.h>
24 #if HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
28 MODULE_ID("$Id: control.c,v 1.3 2000/03/04 21:10:59 tom Exp $")
30 /* terminfo test program control subroutines */
32 #if HAVE_GETTIMEOFDAY
33 #define MY_TIMER struct timeval
34 #else
35 #define MY_TIMER time_t
36 #endif
38 /* globals */
39 int test_complete; /* counts number of tests completed */
41 char txt_longer_test_time[80]; /* +) use longer time */
42 char txt_shorter_test_time[80]; /* -) use shorter time */
43 int pad_test_duration = 1; /* number of seconds for a pad test */
44 int auto_pad_mode; /* run the time tests */
45 int no_alarm_event; /* TRUE if the alarm has not gone off yet */
46 int usec_run_time; /* length of last test in microseconds */
47 MY_TIMER stop_watch[MAX_TIMERS]; /* Hold the start timers */
49 char txt_longer_augment[80]; /* >) use bigger augment */
50 char txt_shorter_augment[80]; /* <) use smaller augment */
52 /* caps under test data base */
53 int tt_delay_max; /* max number of milliseconds we can delay */
54 int tt_delay_used; /* number of milliseconds consumed in delay */
55 const char *tt_cap[TT_MAX]; /* value of string */
56 int tt_affected[TT_MAX]; /* lines or columns effected (repetition factor) */
57 int tt_count[TT_MAX]; /* Number of times sent */
58 int tt_delay[TT_MAX]; /* Number of milliseconds delay */
59 int ttp; /* number of entries used */
61 /* Saved value of the above data base */
62 const char *tx_cap[TT_MAX]; /* value of string */
63 int tx_affected[TT_MAX]; /* lines or columns effected (repetition factor) */
64 int tx_count[TT_MAX]; /* Number of times sent */
65 int tx_index[TT_MAX]; /* String index */
66 int tx_delay[TT_MAX]; /* Number of milliseconds delay */
67 int txp; /* number of entries used */
68 int tx_characters; /* printing characters sent by test */
69 int tx_cps; /* characters per second */
70 struct test_list *tx_source; /* The test that generated this data */
72 extern struct test_menu pad_menu; /* Pad menu structure */
73 extern struct test_list pad_test_list[];
75 #define RESULT_BLOCK 1024
76 static int blocks; /* number of result blocks available */
77 static struct test_results *results; /* pointer to next available */
78 struct test_results *pads[STRCOUNT]; /* save pad results here */
81 ** event_start(number)
83 ** Begin the stopwatch at the current time-of-day.
85 void
86 event_start(int n)
88 #if HAVE_GETTIMEOFDAY
89 (void) gettimeofday(&stop_watch[n], (struct timezone *)0);
90 #else
91 stop_watch[n] = time((time_t *)0);
92 #endif
96 ** event_time(number)
98 ** Return the number of milliseconds since this stop watch began.
100 long
101 event_time(int n)
103 #if HAVE_GETTIMEOFDAY
104 MY_TIMER current_time;
106 (void) gettimeofday(&current_time, (struct timezone *)0);
107 return ((current_time.tv_sec - stop_watch[n].tv_sec) * 1000000)
108 + current_time.tv_usec - stop_watch[n].tv_usec;
109 #else
110 return (time((time_t *)0) - stop_watch[n]) * 1000;
111 #endif
114 /*****************************************************************************
116 * Execution control for string capability tests
118 *****************************************************************************/
121 ** get_next_block()
123 ** Get a results block for pad test data.
125 static struct test_results *
126 get_next_block(void)
128 if (blocks <= 0) {
129 results = (struct test_results *)
130 malloc(sizeof(struct test_results) * RESULT_BLOCK);
131 if (!results) {
132 ptextln("Malloc failed");
133 return (struct test_results *) 0;
135 blocks = RESULT_BLOCK;
137 blocks--;
138 return results++;
142 ** set_augment_txt()
144 ** Initialize the augment menu selections
146 void
147 set_augment_txt(void)
149 sprintf(txt_longer_augment,
150 ">) Change lines/characters effected to %d", augment << 1);
151 sprintf(txt_shorter_augment,
152 "<) Change lines/characters effected to %d", augment >> 1);
155 void
156 control_init(void)
158 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
159 pad_test_duration + 1);
160 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
161 pad_test_duration - 1);
162 set_augment_txt();
166 ** msec_cost(cap, affected-count)
168 ** Return the number of milliseconds delay needed by the cap.
171 msec_cost(
172 const char *const cap,
173 int affcnt)
175 int dec, value, total, star, ch;
176 const char *cp;
178 if (!cap) {
179 return 0;
181 total = 0;
182 for (cp = cap; *cp; cp++) {
183 if (*cp == '$' && cp[1] == '<') {
184 star = 1;
185 value = dec = 0;
186 for (cp += 2; (ch = *cp); cp++) {
187 if (ch >= '0' && ch <= '9') {
188 value = value * 10 + (ch - '0');
189 dec *= 10;
190 } else
191 if (ch == '.') {
192 dec = 1;
193 } else
194 if (ch == '*') {
195 star = affcnt;
196 } else
197 if (ch == '>') {
198 break;
201 if (dec > 1) {
202 total += (value * star) / dec;
203 } else {
204 total += (value * star);
208 return total;
212 ** liberated(cap)
214 ** Return the cap without padding
216 char *
217 liberated(char *cap)
219 static char cb[1024];
220 char *ts, *ls;
222 cb[0] = '\0';
223 ls = NULL;
224 if (cap) {
225 for (ts = cb; (*ts = *cap); ++cap) {
226 if (*cap == '$' && cap[1] == '<') {
227 ls = ts;
229 ++ts;
230 if (*cap == '>') {
231 if (ls) {
232 ts = ls;
233 ls = NULL;
238 return cb;
242 ** page_loop()
244 ** send CR/LF or go home and bump letter
246 void
247 page_loop(void)
249 if (line_count + 2 >= lines) {
250 NEXT_LETTER;
251 go_home();
252 } else {
253 put_crlf();
258 ** skip_pad_test(test-list-entry, state, ch, text)
260 ** Print the start test line. Handle start up commands.
261 ** Return TRUE if a return is requested.
264 skip_pad_test(
265 struct test_list *test,
266 int *state,
267 int *ch,
268 const char *text)
270 char rep_text[16];
272 while(1) {
273 if (text) {
274 ptext(text);
276 if ((test->flags & MENU_LC_MASK)) {
277 sprintf(rep_text, " *%d", augment);
278 ptext(rep_text);
280 ptext(" [n] > ");
281 *ch = wait_here();
282 if (*ch == 's') {
283 /* Skip is converted to next */
284 *ch = 'n';
285 return TRUE;
287 if (*ch == 'q') {
288 /* Quit is converted to help */
289 *ch = '?';
290 return TRUE;
292 if (*ch == '\r' || *ch == '\n' || *ch == 'n' || *ch == 'r') {
293 /* this is the only response that allows the test to run */
294 *ch = 0;
296 if (subtest_menu(pad_test_list, state, ch)) {
297 continue;
299 return (*ch != 0);
304 ** pad_done_message(test_list)
306 ** Print the Done message and request input.
308 void
309 pad_done_message(
310 struct test_list *test,
311 int *state,
312 int *ch)
314 int default_action = 0;
315 char done_message[128];
316 char rep_text[16];
318 while (1) {
319 if ((test->flags & MENU_LC_MASK)) {
320 sprintf(rep_text, "*%d", augment);
321 } else {
322 rep_text[0] = '\0';
324 if (test->caps_done) {
325 sprintf(done_message, "(%s)%s Done ", test->caps_done,
326 rep_text);
327 ptext(done_message);
328 } else {
329 if (rep_text[0]) {
330 ptext(rep_text);
331 ptext(" ");
333 ptext("Done ");
335 if (debug_level & 2) {
336 dump_test_stats(test, state, ch);
337 } else {
338 *ch = wait_here();
340 if (*ch == '\r' || *ch == '\n') {
341 *ch = default_action;
342 return;
344 if (*ch == 's' || *ch == 'n') {
345 *ch = 0;
346 return;
348 if (strchr(pad_repeat_test, *ch)) {
349 /* default action is now repeat */
350 default_action = 'r';
352 if (subtest_menu(pad_test_list, state, ch)) {
353 continue;
355 return;
360 ** sliding_scale(dividend, factor, divisor)
362 ** Return (dividend * factor) / divisor
365 sliding_scale(
366 int dividend,
367 int factor,
368 int divisor)
370 double d = dividend;
372 if (divisor) {
373 d = (d * (double) factor) / (double) divisor;
374 return (int) (d + 0.5);
376 return 0;
380 ** pad_test_startup()
382 ** Do the stuff needed to begin a test.
384 void
385 pad_test_startup(
386 int do_clear)
388 if (do_clear) {
389 put_clear();
391 repeats = augment;
392 raw_characters_sent = 0;
393 test_complete = ttp = char_count = tt_delay_used = 0;
394 letter = letters[letter_number = 0];
395 if (pad_test_duration <= 0) {
396 pad_test_duration = 1;
398 tt_delay_max = pad_test_duration * 1000;
399 set_alarm_clock(pad_test_duration);
400 event_start(TIME_TEST);
404 ** still_testing()
406 ** This function is called to see if the test loop should be terminated.
409 still_testing(void)
411 fflush(stdout);
412 test_complete++;
413 return EXIT_CONDITION;
417 ** pad_test_shutdown()
419 ** Do the stuff needed to end a test.
421 void
422 pad_test_shutdown(
423 struct test_list *t,
424 int crlf)
426 int i;
427 int counts; /* total counts */
428 int ss; /* Save string index */
429 int cpo; /* characters per operation */
430 int delta; /* difference in characters */
431 int bogus; /* Time is inaccurate */
432 struct test_results *r; /* Results of current test */
433 int ss_index[TT_MAX]; /* String index */
435 if (tty_can_sync == SYNC_TESTED) {
436 bogus = tty_sync_error();
437 } else {
438 bogus = 1;
440 usec_run_time = event_time(TIME_TEST);
441 tx_source = t;
442 tx_characters = raw_characters_sent;
443 tx_cps = sliding_scale(tx_characters, 1000000, usec_run_time);
445 /* save the data base */
446 for (txp = ss = counts = 0; txp < ttp; txp++) {
447 tx_cap[txp] = tt_cap[txp];
448 tx_count[txp] = tt_count[txp];
449 tx_delay[txp] = tt_delay[txp];
450 tx_affected[txp] = tt_affected[txp];
451 tx_index[txp] = get_string_cap_byvalue(tt_cap[txp]);
452 if (tx_index[txp] >= 0) {
453 if (cap_match(t->caps_done, strnames[tx_index[txp]])) {
454 ss_index[ss++] = txp;
455 counts += tx_count[txp];
460 if (crlf) {
461 put_crlf();
463 if (counts == 0 || tty_cps == 0 || bogus) {
464 /* nothing to do */
465 return;
467 /* calculate the suggested pad times */
468 delta = usec_run_time - sliding_scale(tx_characters, 1000000, tty_cps);
469 if (delta < 0) {
470 /* probably should bump tx_characters */
471 delta = 0;
473 cpo = delta / counts;
474 for (i = 0; i < ss; i++) {
475 if (!(r = get_next_block())) {
476 return;
478 r->next = pads[tx_index[ss_index[i]]];
479 pads[tx_index[ss_index[i]]] = r;
480 r->test = t;
481 r->reps = tx_affected[ss_index[i]];
482 r->delay = cpo;
487 ** show_cap_results(index)
489 ** Display the previous results
491 static void
492 show_cap_results(
493 int x)
495 struct test_results *r; /* a result */
496 int delay;
498 if ((r = pads[x])) {
499 sprintf(temp, "(%s)", strnames[x]);
500 ptext(temp);
501 while (r) {
502 sprintf(temp, "$<%d>", r->delay / 1000);
503 put_columns(temp, strlen(temp), 10);
504 r = r->next;
506 r = pads[x];
507 while (r) {
508 if (r->reps > 1) {
509 delay = r->delay / (r->reps * 100);
510 sprintf(temp, "$<%d.%d*>", delay / 10, delay % 10);
511 put_columns(temp, strlen(temp), 10);
513 r = r->next;
515 put_crlf();
520 ** dump_test_stats(test_list, status, ch)
522 ** Dump the statistics about the last test
524 void
525 dump_test_stats(
526 struct test_list *t,
527 int *state,
528 int *ch)
530 int i, j;
531 char tbuf[32];
532 int x[32];
534 put_crlf();
535 if (tx_source && tx_source->caps_done) {
536 cap_index(tx_source->caps_done, x);
537 if (x[0] >= 0) {
538 sprintf(temp, "Caps summary for (%s)",
539 tx_source->caps_done);
540 ptextln(temp);
541 for (i = 0; x[i] >= 0; i++) {
542 show_cap_results(x[i]);
544 put_crlf();
547 sprintf(tbuf, "%011u", usec_run_time);
548 sprintf(temp, "Test time: %d.%s, characters per second %d, characters %d",
549 usec_run_time / 1000000, &tbuf[5], tx_cps, tx_characters);
550 ptextln(temp);
551 for (i = 0; i < txp; i++) {
552 if ((j = get_string_cap_byvalue(tx_cap[i])) >= 0) {
553 sprintf(tbuf, "(%s)", strnames[j]);
554 } else {
555 strcpy(tbuf, "(?)");
557 sprintf(temp, "%8d %3d $<%3d> %8s %s",
558 tx_count[i], tx_affected[i], tx_delay[i],
559 tbuf, expand(tx_cap[i]));
560 putln(temp);
562 generic_done_message(t, state, ch);
566 ** longer_test_time(test_list, status, ch)
568 ** Extend the number of seconds for each test.
570 void
571 longer_test_time(
572 struct test_list *t GCC_UNUSED,
573 int *state GCC_UNUSED,
574 int *ch)
576 pad_test_duration += 1;
577 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
578 pad_test_duration + 1);
579 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
580 pad_test_duration - 1);
581 sprintf(temp, "Tests will run for %d seconds", pad_test_duration);
582 ptext(temp);
583 *ch = REQUEST_PROMPT;
587 ** shorter_test_time(test_list, status, ch)
589 ** Shorten the number of seconds for each test.
591 void
592 shorter_test_time(
593 struct test_list *t GCC_UNUSED,
594 int *state GCC_UNUSED,
595 int *ch)
597 if (pad_test_duration > 1) {
598 pad_test_duration -= 1;
599 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
600 pad_test_duration + 1);
601 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
602 pad_test_duration - 1);
604 sprintf(temp, "Tests will run for %d second%s", pad_test_duration,
605 pad_test_duration > 1 ? "s" : "");
606 ptext(temp);
607 *ch = REQUEST_PROMPT;
611 ** longer_augment(test_list, status, ch)
613 ** Lengthen the number of lines/characters effected
615 void
616 longer_augment(
617 struct test_list *t,
618 int *state GCC_UNUSED,
619 int *ch)
621 augment <<= 1;
622 set_augment_txt();
623 if (augment_test) {
624 t = augment_test;
626 sprintf(temp, "The pad tests will effect %d %s.", augment,
627 ((t->flags & MENU_LC_MASK) == MENU_lines) ?
628 "lines" : "characters");
629 ptextln(temp);
630 *ch = REQUEST_PROMPT;
634 ** shorter_augment(test_list, status, ch)
636 ** Shorten the number of lines/characters effected
638 void
639 shorter_augment(
640 struct test_list *t,
641 int *state GCC_UNUSED,
642 int *ch)
644 if (augment > 1) {
645 /* don't let the augment go to zero */
646 augment >>= 1;
648 set_augment_txt();
649 if (augment_test) {
650 t = augment_test;
652 sprintf(temp, "The pad tests will effect %d %s.", augment,
653 ((t->flags & MENU_LC_MASK) == MENU_lines) ?
654 "lines" : "characters");
655 ptextln(temp);
656 *ch = REQUEST_PROMPT;