* .version: bumped version to 2.4.7
[fw/sdcc] / support / regression / fwk / lib / testfwk.c
1 /** Test framework support functions.
2  */
3 #include <testfwk.h>
4 #include <stdarg.h>
5
6 #ifdef __ds390
7 #include <tinibios.h> /* main() must see the ISR declarations */
8 #endif
9
10 #if defined(PORT_HOST) || defined(SDCC_z80) || defined(SDCC_gbz80)
11 #define _REENTRANT
12 #else
13 #define _REENTRANT reentrant
14 #endif
15
16 #if defined(SDCC_mcs51)
17 /* until changed, isr's must have a prototype in the module containing main */
18 void T2_isr (void) interrupt 5;
19 #endif
20
21 /** Define this if the port's div or mod functions are broken.
22     A slow loop based method will be substituded.
23 */
24 //#define BROKEN_DIV_MOD                1
25
26 void _putchar(char c);
27 void _exitEmu(void);
28
29 #if BROKEN_DIV_MOD
30 int __div(int num, int denom)
31 {
32     int q = 0;
33     while (num >= denom) {
34         q++;
35         num -= denom;
36     }
37     return q;
38 }
39
40 int __mod(int num, int denom)
41 {
42     while (num >= denom) {
43         num -= denom;
44     }
45     return num;
46 }
47 #else
48 int __div(int num, int denom)
49 {
50     return num/denom;
51 }
52
53 int __mod(int num, int denom)
54 {
55     return num%denom;
56 }
57 #endif
58
59 static void _printn(int n) _REENTRANT
60 {
61     int rem;
62
63     if (n < 0) {
64         _putchar('-');
65         n = -n;
66     }
67
68     rem = __mod(n, 10);
69     if (rem != n) {
70         _printn(__div(n, 10));
71     }
72     _putchar('0' + rem);
73 }
74
75 void __printf(const char *szFormat, ...) REENTRANT
76 {
77     va_list ap;
78     va_start(ap, szFormat);
79
80     while (*szFormat) {
81         if (*szFormat == '%') {
82             switch (*++szFormat) {
83             case 's': {
84                 char *sz = va_arg(ap, char *);
85                 while (*sz) {
86                     _putchar(*sz++);
87                 }
88                 break;
89             }
90             case 'u': {
91                 int i = va_arg(ap, int);
92                 _printn(i);
93                 break;
94             }
95             case '%':
96                 _putchar('%');
97                 break;
98             default:
99                 break;
100             }
101         }
102         else {
103             _putchar(*szFormat);
104         }
105         szFormat++;
106     }
107     va_end(ap);
108 }
109
110 int __numTests;
111 int __numFailures;
112
113 void
114 __fail(const char *szMsg, const char *szCond, const char *szFile, int line)
115 {
116     __printf("--- FAIL: \"%s\" on %s at %s:%u\n", szMsg, szCond, szFile, line);
117     __numFailures++;
118 }
119
120 int
121 main(void)
122 {
123     TESTFUNP *cases;
124     int numCases = 0;
125
126     __printf("--- Running: %s\n", getSuiteName());
127
128     cases = suite();
129
130     while (*cases) {
131         __printf("Running %u\n", numCases);
132         (*cases)();
133         cases++;
134         numCases++;
135     }
136
137     __printf("--- Summary: %u/%u/%u: %u failed of %u tests in %u cases.\n",
138            __numFailures, __numTests, numCases,
139            __numFailures, __numTests, numCases
140            );
141
142     _exitEmu();
143
144     return 0;
145 }