#include <tack.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
MODULE_ID("$Id: control.c,v 1.1.1.1 2001/11/29 20:40:59 jevans Exp $")
#if HAVE_GETTIMEOFDAY
#define MY_TIMER struct timeval
#else
#define MY_TIMER time_t
#endif
int test_complete;
char txt_longer_test_time[80];
char txt_shorter_test_time[80];
int pad_test_duration = 1;
int auto_pad_mode;
int no_alarm_event;
int usec_run_time;
MY_TIMER stop_watch[MAX_TIMERS];
char txt_longer_augment[80];
char txt_shorter_augment[80];
int tt_delay_max;
int tt_delay_used;
const char *tt_cap[TT_MAX];
int tt_affected[TT_MAX];
int tt_count[TT_MAX];
int tt_delay[TT_MAX];
int ttp;
const char *tx_cap[TT_MAX];
int tx_affected[TT_MAX];
int tx_count[TT_MAX];
int tx_index[TT_MAX];
int tx_delay[TT_MAX];
int txp;
int tx_characters;
int tx_cps;
struct test_list *tx_source;
extern struct test_menu pad_menu;
extern struct test_list pad_test_list[];
#define RESULT_BLOCK 1024
static int blocks;
static struct test_results *results;
struct test_results *pads[STRCOUNT];
void
event_start(int n)
{
#if HAVE_GETTIMEOFDAY
(void) gettimeofday(&stop_watch[n], (struct timezone *)0);
#else
stop_watch[n] = time((time_t *)0);
#endif
}
long
event_time(int n)
{
#if HAVE_GETTIMEOFDAY
MY_TIMER current_time;
(void) gettimeofday(¤t_time, (struct timezone *)0);
return ((current_time.tv_sec - stop_watch[n].tv_sec) * 1000000)
+ current_time.tv_usec - stop_watch[n].tv_usec;
#else
return (time((time_t *)0) - stop_watch[n]) * 1000;
#endif
}
static struct test_results *
get_next_block(void)
{
if (blocks <= 0) {
results = (struct test_results *)
malloc(sizeof(struct test_results) * RESULT_BLOCK);
if (!results) {
ptextln("Malloc failed");
return (struct test_results *) 0;
}
blocks = RESULT_BLOCK;
}
blocks--;
return results++;
}
void
set_augment_txt(void)
{
sprintf(txt_longer_augment,
">) Change lines/characters effected to %d", augment << 1);
sprintf(txt_shorter_augment,
"<) Change lines/characters effected to %d", augment >> 1);
}
void
control_init(void)
{
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
set_augment_txt();
}
int
msec_cost(
const char *const cap,
int affcnt)
{
int dec, value, total, star, ch;
const char *cp;
if (!cap) {
return 0;
}
total = 0;
for (cp = cap; *cp; cp++) {
if (*cp == '$' && cp[1] == '<') {
star = 1;
value = dec = 0;
for (cp += 2; (ch = *cp); cp++) {
if (ch >= '0' && ch <= '9') {
value = value * 10 + (ch - '0');
dec *= 10;
} else
if (ch == '.') {
dec = 1;
} else
if (ch == '*') {
star = affcnt;
} else
if (ch == '>') {
break;
}
}
if (dec > 1) {
total += (value * star) / dec;
} else {
total += (value * star);
}
}
}
return total;
}
char *
liberated(char *cap)
{
static char cb[1024];
char *ts, *ls;
cb[0] = '\0';
ls = NULL;
if (cap) {
for (ts = cb; (*ts = *cap); ++cap) {
if (*cap == '$' && cap[1] == '<') {
ls = ts;
}
++ts;
if (*cap == '>') {
if (ls) {
ts = ls;
ls = NULL;
}
}
}
}
return cb;
}
void
page_loop(void)
{
if (line_count + 2 >= lines) {
NEXT_LETTER;
go_home();
} else {
put_crlf();
}
}
int
skip_pad_test(
struct test_list *test,
int *state,
int *ch,
const char *text)
{
char rep_text[16];
while(1) {
if (text) {
ptext(text);
}
if ((test->flags & MENU_LC_MASK)) {
sprintf(rep_text, " *%d", augment);
ptext(rep_text);
}
ptext(" [n] > ");
*ch = wait_here();
if (*ch == 's') {
*ch = 'n';
return TRUE;
}
if (*ch == 'q') {
*ch = '?';
return TRUE;
}
if (*ch == '\r' || *ch == '\n' || *ch == 'n' || *ch == 'r') {
*ch = 0;
}
if (subtest_menu(pad_test_list, state, ch)) {
continue;
}
return (*ch != 0);
}
}
void
pad_done_message(
struct test_list *test,
int *state,
int *ch)
{
int default_action = 0;
char done_message[128];
char rep_text[16];
while (1) {
if ((test->flags & MENU_LC_MASK)) {
sprintf(rep_text, "*%d", augment);
} else {
rep_text[0] = '\0';
}
if (test->caps_done) {
sprintf(done_message, "(%s)%s Done ", test->caps_done,
rep_text);
ptext(done_message);
} else {
if (rep_text[0]) {
ptext(rep_text);
ptext(" ");
}
ptext("Done ");
}
if (debug_level & 2) {
dump_test_stats(test, state, ch);
} else {
*ch = wait_here();
}
if (*ch == '\r' || *ch == '\n') {
*ch = default_action;
return;
}
if (*ch == 's' || *ch == 'n') {
*ch = 0;
return;
}
if (strchr(pad_repeat_test, *ch)) {
default_action = 'r';
}
if (subtest_menu(pad_test_list, state, ch)) {
continue;
}
return;
}
}
int
sliding_scale(
int dividend,
int factor,
int divisor)
{
double d = dividend;
if (divisor) {
d = (d * (double) factor) / (double) divisor;
return (int) (d + 0.5);
}
return 0;
}
void
pad_test_startup(
int do_clear)
{
if (do_clear) {
put_clear();
}
repeats = augment;
raw_characters_sent = 0;
test_complete = ttp = char_count = tt_delay_used = 0;
letter = letters[letter_number = 0];
if (pad_test_duration <= 0) {
pad_test_duration = 1;
}
tt_delay_max = pad_test_duration * 1000;
set_alarm_clock(pad_test_duration);
event_start(TIME_TEST);
}
int
still_testing(void)
{
fflush(stdout);
test_complete++;
return EXIT_CONDITION;
}
void
pad_test_shutdown(
struct test_list *t,
int crlf)
{
int i;
int counts;
int ss;
int cpo;
int delta;
int bogus;
struct test_results *r;
int ss_index[TT_MAX];
if (tty_can_sync == SYNC_TESTED) {
bogus = tty_sync_error();
} else {
bogus = 1;
}
usec_run_time = event_time(TIME_TEST);
tx_source = t;
tx_characters = raw_characters_sent;
tx_cps = sliding_scale(tx_characters, 1000000, usec_run_time);
for (txp = ss = counts = 0; txp < ttp; txp++) {
tx_cap[txp] = tt_cap[txp];
tx_count[txp] = tt_count[txp];
tx_delay[txp] = tt_delay[txp];
tx_affected[txp] = tt_affected[txp];
tx_index[txp] = get_string_cap_byvalue(tt_cap[txp]);
if (tx_index[txp] >= 0) {
if (cap_match(t->caps_done, strnames[tx_index[txp]])) {
ss_index[ss++] = txp;
counts += tx_count[txp];
}
}
}
if (crlf) {
put_crlf();
}
if (counts == 0 || tty_cps == 0 || bogus) {
return;
}
delta = usec_run_time - sliding_scale(tx_characters, 1000000, tty_cps);
if (delta < 0) {
delta = 0;
}
cpo = delta / counts;
for (i = 0; i < ss; i++) {
if (!(r = get_next_block())) {
return;
}
r->next = pads[tx_index[ss_index[i]]];
pads[tx_index[ss_index[i]]] = r;
r->test = t;
r->reps = tx_affected[ss_index[i]];
r->delay = cpo;
}
}
static void
show_cap_results(
int x)
{
struct test_results *r;
int delay;
if ((r = pads[x])) {
sprintf(temp, "(%s)", strnames[x]);
ptext(temp);
while (r) {
sprintf(temp, "$<%d>", r->delay / 1000);
put_columns(temp, strlen(temp), 10);
r = r->next;
}
r = pads[x];
while (r) {
if (r->reps > 1) {
delay = r->delay / (r->reps * 100);
sprintf(temp, "$<%d.%d*>", delay / 10, delay % 10);
put_columns(temp, strlen(temp), 10);
}
r = r->next;
}
put_crlf();
}
}
void
dump_test_stats(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
char tbuf[32];
int x[32];
put_crlf();
if (tx_source && tx_source->caps_done) {
cap_index(tx_source->caps_done, x);
if (x[0] >= 0) {
sprintf(temp, "Caps summary for (%s)",
tx_source->caps_done);
ptextln(temp);
for (i = 0; x[i] >= 0; i++) {
show_cap_results(x[i]);
}
put_crlf();
}
}
sprintf(tbuf, "%011u", usec_run_time);
sprintf(temp, "Test time: %d.%s, characters per second %d, characters %d",
usec_run_time / 1000000, &tbuf[5], tx_cps, tx_characters);
ptextln(temp);
for (i = 0; i < txp; i++) {
if ((j = get_string_cap_byvalue(tx_cap[i])) >= 0) {
sprintf(tbuf, "(%s)", strnames[j]);
} else {
strcpy(tbuf, "(?)");
}
sprintf(temp, "%8d %3d $<%3d> %8s %s",
tx_count[i], tx_affected[i], tx_delay[i],
tbuf, expand(tx_cap[i]));
putln(temp);
}
generic_done_message(t, state, ch);
}
void
longer_test_time(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
pad_test_duration += 1;
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
sprintf(temp, "Tests will run for %d seconds", pad_test_duration);
ptext(temp);
*ch = REQUEST_PROMPT;
}
void
shorter_test_time(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
if (pad_test_duration > 1) {
pad_test_duration -= 1;
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
}
sprintf(temp, "Tests will run for %d second%s", pad_test_duration,
pad_test_duration > 1 ? "s" : "");
ptext(temp);
*ch = REQUEST_PROMPT;
}
void
longer_augment(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
augment <<= 1;
set_augment_txt();
if (augment_test) {
t = augment_test;
}
sprintf(temp, "The pad tests will effect %d %s.", augment,
((t->flags & MENU_LC_MASK) == MENU_lines) ?
"lines" : "characters");
ptextln(temp);
*ch = REQUEST_PROMPT;
}
void
shorter_augment(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
if (augment > 1) {
augment >>= 1;
}
set_augment_txt();
if (augment_test) {
t = augment_test;
}
sprintf(temp, "The pad tests will effect %d %s.", augment,
((t->flags & MENU_LC_MASK) == MENU_lines) ?
"lines" : "characters");
ptextln(temp);
*ch = REQUEST_PROMPT;
}