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