2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
4 ** This file is part of TACK.
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)
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.
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
28 MODULE_ID("$Id: control.c,v 1.9 2006/06/24 21:27:53 tom Exp $")
30 /* terminfo test program control subroutines */
33 #define MY_TIMER struct timeval
35 #define MY_TIMER time_t
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 static 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 unsigned long usec_run_time; /* length of last test in microseconds */
47 static 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 unsigned long tx_cps; /* characters per second */
70 static struct test_list *tx_source; /* The test that generated this data */
72 #define RESULT_BLOCK 1024
73 static int blocks; /* number of result blocks available */
74 static struct test_results *results; /* pointer to next available */
75 static struct test_results **pads; /* save pad results here */
81 pads = (struct test_results **)calloc(MAX_STRINGS, sizeof(struct test_results *));
86 ** event_start(number)
88 ** Begin the stopwatch at the current time-of-day.
94 (void) gettimeofday(&stop_watch[n], (struct timezone *)0);
96 stop_watch[n] = time((time_t *)0);
101 ** event_time(number)
103 ** Return the number of milliseconds since this stop watch began.
108 #if HAVE_GETTIMEOFDAY
109 MY_TIMER current_time;
111 (void) gettimeofday(¤t_time, (struct timezone *)0);
112 return ((current_time.tv_sec - stop_watch[n].tv_sec) * 1000000)
113 + current_time.tv_usec - stop_watch[n].tv_usec;
115 return (time((time_t *)0) - stop_watch[n]) * 1000;
119 /*****************************************************************************
121 * Execution control for string capability tests
123 *****************************************************************************/
128 ** Get a results block for pad test data.
130 static struct test_results *
134 results = (struct test_results *)
135 malloc(sizeof(struct test_results) * RESULT_BLOCK);
137 ptextln("Malloc failed");
138 return (struct test_results *) 0;
140 blocks = RESULT_BLOCK;
149 ** Initialize the augment menu selections
152 set_augment_txt(void)
154 sprintf(txt_longer_augment,
155 ">) Change lines/characters effected to %d", augment << 1);
156 sprintf(txt_shorter_augment,
157 "<) Change lines/characters effected to %d", augment >> 1);
163 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
164 pad_test_duration + 1);
165 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
166 pad_test_duration - 1);
171 ** msec_cost(cap, affected-count)
173 ** Return the number of milliseconds delay needed by the cap.
177 const char *const cap,
180 int dec, value, total, star, ch;
187 for (cp = cap; *cp; cp++) {
188 if (*cp == '$' && cp[1] == '<') {
191 for (cp += 2; (ch = *cp); cp++) {
192 if (ch >= '0' && ch <= '9') {
193 value = value * 10 + (ch - '0');
207 total += (value * star) / dec;
209 total += (value * star);
219 ** Return the cap without padding
224 static char cb[1024];
230 for (ts = cb; (*ts = *cap); ++cap) {
231 if (*cap == '$' && cap[1] == '<') {
249 ** send CR/LF or go home and bump letter
254 if (line_count + 2 >= lines) {
263 ** skip_pad_test(test-list-entry, state, ch, text)
265 ** Print the start test line. Handle start up commands.
266 ** Return TRUE if a return is requested.
270 struct test_list *test,
281 if ((test->flags & MENU_LC_MASK)) {
282 sprintf(rep_text, " *%d", augment);
288 /* Skip is converted to next */
293 /* Quit is converted to help */
297 if (*ch == '\r' || *ch == '\n' || *ch == 'n' || *ch == 'r') {
298 /* this is the only response that allows the test to run */
301 if (subtest_menu(pad_test_list, state, ch)) {
309 ** pad_done_message(test_list)
311 ** Print the Done message and request input.
315 struct test_list *test,
319 int default_action = 0;
320 char done_message[128];
324 if ((test->flags & MENU_LC_MASK)) {
325 sprintf(rep_text, "*%d", augment);
329 if (test->caps_done) {
330 sprintf(done_message, "(%s)%s Done ", test->caps_done,
340 if (debug_level & 2) {
341 dump_test_stats(test, state, ch);
345 if (*ch == '\r' || *ch == '\n') {
346 *ch = default_action;
349 if (*ch == 's' || *ch == 'n') {
353 if (strchr(pad_repeat_test, *ch)) {
354 /* default action is now repeat */
355 default_action = 'r';
357 if (subtest_menu(pad_test_list, state, ch)) {
365 ** sliding_scale(dividend, factor, divisor)
367 ** Return (dividend * factor) / divisor
373 unsigned long divisor)
378 d = (d * (double) factor) / (double) divisor;
379 return (int) (d + 0.5);
385 ** pad_test_startup()
387 ** Do the stuff needed to begin a test.
397 raw_characters_sent = 0;
398 test_complete = ttp = char_count = tt_delay_used = 0;
399 letter = letters[letter_number = 0];
400 if (pad_test_duration <= 0) {
401 pad_test_duration = 1;
403 tt_delay_max = pad_test_duration * 1000;
404 set_alarm_clock(pad_test_duration);
405 event_start(TIME_TEST);
411 ** This function is called to see if the test loop should be terminated.
418 return EXIT_CONDITION;
422 ** pad_test_shutdown()
424 ** Do the stuff needed to end a test.
432 int counts; /* total counts */
433 int ss; /* Save string index */
434 int cpo; /* characters per operation */
435 int delta; /* difference in characters */
436 int bogus; /* Time is inaccurate */
437 struct test_results *r; /* Results of current test */
438 int ss_index[TT_MAX]; /* String index */
441 if (tty_can_sync == SYNC_TESTED) {
442 bogus = tty_sync_error();
446 usec_run_time = event_time(TIME_TEST);
448 tx_characters = raw_characters_sent;
449 tx_cps = sliding_scale(tx_characters, 1000000, usec_run_time);
451 /* save the data base */
452 for (txp = ss = counts = 0; txp < ttp; txp++) {
453 tx_cap[txp] = tt_cap[txp];
454 tx_count[txp] = tt_count[txp];
455 tx_delay[txp] = tt_delay[txp];
456 tx_affected[txp] = tt_affected[txp];
457 tx_index[txp] = get_string_cap_byvalue(tt_cap[txp]);
458 if (tx_index[txp] >= 0) {
459 if (cap_match(t->caps_done, strnames[tx_index[txp]])) {
460 ss_index[ss++] = txp;
461 counts += tx_count[txp];
469 if (counts == 0 || tty_cps == 0 || bogus) {
473 /* calculate the suggested pad times */
474 delta = usec_run_time - sliding_scale(tx_characters, 1000000, tty_cps);
476 /* probably should bump tx_characters */
479 cpo = delta / counts;
480 for (i = 0; i < ss; i++) {
481 if (!(r = get_next_block())) {
484 r->next = pads[tx_index[ss_index[i]]];
485 pads[tx_index[ss_index[i]]] = r;
487 r->reps = tx_affected[ss_index[i]];
493 ** show_cap_results(index)
495 ** Display the previous results
501 struct test_results *r; /* a result */
506 sprintf(temp, "(%s)", strnames[x]);
509 sprintf(temp, "$<%d>", r->delay / 1000);
510 put_columns(temp, (int) strlen(temp), 10);
516 delay = r->delay / (r->reps * 100);
517 sprintf(temp, "$<%d.%d*>", delay / 10, delay % 10);
518 put_columns(temp, (int) strlen(temp), 10);
527 ** dump_test_stats(test_list, status, ch)
529 ** Dump the statistics about the last test
542 if (tx_source && tx_source->caps_done) {
543 cap_index(tx_source->caps_done, x);
545 sprintf(temp, "Caps summary for (%s)",
546 tx_source->caps_done);
548 for (i = 0; x[i] >= 0; i++) {
549 show_cap_results(x[i]);
554 sprintf(tbuf, "%011lu", usec_run_time);
555 sprintf(temp, "Test time: %lu.%s, characters per second %lu, characters %d",
556 usec_run_time / 1000000UL, &tbuf[5], tx_cps, tx_characters);
558 for (i = 0; i < txp; i++) {
559 if ((j = get_string_cap_byvalue(tx_cap[i])) >= 0) {
560 sprintf(tbuf, "(%s)", strnames[j]);
564 sprintf(temp, "%8d %3d $<%3d> %8s %s",
565 tx_count[i], tx_affected[i], tx_delay[i],
566 tbuf, expand(tx_cap[i]));
569 generic_done_message(t, state, ch);
573 ** longer_test_time(test_list, status, ch)
575 ** Extend the number of seconds for each test.
579 struct test_list *t GCC_UNUSED,
580 int *state GCC_UNUSED,
583 pad_test_duration += 1;
584 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
585 pad_test_duration + 1);
586 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
587 pad_test_duration - 1);
588 sprintf(temp, "Tests will run for %d seconds", pad_test_duration);
590 *ch = REQUEST_PROMPT;
594 ** shorter_test_time(test_list, status, ch)
596 ** Shorten the number of seconds for each test.
600 struct test_list *t GCC_UNUSED,
601 int *state GCC_UNUSED,
604 if (pad_test_duration > 1) {
605 pad_test_duration -= 1;
606 sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
607 pad_test_duration + 1);
608 sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
609 pad_test_duration - 1);
611 sprintf(temp, "Tests will run for %d second%s", pad_test_duration,
612 pad_test_duration > 1 ? "s" : "");
614 *ch = REQUEST_PROMPT;
618 ** longer_augment(test_list, status, ch)
620 ** Lengthen the number of lines/characters effected
625 int *state GCC_UNUSED,
633 sprintf(temp, "The pad tests will effect %d %s.", augment,
634 ((t->flags & MENU_LC_MASK) == MENU_lines) ?
635 "lines" : "characters");
637 *ch = REQUEST_PROMPT;
641 ** shorter_augment(test_list, status, ch)
643 ** Shorten the number of lines/characters effected
648 int *state GCC_UNUSED,
652 /* don't let the augment go to zero */
659 sprintf(temp, "The pad tests will effect %d %s.", augment,
660 ((t->flags & MENU_LC_MASK) == MENU_lines) ?
661 "lines" : "characters");
663 *ch = REQUEST_PROMPT;