Mercurial > repo
comparison interps/c-intercal/inst/include/ick-0.29/ick_ec.h @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 /***************************************************************************** | |
2 | |
3 NAME | |
4 ick_ec.h -- external call support between C and C-INTERCAL | |
5 | |
6 LICENSE TERMS | |
7 Copyright (C) 2008 Alex Smith | |
8 | |
9 This program is free software; you can redistribute it and/or modify | |
10 it under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; either version 2 of the License, or | |
12 (at your option) any later version. | |
13 | |
14 This program is distributed in the hope that it will be useful, | |
15 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 GNU General Public License for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with this program; if not, write to the Free Software | |
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | |
23 ***************************************************************************/ | |
24 | |
25 /* The external calls to C work via ICK_EC_FUNCs; whenever a suckpoint is | |
26 encountered, all ICK_EC_FUNCs are run with ick_global_checkmode set to 1, | |
27 and when a NEXT is called but finds no target in the INTERCAL program, all | |
28 ICK_EC_FUNCs are run with ick_global_checkmode set to 2. COME FROMs and | |
29 NEXT FROMs don't steal control immediately (they know where to steal | |
30 control from using ick_global_linelabel), but instead set ick_global_goto | |
31 to a 'high' line label (one of the internal ones above 65536 which are | |
32 allocated for this sort of purpose, and inside the preprocessor) or error | |
33 if it's set nonzero already. After verifying that exactly one COME or NEXT | |
34 FROM is involved, the INTERCAL program will NEXT to the high line label | |
35 (whether it leaves a NEXT stack entry will depend on whether COME FROM or | |
36 NEXT FROM was used, which is communicated by a NEXT FROM setting the | |
37 checkmode to 3, which is identical to 1 in all other respects). | |
38 | |
39 To prevent this process running the program out of stack space (which would | |
40 happen with a naive implementation if there were many COME FROMs from | |
41 inside the C program back to inside the C program), all transitions but | |
42 NEXTs are done indirectly, by jumping back inside a relevant invocation of | |
43 ick_dogoto and changing its targets. (So effectively, to GOTO a particular | |
44 destination, you go back in time to the last time you NEXTed - or to | |
45 implement a FORGET, the last-but-n-time you NEXTed - and redo it with a | |
46 different target.) | |
47 */ | |
48 | |
49 #if ICK_HAVE_STDINT_H+1 == 2 | |
50 #include <stdint.h> | |
51 #else | |
52 /* Ensure that uint32_t, etc, aren't implemented as compatibility macros | |
53 so that we can implement them as typedefs. */ | |
54 #undef uint32_t | |
55 #undef uint16_t | |
56 typedef unsigned int uint32_t; | |
57 typedef unsigned short uint16_t; | |
58 #endif | |
59 | |
60 #ifndef ICK_ABCESS_H_INCLUDED | |
61 typedef unsigned short ick_type16; | |
62 typedef unsigned int ick_type32; | |
63 #endif | |
64 | |
65 #define ICK_EC_FUNC_START(id) \ | |
66 ICK_EC_PP_0(id) \ | |
67 void id(void) \ | |
68 { \ | |
69 void* ick_local_createdata = \ | |
70 ick_global_createdata; \ | |
71 int ick_local_checkmode = ick_global_checkmode; \ | |
72 if(ick_global_checkmode==6) \ | |
73 { \ | |
74 goto ick_l6_ICK_EC_PP_6; \ | |
75 } \ | |
76 if(ick_global_checkmode==2) \ | |
77 { \ | |
78 goto ick_l2_ICK_EC_PP_2; \ | |
79 } \ | |
80 else if(ick_global_checkmode==1 || \ | |
81 ick_global_checkmode==3) \ | |
82 { \ | |
83 goto ick_l1_ICK_EC_PP_1; \ | |
84 } \ | |
85 ick_local_checkmode=ick_global_checkmode=0; | |
86 | |
87 #define ick_linelabel(expr) ick_labeledblock(expr,0) | |
88 | |
89 #define ick_labeledblock(expr,block) \ | |
90 do { \ | |
91 if(0) \ | |
92 { \ | |
93 ick_l2_ICK_EC_PP_2: ; \ | |
94 if(ick_global_linelabel != (expr) || (expr) > 65535) \ | |
95 goto ick_l2_ICK_EC_PP_2; \ | |
96 ick_global_checkmode = 0; \ | |
97 } \ | |
98 block ; \ | |
99 ick_checksuckpoint(expr); \ | |
100 } \ | |
101 while(0) | |
102 | |
103 #define ick_linelabelnosp(expr) \ | |
104 do { \ | |
105 if(0) \ | |
106 { \ | |
107 ick_l2_ICK_EC_PP_2: ; \ | |
108 if(ick_global_linelabel != (expr) || (expr) > 65535) \ | |
109 goto ick_l2_ICK_EC_PP_2; \ | |
110 ick_global_checkmode = 0; \ | |
111 } \ | |
112 } \ | |
113 while(0) | |
114 | |
115 #define ick_forget(amount) \ | |
116 do { \ | |
117 ick_scheduleforget(amount); \ | |
118 ick_dogoto(ICK_EC_PP_3,-1,0); \ | |
119 ick_lose(ICK_IE778, -1, (char*) NULL); \ | |
120 return; \ | |
121 ick_l2_ICK_EC_PP_2: ; \ | |
122 if(ick_global_linelabel != ICK_EC_PP_3) \ | |
123 goto ick_l2_ICK_EC_PP_2; \ | |
124 ick_global_checkmode = 0; \ | |
125 } while(0) | |
126 | |
127 | |
128 #define ick_startup(block) \ | |
129 if(0) \ | |
130 { \ | |
131 ick_l6_ICK_EC_PP_6: \ | |
132 ick_global_checkmode=0; \ | |
133 block ; \ | |
134 ick_global_checkmode=ick_local_checkmode; \ | |
135 goto ick_l6_ICK_EC_PP_6; \ | |
136 } | |
137 | |
138 #define ick_comefrom(expr) \ | |
139 if(0) \ | |
140 { \ | |
141 ick_l1_ICK_EC_PP_1: ; \ | |
142 if(ick_global_linelabel == (expr) && (expr) <= 65535) \ | |
143 { \ | |
144 if(ick_global_goto) ick_lose(ICK_IE555, -1, (char*)0); \ | |
145 ick_global_goto = ICK_EC_PP_3; \ | |
146 } \ | |
147 goto ick_l1_ICK_EC_PP_1; \ | |
148 ick_l2_ICK_EC_PP_2: ; \ | |
149 if(ick_global_linelabel != ICK_EC_PP_3) \ | |
150 goto ick_l2_ICK_EC_PP_2; \ | |
151 ick_global_checkmode = 0; \ | |
152 } | |
153 | |
154 #define ick_comefromif(expr,condition) \ | |
155 ick_docomefromif(expr,-1,condition) | |
156 | |
157 #define ick_docomefromif(expr,lbl,condition) \ | |
158 if(0) \ | |
159 { \ | |
160 ick_l1_ICK_EC_PP_1: ; \ | |
161 if(ick_global_linelabel == (expr) && (expr) <= 65535) \ | |
162 if(condition) \ | |
163 { \ | |
164 if(ick_global_goto) ick_lose(ICK_IE555, lbl, (char*)0); \ | |
165 ick_global_goto = ICK_EC_PP_3; \ | |
166 } \ | |
167 goto ick_l1_ICK_EC_PP_1; \ | |
168 ick_l2_ICK_EC_PP_2: ; \ | |
169 if(ick_global_linelabel != ICK_EC_PP_3) \ | |
170 goto ick_l2_ICK_EC_PP_2; \ | |
171 ick_global_checkmode = 0; \ | |
172 } | |
173 | |
174 #define ick_nextfrom(expr) \ | |
175 if(0) \ | |
176 { \ | |
177 ick_l1_ICK_EC_PP_1: ; \ | |
178 if(ick_global_linelabel == (expr) && (expr) <= 65535) \ | |
179 { \ | |
180 if(ick_global_goto) ick_lose(ICK_IE555, -1, (char*)0); \ | |
181 ick_global_goto = ICK_EC_PP_3; \ | |
182 ick_global_checkmode = 3; \ | |
183 } \ | |
184 goto ick_l1_ICK_EC_PP_1; \ | |
185 ick_l2_ICK_EC_PP_2: ; \ | |
186 if(ick_global_linelabel != ICK_EC_PP_3) \ | |
187 goto ick_l2_ICK_EC_PP_2; \ | |
188 ick_global_checkmode = 0; \ | |
189 } | |
190 | |
191 #define ick_nextfromif(expr,condition) \ | |
192 ick_donextfromif(expr,-1,condition) | |
193 | |
194 #define ick_donextfromif(expr,lbl,condition) \ | |
195 if(0) \ | |
196 { \ | |
197 ick_l1_ICK_EC_PP_1: ; \ | |
198 if(ick_global_linelabel == (expr) && (expr) <= 65535) \ | |
199 if(condition) \ | |
200 { \ | |
201 if(ick_global_goto) ick_lose(ICK_IE555, lbl, (char*)0); \ | |
202 ick_global_goto = ICK_EC_PP_3; \ | |
203 ick_global_checkmode = 3; \ | |
204 } \ | |
205 goto ick_l1_ICK_EC_PP_1; \ | |
206 ick_l2_ICK_EC_PP_2: ; \ | |
207 if(ick_global_linelabel != ICK_EC_PP_3) \ | |
208 goto ick_l2_ICK_EC_PP_2; \ | |
209 ick_global_checkmode = 0; \ | |
210 } | |
211 | |
212 | |
213 #define ICK_EC_FUNC_END \ | |
214 if(ick_local_checkmode) ick_resume(1); \ | |
215 ick_l1_ICK_EC_PP_1: ; \ | |
216 ick_l6_ICK_EC_PP_6: ; \ | |
217 ick_l2_ICK_EC_PP_2: return; \ | |
218 } | |
219 | |
220 #define ick_next(label) do{ \ | |
221 if((label)<=65535) \ | |
222 ick_dogoto((label),-1,1); \ | |
223 } while(0) | |
224 | |
225 #define ick_goto(label) do{ \ | |
226 if((label)<=65535) \ | |
227 ick_dogoto((label),-1,0); \ | |
228 } while(0) | |
229 | |
230 #define ick_resume(amount) ick_doresume((amount),-1) | |
231 | |
232 #define ick_return_or_resume() do{ \ | |
233 if(ick_local_checkmode) ick_doresume(1,-1); \ | |
234 return; \ | |
235 } while(0) | |
236 | |
237 /*@maynotreturn@*/ void ick_dogoto(unsigned long, int, int); | |
238 void ick_scheduleforget(unsigned short); | |
239 /*@noreturn@*/ void ick_doresume(unsigned short, int); | |
240 /*@maynotreturn@*/ void ick_checksuckpoint(unsigned long); | |
241 void ick_runstartups(void); | |
242 /*@maynotreturn@*/ uint32_t ick_dounop(char*, uint32_t, uint32_t, int, | |
243 unsigned long, unsigned long, unsigned long, | |
244 ick_type32(*)(ick_type32), | |
245 ick_type32(*)(ick_type32), | |
246 ick_type32(*)(ick_type32), | |
247 void(*)(ick_type32, void(*)()), | |
248 void(*)(ick_type32, void(*)()), | |
249 void(*)(ick_type32, void(*)()), | |
250 /*@observer@*/ const char*); | |
251 | |
252 void ick_allecfuncs(void); /* in generated program */ | |
253 | |
254 extern int ick_global_checkmode; | |
255 extern unsigned long ick_global_linelabel; | |
256 extern unsigned long ick_global_goto; | |
257 extern void* ick_global_createdata; | |
258 | |
259 /* Variables. */ | |
260 typedef struct ick_ec_var_tag | |
261 { | |
262 int ick_ec_vartype; | |
263 int ick_ec_extername; | |
264 int ick_ec_intername; | |
265 } ick_ec_var; | |
266 | |
267 extern ick_ec_var ick_ec_vars[]; | |
268 | |
269 #define ICK_EC_VARS_END 5 | |
270 | |
271 uint16_t ick_getonespot(unsigned short); | |
272 void ick_setonespot(unsigned short, uint16_t); | |
273 uint32_t ick_gettwospot(unsigned short); | |
274 void ick_settwospot(unsigned short, uint32_t); | |
275 | |
276 void ick_create(const char*, unsigned long); | |
277 | |
278 /* For accessing the arguments to an ick_created command */ | |
279 int ick_c_i_width(int); | |
280 int ick_c_i_isarray(int); | |
281 unsigned short ick_c_i_varnumber(int); | |
282 uint32_t ick_c_i_value(int); | |
283 /* These require -a to work */ | |
284 uint32_t ick_c_i_getvalue(int); | |
285 void ick_c_i_setvalue(int, uint32_t); | |
286 | |
287 #define ick_c_width(a) ick_c_i_width((ick_global_createdata=ick_local_createdata,(a))) | |
288 #define ick_c_isarray(a) ick_c_i_isarray((ick_global_createdata=ick_local_createdata,(a))) | |
289 #define ick_c_varnumber(a) ick_c_i_varnumber((ick_global_createdata=ick_local_createdata,(a))) | |
290 #define ick_c_value(a) ick_c_i_value((ick_global_createdata=ick_local_createdata,(a))) | |
291 #define ick_c_getvalue(a) ick_c_i_getvalue((ick_global_createdata=ick_local_createdata,(a))) | |
292 #define ick_c_setvalue(a,n) ick_c_i_setvalue((ick_global_createdata=ick_local_createdata,(a)),(n)) | |
293 | |
294 /* Fragments of ick_lose.h, that don't impinge on unmangled namespace. */ | |
295 #define ICK_IE555 "555 FLOW DIAGRAM IS EXCESSIVELY CONNECTED\n\ | |
296 ON THE WAY TO %d\n" | |
297 #define ICK_IE778 "778 UNEXPLAINED COMPILER BUG\n\ | |
298 ON THE WAY TO %d\n" | |
299 | |
300 extern void /*@noreturn@*/ ick_lose(const char *m, int n, /*@null@*/ const char *s) | |
301 #ifdef __GNUC__ | |
302 __attribute__ ((noreturn)) | |
303 #endif | |
304 ; |