File: ick_ec.h

package info (click to toggle)
intercal 30:0.30-2
  • links: PTS
  • area: main
  • in suites: bullseye, sid
  • size: 4,044 kB
  • sloc: ansic: 8,936; sh: 1,274; yacc: 1,073; lex: 518; lisp: 460; makefile: 435; perl: 295
file content (304 lines) | stat: -rw-r--r-- 10,166 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*****************************************************************************

NAME
    ick_ec.h -- external call support between C and C-INTERCAL

LICENSE TERMS
    Copyright (C) 2008 Alex Smith

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

/* The external calls to C work via ICK_EC_FUNCs; whenever a suckpoint is
   encountered, all ICK_EC_FUNCs are run with ick_global_checkmode set to 1,
   and when a NEXT is called but finds no target in the INTERCAL program, all
   ICK_EC_FUNCs are run with ick_global_checkmode set to 2. COME FROMs and
   NEXT FROMs don't steal control immediately (they know where to steal
   control from using ick_global_linelabel), but instead set ick_global_goto
   to a 'high' line label (one of the internal ones above 65536 which are
   allocated for this sort of purpose, and inside the preprocessor) or error
   if it's set nonzero already. After verifying that exactly one COME or NEXT
   FROM is involved, the INTERCAL program will NEXT to the high line label
   (whether it leaves a NEXT stack entry will depend on whether COME FROM or
   NEXT FROM was used, which is communicated by a NEXT FROM setting the
   checkmode to 3, which is identical to 1 in all other respects).

   To prevent this process running the program out of stack space (which would
   happen with a naive implementation if there were many COME FROMs from
   inside the C program back to inside the C program), all transitions but
   NEXTs are done indirectly, by jumping back inside a relevant invocation of
   ick_dogoto and changing its targets. (So effectively, to GOTO a particular
   destination, you go back in time to the last time you NEXTed - or to
   implement a FORGET, the last-but-n-time you NEXTed - and redo it with a
   different target.)
*/

#if ICK_HAVE_STDINT_H+1 == 2
#include <stdint.h>
#else
/* Ensure that uint32_t, etc, aren't implemented as compatibility macros
   so that we can implement them as typedefs. */
#undef uint32_t
#undef uint16_t
typedef unsigned int   uint32_t;
typedef unsigned short uint16_t;
#endif

#ifndef ICK_ABCESS_H_INCLUDED
typedef unsigned short ick_type16;
typedef unsigned int   ick_type32;
#endif

#define ICK_EC_FUNC_START(id)			  \
ICK_EC_PP_0(id)  	  		          \
void id(void)					  \
{						  \
  void* ick_local_createdata =			  \
    ick_global_createdata;			  \
  int ick_local_checkmode = ick_global_checkmode; \
  if(ick_global_checkmode==6)			  \
  {						  \
    goto ick_l6_ICK_EC_PP_6;			  \
  }						  \
  if(ick_global_checkmode==2)			  \
  {						  \
    goto ick_l2_ICK_EC_PP_2;			  \
  }						  \
  else if(ick_global_checkmode==1 ||		  \
	  ick_global_checkmode==3)		  \
  {						  \
    goto ick_l1_ICK_EC_PP_1;			  \
  }						  \
  ick_local_checkmode=ick_global_checkmode=0;

#define ick_linelabel(expr) ick_labeledblock(expr,0)

#define ick_labeledblock(expr,block)			    \
  do {							    \
    if(0)						    \
    {							    \
    ick_l2_ICK_EC_PP_2: ;				    \
      if(ick_global_linelabel != (expr) || (expr) > 65535)  \
	goto ick_l2_ICK_EC_PP_2;			    \
      ick_global_checkmode = 0;				    \
    }							    \
    block ;						    \
    ick_checksuckpoint(expr);				    \
  }							    \
  while(0)

#define ick_linelabelnosp(expr)				    \
  do {							    \
    if(0)						    \
    {							    \
    ick_l2_ICK_EC_PP_2: ;				    \
      if(ick_global_linelabel != (expr) || (expr) > 65535)  \
	goto ick_l2_ICK_EC_PP_2;			    \
      ick_global_checkmode = 0;				    \
    }							    \
  }							    \
  while(0)

#define ick_forget(amount)			\
  do {						\
    ick_scheduleforget(amount);			\
    ick_dogoto(ICK_EC_PP_3,-1,0);		\
    ick_lose(ICK_IE778, -1, (char*) NULL);	\
    return;					\
  ick_l2_ICK_EC_PP_2: ;				\
    if(ick_global_linelabel != ICK_EC_PP_3)	\
      goto ick_l2_ICK_EC_PP_2;			\
    ick_global_checkmode = 0;			\
  } while(0)


#define ick_startup(block)			\
  if(0)						\
  {						\
  ick_l6_ICK_EC_PP_6:				\
    ick_global_checkmode=0;			\
    block ;					\
    ick_global_checkmode=ick_local_checkmode;	\
    goto ick_l6_ICK_EC_PP_6;			\
  }

#define ick_comefrom(expr)					 \
  if(0)								 \
  {								 \
  ick_l1_ICK_EC_PP_1: ;						 \
    if(ick_global_linelabel == (expr) && (expr) <= 65535)	 \
    {								 \
      if(ick_global_goto) ick_lose(ICK_IE555, -1, (char*)0);	 \
      ick_global_goto = ICK_EC_PP_3;				 \
    }								 \
    goto ick_l1_ICK_EC_PP_1;					 \
  ick_l2_ICK_EC_PP_2: ;						 \
    if(ick_global_linelabel != ICK_EC_PP_3)			 \
      goto ick_l2_ICK_EC_PP_2;					 \
    ick_global_checkmode = 0;					 \
  }

#define ick_comefromif(expr,condition) \
  ick_docomefromif(expr,-1,condition)

#define ick_docomefromif(expr,lbl,condition)	                 \
  if(0)								 \
  {								 \
  ick_l1_ICK_EC_PP_1: ;						 \
    if(ick_global_linelabel == (expr) && (expr) <= 65535)	 \
      if(condition)						 \
      {								 \
	if(ick_global_goto) ick_lose(ICK_IE555, lbl, (char*)0);	 \
	ick_global_goto = ICK_EC_PP_3;				 \
      }								 \
    goto ick_l1_ICK_EC_PP_1;					 \
  ick_l2_ICK_EC_PP_2: ;						 \
    if(ick_global_linelabel != ICK_EC_PP_3)			 \
      goto ick_l2_ICK_EC_PP_2;					 \
    ick_global_checkmode = 0;					 \
  }

#define ick_nextfrom(expr)					 \
  if(0)								 \
  {								 \
  ick_l1_ICK_EC_PP_1: ;						 \
    if(ick_global_linelabel == (expr) && (expr) <= 65535)	 \
    {								 \
      if(ick_global_goto) ick_lose(ICK_IE555, -1, (char*)0);	 \
      ick_global_goto = ICK_EC_PP_3;				 \
      ick_global_checkmode = 3;					 \
    }								 \
    goto ick_l1_ICK_EC_PP_1;					 \
  ick_l2_ICK_EC_PP_2: ;						 \
    if(ick_global_linelabel != ICK_EC_PP_3)			 \
      goto ick_l2_ICK_EC_PP_2;					 \
    ick_global_checkmode = 0;					 \
  }

#define ick_nextfromif(expr,condition) \
  ick_donextfromif(expr,-1,condition)

#define ick_donextfromif(expr,lbl,condition)	                 \
  if(0)								 \
  {								 \
  ick_l1_ICK_EC_PP_1: ;						 \
    if(ick_global_linelabel == (expr) && (expr) <= 65535)	 \
      if(condition)						 \
      {								 \
	if(ick_global_goto) ick_lose(ICK_IE555, lbl, (char*)0);	 \
	ick_global_goto = ICK_EC_PP_3;				 \
	ick_global_checkmode = 3;				 \
      }								 \
    goto ick_l1_ICK_EC_PP_1;					 \
  ick_l2_ICK_EC_PP_2: ;						 \
    if(ick_global_linelabel != ICK_EC_PP_3)			 \
      goto ick_l2_ICK_EC_PP_2;					 \
    ick_global_checkmode = 0;					 \
  }


#define ICK_EC_FUNC_END				\
  if(ick_local_checkmode) ick_resume(1);	\
ick_l1_ICK_EC_PP_1: ;				\
ick_l6_ICK_EC_PP_6: ;				\
ick_l2_ICK_EC_PP_2: return;			\
}

#define ick_next(label) do{			\
    if((label)<=65535)				\
      ick_dogoto((label),-1,1);			\
  } while(0)

#define ick_goto(label) do{			\
    if((label)<=65535)				\
      ick_dogoto((label),-1,0);			\
  } while(0)

#define ick_resume(amount) ick_doresume((amount),-1)

#define ick_return_or_resume() do{		\
    if(ick_local_checkmode) ick_doresume(1,-1); \
    return;					\
  } while(0)

/*@maynotreturn@*/ void ick_dogoto(unsigned long, int, int);
void ick_scheduleforget(unsigned short);
/*@noreturn@*/ void ick_doresume(unsigned short, int);
/*@maynotreturn@*/ void ick_checksuckpoint(unsigned long);
void ick_runstartups(void);
/*@maynotreturn@*/ uint32_t ick_dounop(char*, uint32_t, uint32_t, int,
				       unsigned long, unsigned long, unsigned long,
				       ick_type32(*)(ick_type32),
				       ick_type32(*)(ick_type32),
				       ick_type32(*)(ick_type32),
				       void(*)(ick_type32, void(*)()),
				       void(*)(ick_type32, void(*)()),
				       void(*)(ick_type32, void(*)()),
			/*@observer@*/ const char*);

void ick_allecfuncs(void); /* in generated program */

extern int ick_global_checkmode;
extern unsigned long ick_global_linelabel;
extern unsigned long ick_global_goto;
extern void* ick_global_createdata;

/* Variables. */
typedef struct ick_ec_var_tag
{
  int ick_ec_vartype;
  int ick_ec_extername;
  int ick_ec_intername;
} ick_ec_var;

extern ick_ec_var ick_ec_vars[];

#define ICK_EC_VARS_END 5

uint16_t ick_getonespot(unsigned short);
void ick_setonespot(unsigned short, uint16_t);
uint32_t ick_gettwospot(unsigned short);
void ick_settwospot(unsigned short, uint32_t);

void ick_create(const char*, unsigned long);

/* For accessing the arguments to an ick_created command */
int ick_c_i_width(int);
int ick_c_i_isarray(int);
unsigned short ick_c_i_varnumber(int);
uint32_t ick_c_i_value(int);
/* These require -a to work */
uint32_t ick_c_i_getvalue(int);
void ick_c_i_setvalue(int, uint32_t);

#define ick_c_width(a) ick_c_i_width((ick_global_createdata=ick_local_createdata,(a)))
#define ick_c_isarray(a) ick_c_i_isarray((ick_global_createdata=ick_local_createdata,(a)))
#define ick_c_varnumber(a) ick_c_i_varnumber((ick_global_createdata=ick_local_createdata,(a)))
#define ick_c_value(a) ick_c_i_value((ick_global_createdata=ick_local_createdata,(a)))
#define ick_c_getvalue(a) ick_c_i_getvalue((ick_global_createdata=ick_local_createdata,(a)))
#define ick_c_setvalue(a,n) ick_c_i_setvalue((ick_global_createdata=ick_local_createdata,(a)),(n))

/* Fragments of ick_lose.h, that don't impinge on unmangled namespace. */
#define ICK_IE555 "555 FLOW DIAGRAM IS EXCESSIVELY CONNECTED\n\
	ON THE WAY TO %d\n"
#define ICK_IE778 "778 UNEXPLAINED COMPILER BUG\n\
	ON THE WAY TO %d\n"

extern void /*@noreturn@*/ ick_lose(const char *m, int n, /*@null@*/ const char *s)
#ifdef __GNUC__
  __attribute__ ((noreturn))
#endif
;