46a4f42331ff89f8cabc7b7be0f2f955c52613e3
[ncurses.git] / test / hashtest.c
1 /*
2  * hashtest.c -- test hash mapping
3  *
4  * Generate timing statistics for vertical-motion optimization.
5  *
6  * $Id: hashtest.c,v 1.23 2002/10/19 22:11:24 tom Exp $
7  */
8
9 #ifdef TRACE
10 #define Trace(p) _tracef p
11 #define USE_TRACE 1
12 #else
13 #define Trace(p)                /* nothing */
14 #define USE_TRACE 0
15 #endif
16
17 #include <test.priv.h>
18
19 #define LO_CHAR ' '
20 #define HI_CHAR '~'
21
22 static bool continuous = FALSE;
23 static bool reverse_loops = FALSE;
24 static bool single_step = FALSE;
25 static bool extend_corner = FALSE;
26 static int foot_lines = 0;
27 static int head_lines = 0;
28
29 static void
30 cleanup(void)
31 {
32     move(LINES - 1, 0);
33     clrtoeol();
34     refresh();
35     endwin();
36 }
37
38 static RETSIGTYPE
39 finish(int sig GCC_UNUSED)
40 {
41     cleanup();
42     ExitProgram(EXIT_FAILURE);
43 }
44
45 static void
46 genlines(int base)
47 {
48     int i, j;
49
50 #if USE_TRACE
51     if (base == 'a')
52         Trace(("Resetting screen"));
53     else
54         Trace(("Painting `%c' screen", base));
55 #endif
56
57     /* Do this so writes to lower-right corner don't cause a spurious
58      * scrolling operation.  This _shouldn't_ break the scrolling
59      * optimization, since that's computed in the refresh() call.
60      */
61     scrollok(stdscr, FALSE);
62
63     move(0, 0);
64     for (i = 0; i < head_lines; i++)
65         for (j = 0; j < COLS; j++)
66             addch((j % 8 == 0) ? ('A' + j / 8) : '-');
67
68     move(head_lines, 0);
69     for (i = head_lines; i < LINES - foot_lines; i++) {
70         int c = (base - LO_CHAR + i) % (HI_CHAR - LO_CHAR + 1) + LO_CHAR;
71         int hi = (extend_corner || (i < LINES - 1)) ? COLS : COLS - 1;
72         for (j = 0; j < hi; j++)
73             addch(c);
74     }
75
76     for (i = LINES - foot_lines; i < LINES; i++) {
77         move(i, 0);
78         for (j = 0; j < (extend_corner ? COLS : COLS - 1); j++)
79             addch((j % 8 == 0) ? ('A' + j / 8) : '-');
80     }
81
82     scrollok(stdscr, TRUE);
83     if (single_step) {
84         move(LINES - 1, 0);
85         getch();
86     } else
87         refresh();
88 }
89
90 static void
91 one_cycle(int ch)
92 {
93     if (continuous) {
94         genlines(ch);
95     } else if (ch != 'a') {
96         genlines('a');
97         genlines(ch);
98     }
99 }
100
101 static void
102 run_test(bool optimized GCC_UNUSED)
103 {
104     char ch;
105     int lo = continuous ? LO_CHAR : 'a' - LINES;
106     int hi = continuous ? HI_CHAR : 'a' + LINES;
107
108     if (lo < LO_CHAR)
109         lo = LO_CHAR;
110     if (hi > HI_CHAR)
111         hi = HI_CHAR;
112
113 #if defined(TRACE) || defined(NCURSES_TEST)
114     if (optimized) {
115         Trace(("With hash mapping"));
116         _nc_optimize_enable |= OPTIMIZE_HASHMAP;
117     } else {
118         Trace(("Without hash mapping"));
119         _nc_optimize_enable &= ~OPTIMIZE_HASHMAP;
120     }
121 #endif
122
123     if (reverse_loops)
124         for (ch = hi; ch >= lo; ch--)
125             one_cycle(ch);
126     else
127         for (ch = lo; ch <= hi; ch++)
128             one_cycle(ch);
129 }
130
131 static void
132 usage(void)
133 {
134     static const char *const tbl[] =
135     {
136         "Usage: hashtest [options]"
137         ,""
138         ,"Options:"
139         ,"  -c      continuous (don't reset between refresh's)"
140         ,"  -f num  leave 'num' lines constant for footer"
141         ,"  -h num  leave 'num' lines constant for header"
142         ,"  -l num  repeat test 'num' times"
143         ,"  -n      test the normal optimizer"
144         ,"  -o      test the hashed optimizer"
145         ,"  -r      reverse the loops"
146         ,"  -s      single-step"
147         ,"  -x      assume lower-right corner extension"
148     };
149     size_t n;
150
151     for (n = 0; n < SIZEOF(tbl); n++)
152         fprintf(stderr, "%s\n", tbl[n]);
153     ExitProgram(EXIT_FAILURE);
154 }
155
156 int
157 main(int argc, char *argv[])
158 {
159     int c;
160     int test_loops = 1;
161     int test_normal = FALSE;
162     int test_optimize = FALSE;
163
164     setlocale(LC_ALL, "");
165
166     while ((c = getopt(argc, argv, "cf:h:l:norsx")) != EOF) {
167         switch (c) {
168         case 'c':
169             continuous = TRUE;
170             break;
171         case 'f':
172             foot_lines = atoi(optarg);
173             break;
174         case 'h':
175             head_lines = atoi(optarg);
176             break;
177         case 'l':
178             test_loops = atoi(optarg);
179             break;
180         case 'n':
181             test_normal = TRUE;
182             break;
183         case 'o':
184             test_optimize = TRUE;
185             break;
186         case 'r':
187             reverse_loops = TRUE;
188             break;
189         case 's':
190             single_step = TRUE;
191             break;
192         case 'x':
193             extend_corner = TRUE;
194             break;
195         default:
196             usage();
197         }
198     }
199     if (!test_normal && !test_optimize) {
200         test_normal = TRUE;
201         test_optimize = TRUE;
202     }
203 #if USE_TRACE
204     trace(TRACE_TIMES);
205 #endif
206
207     (void) signal(SIGINT, finish);      /* arrange interrupts to terminate */
208
209     (void) initscr();           /* initialize the curses library */
210     keypad(stdscr, TRUE);       /* enable keyboard mapping */
211     (void) nonl();              /* tell curses not to do NL->CR/NL on output */
212     (void) cbreak();            /* take input chars one at a time, no wait for \n */
213     (void) noecho();            /* don't echo input */
214     scrollok(stdscr, TRUE);
215
216     while (test_loops-- > 0) {
217         if (test_normal)
218             run_test(FALSE);
219         if (test_optimize)
220             run_test(TRUE);
221     }
222
223     cleanup();                  /* we're done */
224     ExitProgram(EXIT_SUCCESS);
225 }
226 /* hashtest.c ends here */