1 /** Function pointer tests.
2 
3     type: bool, char, int, long
4  */
5 #include <testfwk.h>
6 
7 #ifdef __SDCC
8 #pragma std_sdcc99
9 #endif
10 
11 #include <stdbool.h>
12 
13 #define TYPE_{type}
14 
15 /* Must use a typedef as there is no way of adding the code modifier
16    on the z80.
17 */
18 typedef void (*NOARGFUNPTR)(void);
19 typedef void (*ONEARGFUNPTR)({type}) __reentrant;
20 typedef long int (*FOURARGFUNPTR)(char, char, long int, long int) __reentrant;
21 typedef {type} (*TYPEFUNPTR)({type}, {type}) __reentrant;
22 
23 int count;
24 FOURARGFUNPTR fafp;
25 TYPEFUNPTR tfp;
26 
27 void
incCount(void)28 incCount(void)
29 {
30   count++;
31 }
32 
33 void
34 incBy({type} a) __reentrant
35 {
36   count += a;
37 }
38 
f6(char a,char b,long int c,long int d)39 long int f6(char a, char b, long int c, long int d) __reentrant
40 {
41   switch (a)
42     {
43     case 0: return a;
44     case 1: return b;
45     case 2: return c;
46     case 3: return d;
47     }
48   return 0;
49 }
50 
51 
52 void
callViaPtr(NOARGFUNPTR fptr)53 callViaPtr(NOARGFUNPTR fptr)
54 {
55   (*fptr)();
56 }
57 
58 void
59 callViaPtr2(ONEARGFUNPTR fptr, {type} arg)
60 {
61   (*fptr)(arg);
62 }
63 
64 void
callViaPtr3(void (* fptr)(void))65 callViaPtr3(void (*fptr)(void))
66 {
67   (*fptr)();
68 }
69 
70 void
callViaPtrAnsi(NOARGFUNPTR fptr)71 callViaPtrAnsi(NOARGFUNPTR fptr)
72 {
73   fptr();
74 }
75 
76 void
77 callViaPtr2Ansi(ONEARGFUNPTR fptr, {type} arg)
78 {
79   fptr(arg);
80 }
81 
82 void
callViaPtr3Ansi(void (* fptr)(void))83 callViaPtr3Ansi(void (*fptr)(void))
84 {
85   fptr();
86 }
87 
88 {type} f_ret({type} arg1, {type} arg2) __reentrant
89 {
90   {type} local;
91   local = !arg1;
92   return (local & arg2);
93 }
94 
95 
96 void
testFunPtr(void)97 testFunPtr(void)
98 {
99 #if !defined(__SDCC_pdk14) // Lack of memory
100   fafp = f6;
101 
102   ASSERT(count == 0);
103   callViaPtr(incCount);
104   ASSERT(count == 1);
105   callViaPtr2(incBy, 7);
106   ASSERT(count == 8 || count == 2);
107 
108   ASSERT((*fafp)(0, 0x55, 0x12345678, 0x9abcdef0) == 0);
109   ASSERT((*fafp)(1, 0x55, 0x12345678, 0x9abcdef0) == 0x55);
110   ASSERT((*fafp)(2, 0x55, 0x12345678, 0x9abcdef0) == 0x12345678);
111   ASSERT((*fafp)(3, 0x55, 0x12345678, 0x9abcdef0) == 0x9abcdef0);
112 #endif
113 }
114 
115 void
testFunPtrAnsi(void)116 testFunPtrAnsi(void)
117 {
118 #if !defined(__SDCC_pdk14) // Lack of memory
119   fafp = f6;
120 
121   count = 0;
122   callViaPtrAnsi(incCount);
123   ASSERT(count == 1);
124   callViaPtr2Ansi(incBy, 7);
125   ASSERT(count == 8 || count == 2);
126 
127   ASSERT(fafp(0, 0x55, 0x12345678, 0x9abcdef0) == 0);
128   ASSERT(fafp(1, 0x55, 0x12345678, 0x9abcdef0) == 0x55);
129   ASSERT(fafp(2, 0x55, 0x12345678, 0x9abcdef0) == 0x12345678);
130   ASSERT(fafp(3, 0x55, 0x12345678, 0x9abcdef0) == 0x9abcdef0);
131 #endif
132 }
133 
134 void
testFunPtrReturn(void)135 testFunPtrReturn(void)
136 {
137 #if !defined(__SDCC_pdk14) // Lack of memory
138 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
139   tfp = f_ret;
140 
141   ASSERT(tfp(0, 0) == 0);
142   ASSERT(tfp(0, 1) == 1);
143   ASSERT(tfp(1, 0) == 0);
144   ASSERT(tfp(1, 1) == 0);
145 #endif
146 #endif
147 }
148 
149