diff interps/c-intercal/src/ick_ec.h @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/c-intercal/src/ick_ec.h	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,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
+;