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 ;