./doc/ick.info-1
./doc/ick.info-2
./doc/ick.txt
+./etc/cfunge.patch
+./etc/cftoec.sh
+./etc/IFFI.spec
+./etc/IFFI/IFFI.h
+./etc/IFFI/IFFI.c
./etc/ctrlmfix.bat
./etc/ctrlmfix.sh
./etc/intercal.el
+./pit/explib/ecto_b98.c
./pit/explib/syslibc.doc
./pit/explib/compunex.c
./pit/explib/syslibc.c
./pit/unlambda.i
./pit/yapp.doc
./pit/yapp.i
-./src/autoscan.log
./src/abcess.h
./src/arrgghh.c
./src/atari.bin
all: bin/ick@EXEEXT@ bin/convickt@EXEEXT@ lib/libick.a lib/libickmt.a lib/libyuk.a lib/libickec.a ial
-ial: include/ick_ec.h include/fiddle.h include/abcess.h include/ick_lose.h include/yuk.h include/syslib.i include/syslib.3i include/syslib.4i include/syslib.5i include/syslib.6i include/syslib.7i lib/ick-wrap.c lib/pickwrap.c lib/coopt.sh lib/COPYING.txt lib/syslibc.c lib/compunex.c include/atari.bin include/baudot.bin include/ebcdic.bin include/latin1.bin
+ial: include/ick_ec.h include/fiddle.h include/abcess.h include/ick_lose.h include/yuk.h include/syslib.i include/syslib.3i include/syslib.4i include/syslib.5i include/syslib.6i include/syslib.7i lib/ick-wrap.c lib/pickwrap.c lib/coopt.sh lib/COPYING.txt lib/syslibc.c lib/compunex.c lib/ecto_b98.c include/atari.bin include/baudot.bin include/ebcdic.bin include/latin1.bin
include/ick_ec.h: src/ick_ec.h
-cp src/ick_ec.h include/ick_ec.h
-cp pit/explib/syslibc.c lib/syslibc.c
lib/compunex.c:pit/explib/compunex.c
-cp pit/explib/compunex.c lib/compunex.c
+lib/ecto_b98.c:pit/explib/ecto_b98.c
+ -cp pit/explib/ecto_b98.c lib/ecto_b98.c
include/atari.bin:src/atari.bin
-cp src/atari.bin include/atari.bin
cp lib/libickmt.a $(DESTDIR)$(libdir)
cp lib/libickec.a $(DESTDIR)$(libdir)
cp lib/libyuk.a $(DESTDIR)$(libdir)
+ sh -c 'cp lib/libick_ecto_b98.a $(DESTDIR)$(libdir) || true'
-mkdir -p $(DESTDIR)$(incdir)
cp src/ick_lose.h src/abcess.h src/fiddle.h src/yuk.h $(DESTDIR)$(incdir)
cp src/ick_ec.h $(DESTDIR)$(incdir)
rm -f $(DESTDIR)$(bindir)/ick@EXEEXT@ $(DESTDIR)$(libdir)/libick.a
rm -f $(DESTDIR)$(bindir)/convickt@EXEEXT@
rm -f $(DESTDIR)$(libdir)/libickmt.a $(DESTDIR)$(libdir)/libyuk.a
+ rm -f $(DESTDIR)$(libdir)/libickec.a $(DESTDIR)$(libdir)/libick_ecto_*.a
rm -f ${DESTDIR}${infodir}/ick.i*
rm -f $(DESTDIR)$(mandir)/man1/ick.1*
rm -f $(DESTDIR)$(mandir)/man1/convickt.1*
cleanick.sh --|(use .bat under command.com/cmd, and .sh under bash)
etc/ctrlmfix.sh --/
+etc/cftoec.sh -- script to convert cfunge to a library (see below)
+etc/IFFI* -- input to that script
+etc/cfunge.patch -- more input to that script
+etc/temp -- temporary directory used by that script
+
config.sh -- GNU Autoconf script that generates a makefile
from Makefile.in
ickspec.in -- Input to config.sh
lib/* -- Directory that holds library files after the build
pit/* -- sample INTERCAL code; see pit/CATALOG
+pit/explib/* -- source code for expansion libraries
+pit/lib/syslib.*i -- source code for the system libraries
HOW TO GET STARTED
compiler-specific data (like the names of data types and the syntax for
specifying the device type, fuses, and various commands).
+ NOTES ON THE C-INTERCAL / CFUNGE EXTERNAL CALLS SYSTEM
+
+Code is provided to allow linking of Funge-98 programs to INTERCAL programs;
+however, this requires a Funge-98 interpreter, which is not present in this
+distribution. Therefore, in order to do this, a Funge-98 interpreter must
+first be downloaded and prepared for use with C-INTERCAL. At present, code is
+only available for linking with 'cfunge', a Funge-98 interpreter written in
+C. You can get the latest sources for that interpreter from the Internet via
+the bzr version-control system by running this command:
+
+bzr branch http://rage.kuonet.org/~anmaster/bzr/cfunge
+
+Once you have the source code to cfunge, you can compile it into a library
+suitable for use by C-INTERCAL by changing to the /etc directory of the
+C-INTERCAL distribution, and running the cftoec.sh shell script in that
+directory with the path to the cfunge distribution as an argument. The script
+will make a copy of cfunge, modify it as required, and then place the
+resulting library (libick_ecto_b98.a) in the /lib directory of the C-INTERCAL
+distribution; installing (or reinstalling) C-INTERCAL after that will copy
+that library into the correct location in your filesystem.
+
+For information on actually using this system once you've set it up, consult
+the Revamped Manual.
+
LICENSING
C-INTERCAL is now distributed under the General Public License, except for the
--- /dev/null
+%fingerprint-spec 1.1
+%fprint:IFFI
+%url:http://example.com
+%desc:INTERCAL-like Foreign Function Interface
+%safe:false
+%begin-instrs
+#I name desc
+C comeFrom In markmode COME FROM the top of stack
+F forget FORGET NEXT stack entries equal to top of stack
+L label Use top of stack as a line label for this point
+M marker Marks points where the code can be entered from outside
+N next Try to NEXT to the line labelled with the top of stack
+R resume RESUME to the top-of-stackth NEXT stack entry
+X nextFrom In markmode NEXT FROM the top of stack
+%end
--- /dev/null
+/* -*- mode: C; coding: utf-8; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
+ *
+ * cfunge - a conformant Befunge93/98/08 interpreter in C.
+ * Copyright (C) 2008 Arvid Norlander <anmaster AT tele2 DOT se>
+ * 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 3 of the License, or
+ * (at the proxy's option) any later version. Arvid Norlander is a
+ * proxy who can decide which future versions of the GNU General Public
+ * License can be used.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "IFFI.h"
+#include "../../stack.h"
+#include "../../settings.h"
+#include "../../interpreter.h"
+
+static instructionPointer *iffiIP = NULL;
+
+// Communication functions with the ecto_b98 expansion library
+void ick_SaveIPPosDelta(struct ick_ipposdeltatype* ippd)
+{
+ ippd->ix = iffiIP->position.x;
+ ippd->iy = iffiIP->position.y;
+ ippd->dx = iffiIP->delta.x;
+ ippd->dy = iffiIP->delta.y;
+}
+
+void ick_RestoreIPPosDelta(struct ick_ipposdeltatype* ippd)
+{
+ iffiIP->position.x = ippd->ix;
+ iffiIP->position.y = ippd->iy;
+ iffiIP->delta.x = ippd->dx;
+ iffiIP->delta.y = ippd->dy;
+}
+
+void ick_InterpreterRun(void)
+{
+ if (!FungeSpaceCreate()) {
+ perror("Couldn't create funge space!?");
+ exit(EXIT_FAILURE);
+ }
+ FungeSpaceLoadString(ick_iffi_befungeString);
+ iffiIP = ipCreate();
+ if (iffiIP == NULL) {
+ perror("Couldn't create instruction pointer!?");
+ exit(EXIT_FAILURE);
+ }
+ {
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL)) {
+ perror("Couldn't get time of day?!");
+ exit(EXIT_FAILURE);
+ }
+ /* Set up randomness */
+ srandom(tv.tv_usec);
+ }
+ if(ick_printflow) SettingTraceLevel=9;
+ ick_InterpreterMainLoop();
+}
+
+void ick_iffi_InterpreterOneIteration(void)
+{
+ FUNGEDATATYPE opcode;
+ opcode = FungeSpaceGet(&iffiIP->position);
+
+ if (SettingTraceLevel > 8) {
+ fprintf(stderr, "x=%" FUNGEVECTORPRI " y=%" FUNGEVECTORPRI
+ ": %c (%" FUNGEDATAPRI ")\n",
+ iffiIP->position.x, iffiIP->position.y, (char)opcode, opcode);
+ PrintStackTop(iffiIP->stack);
+ } else if (SettingTraceLevel > 3) {
+ fprintf(stderr, "x=%" FUNGEVECTORPRI " y=%" FUNGEVECTORPRI
+ ": %c (%" FUNGEDATAPRI ")\n",
+ iffiIP->position.x, iffiIP->position.y, (char)opcode, opcode);
+ } else if (SettingTraceLevel > 2)
+ fprintf(stderr, "%c", (char)opcode);
+
+ ExecuteInstruction(opcode, iffiIP);
+ if (iffiIP->needMove)
+ ipForward(iffiIP, 1);
+ else
+ iffiIP->needMove = true;
+}
+
+// C - In markmode COME FROM the top of stack
+static void FingerIFFIcomeFrom(instructionPointer * ip)
+{
+ FUNGEDATATYPE l;
+
+ l = StackPop(ip->stack);
+
+ if (ick_iffi_inmarkmode) {
+ ick_iffi_breakloop = 1;
+ ick_iffi_linelabel = l;
+ ick_iffi_comingfrom = 1;
+ }
+}
+
+// F - FORGET NEXT stack entries equal to top of stack
+static void FingerIFFIforget(instructionPointer * ip)
+{
+ FUNGEDATATYPE f;
+
+ if (ick_iffi_inmarkmode) { /* this is an error in the user's code */
+ ipReverse(ip);
+ return;
+ }
+
+ f = StackPop(ip->stack);
+
+ if (f > 81 || f < 0) f = 81;
+
+ ick_iffi_forgetcount = f;
+}
+
+// L - Use top of stack as a line label for this point
+static void FingerIFFIlabel(instructionPointer * ip)
+{
+ FUNGEDATATYPE l;
+
+ l = StackPop(ip->stack);
+
+ ick_iffi_breakloop = 1;
+ ick_iffi_linelabel = l;
+ ick_iffi_sucking = 1;
+}
+
+// M - Marks points where the code can be entered from outside
+static void FingerIFFImarker(instructionPointer * ip)
+{
+ (void) ip;
+ ick_iffi_breakloop = ick_iffi_inmarkmode;
+}
+
+// N - Try to NEXT to the line labelled with the top of stack
+static void FingerIFFInext(instructionPointer * ip)
+{
+ FUNGEDATATYPE l;
+
+ if (ick_iffi_inmarkmode) { /* this is an error in the user's code */
+ ipReverse(ip);
+ return;
+ }
+
+ l = StackPop(ip->stack);
+
+ ick_iffi_breakloop = 1;
+ ick_iffi_linelabel = l;
+ ick_iffi_nexting = 1;
+}
+
+// R - RESUME to the top-of-stackth NEXT stack entry
+static void FingerIFFIresume(instructionPointer * ip)
+{
+ FUNGEDATATYPE f;
+
+ if (ick_iffi_inmarkmode) { /* this is an error in the user's code */
+ ipReverse(ip);
+ return;
+ }
+
+ f = StackPop(ip->stack);
+
+ if (f > 81 || f < 0) f = 81;
+
+ ick_iffi_forgetcount = f;
+
+ ick_iffi_resuming = 1;
+
+ ick_iffi_breakloop = 1;
+}
+
+// X - In markmode NEXT FROM the top of stack
+static void FingerIFFInextFrom(instructionPointer * ip)
+{
+ FUNGEDATATYPE l;
+
+ l = StackPop(ip->stack);
+
+ if (ick_iffi_inmarkmode) {
+ ick_iffi_breakloop = 1;
+ ick_iffi_linelabel = l;
+ ick_iffi_nextingfrom = 1;
+ }
+}
+
+bool FingerIFFIload(instructionPointer * ip)
+{
+ static int firstload = 1;
+ ick_iffi_breakloop = firstload;
+ firstload = 0;
+ ManagerAddOpcode(IFFI, 'C', comeFrom)
+ ManagerAddOpcode(IFFI, 'F', forget)
+ ManagerAddOpcode(IFFI, 'L', label)
+ ManagerAddOpcode(IFFI, 'M', marker)
+ ManagerAddOpcode(IFFI, 'N', next)
+ ManagerAddOpcode(IFFI, 'R', resume)
+ ManagerAddOpcode(IFFI, 'X', nextFrom)
+ return true;
+}
--- /dev/null
+/* -*- mode: C; coding: utf-8; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
+ *
+ * cfunge - a conformant Befunge93/98/08 interpreter in C.
+ * Copyright (C) 2008 Arvid Norlander <anmaster AT tele2 DOT se>
+ * 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 3 of the License, or
+ * (at the proxy's option) any later version. Arvid Norlander is a
+ * proxy who can decide which future versions of the GNU General Public
+ * License can be used.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _HAD_SRC_FINGERPRINTS_IFFI_H
+#define _HAD_SRC_FINGERPRINTS_IFFI_H
+
+#include "../../global.h"
+#include "../manager.h"
+
+#ifdef CONCURRENT_FUNGE
+#error The C-INTERCAL/cfunge external calls interface cannot be used concurrently
+#endif
+
+struct ick_ipposdeltatype
+{
+ long long ix, iy, dx, dy;
+};
+
+bool FingerIFFIload(instructionPointer * ip);
+
+void ick_InterpreterMainLoop(void);
+
+extern unsigned short ick_iffi_forgetcount;
+extern int ick_iffi_nexting;
+extern int ick_iffi_comingfrom;
+extern int ick_iffi_nextingfrom;
+extern int ick_iffi_sucking;
+extern int ick_iffi_resuming;
+extern uint32_t ick_iffi_linelabel;
+extern int ick_iffi_breakloop;
+extern int ick_iffi_inmarkmode;
+
+extern const char * ick_iffi_befungeString;
+extern int ick_printflow;
+
+#endif
--- /dev/null
+#! /bin/sh
+# This shell-script takes one argument, the path to a source
+# distribution of cfunge, and compiles that source distribution into a
+# library (libick_ecto_b98.a) suitable for linking to C-INTERCAL
+# programs.
+
+test x$1 != x || (
+ echo Please give the path to the root of a cfunge source
+ echo distribution as an argument to this script.
+ exit 1
+) || exit 1
+
+CFUNGEPATH=`realpath $1` || (
+ echo Please give the path to the root of a cfunge source
+ echo distribution as an argument to this script\; the directory
+ echo or file you gave does not exist.
+ exit 1
+) || exit 1
+
+test -f $CFUNGEPATH/src/interpreter.c || (
+ echo Please give the path to the root of a cfunge source
+ echo distribution as an argument to this script.
+ echo You gave $CFUNGEPATH, but it does not appear to be a cfunge
+ echo source distribution.
+ exit 1
+) || exit 1
+
+test -f IFFI.spec || (
+ echo Please run this script in the /etc directory of your
+ echo C-INTERCAL distribution.
+ exit 1
+) || exit 1
+
+echo Compiling cfunge into a library suitable for use with C-INTERCAL:
+
+cd temp
+
+CFLAGS="--std=c99 -DUSE32 -DDISABLE_GC -DFUNGE_EXTERNAL_LIBRARY -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -DFUNGEHANDPRINT=0x43464649"
+
+echo " " Duplicating cfunge source tree so that it can be modified...
+cp -r $CFUNGEPATH/src $CFUNGEPATH/lib .
+
+echo " " Patching cfunge source tree for use with C-INTERCAL...
+patch -p0 < ../cfunge.patch
+
+echo " " Adding the IFFI fingerprint...
+cp -r ../IFFI ../IFFI.spec src/fingerprints
+
+echo " " Regenerating fingerprint lists...
+$CFUNGEPATH/tools/gen_fprint_list.sh > /dev/null
+
+# Trust the filenames that are in the cfunge directory tree; if the user's
+# trying to trick themselves into running this on something that looks like
+# the cfunge directory tree but which has spaces or quotes in the filenames,
+# I really can't be bothered to save them from themself. Dump all the resulting
+# object files in this temp directory.
+echo " " Compiling source...
+find . -name '*.c' -printf "gcc $CFLAGS -c %p -o %f.o\n" | sh
+
+echo " " Creating library...
+ar cr ../../lib/libick_ecto_b98.a *.o
+ranlib ../../lib/libick_ecto_b98.a
+
+echo " " Cleaning up...
+rm -rf *
+cd ..
+
+echo Finished, unless there were errors.
--- /dev/null
+=== modified file 'src/global.h'
+--- src/global.h 2008-06-30 15:54:08 +0000
++++ src/global.h 2008-07-05 17:14:43 +0000
+@@ -158,7 +158,9 @@
+
+
+ /// Handprint: CFUN
+-#define FUNGEHANDPRINT 0x4346554e
++#ifndef FUNGEHANDPRINT
++# define FUNGEHANDPRINT 0x4346554e
++#endif
+ /// Version, for -V.
+ #define APPVERSION "0.2.1-pre2"
+ /// For y instruction.
+
tests/testcreate.i A test for the CREATE statement\r
explib/syslibc.c The INTERCAL base 2 syslib, optimised version in C\r
explib/compunex.c An example flow-control routine (computed NEXT)\r
+ explib/ecto_b98.c A library that links INTERCAL and Funge-98 code\r
sort.i An insertion-sort program testing computed ABSTAIN\r
continuation.i A continuation library and example program\r
continuation.doc About usage and internals of the continuation library\r
--- /dev/null
+/***************************************************************************
+
+NAME
+ ecto_b98.c - glue code for linking .b98 files with .i files
+
+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.
+
+ Note that this code is designed to be linked against a GPLv3 library
+ (producing a GPLv3 output), and therefore it is recommended that
+ modifications to this code are compatible with GPLv3, although this
+ is not a legal requirement.
+
+***************************************************************************/
+
+/* This is an expansion library designed to link with the Funge-98 interpreter
+ cfunge (when compiled as a library); this is glue code which hooks into the
+ INTERCAL control structure, and uses functions in glue code which hooks
+ into the Funge control structure in cfunge. The Befunge program itself that
+ is interpreted is stored in yet another .cio file, and accessed via the
+ extern variables ick_iffi_befungeString, ick_iffi_markerposns, and
+ ick_iffi_markercount. The name ecto_b98 is magical, and causes this library
+ to be included when a .b98 files is encountered on the command line (as
+ well as the cfunge library itself, which has the magical name
+ libick_ecto_b98.a).
+
+ The library itself works by using label names that have a special meaning
+ to ick, along with ICK_EC_FUNCs, to cause a compiled C-INTERCAL program to
+ also search in the Befunge program for line labels, COME FROMs, and NEXT
+ FROMs, as well as in the INTERCAL program itself. It also allows the
+ Befunge program to use INTERCAL control flow structures (even to itself),
+ by monitoring flags set in a Funge-98 fingerprint (IFFI, which accounts
+ for most of the variable names) and simulating the required structure
+ (such as FORGET or NEXT) somewhere where cfunge itself will be unaffected
+ and unaware of what is going on.
+
+ In general, INTERCAL control flow structures affect only the position and
+ delta of the IP in the Befunge program, not anything else. (In particular,
+ the Befunge stack is unaffected.)
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <ick_ec.h>
+
+extern int ick_printflow;
+
+struct ick_ipposdeltatype
+{
+ long long ix, iy, dx, dy;
+};
+
+void ick_InterpreterMainLoop(void);
+void ick_InterpreterRun(void);
+void ick_iffi_InterpreterOneIteration(void);
+void ick_iffi_HandleControl(void);
+void ick_SaveIPPosDelta(struct ick_ipposdeltatype*);
+void ick_RestoreIPPosDelta(struct ick_ipposdeltatype*);
+
+unsigned short ick_iffi_forgetcount=0;
+int ick_iffi_nexting=0;
+int ick_iffi_comingfrom=0;
+int ick_iffi_nextingfrom=0;
+int ick_iffi_sucking=0;
+int ick_iffi_resuming=0;
+uint32_t ick_iffi_linelabel=0;
+int ick_iffi_breakloop=0; /* becomes 1 when IFFI's loaded or mark-mode ends */
+int ick_iffi_inmarkmode=0;
+
+extern const char* ick_iffi_befungeString;
+extern long long ick_iffi_markerposns[][2];
+extern int ick_iffi_markercount;
+
+ICK_EC_FUNC_START(ick_InterpreterMainLoop)
+{
+ ick_startup( {ick_InterpreterRun();} ); /* could be put anywhere, is put here
+ for convenience */
+
+ /* we enter here when running at startup code and continue until IFFI is loaded */
+
+ if(0)
+ {
+ ick_l2_ICK_EC_PP_2: /* this will be automatically replaced with a valid label,
+ as will the next occurence of it, by ick when it does
+ linking (i.e. this is not an infinite loop). */
+ if(ick_global_linelabel != 0x70001ff1 &&
+ ick_global_linelabel != 0x70001ff2)
+ goto ick_l2_ICK_EC_PP_2;
+ /* If control reaches this point, a COME FROM or NEXT has just completed,
+ and the IP already in the correct place. Continue, outside markmode. */
+ ick_iffi_nexting = 0;
+ ick_iffi_comingfrom = 0;
+ ick_iffi_nextingfrom = 0;
+ ick_iffi_sucking = 0;
+ ick_iffi_inmarkmode = 0;
+ ick_global_checkmode = 0;
+ /* If a NEXT has just completed, do a suckpoint-check on that line label
+ (in case someone COMEs FROM the target of the NEXT). */
+ if(ick_global_linelabel == 0x70001ff2)
+ {
+ auto struct ick_ipposdeltatype ippd;
+ ick_SaveIPPosDelta(&ippd);
+ ick_iffi_sucking = 0;
+ ick_checksuckpoint(ick_iffi_linelabel); /* may not return */
+ ick_RestoreIPPosDelta(&ippd);
+ }
+ }
+
+ick_iffi_iml_rerun:
+
+ ick_iffi_breakloop=0;
+ while(!ick_iffi_breakloop)
+ {
+ ick_iffi_InterpreterOneIteration();
+ if (ick_iffi_forgetcount && !ick_iffi_breakloop)
+ {
+ ick_forget(ick_iffi_forgetcount);
+ ick_iffi_forgetcount = 0;
+ }
+ }
+ /* There are several reasons why we could reach this point. Most of them,
+ we just fall off the end of the function and whatever called us handles
+ the program flow from there. However, if the loop broke due to a RESUME,
+ line label or NEXT, we need to handle it. */
+ if(ick_iffi_resuming)
+ {
+ unsigned short iifctemp = ick_iffi_forgetcount;
+ ick_iffi_resuming = 0;
+ ick_iffi_forgetcount = 0;
+ ick_resume(iifctemp); /* never returns */
+ }
+ if(ick_iffi_nexting)
+ {
+ /* To handle a NEXT, we need to save the relevant IP information (position
+ and delta, which are the only things saved/restored on the NEXT stack)
+ onto the C stack. This is done in a struct ick_ipposdatatype, using the
+ functions available for such save/restore. */
+ auto struct ick_ipposdeltatype ippd;
+ ick_SaveIPPosDelta(&ippd);
+ ick_iffi_nexting = 0;
+ ick_next(ick_iffi_linelabel); /* may not return */
+ ick_RestoreIPPosDelta(&ippd);
+ goto ick_iffi_iml_rerun; /* continue the main loop if we got here */
+ }
+ if(ick_iffi_sucking && ! ick_iffi_inmarkmode)
+ {
+ /* Handle a line-label encountered in normal execution. */
+ auto struct ick_ipposdeltatype ippd;
+ ick_SaveIPPosDelta(&ippd);
+ ick_iffi_sucking = 0;
+ ick_checksuckpoint(ick_iffi_linelabel); /* may not return */
+ ick_RestoreIPPosDelta(&ippd);
+ goto ick_iffi_iml_rerun; /* continue the main loop if we got here */
+ }
+}
+ICK_EC_FUNC_END
+
+ICK_EC_FUNC_START(ick_iffi_HandleControl)
+{
+ static int recursing=0;
+ int markerno, dirno, nextcheck;
+ struct ick_ipposdeltatype ippd;
+
+ /* The label names here are magical internal identifiers. That means that this
+ is not in fact an infinite loop, but is instead a handler for sucking in
+ from line labels. The 0x70001ff1 is a magic number used specifically by
+ this code. */
+ if(0)
+ {
+ ick_l1_ICK_EC_PP_1:
+ if(ick_global_linelabel > 65535)
+ goto skipsearch; /* there can't be a match, don't check to avoid recursion */
+ nextcheck = 0;
+ if(ick_printflow)
+ fprintf(stderr,"[cfcheck:%d]\n",(int)ick_global_linelabel);
+ }
+
+ if(0)
+ {
+ ick_l2_ICK_EC_PP_2:
+ if(ick_global_linelabel > 65535)
+ goto skipsearch; /* there can't be a match, don't check to avoid recursion */
+ nextcheck = 1;
+ if(ick_printflow)
+ fprintf(stderr,"[llcheck:%d]\n",(int)ick_global_linelabel);
+ }
+
+ assert(!recursing);
+
+ recursing=1;
+
+ ick_SaveIPPosDelta(&ippd);
+
+ markerno=ick_iffi_markercount;
+ while(markerno--)
+ {
+ dirno=4;
+ while(dirno--)
+ {
+ struct ick_ipposdeltatype tippd;
+ tippd.ix=ick_iffi_markerposns[markerno][0];
+ tippd.iy=ick_iffi_markerposns[markerno][1];
+ tippd.dx=(dirno == 3 ? -1 : dirno == 1 ? 1 : 0);
+ tippd.dy=(dirno == 0 ? -1 : dirno == 2 ? 1 : 0);
+ if(ick_printflow)
+ fprintf(stderr, "Checking for %s at (%lld, %lld) going %c...\n",
+ nextcheck ? "line label" : "COME FROM/NEXT FROM",
+ tippd.ix, tippd.iy, dirno["^>v<"]);
+ tippd.ix += tippd.dx;
+ tippd.iy += tippd.dy;
+ ick_RestoreIPPosDelta(&tippd);
+ ick_iffi_inmarkmode = 1;
+ ick_local_checkmode = ick_global_checkmode;
+ ick_global_checkmode = 0;
+ ick_InterpreterMainLoop();
+ ick_global_checkmode = ick_local_checkmode;
+ ick_iffi_inmarkmode = 0;
+ if((ick_iffi_nextingfrom||ick_iffi_comingfrom) &&
+ ick_iffi_linelabel == ick_global_linelabel && !nextcheck)
+ {
+ if(ick_printflow)
+ fprintf(stderr,"%s FROM found!\n",ick_iffi_comingfrom?"COME":"NEXT");
+ /* Error out on multiple COME FROM/NEXT FROM with the same target. */
+ if(ick_global_goto) ick_lose(ICK_IE555, -1, (char*)0);
+ ick_global_goto=0x70001FF1; /* we found a suckpoint */
+ if(ick_iffi_nextingfrom) ick_global_checkmode = 3; /* do a next from */
+ /* if it's a come-from, the checkmode is already correct */
+ ick_SaveIPPosDelta(&ippd);
+ }
+ if(ick_iffi_sucking && ick_iffi_linelabel == ick_global_linelabel &&
+ nextcheck)
+ {
+ if(ick_printflow)
+ fprintf(stderr,"Line label found!\n");
+ /* Another part of the code is NEXTing to this line label. */
+ ick_SaveIPPosDelta(&ippd);
+ nextcheck = 2; /* when this loop ends, goto the main loop */
+ }
+ ick_iffi_nextingfrom = 0;
+ ick_iffi_comingfrom = 0;
+ ick_iffi_sucking = 0;
+ }
+ }
+
+ if(ick_printflow) fprintf(stderr,"Checks finished.\n");
+
+ /* Set the IP to what we want it to be on resume, or otherwise return it to
+ its original value. (Returning it to its original value is unneccesary
+ but harmless.) */
+ ick_RestoreIPPosDelta(&ippd);
+ recursing=0;
+ ick_iffi_linelabel = ick_global_linelabel;
+ if(nextcheck == 2)
+ ick_dogoto(0x70001FF2,-1,0);
+skipsearch:
+ if(nextcheck)
+ goto ick_l2_ICK_EC_PP_2;
+ else
+ goto ick_l1_ICK_EC_PP_1;
+}
+ICK_EC_FUNC_END
#else
(void) snprintf(buf2, sizeof buf2,
#endif
- "%s --std=c%d -E -I%s -I%s -I%s/../include "
+ "%s --std=c%d -E -DICK_HAVE_STDINT_H=%d "
+ "-I%s -I%s -I%s/../include "
"-x c %s.c%c%c > %s.cio",
compiler, argv[optind][strlen(argv[optind])+2]=='9'?99:89,
+ ICK_HAVE_STDINT_H+1-1,
includedir, path, path, argv[optind],
argv[optind][strlen(argv[optind])+2]=='9'?
(needc99=1),'9':' ',