1 /*
2 
3   Copyright (c) 2006-2013 uim Project https://github.com/uim/uim
4 
5   All rights reserved.
6 
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
10 
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in the
15      documentation and/or other materials provided with the distribution.
16   3. Neither the name of authors nor the names of its contributors
17      may be used to endorse or promote products derived from this software
18      without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30   SUCH DAMAGE.
31 
32 */
33 
34 #include <assert.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 
38 #include "uim.h"
39 #include "uim-scm.h"
40 
41 #define TEST_STACK_START(protected, actual)				     \
42   fprintf(stderr, "stack growth dir = %s, protected = %p, actual = %p\n",    \
43 	  (stack_dir == STACK_GROWS_DOWNWARDS) ? "downwards" : "upwards",    \
44 	  protected, actual);						     \
45   if (stack_dir == STACK_GROWS_DOWNWARDS) {				     \
46       assert(actual <= protected);					     \
47   } else {								     \
48       assert(actual >= protected);					     \
49   }
50 
51 enum stack_growth_dir {
52   STACK_GROWS_DOWNWARDS,
53   STACK_GROWS_UPWARDS
54 };
55 
56 
57 static enum stack_growth_dir stack_dir;
58 static void *volatile stack_start_protected;
59 static void *volatile stack_start_actual;
60 
61 static void (*volatile fvv_internal)(void);
62 static int  (*volatile fiv_internal)(void);
63 static void (*volatile fvi_internal)(int);
64 static int  (*volatile fii_internal)(int);
65 static uim_lisp *(*volatile fspv_internal)(void);
66 static uim_lisp *(*volatile fspsp_internal)(uim_lisp *dummy);
67 
68 static enum stack_growth_dir probe_stack_growth_dir(void);
69 static enum stack_growth_dir probe_stack_growth_dir2(void *upper_frame);
70 static void fvv(void);
71 static int  fiv(void);
72 static void fvi(int dummy);
73 static int  fii(int dummy);
74 static uim_lisp *fspv(void);
75 static uim_lisp *fspsp(uim_lisp *dummy);
76 
77 
78 static enum stack_growth_dir
probe_stack_growth_dir(void)79 probe_stack_growth_dir(void)
80 {
81   int stack_start;
82 
83   return probe_stack_growth_dir2(&stack_start);
84 }
85 
86 static enum stack_growth_dir
probe_stack_growth_dir2(void * upper_frame)87 probe_stack_growth_dir2(void *upper_frame)
88 {
89   int stack_start;
90 
91   if ((void *)&stack_start < upper_frame)
92     return STACK_GROWS_DOWNWARDS;
93   else
94     return STACK_GROWS_UPWARDS;
95 }
96 
97 static void
fvv(void)98 fvv(void)
99 {
100   uim_lisp stack_start;
101 
102   stack_start_actual = &stack_start;
103 }
104 
105 static int
fiv(void)106 fiv(void)
107 {
108   uim_lisp stack_start;
109 
110   stack_start_actual = &stack_start;
111   return 0;
112 }
113 
114 static void
fvi(int dummy)115 fvi(int dummy)
116 {
117   uim_lisp stack_start;
118 
119   stack_start_actual = &stack_start;
120 }
121 
122 static int
fii(int dummy)123 fii(int dummy)
124 {
125   uim_lisp stack_start;
126 
127   stack_start_actual = &stack_start;
128   return 0;
129 }
130 
131 static uim_lisp *
fspv(void)132 fspv(void)
133 {
134   uim_lisp stack_start;
135 
136   stack_start_actual = &stack_start;
137   return NULL;
138 }
139 
140 static uim_lisp *
fspsp(uim_lisp * dummy)141 fspsp(uim_lisp *dummy)
142 {
143   uim_lisp stack_start;
144 
145   stack_start_actual = &stack_start;
146   return dummy;
147 }
148 
149 int
main(void)150 main(void)
151 {
152   uim_init();
153 
154   stack_dir = probe_stack_growth_dir();
155   fvv_internal = fvv;
156   fiv_internal = fiv;
157   fvi_internal = fvi;
158   fii_internal = fii;
159   fspv_internal = fspv;
160   fspsp_internal = fspsp;
161 
162   stack_start_protected = uim_scm_gc_current_stack();
163   uim_scm_gc_protect_stack(stack_start_protected);
164   (*fvv_internal)();
165   uim_scm_gc_unprotect_stack(stack_start_protected);
166   TEST_STACK_START(stack_start_protected, stack_start_actual);
167 
168   stack_start_protected = uim_scm_gc_current_stack();
169   uim_scm_gc_protect_stack(stack_start_protected);
170   (*fiv_internal)();
171   uim_scm_gc_unprotect_stack(stack_start_protected);
172   TEST_STACK_START(stack_start_protected, stack_start_actual);
173 
174   stack_start_protected = uim_scm_gc_current_stack();
175   uim_scm_gc_protect_stack(stack_start_protected);
176   (*fvi_internal)(0);
177   uim_scm_gc_unprotect_stack(stack_start_protected);
178   TEST_STACK_START(stack_start_protected, stack_start_actual);
179 
180   stack_start_protected = uim_scm_gc_current_stack();
181   uim_scm_gc_protect_stack(stack_start_protected);
182   (*fii_internal)(0);
183   uim_scm_gc_unprotect_stack(stack_start_protected);
184   TEST_STACK_START(stack_start_protected, stack_start_actual);
185 
186   stack_start_protected = uim_scm_gc_current_stack();
187   uim_scm_gc_protect_stack(stack_start_protected);
188   (*fspv_internal)();
189   uim_scm_gc_unprotect_stack(stack_start_protected);
190   TEST_STACK_START(stack_start_protected, stack_start_actual);
191 
192   stack_start_protected = uim_scm_gc_current_stack();
193   uim_scm_gc_protect_stack(stack_start_protected);
194   (*fspsp_internal)((uim_lisp *)NULL);
195   uim_scm_gc_unprotect_stack(stack_start_protected);
196   TEST_STACK_START(stack_start_protected, stack_start_actual);
197 
198   uim_quit();
199 
200   fprintf(stderr, "tests succeeded.\n");
201 
202   return EXIT_SUCCESS;
203 }
204