SS = Steve Swales
LHH = Louis Howell
BLR = Brian Raiter
+AIS = Alex Smith
1) (ESR) INTERCAL would be intrinsically a crock even if it worked right.
the modified behavior of select's return type depends on this, so
there's not much we can do about it as things stand.
+4) (AIS) In multithread programs, a thread doing the equivalent of
+ (10) DO COME FROM (10) will cause the entire program to get stuck in
+ an infinite loop, because all COMING FROM a statement counts as part
+ of that statement, and all statements are atomic.
+
+5) (AIS) In a multithreaded backtracking program, you can't fork a thread
+ which has backtrack points in it. The problem is that backtracking past
+ the fork from one but not both of the new threads would lead to a
+ situation in which the fork hadn't happened in one possible route from
+ the fork, but had in the other. This is clearly absurd, even by the
+ standards of INTERCAL.
+
TO DO
1. (ESR) Add more optimization templates, esp. idioms for +, -, *, /.
#
# Productions for the INTERCAL distribution
#
+VERSION=@PACKAGE_VERSION@
# Common prefix for machine-independent installed files.
prefix = @prefix@
# This can be overridden from the command line
DESTDIR=
+# Location of GNU GPL. This will be automatically copied if not required during install.
+# If not using install, change this to any copy of the GNU GPL that exists on your system.
+# This is required because the yuk debugger reads commands interactively, and so must be
+# able to display a copy of the GPL on demand. This is only possible if yuk can find a copy.
+# If you want to delete or move the distribution files, then you will have to move COPYING
+# to another directory; otherwise, you can aim this at COPYING.
+# It's also possible to aim this at a copy of COPYING from another GPL program.
+copyloc = ${DESTDIR}${datadir}/COPYING
+
CC = @CC@
-CFLAGS = @CFLAGS@ -DICKINCLUDEDIR=\"$(incdir)\" -DICKLIBDIR=\"$(datadir)\" -DYYDEBUG
+CFLAGS = @CFLAGS@ -DICKINCLUDEDIR=\"$(incdir)\" -DICKLIBDIR=\"$(datadir)\" -DICKBINDIR=\"$(bindir)\" -DYYDEBUG -DYUKCOPYLOC=\"$(copyloc)\"
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXFLAGS=
LOADLIBS = @LIBS@ @INTLLIBS@ @LEXLIB@
-CSOURCES = ick.y lexer.l feh.c lose.c fiddle.c perpetrate.c
+CSOURCES = ick.y lexer.l feh.c lose.c fiddle.c perpetrate.c unravel.c
ISOURCES = cesspool.c arrgghh.c ick-wrap.c numerals.c
-HEADERS = ick.h lose.h sizes.h abcess.h fiddle.h feh.h
+YSOURCES = yuk.c
+HEADERS = ick.h lose.h sizes.h abcess.h fiddle.h feh.h yuk.h
BUILD = Makefile.in Makefile configure.ac configure config.h.in intercal.spec.in intercal.spec install.sh
-MISC = intercal.el
+MISC = intercal.el coopt.sh
DOCS = BUGS COPYING NEWS README
-SOURCES = $(CSOURCES) $(ISOURCES) $(HEADERS) $(BUILD) $(MISC) $(DOCS) pit doc
+SOURCES = $(CSOURCES) $(ISOURCES) $(YSOURCES) $(HEADERS) $(BUILD) $(MISC) $(DOCS) pit doc
+
+all: ick libick.a libickmt.a libyuk.a
+
+copycopy: COPYING
+ -mkdir $(DESTDIR)$(datadir)
+ -if cp $(copyloc) /dev/null ; then : ; else cp COPYING $(copyloc) ; fi
-all: ick libick.a
+checkcopy:
+ @echo If the following line fails, change \"copyloc\" in your makefile.
+ cp $(copyloc) /dev/null
ick: ick.o lexer.o feh.o lose.o fiddle.o perpetrate.o
$(CC) perpetrate.o ick.o lexer.o feh.o lose.o fiddle.o $(LDFLAGS) -o ick
feh.o: feh.c feh.h y.tab.h ick.h fiddle.h lose.h sizes.h
perpetrate.o: perpetrate.c y.tab.h ick.h lose.h sizes.h
cesspool.o: cesspool.c numerals.c abcess.h lose.h sizes.h
+unravel.o: unravel.c abcess.h lose.h sizes.h
lose.o: lose.h
fiddle.o: fiddle.h sizes.h
+yuk.o: checkcopy yuk.h lose.h sizes.h abcess.h
libick.a: cesspool.o lose.o fiddle.o arrgghh.o
ar cr libick.a cesspool.o lose.o fiddle.o arrgghh.o
-ranlib libick.a
-install: all
+libickmt.a: cesspool.o unravel.o lose.o fiddle.o arrgghh.o
+ ar cr libickmt.a cesspool.o unravel.o lose.o fiddle.o arrgghh.o
+ -ranlib libickmt.a
+
+libyuk.a: yuk.o
+ ar cr libyuk.a yuk.o
+ -ranlib libyuk.a
+
+install: copycopy all
cp ick $(DESTDIR)$(bindir)
cp libick.a $(DESTDIR)$(libdir)
+ cp libickmt.a $(DESTDIR)$(libdir)
+ cp libyuk.a $(DESTDIR)$(libdir)
-mkdir -p $(DESTDIR)$(incdir)
- cp lose.h abcess.h fiddle.h $(DESTDIR)$(incdir)
+ cp lose.h abcess.h fiddle.h yuk.h $(DESTDIR)$(incdir)
-mkdir $(DESTDIR)$(datadir)
(cp -r pit $(DESTDIR)$(datadir))
cp ick-wrap.c $(DESTDIR)$(datadir)
+ cp coopt.sh $(DESTDIR)$(bindir)
uninstall:
rm -f $(DESTDIR)$(bindir)/ick $(DESTDIR)$(libdir)/libick.a
+ rm -f $(DESTDIR)$(bindir)/coopt.sh
+ rm -f $(DESTDIR)$(libdir)/libickmt.a $(DESTDIR)$(libdir)/libyuk.a
rm -fr $(DESTDIR)$(incdir) $(DESTDIR)$(datadir)
TAGS: $(SOURCES)
clean:
rm -f yacc.* y.tab.* y.output *~ *.[oa] lexer.c ick.c lextest ick
- rm -f intercal-@PACKAGE_VERSION@.tar.gz intercal.spec
+ rm -f intercal-@PACKAGE_VERSION@.tar.gz intercal.spec core
NEW IN THIS RELEASE
+ Release ? (by ?) ?
+
+(All these changes were by AIS)
+
+1. Added support for computed ABSTAIN and TRY AGAIN.
+
+2. Added support for computed COME FROM.
+
+3. Added support for multithread programs. This includes ONCE and AGAIN,
+which also work in singlethread programs.
+
+4. Expanded intercal.el to support Font Lock and some utilities for generating
+INTERCAL-style constants. It also works with the compilation routines of Emacs
+to compile INTERCAL programs without the need for make. Degenerated C code now
+has a mode line to help with Emacs compatibility.
+
+5. Added a rudimentary debugger and profiler for singlethread programs. The
+debugger's features include useful things like 'write out INTERCAL expression
+in simpler terms' (which is only possible if -O is on). The profiler works
+much like gcov, counting the length of time spent in and number of executions
+of each command in the code.
+
+6. Changed searching for includes, libraries, syslib, skeleton. This is so that
+non-root users, or people who want to evaluate ick, can do so more simply. The
+compiler will search for the above files in the directory they should have been
+installed in, the current directory, and the directory in which ick's
+executable resides (in that order). Skeleton problems, in particular, seem to
+have been a major problem for unfamiliar users trying out ick.
+
+7. Added several new test programs to the Pit.
+
+8. Greatly expanded the original optimizer (which optimizes expressions). It
+can now recognize most of the idioms in syslib, and many idioms in other Pit
+programs. Also added a new optimizer, to try to optimize program flow, which is
+important because otherwise INTERCAL wouldn't have any rudimentary optimizers.
+There is also the -F optimizer, which I hope will become infamous. It creates
+object code which is close to maximally fast in some specialized situations, at
+the expense of compile time (compilation can take a very long time when -F is
+active) and object file size. I suggest checking its effect on primes.i.
+
+9. Fixed the grammar (again) in a spark/ears situation involving array
+subscripts, after proving that the previous fixes weren't adequate.
+
+10. Added support for backtracking (MAYBE, GO AHEAD, GO BACK). Note that it is
+possible for multithreading, backtracking, computed ABSTAIN, and computed COME
+FROM to all be used simultaneously in the same program, to help maximize
+obfuscation.
+
+11. Added an option (-l) for generating warnings. To prevent this actually being
+useful, it is designed to generate far too many warnings, which all have to be
+trawled through to find the important ones, and has no way to turn the
+unimportant ones off.
+
+12. Added the +printflow and +mystery options for executing INTERCAL programs.
+Note that it is not entirely obvious what either of them do (+printflow is a
+debugging aid, but the output is somewhat obfuscated, and I am not going to
+explain what +mystery does in this document).
+
Release 0.24 (by Eric S. Raymond) 31 Dec 2003
1. RPMs can now be built by non-root users.
NEWS -- info on features and fixes new in this release
intercal.el -- elisp for editing INTERCAL code under GNU Emacs
-doc/README -- historical notes on the docs
+doc/READ.ME -- historical notes on the docs
doc/intercal.mm -- the manual in groffable form
doc/THEORY -- some notes on the internals of the INTERCAL compiler
cesspool.c -- the INTERCAL runtime support code
numerals.c -- numerals table for INTERCAL input
sizes.h -- variables defining the numeric base
+unravel.c -- multithreading functions
+yuk.[ch] -- INTERCAL debugger and profiler
+coopt.sh -- shell-script to help out the -F optimizer
pit/* -- sample INTERCAL code; see pit/CATALOG
ick foo.i
-There's a -c option that leaves the generated `foo.c' in place for inspection
-(suppressing compilation to machine code), a -d option that enables verbose
-parse reporting from the yacc/bison parser, a -t option that requires strict
-INTERCAL-72 compliance (rejecting COME FROM and the extensions for bases other
-than two), a -b option that disables the INTERCAL-72 random-bug feature,
-and an -O option that enables the (hah!) optimizer. Invoking ick -?
-prints a usage message. Other than that, yer on yer own.
+There's a -c option that leaves the generated `foo.c' in place for
+inspection (suppressing compilation to machine code), a -d option that
+enables verbose parse reporting from the yacc/bison parser, a -t
+option that requires strict INTERCAL-72 compliance (rejecting COME
+FROM and the extensions for bases other than two), a -b option that
+disables the INTERCAL-72 random-bug feature, and an -O option that
+enables the (hah!) optimizer (which can be invoked at higher levels
+with -Of or -F). Invoking ick -? prints a usage message. The -m
+option enables multithreading extensions. If you need to debug code,
+you can use -y to invoke the debugger immediately after compilation,
+-p to invoke the profiler immediately after compilation, or -g to
+generate the C code in such a way that it can be debugged with a C
+debugger. -h, -H, and -hH generate debugging output from the
+optimizer, which is useful if you need to understand an INTERCAL
+program, and -l turns on warnings (far too many warnings!). If ick
+itself needs debugging, the -U option will cause it to dump core on
+E778. Other than that, yer on yer own.
Another switch affects C-INTERCAL's runtime behavior. The `-C'
option forces output in "clockface" mode, for superstitious users who
Every INTERCAL runtime also accepts certain options at runtime (code by
Steve Swales). These include [+/-]help, [+/-]traditional, and [+/-]wimpmode.
The help option (with either + or -) triggers a 'usage' message. The
-+traditional option is presently a no-op.
++traditional option is presently a no-op. Also available are [+/-] printflow,
+which gives information that may or may not be helpful for debugging a program,
+and [+/-] mystery, which is undocumented. Note that these options are not
+necessarily available if the program is compiled with -F.
Steve writes: "The wimpmode option is the most interesting. I found myself
always running my test programs with filters on both ends to work around the
using the current versions of gcc, flex, and bison, C-INTERCAL should
build with no warnings.
+As the debugger is interactive, it needs to be able to find the GNU GPL.
+The Makefile attempts to copy the GPL to /dev/null to prove it exists. If
+this fails, you will have to point the Makefile to a copy of the GPL
+yourself. You can always copy the one included with this distribution
+somewhere safe and use that (what the Makefile will try to do by default).
+
LICENSING
C-INTERCAL is now distributed under the General Public License,
/* abcess.h -- functions used by compiled INTERCAL programs */
+/* AIS note: This header file now serves two purposes. For non-multithread
+ programs, it serves as headers to the degenerated code and many support
+ functions. For multithread programs, this header file adds extra functions
+ only when compiling the degenerated code and unravel.c, and holds its
+ previous contents during other files. */
+
typedef int bool;
#define TRUE 1
#define FALSE 0
#define TAIL 2
#define HYBRID 3
+#define MAXNEXT 80 /* AIS: Moved from cesspool.c */
+
/* the following two types must both promote to unsigned int in expressions */
typedef unsigned short type16;
} data;
} array;
+/* AIS: Moved from cesspool.c */
+typedef struct stashbox_t /* this is a save-stack element */
+{
+ unsigned int type; /* variable type */
+ unsigned int index; /* variable's index within the type */
+ union /* the data itself */
+ {
+ type16 onespot;
+ type32 twospot;
+ array *a;
+ } save;
+ struct stashbox_t *next; /* pointer to next-older stashbox */
+} stashbox;
+
+/* AIS: files to take input and output from */
+extern FILE* cesspoolin;
+extern FILE* cesspoolout;
+
/* defined in cesspool.c */
extern void pushnext(int n);
extern unsigned int popnext(int n);
extern unsigned int assign(char *dest, unsigned int type, bool forget,
unsigned int value);
+/* AIS: yuk and unravel need these */
+extern int* next;
+extern int nextindex;
+extern stashbox* first;
+
+/* AIS: Implement the +mystery command line option. */
+extern unsigned long mysteryc;
+extern int mystery;
+#define MYSTERYLINE if(mystery && mysteryc++ > 4000000000LU) exit(42);
+
+/* AIS: Handle multiple COME FROMs aiming at the same line */
+extern int multicome0(int errlineno, jmp_buf pc);
+
#ifdef _POSIX_SOURCE
extern char *aref(unsigned int type, ...);
extern void resize(unsigned int type, ...);
/* defined in arrgghh.c */
extern void parseargs(int argc, char **argv);
+/* AIS: Multithreading types and defines */
+#if MULTITHREAD != 0
+typedef struct tag_ickthread ickthread;
+struct tag_ickthread
+{
+ void* varforget[8]; /* holds all four variable types, and forgetting data */
+ int* nextstack;
+ int nextpointer;
+ jmp_buf pc; /* program counter */
+ stashbox* sb; /* holds all stash data */
+ ickthread* next;
+ ickthread* choicepoint; /* the top choicepoint available. Used as a next
+ pointer in the choicepoint stack. */
+ int stale; /* if this is a choicepoint, whether it's a stale choicepoint. */
+ int refcount; /* when Threaded INTERCAL and Backtracking INTERCAL are
+ combined, reference-counting on choicepoints is needed
+ so that backtracking past multithreading is possible.
+ This also allows for garbage-collection of choicepoints.
+ (Luckily, choicepoints cannot refer to themselves, so this
+ mechanism works.) This only applies to ickthreads that are
+ acting as choicepoints, not those acting as threads. */
+ int ccfc; /* number of comefroms currently active */
+ int skipto; /* compucome line number */
+ jmp_buf cjb; /* keeps track of compucomes */
+};
+extern ickthread* ickmt_cur; /* current thread */
+extern ickthread* ickmt_prev; /* previous thread: an optimisation to make
+ thread switching O(1), not O(n), with
+ respect to the number of threads */
+#define NEXTTHREAD if(printflow) printf("[%d]",lineno); \
+ if(setjmp(cjb) == 0) \
+ nextthread(cjb, lineno, 3);
+
+extern void nextthread(jmp_buf pc, int errlineno, int flags);
+extern void killthread(void);
+extern void ickmtinit(void);
+extern int multicome1(int errlineno, jmp_buf pc);
+extern void choicepoint(void);
+extern void choiceahead(void);
+extern void choiceback(void);
+
+/* from ick-wrap.c, declare as extern so they can be accessed by cesspool.c,
+ unravel.c */
+extern int onespotcount;
+extern int twospotcount;
+extern int tailcount;
+extern int hybridcount;
+
+extern int oldabstain;
+extern int gonebackto;
+extern int ccfc;
+extern int skipto;
+extern jmp_buf btjb;
+extern jmp_buf cjb;
+
+#define MULTICOME multicome1
+#else
+#define MULTICOME multicome0
+#endif /* MULTITHREAD */
+
+/* AIS: Used by the debugger, multithread code */
+#if (MULTITHREAD != 0) || (YUKDEBUG != 0)
+extern type16* onespots;
+extern bool* oneforget;
+extern type32* twospots;
+extern bool* twoforget;
+extern array* tails;
+extern bool* tailforget;
+extern array* hybrids;
+extern bool* hyforget;
+#endif
+
/* abcess.h ends here */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <setjmp.h>
#include "abcess.h"
#include "lose.h"
int traditional = 0;
int wimp_mode = 0;
+int printflow = 0; /* AIS */
+int mystery = 0; /* AIS */
+
+unsigned long mysteryc = 0; /* AIS */
void
parseargs(int argc, char **argv)
static char *flags[] = {
"help",
"wimpmode",
- "traditional"
+ "traditional",
+ "printflow", /* AIS */
+ "mystery", /* AIS */
};
static int *bools[] = {
&helpflag,
&wimp_mode,
- &traditional
+ &traditional,
+ &printflow, /* AIS */
+ &mystery, /* AIS */
};
static int nflags = (int)(sizeof(flags)/sizeof(flags[0]));
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <setjmp.h>
#ifdef _POSIX_SOURCE
#include <stdarg.h>
#include "numerals.c"
+FILE* cesspoolin = stdin;
+FILE* cesspoolout = stdout;
+/* AIS: In a future version of ick or yuk, these might not be constants */
+
/**********************************************************************
*
* The following functions manipulate the nexting stack
*
*********************************************************************/
-#define MAXNEXT 80
-
-int next[MAXNEXT];
+int* next; /* AIS: now allocated by ick-wrap.c */
int nextindex = 0;
void pushnext(int n)
int n;
extern int wimp_mode;
- if (fgets(buf, BUFSIZ, stdin) == (char *)NULL)
+ if (fgets(buf, BUFSIZ, cesspoolin) == (char *)NULL)
lose(E562, lineno, (char *)NULL);
n = strlen(buf) - 1;
if (n > 0 && buf[n-1] == '\r')
extern int wimp_mode;
if(wimp_mode) {
- printf("%u\n",val);
+ (void) fprintf(cesspoolout,"%u\n",val);
}
else {
butcher(val, result);
- (void) puts(result);
+ (void) fprintf(cesspoolout,"%s\n",result);
}
- fflush(stdout);
+ fflush(cesspoolout);
}
/**********************************************************************
lose(E241, lineno, (char *)NULL);
for (i = 0 ; i < a->dims[0] ; i++) {
- v = ((c=getchar()) == EOF) ? 256 : (c - lastin) % 256;
+ v = ((c=fgetc(cesspoolin)) == EOF) ? 256 : (c - lastin) % 256;
lastin = c;
if (!forget) {
if (type == TAIL)
c = (c & 0x0f) << 4 | (c & 0xf0) >> 4;
c = (c & 0x33) << 2 | (c & 0xcc) >> 2;
c = (c & 0x55) << 1 | (c & 0xaa) >> 1;
- putchar(c);
+ fputc(c,cesspoolout);
if (c == '\n')
- fflush(stdout);
+ fflush(cesspoolout);
}
}
a = va_arg(ap, array*);
forget = va_arg(ap, bool);
+ if (!a->rank) a->dims = 0; /* AIS: a->dims no longer initialised */
+
r = va_arg(ap, unsigned int);
if (!forget) {
a->rank = r;
*
*********************************************************************/
-typedef struct stashbox_t /* this is a save-stack element */
-{
- unsigned int type; /* variable type */
- unsigned int index; /* variable's index within the type */
- union /* the data itself */
- {
- type16 onespot;
- type32 twospot;
- array *a;
- } save;
- struct stashbox_t *next; /* pointer to next-older stashbox */
-} stashbox;
-
-static stashbox *first;
+stashbox *first; /* AIS: made non-static so it can be seen by unravel.c */
void stashinit(void)
{
#endif /* UNIX */
}
+/**********************************************************************
+ *
+ * AIS: This function is called when two COME FROMs reference the same
+ * line at runtime. multicome0 is used in a non-multithread
+ * program; it produces an error. For multicome1, see unravel.c.
+ *
+ *********************************************************************/
+
+int multicome0(int errlineno, jmp_buf pc)
+{
+ lose(E555, errlineno, (char *) NULL);
+ /* this line number is quite possibly going to be wildly inaccurate */
+ return 0;
+}
+
/* cesspool.c ends here */
--- /dev/null
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.57 for intercal 0.25.
+#
+# Report bugs to <esr@thyrsus.com>.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='intercal'
+PACKAGE_TARNAME='intercal'
+PACKAGE_VERSION='0.25'
+PACKAGE_STRING='intercal 0.25'
+PACKAGE_BUGREPORT='esr@thyrsus.com'
+
+ac_unique_file="lose.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS YACC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LEX LEXLIB LEX_OUTPUT_ROOT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE CPP EGREP LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures intercal 0.25 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of intercal 0.25:";;
+ esac
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <esr@thyrsus.com>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+intercal configure 0.25
+generated by GNU Autoconf 2.57
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by intercal $as_me 0.25, which was
+generated by GNU Autoconf 2.57. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core core.* *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+for ac_prog in 'bison -y' byacc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_YACC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ ''\
+ '#include <stdlib.h>' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+for ac_prog in flex lex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_LEX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LEX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+ echo "$as_me:$LINENO: result: $LEX" >&5
+echo "${ECHO_T}$LEX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test -z "$LEXLIB"
+then
+ echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5
+echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6
+if test "${ac_cv_lib_fl_yywrap+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char yywrap ();
+int
+main ()
+{
+yywrap ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_fl_yywrap=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_fl_yywrap=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5
+echo "${ECHO_T}$ac_cv_lib_fl_yywrap" >&6
+if test $ac_cv_lib_fl_yywrap = yes; then
+ LEXLIB="-lfl"
+else
+ echo "$as_me:$LINENO: checking for yywrap in -ll" >&5
+echo $ECHO_N "checking for yywrap in -ll... $ECHO_C" >&6
+if test "${ac_cv_lib_l_yywrap+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ll $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char yywrap ();
+int
+main ()
+{
+yywrap ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_l_yywrap=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_l_yywrap=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5
+echo "${ECHO_T}$ac_cv_lib_l_yywrap" >&6
+if test $ac_cv_lib_l_yywrap = yes; then
+ LEXLIB="-ll"
+fi
+
+fi
+
+fi
+
+if test "x$LEX" != "x:"; then
+ echo "$as_me:$LINENO: checking lex output file root" >&5
+echo $ECHO_N "checking lex output file root... $ECHO_C" >&6
+if test "${ac_cv_prog_lex_root+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # The minimal lex program is just a single line: %%. But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+cat >conftest.l <<_ACEOF
+%%
+%%
+_ACEOF
+{ (eval echo "$as_me:$LINENO: \"$LEX conftest.l\"") >&5
+ (eval $LEX conftest.l) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+else
+ { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5
+echo "$as_me: error: cannot find output from $LEX; giving up" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_root" >&6
+rm -f conftest.l
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5
+echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6
+if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS=$LIBS
+LIBS="$LIBS $LEXLIB"
+cat >conftest.$ac_ext <<_ACEOF
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_lex_yytext_pointer=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define YYTEXT_POINTER 1
+_ACEOF
+
+fi
+
+fi
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+all:
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Checks for libraries.
+
+# Checks for header files.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+for ac_header in memory.h stddef.h stdlib.h string.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5
+echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdbool.h>
+#ifndef bool
+# error bool is not defined
+#endif
+#ifndef false
+# error false is not defined
+#endif
+#if false
+# error false is not 0
+#endif
+#ifndef true
+# error true is not defined
+#endif
+#if true != 1
+# error true is not 1
+#endif
+#ifndef __bool_true_false_are_defined
+# error __bool_true_false_are_defined is not defined
+#endif
+
+ struct s { _Bool s: 1; _Bool t; } s;
+
+ char a[true == 1 ? 1 : -1];
+ char b[false == 0 ? 1 : -1];
+ char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+ char d[(bool) -0.5 == true ? 1 : -1];
+ bool e = &s;
+ char f[(_Bool) -0.0 == false ? 1 : -1];
+ char g[true];
+ char h[sizeof (_Bool)];
+ char i[sizeof s.t];
+
+int
+main ()
+{
+ return !a + !b + !c + !d + !e + !f + !g + !h + !i;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdbool_h=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdbool_h=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6
+echo "$as_me:$LINENO: checking for _Bool" >&5
+echo $ECHO_N "checking for _Bool... $ECHO_C" >&6
+if test "${ac_cv_type__Bool+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((_Bool *) 0)
+ return 0;
+if (sizeof (_Bool))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type__Bool=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type__Bool=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5
+echo "${ECHO_T}$ac_cv_type__Bool" >&6
+if test $ac_cv_type__Bool = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STDBOOL_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+ return 0;
+if (sizeof (size_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+
+# Checks for library functions.
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_malloc_0_nonnull=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if STDC_HEADERS || HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+exit (malloc (0) ? 0 : 1);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_malloc_0_nonnull=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+ LIBOBJS="$LIBOBJS malloc.$ac_objext"
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
+echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6
+if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_realloc_0_nonnull=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if STDC_HEADERS || HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+exit (realloc (0, 0) ? 0 : 1);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_realloc_0_nonnull=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6
+if test $ac_cv_func_realloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 1
+_ACEOF
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 0
+_ACEOF
+
+ LIBOBJS="$LIBOBJS realloc.$ac_objext"
+
+cat >>confdefs.h <<\_ACEOF
+#define realloc rpl_realloc
+_ACEOF
+
+fi
+
+
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_signal=void
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+
+
+
+for ac_func in memset strrchr strtol strtoul
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+{ echo "$as_me:$LINENO: Version is $PACKAGE_VERSION" >&5
+echo "$as_me: Version is $PACKAGE_VERSION" >&6;}
+ ac_config_files="$ac_config_files Makefile intercal.spec"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by intercal $as_me 0.25, which was
+generated by GNU Autoconf 2.57. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+intercal config.status 0.25
+configured by $0, generated by GNU Autoconf 2.57,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "intercal.spec" ) CONFIG_FILES="$CONFIG_FILES intercal.spec" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@YACC@,$YACC,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@LEX@,$LEX,;t t
+s,@LEXLIB@,$LEXLIB,;t t
+s,@LEX_OUTPUT_ROOT@,$LEX_OUTPUT_ROOT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LN_S@,$LN_S,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo $f;;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo $f
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo $srcdir/$f
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
--- /dev/null
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.57)
+AC_INIT(intercal, 0.25, esr@thyrsus.com)
+AC_CONFIG_SRCDIR([lose.h])
+#AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_LEX
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([memory.h stddef.h stdlib.h string.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS([memset strrchr strtol strtoul])
+
+AC_MSG_NOTICE(Version is $PACKAGE_VERSION)
+AC_OUTPUT(Makefile intercal.spec)
--- /dev/null
+#!/bin/sh
+###########################################################################
+#
+# Name
+# coopt.sh -- an inefficient optimizer that can produce very efficient
+# code
+#
+# DESCRIPTION
+# This optimizer is only run on noninteractive code that takes no
+# output. (It's designed to run on executables produced by INTERCAL
+# code, but will run on other executables that support the +mystery
+# option). It optimizes the file by replacing it by one that simply
+# produces the required output! Therefore, it creates fast but
+# inefficient code. If the file to be optimized hits an error or
+# is terminated by +mystery, then no changes are made.
+#
+# LICENSE TERMS
+# Copyright (C) 2006 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.
+#
+###########################################################################
+
+rm icktemp.out >/dev/null 2>/dev/null
+if $1 +mystery >icktemp.out 2>/dev/null ; then : ; else exit 0 ; fi
+if grep 'ickoutTERM???!' icktemp.out ; then rm icktemp.out ; exit 0 ; fi
+echo 'ickoutTERM???!' >> icktemp.out
+rm $1
+echo "#!/bin/sh
+cat <<'ickoutTERM???!'" | cat - icktemp.out > $1
+chmod +x $1
+rm icktemp.out
+exit 0
--- /dev/null
+This directory contains the documentation (such as it is) for INTERCAL.
+
+READ.ME
+ This file.
+
+intercal.mm:
+ Masters for the INTERCAL manual (needs pic to render illos)
+ This has been carefully proofread against the original paper
+ version.
+
+THEORY
+ Implementation notes on the C-INTERCAL implementation.
+
+chip.spec:
+ Christian Brunschen's spec sheet for the INTERCAL chip.
+
+Note 1: The TeX version we formerly distributed has been dropped. The
+combination of groff and pic does an effective job of rendering the
+illustrations and is easier to maintain.
+
+Note 2: The supplemental reference manual, ick.txt, has been merged
+into the intercal manual. (It is still possible to generate the
+original; see the Makefile.)
+
+Note 3: The flat-ASCII directly transcribed from the paper original is
+also gone. You can regenerate something very close to it with `make
+original.txt'. The differences will be (a) page breaks may fall in
+different places, (b) the circuit diagrams present in the paper
+version but absent in the ASCII transcription are instead poorly
+approximated with ASCII boxology, (c) every "butchered Roman numeral"
+is preceded and followed by a line break, (d) the hanging-indent list
+of Princeton compiler options has all marks above each description,
+rather than to its left.
+
+The aim of these changes was to reduce to one the number of manual masters that
+need to be maintained.
+++ /dev/null
-This directory contains the documentation (such as it is) for INTERCAL.
-
-READ.ME
- This file.
-
-intercal.mm:
- Masters for the INTERCAL manual (needs pic to render illos)
- This has been carefully proofread against the original paper
- version.
-
-THEORY
- Implementation notes on the C-INTERCAL implementation.
-
-chip.spec:
- Christian Brunschen's spec sheet for the INTERCAL chip.
-
-Note 1: The TeX version we formerly distributed has been dropped. The
-combination of groff and pic does an effective job of rendering the
-illustrations and is easier to maintain.
-
-Note 2: The supplemental reference manual, ick.txt, has been merged
-into the intercal manual. (It is still possible to generate the
-original; see the Makefile.)
-
-Note 3: The flat-ASCII directly transcribed from the paper original is
-also gone. You can regenerate something very close to it with `make
-original.txt'. The differences will be (a) page breaks may fall in
-different places, (b) the circuit diagrams present in the paper
-version but absent in the ASCII transcription are instead poorly
-approximated with ASCII boxology, (c) every "butchered Roman numeral"
-is preceded and followed by a line break, (d) the hanging-indent list
-of Princeton compiler options has all marks above each description,
-rather than to its left.
-
-The aim of these changes was to reduce to one the number of manual masters that
-need to be maintained.
extern. To add new numeral tokens, simply put them in the numerals
initializer.
+AIS: Now computed COME FROM is in the language, the lexer is called forth to
+ do a bit of syntax analysis, by distinguishing it from an ordinary
+ COME FROM and passing different symbols to the parser. The lexer is also
+ responsible for helping the parser to match sparks and ears in complicated
+ array situations, by distinguishing possibly closing sparkears from
+ definitely opening sparkears.
+
Compilation
The parser builds an array of tuples, one for each INTERCAL statement. Most
INTERCAL idioms for `test for equality', `test for nonzeroness', and
the C logical operators &, |, ^, and ~.
+AIS: The optimizer has now been expanded. See below.
+
Code Generation
Each line of INTERCAL is translated into a C if()-then; the guard part
much-needed delinting while porting it for ANSI C, flex and Linux. He
also improved the lexical analyzer's line tracking.
+ Code Generation 2 (by AIS)
+
+The recent additions to the language have made code generation
+potentially more complicated, depending on which switches are on. Each
+INTERCAL command is still translated into an if()-then, but with extra
+guards around it. COME FROM is still handled the same way, but only in
+singlethreaded programs with no computed COME FROMs. For anything more
+complicated than that, a general COMING FROM mechanism is invoked. C's
+most confusing control-flow identifiers, setjmp and longjmp, are
+used. When computed COME FROMs are involved, after every labeled
+statement, a set of gotos are done to check each in turn. A jmp_buf,
+cjb, is used to store the point in the program where the check
+started. Each COME FROM leading to that line and computed COME FROM
+anywhere in the program is checked, and modifies cjb to aim for its
+suckpoint if neccesary. In the case of a multithreaded program, one
+cjb will be stored in a linked ring of threads, and the other will be
+the one in the main program.
+Extra guards are also added for ONCE/AGAIN; the position of this guard
+depends on whether the command is a NEXT or something else. ONCE/AGAIN
+are quite legal even in singlethreaded programs. Computed ABSTAIN is
+dealt with by allowing the abstain[] array to hold values other than 0
+or 1.
+Multithreading is supported by a new library, libickmt.a, to hold the
+multithread versions of libick.a functions. See unravel.c for an
+explanation of the full gory details of the multithread implementation
+(it has many comments explaining the implementation at the top).
+
+ Optimisation (by AIS)
+
+When I got my C-INTERCAL distribution, it only had a rudimentary
+optimiser. Constant folding had already been done, and the following
+optimisations. The following is mixed INTERCAL and C, sometimes in the
+same statement. It should be clear from context and whether I have
+used INTERCAL spark-ears or C brackets which language is which, although
+in some places I've mixed them. Note that apart from constant folding, the
+optimizer is only run in binary.
+
+Optimizations available with -O
+
+Optimisations that had already been done
+Constant folding
+'Vx$y'~"#0x55555555" into (x | y)
+'?x$y'~"#0x55555555" into (x ^ y)
+'&x$y'~"#0x55555555" into (x & y)
+(x ^ 0xFFFF) or (x ^ 0xFFFFFFFF) into ~x
+I added:
+Support for the first three examples above for some appropriate constants
+other than 0x55555555 (e.g. 0x1555)
+x~k into (x & k) where k is 2**n-1
+x~k into !!(x & k) where k is 2**n
+x~k into (x & k)>>1 where k is 2**n-2
+'x$0'~k into (x & <something appropriate>)<<1 for values of k that represent
+ left-shifts
+'x$1'~k into ((x & <something appropriate>)<<1) | 1 likewise
+32-bit left-shift idioms
+Double left-shift idioms
+syslib's left-shift by 8 idiom
+'x~x'~1 into ('x~x' & 1) into !!x
+'?x$1'~3 into (x & 1)+ 1
+'?x$2'~3 into 2 - (x & 1)
+(x & 1) & 1 into (x & 1) in the above two cases
+(!!x & 1) into !!x in the two cases above the above case
+Idioms that represent 32-bit logical operations (|, &, ^, ~) into their C
+equivalents
+No-op detection for some C-like idioms
+Simplification of some C-like idioms via the distributive law
+Some C-like operations done only on the even or odd bits of a value
+Some mingle/select combinations that can be replaced with & | and bitshifts
+A truly stupid idiom in syslib that does 32-bit rightshifts by separating
+odd bits and even bits
+Analysis of which bits in a number must always be 0, and which ones
+actually carry information (which can often remove a redundant & or
+other logical operator)
+Idiom recognition for > and !=
+Various other optimizations (many only on partially-optimized code)
+
+Optimizations available with -f (I wrote all these)
+
+Guard removal (if a line can't be abstained, the if(!abstained[x])
+line is removed when possible
+Ignorance checks (if a variable can't be ignored and it can't
+overflow, assignment is done with C's = rather than a function)
+Recognition of NEXT...NEXT...computed RESUME as an idiom for if()
+
+Optimizations available with -F (I wrote this one)
+
+This optimization should mean that INTERCAL suddenly becomes the best
+language for various benchmark programs. Basically, the file is
+analysed to try to determine whether it takes no input and always
+produces the same output. If that is the case, the output is simply a
+shell-script (with executable permissions set and a #! line) that
+outputs the correct output! Therefore, the time required for one run
+of the program is taken up during compilation, and whenever the
+program is executed, it just copies out the predetermined output. This
+means (for instance) that primes.i runs in only a fraction of a second
+when optimized with -F.
+Of course, this tends to slow down the compiler and often produces a
+large object file, which is why it has a command-line option of its own.
\ No newline at end of file
/****************************************************************************
-NAME
+Name
feh.c -- code-generator back-end for ick parser
DESCRIPTION
#include "lose.h"
#include "feh.h"
+/* AIS: The following macro produces optimization debug data. I added all
+ occurences of it in this source file. It also keeps track of whether
+ optimizations have taken place. */
+#define OPTING(x) if(optdebug == 2) {\
+ explexpr(optdebugnode,stderr);\
+ putc('\n',stderr); } \
+ if(optdebug == 3) {\
+ prexpr(optdebugnode,stderr,0);\
+ putc('\n',stderr); } \
+ if(optdebug) fprintf(stderr,"[%s]",#x);\
+ if(optdebug >= 2) putc('\n',stderr);\
+ opted = 1;
+
static int emitlineno; /* line number for errors encountered during emit */
+static void checknodeactbits(node *np); /* AIS: This prototype needed early */
+
+int mark112 = 0; /* AIS: Mark the next generated tuple for W112 */
+
/*************************************************************************
*
* Node allocation functions.
*
- * Nodes are used to represent expresion trees. The emit() function
+ * Nodes are used to represent expression trees. The emit() function
* deallocates them.
*
**************************************************************************/
return(np);
}
+/* By AIS. This function looks remarkably like a C++ copy-constructor to me,
+ just with extra arrows in. */
+node *nodecopy(node* n)
+{
+ node* np;
+ if(!n) return 0;
+ np = cons(n->opcode, nodecopy(n->lval), nodecopy(n->rval));
+ np->constant = n->constant;
+ np->optdata = n->optdata;
+ np->width = n->width;
+ return np;
+}
+
+/* This function by AIS. Compares expressions. In C++, I'd call this
+ node::operator== . */
+static bool nodessame(node* n1, node* n2)
+{
+ if(!n1) return !n2;
+ if(!n2) return 0;
+ if(n1->opcode!=n2->opcode) return 0;
+ if(!nodessame(n1->lval,n2->lval)) return 0;
+ if(!nodessame(n1->rval,n2->rval)) return 0;
+ switch(n1->opcode)
+ {
+ case ONESPOT:
+ case TWOSPOT:
+ case HYBRID:
+ case TAIL:
+ case MESH:
+ case MESH32:
+ return n1->constant == n2->constant;
+ case AND:
+ case OR:
+ case XOR:
+ return n1->width == n2->width;
+ default:
+ return 1;
+ }
+}
+
/*************************************************************************
*
* Variable-name mapping
lose(E197, yylineno, (char *)NULL);
}
+/*************************************************************************
+ *
+ * AIS: Search for the indexth COME_FROM sucking in the given tuple.
+ * Return an int representing the COME_FROM's tn-tuples+1, or -1.
+ * index is based at 1, not 0 as is usual for C.
+ *
+ ***************************************************************************/
+
+int comefromsearch(tuple* tn, unsigned int index)
+{
+ tuple* tp;
+ for (tp = tuples; tp < tuples + lineno; tp++)
+ {
+ if(tp->type == COME_FROM && tp->u.target == tn-tuples+1) index--;
+ if(!index) return tp-tuples+1;
+ }
+ return -1;
+}
+
/*************************************************************************
*
* Tuple allocation functions.
}
memset(tuples + lineno, 0, (tuplecount - lineno) * sizeof(tuple));
}
+ if(mark112) tuples[lineno].warn112 = 1; mark112 = 0; /* AIS */
return(tuples + lineno++);
}
* the compilation of the generated C to fail, like generated gotos to
* nonexistent labels or duplicate labels.
*
+ * AIS: codecheck has another important job, that of filling in information
+ * about COME FROM suckpoints and ABSTAIN/REINSTATE command numbers
+ * into the tuples.
+ *
**************************************************************************/
void codecheck(void)
{
tuple *tp, *up;
+ int notpast1900; /* AIS */
/* check for assignment type mismatches */
/* This check can't be done at compile time---RTFM. [LHH] */
* Check that every NEXT, ABSTAIN, REINSTATE and COME_FROM actually has a
* legitimate target label.
*/
+ notpast1900 = TRUE;
for (tp = tuples; tp < tuples + lineno; tp++)
- if (tp->type == NEXT
+ {
+ if (tp->label == 1900) notpast1900 = FALSE; /* AIS */
+ if (tp->type == NEXT
|| tp->type == ABSTAIN || tp->type == REINSTATE
- || tp->type == COME_FROM)
+ || tp->type == COME_FROM || tp->type == FROM) /* AIS: added FROM. */
{
bool foundit = FALSE;
+ if (tp->u.target >= 1900 && tp->u.target <= 1998)
+ {
+ /* AIS: This program uses syslib.i's random number feature... or are
+ we in syslib already? */
+ if(notpast1900) coopt = 0;
+ }
+
for (up = tuples; up < tuples + lineno; up++)
if (tp->u.target == up->label)
{
/* tell the other tuple if it is a COME FROM target */
else if (tp->type == COME_FROM)
{
- if (up->comefrom)
+ if (up->ncomefrom && !multithread) /* AIS: multithread check */
lose(E555, yylineno, (char *)NULL);
else
- up->comefrom = tp - tuples + 1;
+ up->ncomefrom++; /* AIS: to handle multiple COME FROMs */
}
- /* this substitutes line numbers for label numbers */
- else if (tp->type != NEXT)
+ /* this substitutes line numbers for label numbers
+ AIS: COME FROM now uses this too. This changes the logic
+ slightly so that an !foundit condition would fall through,
+ but as long as lose doesn't return, it's not a problem.
+ (I removed the else before the if.) */
+ if (tp->type != NEXT)
{
tp->u.target = up - tuples + 1;
}
+ else /* AIS */
+ {
+ tp->nexttarget = up - tuples + 1;
+ up->nextable = TRUE;
+ }
}
+ }
+}
+
+/* AIS: Checks if an abstention could affect a tuple. */
+int abstainmatch(int npconstant, int tptype)
+{
+ if(npconstant == tptype) return 1;
+ if(npconstant == ABSTAIN)
+ if(tptype == FROM || tptype == MANYFROM || tptype == DISABLE) return 1;
+ if(npconstant == REINSTATE)
+ if(tptype == DISABLE) return 1;
+ return 0;
}
+/* AIS: Added the third argument to prexpr and prvar. It specifies
+ whether the node should be freed or not. I added the third
+ argument in all calls of prexpr/prvar. This protoype has been moved
+ up through the file so it can be used earlier. */
+static void prexpr(node *np, FILE *fp, int freenode);
+
/*************************************************************************
*
- * Optimizer code.
+ * AIS: Flow optimizer. (I wrote the whole of optimizef.)
+ *
+ * This analyses the flow of the program, checking to see which lines can
+ * have their guards omitted, which lines can be omitted altogether, which
+ * variables can never be ignored, etc. The degenerator lower down can take
+ * this information into account, producing faster and shorter source code.
+ * In an ideal world, we'd end up with the produced INTERCAL looking like
+ * proper C code, but somehow I think that's unlikely to happen.
+ * At the moment, it just checks for unused !abstained[] guards on
+ * statements and removes them (possibly removing comments altogether).
+ * This is minor, but should clear up degenerated code substantially.
+ * It also allows the code for gets to replace assign() with the faster =
+ * in cases where this doesn't affect the behaviour of the program.
+ * See the function itself for what I did to NEXT.
+ *
+ *************************************************************************/
+
+void optimizef(void)
+{
+ tuple* tp, *tpa, *tpb;
+ atom* op;
+ node* np;
+ if(!flowoptimize) lose(E778, yylineno, (char *) NULL);
+ for (tp = tuples; tp < tuples + lineno; tp++) tp->abstainable = 0;
+ /* abstainable holds whether a line's abstention status can change */
+ for (op = oblist; op < obdex; op++) op->ignorable = 0;
+ /* ignorable holds whether a variable's ignorance status can change */
+ for (tp = tuples; tp < tuples + lineno; tp++)
+ {
+ if(tp->maybe) tp->abstainable = 1;
+ if(tp->exechance < 0) tp->initabstain = 1;
+ if(tp->exechance != 100 && tp->exechance != -100) tp->abstainable = 1;
+ if(tp->onceagainflag != onceagain_NORMAL) tp->abstainable = 1;
+ if(tp->type == ABSTAIN || tp->type == FROM)
+ {
+ tpa = tp->u.target - 1 + tuples;
+ if(tpa->exechance >= 0) tpa->abstainable = 1;
+ }
+ if(tp->type == REINSTATE)
+ {
+ tpa = tp->u.target - 1 + tuples;
+ if(tpa->exechance < 0) tpa->abstainable = 1;
+ }
+ if(tp->type == DISABLE || tp->type == MANYFROM)
+ {
+ for (tpa = tuples; tpa < tuples + lineno; tpa++)
+ {
+ np = tp->u.node;
+ if(tp->type == MANYFROM) np = np->rval;
+ for(; np; np = np -> rval)
+ if(abstainmatch(np->constant, tpa->type))
+ if(tpa->exechance >= 0) tpa->abstainable = 1;
+ }
+ }
+ if(tp->type == ENABLE)
+ {
+ for (tpa = tuples; tpa < tuples + lineno; tpa++)
+ {
+ np = tp->u.node;
+ for(; np; np = np -> rval)
+ if(abstainmatch(np->constant, tpa->type))
+ if(tpa->exechance < 0) tpa->abstainable = 1;
+ }
+ }
+ if(tp->type == GETS)
+ checknodeactbits(tp->u.node->rval);
+ /* If optdata shows that the value must always fit in the variable,
+ and the variable cannot be ignored, assign can be replaced by the
+ cheaper =. */
+ if(tp->type == IGNORE)
+ {
+ for (np = tp->u.node; np; np = np->rval)
+ {
+ for (op = oblist; op < obdex; op++)
+ {
+ if(op->type == np->opcode && op->intindex == np->constant)
+ op->ignorable = 1;
+ }
+ }
+ }
+ /* REMEMBERING variables has no effect on this code, because all
+ variables are initially remembered anyway, and so an IGNORE would
+ be needed (and caught above) to have an effect. */
+ }
+ /* There are some flow idioms that maybe should be optimized. The most
+ common is the NEXTing idiom for if(), which looks like this:
+
+ DO (1) NEXT
+ block 2
+ escape via NEXTING or COMEFROM
+ (1) DO (2) NEXT
+ DO FORGET #1
+ block 1
+
+ and elsewhere in the program:
+ (2) DO RESUME <1-or-2-condition>
+
+ Recognizing this idiom is quite difficult because there are a number of
+ problems and common variations.
+ First, the FORGET might be placed elsewhere, or replaced with a higher
+ FORGET later or a higher RESUME later. If there is, in fact, a RESUME #1
+ as the next NEXT-control statement, the idiom won't quite work properly.
+ So to handle this, we need to push the original return address on the
+ NEXT stack if block 1 is taken, unless the next statement is a FORGET #1.
+ Second, there may be abstentions or COME FROMs messing with control flow
+ in the area. The flow optimizer ought to be able to detect this and not
+ optimize the statement if true. (This means that a program which uses
+ gerund abstention on NEXTING or RESUMING, or that uses computed COME FROM,
+ will probably not benefit from this optimization). Third, how should a
+ <1-or-2-condition> be detected? Throughout syslib, the most common
+ condition to use is .5, which isn't inherently 1 or 2. The way round this
+ seems to be to detect a <1-or-2-assignment> as the previous statement,
+ again with checks for COME FROM and abstentions. (I treat MAYBE as a sort
+ of abstention, albeit a temporally undecided one.) So ignorance of the
+ relevant variable needs to be checked for also. The checks are done partly
+ in optimizef() and partly in emit().
+ */
+ if(compucomesused) return; /* That's one check out of the way! */
+
+ np = (node*) NULL;
+ for (tp = tuples; tp < tuples + lineno; tp++)
+ {
+ if(tp->type == GETS)
+ {
+ if(tp->u.node->rval->opcode == C_AND1ADD1 ||
+ tp->u.node->rval->opcode == C_2SUBAND1 ||
+ (tp->u.node->rval->opcode == C_1PLUS ||
+ tp->u.node->rval->opcode == C_2MINUS) &&
+ tp->u.node->rval->rval->optdata == 1)
+ {
+ /* This won't catch all <1-or-2-expressions>, but will get
+ most of them. */
+ if(tp->u.node->lval->opcode != SUB) np = tp->u.node->lval;
+ }
+ else if(np&&nodessame(np, tp->u.node->lval)) np = (node*) NULL;
+ if(tp->nextable) np = (node*) NULL;
+ if(tp->maybe||tp->abstainable) np = (node*) NULL;
+ if(tp->ncomefrom&&multithread) np = (node*) NULL;
+ if(np)
+ { /* IGNORING np might prevent it getting its <1-or-2-value>. */
+ atom* op;
+ int ignorable = 1;
+ for(op = oblist; op < obdex; op++)
+ {
+ if(op->type == np->opcode &&
+ op->intindex == np->constant)
+ {
+ ignorable &= op->ignorable;
+ }
+ }
+ if(ignorable) np = (node*) NULL;
+ }
+ /* np will only have a nonnull value if it's a variable that must be
+ set to a <1-or-2-value> to reach line tp. Regardless of whether
+ maybes have been parsed or not, either maybe or abstainable or
+ both will be 1 on a MAYBE line. The last check is a precaution
+ against MAYBE COME FROM sneakily modifying a variable (although
+ I think it's unlikely that anyone would deliberately try to fool
+ -f like this, it is INTERCAL after all!) */
+ }
+ if(tp->type == COME_FROM || tp->type == COMPUCOME) np = (node*) NULL;
+ if(tp->type == NEXT)
+ {
+ tpa = tuples + tp->nexttarget - 1;
+ if(tpa->type == NEXT && !tp->abstainable && !tpa->abstainable
+ && !tp->ncomefrom && !tpa->ncomefrom)
+ {
+ tpb = tuples + tpa->nexttarget - 1;
+ if(tpb->type == RESUME && ((tpb->u.node->opcode == C_AND1ADD1 ||
+ tpb->u.node->opcode == C_2SUBAND1 ||
+ (tpb->u.node->opcode == C_1PLUS ||
+ tpb->u.node->opcode == C_2MINUS) &&
+ tpb->u.node->rval->optdata == 1) ||
+ np&&nodessame(tpb->u.node,np))&&
+ !tpb->abstainable) /* No COMING FROM a nonabstainable RESUME line! */
+ {
+ tp->optversion = TRUE;
+ tp->u.node = nodecopy(tpb->u.node);
+ /* If tp->u.node is 2, then the statement should translate to a
+ no-op (NEXT...NEXT...RESUME #2). However, if tp->u.node is 1,
+ the statement should translate to a NEXT to the line after the
+ one it's aiming for. As it's aiming for a NEXT, the solution is
+ to NEXT to the return label of the NEXT it's aiming for. This
+ won't trigger any COME FROMs or ONCE/AGAIN flags, or even MAYBEs,
+ on the commands missed out, so the code has checked that they
+ aren't there. */
+ }
+ }
+ np = (node*) NULL;
+ }
+ }
+}
+
+/*************************************************************************
+ *
+ * Expression optimizer.
*
* It's not a very good optimizer, is it?
*
+ * AIS: All free'd pointers set to NULL, to help trace memory problems.
+ * The optimizer can now recognize the majority of syslib's idioms.
+ * The optimizer will make multiple passes. Although I am now happy
+ * with the quality of this optimizer, I'll keep the paragraph above
+ * this one for history's sake. The optimizing functions return 1
+ * if any optimizations were made, apart from optimize itself, which
+ * is void.
+ *
**************************************************************************/
+static int optimize_pass1(node *np);
+static int optimize_pass2(node *np);
+static void checkforintercaloperators(node *np);
+static void checkW534(node *np);
+
+static node* optdebugnode;
+
+/* This function by AIS */
void optimize(node *np)
{
- node *mingleop, *op;
+ int optflag;
+ checknodeactbits(np);
+ checkW534(np); /* This must be done before optimization, and depends on
+ checknodeactbits. */
+ if(optdebug == 1) explexpr(np,stderr);
+ if(optdebug == 1) fprintf(stderr," becomes ");
+ if(optdebug >= 2) optdebugnode = np;
+ optimize_pass1(np); /* Optimize idioms */
+ if(Base!=2)
+ {
+ if(optdebug && optdebug != 3) explexpr(np,stderr);
+ if(optdebug == 3) prexpr(np,stderr,0);
+ if(optdebug) fprintf(stderr,"\n");
+ if(optdebug >= 2) fprintf(stderr,"-----\n");
+ return;
+ }
+ do
+ {
+ checknodeactbits(np); /* Determine bitranges */
+ optflag = optimize_pass2(np); /* Optimize based on those bitranges */
+ optflag |= optimize_pass1(np);
+ } while(optflag); /* Keep optimizing until no optimizations are found */
+ if(optdebug && optdebug != 3) explexpr(np,stderr);
+ if(optdebug == 3) prexpr(np,stderr,0);
+ if(optdebug) fprintf(stderr,"\n");
+ if(optdebug >= 2) fprintf(stderr,"-----\n");
+ checkforintercaloperators(np);
+ if(optuple->type == RESUME && !np->optdata) optuple->warn622 = 1;
+}
- /* recurse so we simplify each node after all its subnodes */
+/* By AIS. This relies on free'd pointers being NULLed. */
+static void nodefree(node *np)
+{
+ if(!np) return;
+ nodefree(np->lval);
+ nodefree(np->rval);
+ free(np);
+}
+
+/* By AIS. This checks W534. */
+static void checkW534(node *np)
+{
+ if(!np) return;
+ if(np->opcode == AND || np->opcode == OR || np->opcode == XOR)
+ {
+ if(np->rval->opcode == SELECT && np->rval->rval->width == 32 &&
+ !(np->rval->rval->optdata&0xffff0000lu))
+ {
+ /* This looks suspicious, in that C-INTERCAL will do an op32,
+ but INTERCAL-72 would have done an op16. */
+ optuple->warn534=1;
+ }
+ }
+ checkW534(np->lval);
+ checkW534(np->rval);
+}
+
+/* By AIS. This checks W018. */
+static void checkforintercaloperators(node *np)
+{
+ if(!np) return;
+ switch(np->opcode)
+ { /* This only comes up in binary. */
+ case AND: case OR: case XOR: case MINGLE: case SELECT:
+ optuple->warn018 = 1;
+ default:
+ checkforintercaloperators(np->lval);
+ checkforintercaloperators(np->rval);
+ return;
+ }
+}
+
+/* By AIS (with a few code fragments copied from elsewhere in this file) */
+static void checknodeactbits(node *np)
+{
+ if (np == (node *)NULL)
+ return;
+ else if (np->lval != (node *)NULL)
+ checknodeactbits(np->lval);
+ if (np->rval != (node *)NULL)
+ checknodeactbits(np->rval);
+
+ switch (np->opcode)
+ {
+ case MINGLE:
+ if(np->lval->optdata & 0xffff0000LU) optuple->warn276 = 1;
+ if(np->rval->optdata & 0xffff0000LU) optuple->warn276 = 1;
+ np->optdata = mingle(np->lval->optdata & 0xffff,
+ np->rval->optdata & 0xffff);
+ /* The bitmask is needed because the output of ~ might always be 16-bit
+ at runtime, but appear 32-bit at compile-time. But this is somewhat
+ suspicious, so we can at least give a warning (W276) if -l is used. */
+ break;
+
+ case SELECT:
+ np->optdata = np->lval->optdata & np->rval->optdata;
+ np->optdata = iselect(np->optdata, np->optdata);
+ break;
+
+ case AND:
+ np->optdata = (np->width==16?and16:and32)(np->rval->optdata);
+ break;
+
+ case OR:
+ case XOR:
+ np->optdata = (np->width==16?or16:or32)(np->rval->optdata);
+ /* This is or in both cases. */
+ break;
+
+ case FIN:
+ case WHIRL:
+ case WHIRL2:
+ case WHIRL3:
+ case WHIRL4:
+ case WHIRL5: /* We must be in binary to reach this point, so: */
+ lose(E997, emitlineno, (char*) NULL);
+ break;
+
+ case MESH:
+ case MESH32:
+ np->optdata = np->constant; /* It's trivial to tell which bits
+ can be nonzero! */
+ break;
+
+ case ONESPOT:
+ case TWOSPOT:
+ case TAIL:
+ case HYBRID:
+ case SUB:
+ np->optdata = np->width == 16 ? 0xffff : 0xffffffffLU;
+ break;
+
+ /* cases from here down are generated by optimize_pass1 */
+ case C_AND:
+ np->optdata = np->lval->optdata & np->rval->optdata;
+ break;
+
+ case C_OR:
+ case C_XOR:
+ np->optdata = np->lval->optdata | np->rval->optdata;
+ /* bitwise-or is correct in both cases */
+ break;
+
+ case C_NOT:
+ np->optdata = np->width == 16 ? 0xffff : 0xffffffffLU;
+ break;
+
+ case C_NOTEQUAL:
+ case C_NNAND:
+ case C_ISNONZERO:
+ case C_XORGREATER:
+ np->optdata = 1; /* that's what !! does! */
+ break;
+
+ case C_AND1ADD1:
+ case C_2SUBAND1:
+ np->optdata = 3; /* the value could be 1 or 2 */
+ break;
+
+ case C_1PLUS:
+ np->optdata = np->rval->optdata | (np->rval->optdata << 1);
+ /* this relies on unsigned overflow handling to work correctly */
+ break;
+
+ case C_2MINUS:
+ if(np->rval->optdata == 1) np->optdata = 3;
+ else np->optdata = (np->width == 16 ? 0xffff : 0xfffffffflu);
+ /* alright, so this might not be ruthless enough, but C_2MINUS is
+ only meant to be generated when the condition is true anyway */
+ break;
+
+ case C_LSHIFT:
+ np->optdata = (np->lval->optdata & np->rval->optdata) << 1;
+ break;
+
+ case C_LSHIFTIN1:
+ np->optdata = ((np->lval->optdata & np->rval->optdata) << 1) | 1;
+ break;
+
+ case C_LSHIFT2:
+ np->optdata = (np->lval->optdata & np->rval->optdata) << 2;
+ break;
+
+ case C_LSHIFT8:
+ np->optdata = (np->lval->optdata & np->rval->optdata) << 8;
+ break;
+
+ case C_RSHIFTBY:
+ if(np->rval->opcode == MESH || np->rval->opcode == MESH32)
+ np->optdata = np->lval->optdata >> np->rval->constant;
+ else np->optdata = (np->width == 16 ? 0xffff : 0xffffffffLU);
+ /* Just like C_2MINUS, play safe if the RHS isn't a constant */
+ break;
+
+ case C_RSHIFT:
+ np->optdata = (np->lval->optdata & np->rval->optdata) >> 1;
+ break;
+
+ case GETS:
+ /* Of course, this doesn't return a value. So this uses the default
+ code just below it, which is why it doesn't end in break;. This
+ has its own case so that W276 can be given on an assignment. */
+ if(np->lval->optdata == 0xffff &&
+ np->rval->optdata & 0xffff0000lu) optuple->warn276 = 1;
+ /* no break;! */
+
+ default:
+ if(np->opcode == BY && !np->lval->optdata) optuple->warn239 = 1;
+ np->optdata = (np->width == 16 ? 0xffff : 0xffffffffLU);
+ /* Some values of opcode are used as placeholders, to save more than 1
+ piece of information in a node. The optdata for these is probably
+ irrelevant, but just in case, we mark all possible bits as active. */
+ break;
+ }
+}
+
+/* This function by AIS. Pass 2 removes redundant logical operations,
+ mostly explicit and implied C_AND. It destroys information needed by
+ Pass 1, which is why it's in a separate function. */
+static int optimize_pass2(node *np)
+{
+ node *op;
+ int opted = 0;
+ /* AIS: Paraphrased from code in the old 'optimize' function */
+ /* recurse so we simplify each node after all its subnodes */
+ if (np == (node *)NULL)
+ return 0;
+ else if (np->lval != (node *)NULL)
+ opted |= optimize_pass2(np->lval);
+ if (np->rval != (node *)NULL)
+ opted |= optimize_pass2(np->rval);
+ /* End of paraphrase */
+
+ /* Put constants of AND-like opcodes on the right */
+ if((np->opcode == C_AND || np->opcode == C_NNAND ||
+ np->opcode == C_LSHIFT || np->opcode == C_LSHIFTIN1 ||
+ np->opcode == C_LSHIFT2 || np->opcode == C_LSHIFT8 ||
+ np->opcode == C_RSHIFT) &&
+ (np->lval->opcode == MESH || np->lval->opcode == MESH32))
+ {
+ OPTING(andlikeconstmove)
+ op = np->lval;
+ np->lval = np->rval;
+ np->rval = op;
+ }
+
+ /* The implicit &1 in C_AND1ADD1 and C_2SUBAND1 may be removable. */
+ if(np->opcode == C_AND1ADD1 && np->rval->optdata == 1)
+ {
+ OPTING(impand1a1)
+ np->opcode = C_1PLUS;
+ }
+ if(np->opcode == C_2SUBAND1 && np->rval->optdata == 1)
+ {
+ OPTING(impand12m)
+ np->opcode = C_2MINUS;
+ }
+
+ if(np->opcode == C_AND && (np->rval->opcode == MESH ||
+ np->rval->opcode == MESH32) &&
+ !(np->lval->optdata & ~np->rval->constant))
+ {
+ OPTING(unneededand)
+ /* This AND is unnecessary. optdata stays the same. */
+ op = np->lval;
+ free(np->rval);
+ *np = *op;
+ free(op);
+ }
+
+ if((np->opcode == C_NNAND || np->opcode == C_RSHIFT) &&
+ (np->rval->opcode == MESH || np->rval->opcode == MESH32) &&
+ !(np->lval->optdata & ~np->rval->constant))
+ {
+ /* The implicit AND here is unneccesary. Eliminate it. */
+ OPTING(unneededimpand)
+ if(np->opcode == C_RSHIFT)
+ {
+ np->rval->constant = 1;
+ np->rval->optdata = 1;
+ np->opcode = C_RSHIFTBY;
+ }
+ else
+ {
+ np->opcode = C_ISNONZERO;
+ free(np->rval);
+ np->rval = np->lval;
+ np->lval = (node*) NULL;
+ }
+ }
+
+ if((np->opcode == C_AND || np->opcode == C_NNAND ||
+ np->opcode == C_LSHIFT || np->opcode == C_LSHIFTIN1 ||
+ np->opcode == C_LSHIFT2 || np->opcode == C_LSHIFT8 ||
+ np->opcode == C_RSHIFT) && np->lval->opcode == C_AND &&
+ (np->rval->opcode == MESH || np->rval->opcode == MESH32) &&
+ (np->lval->rval->opcode == MESH || np->lval->rval->opcode == MESH32))
+ {
+ OPTING(combineand)
+ /* Combine the two ANDs into one. (The AND at np may be implicit.)
+ Leave opdata the same. */
+ np->rval->constant &= np->lval->rval->constant;
+ op = np->lval;
+ free(op->rval);
+ np->lval = op->lval;
+ free(op);
+ }
+
+ if((np->opcode == C_AND || np->opcode == C_NNAND ||
+ np->opcode == C_LSHIFT || np->opcode == C_LSHIFTIN1 ||
+ np->opcode == C_LSHIFT2 || np->opcode == C_LSHIFT8 ||
+ np->opcode == C_RSHIFT) &&
+ (np->rval->opcode == MESH || np->rval->opcode == MESH32) &&
+ (~np->lval->optdata & np->rval->constant))
+ {
+ OPTING(weakenand)
+ /* Reduce the constant in this C_AND-like expression
+ to aid further optimization */
+ np->rval->constant &= np->lval->optdata;
+ }
+ return opted;
+}
+
+/* Pass 1. Optimizes idioms. */
+static int optimize_pass1(node *np) /* AIS: was 'optimize'. Recursive calls in
+ here have been updated. */
+{
+ node *mingleop, *op, *op2;
+ unsigned long temp;
+ int temp2;
+ int opted = 0;
+
+ /* recurse so we simplify each node after all its subnodes
+ AIS: Keep track of whether we've optimized anything. I added
+ all uses of the variable 'opted', and a return value. */
if (np == (node *)NULL)
- return;
+ return 0;
else if (np->lval != (node *)NULL)
- optimize(np->lval);
+ opted |= optimize_pass1(np->lval);
if (np->rval != (node *)NULL)
- optimize(np->rval);
+ opted |= optimize_pass1(np->rval);
/*
* OK, now do complete folding of constant expressions.
/* fold MINGLE operations on constants */
if (np->opcode==MINGLE && (np->lval->opcode==MESH&&np->rval->opcode==MESH))
{
+ OPTING(minglefold)
np->opcode = MESH32;
np->constant = mingle(np->lval->constant, np->rval->constant);
free(np->lval);
free(np->rval);
+ np->lval=(node*)NULL;
+ np->rval=(node*)NULL;
}
/* fold SELECT operations on constants */
&& ((np->lval->opcode==MESH || np->lval->opcode==MESH32)
&& (np->rval->opcode==MESH || np->rval->opcode==MESH32)))
{
+ OPTING(selectfold)
np->opcode = np->rval->opcode;
np->constant = iselect(np->lval->constant, np->rval->constant);
free(np->lval);
free(np->rval);
+ np->lval=(node*)NULL;
+ np->rval=(node*)NULL;
}
/* fold AND operations on 16-bit constants */
if (np->opcode == AND && np->rval->opcode == MESH)
{
+ OPTING(and16fold)
np->opcode = MESH;
np->constant = and16(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/* fold AND operations on 32-bit constants */
if (np->opcode == AND && np->rval->opcode == MESH32)
{
+ OPTING(and32fold)
np->opcode = MESH32;
np->constant = and32(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/* fold OR operations on 16-bit constants */
if (np->opcode == OR && np->rval->opcode == MESH)
{
+ OPTING(or16fold)
np->opcode = MESH;
np->constant = or16(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/* fold OR operations on 32-bit constants */
if (np->opcode == OR && np->rval->opcode == MESH32)
{
+ OPTING(or32fold)
np->opcode = MESH32;
np->constant = or32(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/* fold XOR operations on 16-bit constants */
if (np->opcode == XOR && np->rval->opcode == MESH)
{
+ OPTING(xor16fold)
np->opcode = MESH;
np->constant = xor16(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/* fold XOR operations on 32-bit constants */
if (np->opcode == XOR && np->rval->opcode == MESH32)
{
+ OPTING(xor32fold)
np->opcode = MESH32;
np->constant = xor32(np->rval->constant);
free(np->rval);
+ np->rval=(node*)NULL;
}
/*
/* following optimizations only work in binary */
if (Base != 2)
- return;
+ return opted;
/* recognize the idioms for various C binary logical operations */
if (np->opcode == SELECT
&& mingleop->rval->width == 16
&& mingleop->lval->width == 16)
{
- np->lval = mingleop->lval;
+ OPTING(cbinlogop)
+ free(np->rval); /* AIS */
+
+ np->lval = mingleop->lval;
np->rval = mingleop->rval;
switch(op->opcode)
free(mingleop); free(op);
}
+ /* AIS: Sometimes C binary logical operations have a smaller rval->constant. */
+ if (np->opcode == SELECT
+ && (np->rval->opcode == MESH32||np->rval->opcode == MESH)
+ && (op = np->lval) && !(np->rval->constant&0xAAAAAAAALU)
+ && (op->opcode == AND || op->opcode == OR || op->opcode == XOR)
+ && (mingleop = op->rval) && mingleop->opcode == MINGLE
+ && mingleop->rval->width == 16
+ && mingleop->lval->width == 16)
+ {
+ unsigned long i=iselect(np->rval->constant,0x55555555LU);
+ if(i==iselect(i,i))
+ {
+ OPTING(smallcbinlogop)
+ np->lval = mingleop;
+
+ switch(op->opcode)
+ {
+ case AND: np->lval->opcode = C_AND; break;
+ case OR: np->lval->opcode = C_OR; break;
+ case XOR: np->lval->opcode = C_XOR; break;
+ default: lose(E778, yylineno, (char *)NULL);
+ }
+ np->opcode = C_AND;
+ np->rval->constant=i; /* np->rval->opcode already correct */
+
+ free(op);
+ }
+ }
+
/* recognize idioms for ~ */
if (np->opcode == C_XOR)
{
- if (np->rval->width == 16
+ /* AIS: Warning! We have to check again for C_XOR, else we will
+ be making use of the freed np->lval. This is not strictly necessary in
+ the first case. I added extra conditions to prevent np->lval being
+ used after deallocation, which is how I discovered the error in the
+ first place. (Some code elsewhere was messing up, and I suspected
+ memory allocation problems.) */
+ if (np->opcode == C_XOR && np->rval->width == 16
&& np->lval->opcode == MESH &&np->lval->constant == 0xffff)
{
+ OPTING(cnot1)
np->opcode = C_NOT;
free(np->lval);
+ np->lval=(node*)NULL;
}
- if (np->lval->width == 16
+ if (np->opcode == C_XOR && np->lval->width == 16
&& np->rval->opcode == MESH && np->rval->constant == 0xffff)
{
+ OPTING(cnot2)
np->opcode = C_NOT;
free(np->rval);
np->rval = np->lval;
+ np->lval=(node*)NULL;
}
- if (np->rval->width == 32
- && np->lval->opcode == MESH32 && np->lval->constant == 0xffffffffL)
+ if (np->opcode == C_XOR && np->rval->width == 32
+ && np->lval->opcode == MESH32 && np->lval->constant == 0xffffffffLU)
{
+ OPTING(cnot3)
np->opcode = C_NOT;
free(np->lval);
+ np->lval=(node*)NULL;
}
- if (np->lval->width == 32
- && np->rval->opcode == MESH32 && np->rval->constant == 0xffffffffL)
+ if (np->opcode == C_XOR && np->lval->width == 32
+ && np->rval->opcode == MESH32 && np->rval->constant == 0xffffffffLU)
{
+ OPTING(cnot4)
np->opcode = C_NOT;
free(np->rval);
np->rval = np->lval;
+ np->lval=(node*)NULL;
+ }
+ }
+
+ /* AIS: I wrote everything from here to the end of this function. */
+
+ /* recognize the idiom x~'pow(2,n)-1' */
+ if (np->opcode==SELECT&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ iselect(np->rval->constant,np->rval->constant)==np->rval->constant)
+ {
+ OPTING(pow2m1select)
+ np->opcode = C_AND; /* This is cheaper than both SELECT and C_NNAND.
+ lval, rval already correct. */
+ }
+
+ /* recognize the idiom x~pow(2,n). */
+ if (np->opcode==SELECT&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ iselect(np->rval->constant,np->rval->constant)==1) /* see, INTERCAL
+ operators can be
+ useful in C! */
+ {
+ OPTING(pow2select)
+ np->opcode = C_NNAND; /* lval, rval already correct. C_NNAND is cheaper
+ than iselect. */
+ if(np->rval->constant==1) np->opcode = C_AND;
+ }
+
+ /* recognize select-mingle combinations which can be replaced by &, | and
+ single bitshifts (there are five of these in total)
+ Most of these idioms are used when doing 32-bit logical operations
+ separately on odd and even bits. Although these optimizations can speed
+ up code containing them a bit, their main purpose is to replace the
+ expressions with a consistent, short form that later optimizations can
+ recognize. (In fact, some later optimizations are effectively
+ optimizations on the degenerated C code, not on the INTERCAL original.) */
+ if (np->opcode==MINGLE&&np->lval->opcode==SELECT&&
+ np->lval->rval->opcode==MESH32&&np->lval->rval->constant==0xaaaaaaaa)
+ {
+ OPTING(selectmingle1)
+ np->opcode=C_OR;
+ np->lval->opcode=C_AND;
+ op=np->rval;
+ np->rval=newnode();
+ np->rval->opcode=MINGLE;
+ np->rval->lval=newnode();
+ np->rval->lval->opcode=MESH;
+ np->rval->lval->width=16;
+ np->rval->lval->constant=0;
+ np->rval->rval=op;
+ np->rval->width=32;
+ optimize_pass1(np->rval);
+ optimize_pass1(np->lval);
+ /* replace (a~0xaaaaaaaa)$b with (a&0xaaaaaaaa)|(0$b)
+ if b is a constant, the recursive call to optimize does
+ constant folding */
+ if(np->opcode==C_OR&&np->lval->opcode==C_AND&&
+ np->rval->opcode==MESH32&&np->rval->constant==0)
+ { /* check the conditions again in case it's been optimized */
+ /* get rid of the C_OR */
+ np->opcode=C_AND;
+ op=np->lval;
+ np->lval=op->lval;
+ np->rval->constant=op->rval->constant;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->lval);
+ }
+ else if(np->opcode==C_OR&&np->lval->opcode==C_AND&&
+ np->rval->opcode==MESH32&&np->rval->constant==0x55555555)
+ { /* check the conditions again in case it's been optimized */
+ /* get rid of the C_AND */
+ op=np->lval;
+ np->lval=op->lval;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->lval);
+ }
+ }
+
+ if (np->opcode==MINGLE&&np->rval->opcode==SELECT&&
+ np->rval->rval->opcode==MESH32&&np->rval->rval->constant==0x55555555)
+ {
+ OPTING(selectmingle2)
+ np->opcode=C_OR;
+ np->rval->opcode=C_AND;
+ op=np->lval;
+ np->lval=newnode();
+ np->lval->opcode=MINGLE;
+ np->lval->rval=newnode();
+ np->lval->rval->opcode=MESH;
+ np->lval->rval->width=16;
+ np->lval->rval->constant=0;
+ np->lval->lval=op;
+ np->lval->width=32;
+ optimize_pass1(np->lval);
+ optimize_pass1(np->rval);
+ /* replace b$(a~0x55555555) with (a&0x55555555)|(b$0)
+ if b is a constant, the recursive call to optimize does
+ constant folding */
+ if(np->opcode==C_OR&&np->rval->opcode==C_AND&&
+ np->lval->opcode==MESH32&&np->lval->constant==0)
+ { /* check the conditions again in case it's been optimized */
+ /* get rid of the C_OR */
+ np->opcode=C_AND;
+ op=np->rval;
+ np->rval=op->lval;
+ np->lval->constant=op->rval->constant;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->rval);
+ }
+ else if(np->opcode==C_OR&&np->rval->opcode==C_AND&&
+ np->lval->opcode==MESH32&&np->lval->constant==0xaaaaaaaa)
+ { /* check the conditions again in case it's been optimized */
+ /* get rid of the C_AND */
+ op=np->rval;
+ np->rval=op->lval;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->rval);
+ }
+ }
+
+ if (np->opcode==MINGLE&&np->lval->opcode==SELECT&&
+ np->lval->rval->opcode==MESH32&&np->lval->rval->constant==0x55555555)
+ {
+ OPTING(selectmingle3)
+ np->opcode=C_OR;
+ np->lval->opcode=C_LSHIFT; /* (a&b)<<1 */
+ op=np->rval;
+ np->rval=newnode();
+ np->rval->opcode=MINGLE;
+ np->rval->lval=newnode();
+ np->rval->lval->opcode=MESH;
+ np->rval->lval->width=16;
+ np->rval->lval->constant=0;
+ np->rval->rval=op;
+ np->rval->width=32;
+ optimize_pass1(np->rval);
+ optimize_pass1(np->lval);
+ /* replace (a~0x55555555)$b with ((a&0x55555555)<<1)|(0$b)
+ if b is a constant, the recursive call to optimize does
+ constant folding */
+ if(np->opcode==C_OR&&np->lval->opcode==C_LSHIFT&&
+ np->rval->opcode==MESH32&&np->rval->constant==0)
+ { /* check the conditions again in case it's been optimized */
+ /* get rid of the C_OR */
+ np->opcode=C_LSHIFT;
+ op=np->lval;
+ np->lval=op->lval;
+ np->rval->constant=op->rval->constant;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->lval); /* 32-bit logic recognition */
+ }
+ }
+
+ if (np->opcode==MINGLE&&np->rval->opcode==SELECT&&
+ np->rval->rval->opcode==MESH32&&np->rval->rval->constant==0xaaaaaaaa)
+ {
+ OPTING(selectmingle4)
+ np->opcode=C_OR;
+ np->rval->opcode=C_RSHIFT; /* (a&b)>>1 */
+ op=np->lval;
+ np->lval=newnode();
+ np->lval->opcode=MINGLE;
+ np->lval->rval=newnode();
+ np->lval->rval->opcode=MESH;
+ np->lval->rval->width=16;
+ np->lval->rval->constant=0;
+ np->lval->lval=op;
+ np->lval->width=32;
+ optimize_pass1(np->lval);
+ optimize_pass1(np->rval);
+ /* replace b$(a~0xaaaaaaaa) with ((a&0xaaaaaaaa)>>1)|(b$0)
+ if b is a constant, the recursive call to optimize does
+ constant folding */
+ if(np->opcode==C_OR&&np->rval->opcode==C_RSHIFT&&
+ np->lval->opcode==MESH32&&np->lval->constant==0)
+ { /* check for these conditions again in case it's been optimized */
+ /* get rid of the C_OR */
+ np->opcode=C_RSHIFT;
+ op=np->rval;
+ np->rval=op->lval;
+ np->lval->constant=op->rval->constant;
+ free(op->rval);
+ free(op);
+ optimize_pass1(np->rval);
+ }
+ }
+
+ if(np->opcode==MINGLE&&(np->lval->opcode==MESH||
+ np->lval->opcode==MESH32)&&
+ np->lval->constant==0&&np->rval->opcode==C_LSHIFT&&
+ (np->rval->rval->opcode==MESH||np->rval->rval->opcode==MESH32)&&
+ np->rval->rval->constant==0x7fff&&np->rval->lval->opcode==SELECT&&
+ np->rval->lval->rval->opcode==MESH32&&np->rval->lval->rval->constant==
+ 0x2aaaaaaa)
+ {
+ OPTING(selectmingle5)
+ /* this is equivalent to (np->rval->lval->lval&0x2aaaaaaa)<<1 */
+ np->opcode=C_LSHIFT;
+ np->lval->opcode=MESH32;
+ np->lval->constant=0x2aaaaaaa;
+ op=np->rval;
+ np->rval=op->lval->lval;
+ free(op->lval->rval);
+ free(op->lval);
+ free(op->rval);
+ free(op);
+ }
+
+ /* recognize the idiom (x~x)~1 (already optimized to (x~x)&1). */
+
+ if (np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==1&&np->lval->opcode==SELECT&&
+ nodessame(np->lval->lval,np->lval->rval))
+/* (np->lval->lval->opcode==ONESPOT||np->lval->lval->opcode==TWOSPOT)&&
+ np->lval->lval->opcode==np->lval->rval->opcode&&
+ np->lval->lval->constant==np->lval->rval->constant)*/
+ {
+ OPTING(xselxsel1)
+ free(np->rval);
+ np->rval=np->lval->rval;
+ nodefree(np->lval->lval);
+ free(np->lval);
+ np->lval=(node*) NULL;
+ np->opcode = C_ISNONZERO;
+ }
+
+ /* recognize the idiom (x~y)~1 (already optimized to (x~y)&1) in other cases.
+ if (np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==1&&np->lval->opcode==SELECT)
+ {
+ OPTING(xselysel1)
+ np->opcode = C_NNAND;
+ free(np->rval);
+ np->rval = np->lval->rval;
+ op = np->lval;
+ np->lval = np->lval->lval;
+ free(op);
+ }
+ This idiom is commented out because I thought it simplified to !!(x & y),
+ and of course it doesn't. The next two idioms are (hopefully correct)
+ idioms that were inspired by this idea.
+ */
+
+ /* recognize the idiom (x ~ k) ~ 1 (ie (x ~ k) & 1) for constant k */
+ if(np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==1&&np->lval->opcode==SELECT&&
+ (np->lval->rval->opcode==MESH||np->lval->rval->opcode==MESH32))
+ {
+ OPTING(xselksel1)
+ np->opcode = C_NNAND;
+ free(np->rval);
+ np->rval = np->lval->rval;
+ op = np->lval;
+ np->lval = np->lval->lval;
+ free(op);
+ temp = 1;
+ if(np->rval->constant == 0) temp = 0; else
+ while(!(np->rval->constant % 2))
+ {
+ np->rval->constant /= 2;
+ temp *= 2;
}
+ np->rval->constant = temp;
+ /* So (x ~ k) ~ 1 optimizes to !!(x & n) where n is the lowest set
+ bit in k. */
+ }
+
+ /* recognize the idiom (k ~ x) ~ 1 (ie (k ~ x) & 1) where k is a power
+ of 2 minus 1 */
+ if (np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==1&&np->lval->opcode==SELECT&&
+ (np->lval->lval->opcode==MESH||np->lval->lval->opcode==MESH32)&&
+ iselect(np->lval->lval->constant,np->lval->lval->constant)==
+ np->lval->lval->constant)
+ {
+ OPTING(p2m1selxsel1)
+ np->opcode = C_NNAND;
+ free(np->rval);
+ np->rval = np->lval->rval;
+ op = np->lval;
+ np->lval = np->lval->lval;
+ free(op);
+ }
+
+ /* recognize idioms for left-shift and right-shift */
+ /* 16- or 32-bit right-shift by 1, not necessarily all the bits */
+ if(np->opcode==SELECT&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ iselect(np->rval->constant,np->rval->constant)<<1==np->rval->constant)
+ {
+ OPTING(rshift1)
+ np->opcode = C_RSHIFT; /* Keep rval as it tells us what to & with */
}
+
+ /* 16- or 32-bit right-shift by a higher number */
+ if(np->opcode==SELECT&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ iselect(xor32(np->rval->constant),xor32(np->rval->constant))==3&&
+ !(np->rval->constant&1))
+ {
+ OPTING(rshiftby)
+ np->opcode = C_RSHIFTBY;
+ temp2 = 0;
+ temp = np->rval->constant;
+ while(!(np->rval->constant&1))
+ {
+ np->rval->constant>>=1;
+ temp2++;
+ }
+ np->rval->constant = temp2;
+ op = np->lval;
+ np->lval = newnode();
+ np->lval->width = np->width;
+ np->lval->rval = newnode();
+ np->lval->opcode = C_AND;
+ np->lval->rval->opcode = np->rval->opcode;
+ np->rval->opcode = MESH;
+ np->lval->rval->width = np->rval->width;
+ np->rval->width = 16;
+ np->lval->rval->constant = temp;
+ np->lval->lval = op;
+ optimize_pass1(np->lval); /* not sure what good this will do, but it's good practice
+ to optimize newly created nodes, in case someone invents
+ a new optimization (this caught me out elsewhere) */
+ /* The joke with this optimization is that it comes out with more nodes than
+ when it started. However, under most implementations of C, & and >> are
+ significantly cheaper than iselect. */
+ }
+
+ /* 16-bit left-shift by 1 */
+ if(np->opcode==SELECT&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->lval->opcode==MINGLE&&(np->rval->constant & 0x55555555LU)==1&&
+ (np->lval->rval->opcode==MESH||np->lval->rval->opcode==MESH32)&&
+ (np->lval->rval->constant==0||np->lval->rval->constant==1))
+ {
+ unsigned long i=iselect(np->rval->constant, 0xaaaaaaaaLU);
+ if(i==iselect(i,i))
+ {
+ OPTING(lshift16by1)
+ np->opcode = np->lval->rval->constant?C_LSHIFTIN1:C_LSHIFT;
+ /* We can shift either a 1 or a 0 into the right end of the number. */
+ np->rval->constant=i; /* New effect of this node: (lval->lval & i)<<1 */
+ /* We know that np->rval has the right opcode. */
+ op=np->lval->lval;
+ free(np->lval);
+ np->lval=op;
+ }
+ }
+
+ /* 32-bit left-shift of a variable by 1 */
+ if(np->opcode==C_OR&&np->lval->opcode==C_LSHIFT&&
+ np->rval->opcode==C_LSHIFT)
+ do
+ { /* this is so we can break; out of the if */
+ temp=0;
+ if(np->lval->lval->opcode==MESH32&&
+ np->lval->lval->constant==0x55555555) temp++;
+ if(np->lval->rval->opcode==MESH32&&
+ np->lval->rval->constant==0x55555555) temp++;
+ if(np->rval->lval->opcode==MESH32&&
+ np->rval->lval->constant==0x55555555) temp++;
+ if(np->rval->rval->opcode==MESH32&&
+ np->rval->rval->constant==0x55555555) temp++;
+ if(temp!=1) break;
+ temp=0;
+ if(np->lval->lval->opcode==MESH32&&
+ np->lval->lval->constant==0x2aaaaaaa) temp++;
+ if(np->lval->rval->opcode==MESH32&&
+ np->lval->rval->constant==0x2aaaaaaa) temp++;
+ if(np->rval->lval->opcode==MESH32&&
+ np->rval->lval->constant==0x2aaaaaaa) temp++;
+ if(np->rval->rval->opcode==MESH32&&
+ np->rval->rval->constant==0x2aaaaaaa) temp++;
+ if(temp!=1) break;
+ /* found the two required constants. Now we need two
+ identical TWOSPOTs on opposite sides of the C_OR. */
+ temp=0xffffffff; /* who'd use that many variables? */
+ if(np->lval->lval->opcode==TWOSPOT&&
+ np->rval->lval->opcode==TWOSPOT&&
+ np->lval->lval->constant==
+ np->rval->lval->constant) temp=np->lval->lval->constant;
+ if(np->lval->lval->opcode==TWOSPOT&&
+ np->rval->rval->opcode==TWOSPOT&&
+ np->lval->lval->constant==
+ np->rval->rval->constant) temp=np->lval->lval->constant;
+ if(np->lval->rval->opcode==TWOSPOT&&
+ np->rval->lval->opcode==TWOSPOT&&
+ np->lval->rval->constant==
+ np->rval->lval->constant) temp=np->lval->rval->constant;
+ if(np->lval->rval->opcode==TWOSPOT&&
+ np->rval->rval->opcode==TWOSPOT&&
+ np->lval->rval->constant==
+ np->rval->rval->constant) temp=np->lval->rval->constant;
+ if(temp==0xfffffffff) break;
+ /* recognized a 32-bit leftshift */
+ OPTING(lshift32by1)
+ free(np->lval->lval);
+ free(np->lval->rval);
+ free(np->rval->lval);
+ free(np->rval->rval);
+ np->lval->opcode=TWOSPOT;
+ np->lval->constant=temp;
+ np->rval->opcode=MESH32;
+ np->rval->constant=0x7fffffff;
+ np->lval->lval=(node*)NULL;
+ np->lval->rval=(node*)NULL;
+ np->rval->lval=(node*)NULL;
+ np->rval->rval=(node*)NULL;
+ np->opcode=C_LSHIFT;
+ } while(0);
+
+ /* 16-bit left-shift by 2 */
+ if(np->opcode==C_LSHIFT&&np->lval->opcode==C_LSHIFT&&
+ np->rval->constant==np->lval->rval->constant)
+ {
+ OPTING(lshift16by2)
+ op=np->lval->lval;
+ np->opcode=C_LSHIFT2;
+ free(np->lval);
+ np->lval=op;
+ np->rval->constant>>=1;
+ }
+
+ /* An idiom for 16-bit left-shift by 8 is caught later. */
+
+ /* recognize the idiom '?x$#y'~#3, where y is 1 or 2
+ The ~ is already optimized to &. */
+ if(np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==3&&np->lval->opcode==XOR&&
+ np->lval->rval->opcode==MINGLE&&(mingleop=np->lval->rval)&&
+ (mingleop->rval->opcode==MESH||mingleop->rval->opcode==MESH32)&&
+ (mingleop->rval->constant==1||mingleop->rval->constant==2))
+ {
+ OPTING(xorto1or2)
+ /* This depends only on the rightmost bit of x, and y.
+ For y=1:
+ If 0, answer = 0x1
+ If 1, answer = 0x2
+ For y=2:
+ If 0, answer = 0x2
+ Id 1, answer = 0x1
+ */
+ np->opcode = mingleop->rval->constant==1?C_AND1ADD1:C_2SUBAND1;
+ free(np->rval);
+ np->rval=mingleop->lval;
+ free(mingleop->rval);
+ free(mingleop);
+ free(np->lval);
+ free(mingleop->rval);
+ np->lval=(node*)NULL;
+
+ /* np->rval could be an iselect of a variable with itself,
+ and not have been caught yet (because the &1 was implied,
+ not explicit). Catch this now. */
+ if(np->rval->opcode==SELECT&&
+ (np->rval->lval->opcode==ONESPOT||np->rval->lval->opcode==TWOSPOT)&&
+ np->rval->lval->opcode==np->rval->rval->opcode&&
+ np->rval->lval->constant==np->rval->rval->constant)
+ {
+ np->rval->opcode=C_ISNONZERO;
+ free(np->rval->lval);
+ np->rval->lval=(node*)NULL;
+ }
+
+ /* Even if that didn't work, iselect can still be replaced by nnand
+ (because we have an implicit (x~y)&1) */
+ if(np->rval->opcode==SELECT) np->rval->opcode=C_NNAND;
+
+ /* If we know np->rval must be 0 or 1 at runtime, we can optimize further
+ (to avoid (1&x)&1, (x&1)&1 or (!!x)&1) */
+ if(np->rval->opcode==C_NNAND||np->rval->opcode==C_ISNONZERO||
+ (np->rval->opcode==C_AND&&
+ (np->rval->lval->opcode==MESH||np->rval->lval->opcode==MESH32)
+ &&np->rval->lval->constant==1)
+ ||(np->rval->opcode==C_AND&&
+ (np->rval->rval->opcode==MESH||np->rval->rval->opcode==MESH32)
+ &&np->rval->rval->constant==1)
+ )
+ {
+ np->opcode=np->opcode==C_AND1ADD1?C_1PLUS:C_2MINUS;
+ }
+ }
+
+ /* optimize a select with 0xffffffff (already optimized to &) */
+ if(np->opcode==C_AND&&np->rval->opcode==MESH32&&
+ np->rval->constant==0xffffffff)
+ {
+ OPTING(noopand1r)
+ free(np->rval);
+ op=np->lval;
+ *np=*op; /* copy the whole node */
+ np->width=32;
+ free(op);
+ }
+ if(np->opcode==C_AND&&np->lval->opcode==MESH32&&
+ np->lval->constant==0xffffffff)
+ {
+ OPTING(noopand1l)
+ free(np->lval);
+ op=np->rval;
+ *np=*op; /* copy the whole node */
+ np->width=32;
+ free(op);
+ }
+
+ /* optimize complementing the odd or even bits of a 32-bit number */
+ /* complement odd bits, zero even bits */
+ if(np->opcode==C_LSHIFT&&np->rval->opcode==MESH32&&
+ np->rval->constant==0x55555555&&np->lval->opcode==XOR&&
+ np->lval->width==32&&np->lval->rval->opcode==C_OR&&
+ ((np->lval->rval->rval->opcode==MESH32&&np->lval->rval->rval->
+ constant==0x55555555&&((temp2 = 0),1))||
+ (np->lval->rval->lval->opcode==MESH32&&np->lval->rval->lval->
+ constant==0x55555555&&(temp2 = 1))))
+ {
+ OPTING(com1z0l)
+ /* optimizations so far have given us code which sets all even
+ bits of a 32-bit expression, xor32s it, selects the even bits
+ and left-shifts. This is equivalent to complementing all odd
+ bits of the number and zeroing the even bits. */
+ np->rval->constant = 0xaaaaaaaa;
+ np->lval->rval->opcode = C_AND;
+ op = temp2 ? np->lval->rval->lval : np->lval->rval->rval;
+ op->constant = 0xaaaaaaaa;
+ op = np->lval->rval;
+ free(np->lval);
+ np->lval = op;
+ np->opcode = C_XOR;
+ }
+
+ /* same optimization with np's operands exchanged */
+ if(np->opcode==C_LSHIFT&&np->lval->opcode==MESH32&&
+ np->lval->constant==0x55555555&&np->rval->opcode==XOR&&
+ np->rval->width==32&&np->rval->rval->opcode==C_OR&&
+ ((np->rval->rval->rval->opcode==MESH32&&np->rval->rval->rval->
+ constant==0x55555555&&((temp2 = 0),1))||
+ (np->rval->rval->lval->opcode==MESH32&&np->rval->rval->lval->
+ constant==0x55555555&&(temp2 = 1))))
+ {
+ OPTING(com1z0r)
+ /* optimizations so far have given us code which sets all even
+ bits of a 32-bit expression, xor32s it, selects the even bits
+ and left-shifts. This is equivalent to complementing all odd
+ bits of the number and zeroing the even bits. */
+ np->lval->constant = 0xaaaaaaaa;
+ np->rval->rval->opcode = C_AND;
+ op = temp2 ? np->rval->rval->lval : np->rval->rval->rval;
+ op->constant = 0xaaaaaaaa;
+ op = np->rval->rval;
+ free(np->rval);
+ np->rval = op;
+ np->opcode = C_XOR;
+ }
+
+ /* complement even bits, zero odd bits */
+ if(np->opcode==C_AND&&np->rval->opcode==MESH32&&
+ np->rval->constant==0x55555555&&np->lval->opcode==XOR&&
+ np->lval->width==32&&np->lval->rval->opcode==C_OR&&
+ np->lval->rval->rval->opcode==MESH32&&
+ np->lval->rval->rval->constant==0x55555555&&
+ np->lval->rval->lval->opcode==C_LSHIFT&&
+ np->lval->rval->lval->rval->opcode==MESH32&&
+ np->lval->rval->lval->rval->constant==0x55555555)
+ {
+ OPTING(com0z1)
+ /* There are another 7 ways this expression could be written.
+ However, this is the only way likely to be generated by
+ the rest of the optimizer. */
+ op=np->lval->rval->lval->lval;
+ free(np->lval->rval->lval->rval);
+ free(np->lval->rval->lval);
+ free(np->lval->rval->rval);
+ np->lval->opcode = C_AND;
+ np->opcode = C_XOR;
+ np->lval->lval = op;
+ np->lval->rval->opcode = MESH32;
+ np->lval->rval->lval = (node*) NULL;
+ np->lval->rval->rval = (node*) NULL;
+ np->lval->rval->constant = 0x55555555;
+ /* and np->rval is already correct! */
+ }
+
+ /* optimize no-op C_OR, C_AND, C_XOR
+ (some of these are produced as a result of earlier optimizations).
+ This sort of thing was also used in the days of INTERCAL-72 to
+ convert information to 16- or 32-bit representations. As C-INTERCAL
+ is almost untyped and the typechecker has already run, this can be
+ done safely. One of these cases has already been considered earlier
+ (the one generated by the code (something)~'#65535$#65535'), but it
+ is included it again to complete the list. */
+ /* (something op constant) */
+ if(np->opcode==C_OR&&(np->lval->opcode==MESH||np->lval->opcode==MESH32)
+ &&np->lval->constant==0)
+ {
+ OPTING(nooporl)
+ free(np->lval);
+ op=np->rval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_XOR&&(np->lval->opcode==MESH||np->lval->opcode==MESH32)
+ &&np->lval->constant==0)
+ {
+ OPTING(noopxorl)
+ free(np->lval);
+ op=np->rval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_AND&&(np->lval->opcode==MESH||np->lval->opcode==MESH32)
+ &&np->lval->constant==0xffffffff)
+ {
+ OPTING(noopandl)
+ free(np->lval);
+ op=np->rval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_OR&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)
+ &&np->rval->constant==0)
+ {
+ OPTING(nooporr)
+ free(np->rval);
+ op=np->lval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_XOR&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)
+ &&np->rval->constant==0)
+ {
+ OPTING(noopxorr)
+ free(np->rval);
+ op=np->lval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_AND&&(np->rval->opcode==MESH||np->rval->opcode==MESH32)
+ &&np->rval->constant==0xffffffff)
+ {
+ OPTING(noopandr)
+ free(np->rval);
+ op=np->lval;
+ *np=*op;
+ free(op);
+ }
+ /* something op itself */
+ if((np->opcode==C_AND||np->opcode==C_OR)&&nodessame(np->lval,np->rval))
+ {
+ OPTING(andoritself)
+ nodefree(np->rval);
+ op=np->lval;
+ *np=*op;
+ free(op);
+ }
+ if(np->opcode==C_XOR&&nodessame(np->lval,np->rval))
+ {
+ OPTING(xoritself)
+ nodefree(np->lval);
+ nodefree(np->rval);
+ np->opcode = (np->width==16?MESH:MESH32);
+ np->lval = (node*) NULL;
+ np->rval = (node*) NULL;
+ np->constant = 0;
+ }
+ /* repetitive implicit C_AND */
+ if(np->opcode==C_NNAND&&nodessame(np->lval,np->rval))
+ {
+ OPTING(reptimpand)
+ nodefree(np->lval);
+ np->lval = (node*) NULL;
+ np->opcode = C_ISNONZERO;
+ }
+
+ /* optimize 32-bit complement */
+ if(np->opcode==C_OR&&np->lval->opcode==C_XOR&&np->lval->lval->opcode==C_AND&&
+ np->rval->opcode==C_XOR&&np->rval->lval->opcode==C_AND&&
+ np->lval->rval->opcode==MESH32&&np->lval->lval->rval->opcode==MESH32&&
+ np->rval->rval->opcode==MESH32&&np->rval->lval->rval->opcode==MESH32&&
+ np->lval->rval->constant==np->lval->lval->rval->constant&&
+ np->rval->rval->constant==np->rval->lval->rval->constant&&
+ (np->lval->rval->constant^np->rval->rval->constant)==0xffffffff&&
+ nodessame(np->lval->lval->lval,np->rval->lval->lval))
+ {
+ OPTING(com32)
+ np->opcode = C_NOT;
+ np->width = 32;
+ free(np->rval->lval->lval);
+ free(np->rval->lval->rval);
+ free(np->rval->lval);
+ free(np->rval->rval);
+ free(np->rval);
+ op = np->lval->lval->lval;
+ free(np->lval->lval->rval);
+ free(np->lval->lval);
+ free(np->lval->rval);
+ free(np->lval);
+ np->rval = op;
+ np->lval = (node*)NULL;
+ }
+
+ /* If constant is on the left, move it to the right. This will
+ simplify checking for the remaining optimizations, while not
+ altering the effect of code that cannot be optimized further.
+ (There are furious debates within the C community as to
+ whether a constant should be written on the left or right of
+ an operation. The argument in favour of 'constant on the left'
+ is mainly that it's better at detecting a mistype of = for ==.
+ This code assumes that ick won't make that mistake.) */
+ if(np->opcode==C_LSHIFT||np->opcode==C_AND||np->opcode==C_OR||
+ np->opcode==C_XOR||np->opcode==C_NNAND||np->opcode==C_RSHIFT)
+ { /* all the above opcodes are symmetrical wrt their operands */
+ if(np->lval->opcode==MESH||np->lval->opcode==MESH32)
+ {
+ OPTING(constswitch)
+ op = np->lval;
+ np->lval = np->rval;
+ np->rval = op;
+ }
+ }
+
+ /* 32-bit logical operations on alternate bits.
+ At this point, they have been optimized
+ to an expression of the form op32(oddbits | evenbits)&0x55555555,
+ which is good but still uses the INTERCAL operator op32. We should
+ be able to optimize this using & | ^ and bitshifts. */
+ if((np->opcode==C_AND||np->opcode==C_LSHIFT)&&np->rval->opcode==MESH32&&
+ np->rval->constant==0x55555555&&np->lval->width==32&&
+ (np->lval->opcode==XOR||np->lval->opcode==OR||
+ np->lval->opcode==AND)&&np->lval->rval->opcode==C_OR)
+ do /* so we can break; out */
+ {
+ /* Check to see if the op32 is a C_OR of an oddbits and an
+ evenbits */
+ op=np->lval->rval;
+ temp2=0; /* |=1 for oddbits found, |=2 for evenbits found */
+ if(op->lval->opcode==C_AND&&op->lval->rval->opcode==MESH32&&
+ op->lval->rval->constant==0x55555555) temp2|=2;
+ if(op->lval->opcode==C_AND&&op->lval->rval->opcode==MESH32&&
+ op->lval->rval->constant==0xaaaaaaaa) temp2|=1;
+ if(op->rval->opcode==C_AND&&op->rval->rval->opcode==MESH32&&
+ op->rval->rval->constant==0x55555555) temp2|=2;
+ if(op->rval->opcode==C_AND&&op->rval->rval->opcode==MESH32&&
+ op->rval->rval->constant==0xaaaaaaaa) temp2|=1;
+ if(op->lval->opcode==C_LSHIFT&&op->lval->rval->opcode==MESH32&&
+ op->lval->rval->constant==0x55555555) temp2|=1;
+ if(op->lval->opcode==C_RSHIFT&&op->lval->rval->opcode==MESH32&&
+ op->lval->rval->constant==0xaaaaaaaa) temp2|=2;
+ if(op->rval->opcode==C_LSHIFT&&op->rval->rval->opcode==MESH32&&
+ op->rval->rval->constant==0x55555555) temp2|=1;
+ if(op->rval->opcode==C_RSHIFT&&op->rval->rval->opcode==MESH32&&
+ op->rval->rval->constant==0xaaaaaaaa) temp2|=2;
+ if(temp2!=3) break;
+ /* this expression can be optimized */
+ OPTING(shiftand)
+ if(np->lval->opcode==XOR) op->opcode=C_XOR;
+ if(np->lval->opcode==OR) op->opcode=C_OR;
+ if(np->lval->opcode==AND) op->opcode=C_AND;
+ if(np->opcode==C_LSHIFT)
+ {
+ /* odd-bit-ize the evenbits we found */
+ if(op->lval->rval->constant==0x55555555) op->lval->opcode=C_LSHIFT;
+ if(op->rval->rval->constant==0x55555555) op->rval->opcode=C_LSHIFT;
+ if(op->lval->rval->constant==0xaaaaaaaa) op->lval->opcode=C_AND;
+ if(op->rval->rval->constant==0xaaaaaaaa) op->rval->opcode=C_AND;
+ } else {
+ /* even-bit-ize the oddbits we found */
+ if(op->lval->rval->constant==0x55555555) op->lval->opcode=C_AND;
+ if(op->rval->rval->constant==0x55555555) op->rval->opcode=C_AND;
+ if(op->lval->rval->constant==0xaaaaaaaa) op->lval->opcode=C_RSHIFT;
+ if(op->rval->rval->constant==0xaaaaaaaa) op->rval->opcode=C_RSHIFT;
+ }
+ /* What np should be is now in op */
+ free(np->lval);
+ free(np->rval);
+ *np=*op;
+ } while(0);
+
+ /* Optimize 32-bit logical expressions on the whole number.
+ At this point, the most common idiom for a 32-bit logical operation
+ (we write it here as %) looks like this:
+ ((a&0xaaaaaaaa)%(b&0xaaaaaaaa))|((a&0x55555555)%(b&0x55555555))
+ So first, we use distributive laws to simplify such constructions
+ further.
+
+ The distribution is done at a lower level of the expression tree,
+ but this is where it is done in the sequence of optimizations needed
+ to optimize a 32-bit expression. These optimizations are unlikely to
+ help in 16-bit code, because it's unlikely a programmer would take the
+ effort to code an expression like the ones below unless he/she had to.
+
+ Expressions that distribute:
+ (a&k)&(b&k) == (a&b)&k
+ (a|k)&(b|k) == (a&b)|k
+ (a&k)|(b&k) == (a|b)&k
+ (a|k)|(b|k) == (a|b)|k
+ (a&k)^(b&k) == (a^b)&k */
+ if((np->opcode==C_AND||np->opcode==C_OR||np->opcode==C_XOR)&&
+ (np->lval->opcode==C_AND||np->lval->opcode==C_OR)&&
+ !(np->lval->opcode==C_OR&&np->opcode==C_XOR)&&
+ np->lval->opcode==np->rval->opcode)
+ {
+ if(nodessame(np->lval->lval,np->rval->lval))
+ {
+ OPTING(distribll)
+ nodefree(np->lval->lval);
+ np->lval->lval = np->rval->rval;
+ np->lval->opcode = np->opcode;
+ np->opcode = np->rval->opcode;
+ op = np->rval;
+ np->rval = np->rval->lval;
+ free(op);
+ }
+ else if(nodessame(np->lval->rval,np->rval->lval))
+ {
+ OPTING(distribrl)
+ nodefree(np->lval->rval);
+ np->lval->rval = np->rval->rval;
+ np->lval->opcode = np->opcode;
+ np->opcode = np->rval->opcode;
+ op = np->rval;
+ np->rval = np->rval->lval;
+ free(op);
+ }
+ else if(nodessame(np->lval->lval,np->rval->rval))
+ {
+ OPTING(distriblr)
+ nodefree(np->lval->lval);
+ np->lval->lval = np->rval->lval;
+ np->lval->opcode = np->opcode;
+ np->opcode = np->rval->opcode;
+ op = np->rval;
+ np->rval = np->rval->rval;
+ free(op);
+ }
+ else if(nodessame(np->lval->rval,np->rval->rval))
+ {
+ OPTING(distribrr)
+ nodefree(np->lval->rval);
+ np->lval->rval = np->rval->lval;
+ np->lval->opcode = np->opcode;
+ np->opcode = np->rval->opcode;
+ op = np->rval;
+ np->rval = np->rval->rval;
+ free(op);
+ }
+ }
+
+ /* At this point, the 32-bit logical expression looks like this:
+ (with % substituting for &,|, or ^)
+ (0xaaaaaaaa|0x55555555)&(a%b)
+ Clearly, what is needed is a bit of constant folding on C_OR. We
+ might as well do C_AND and C_XOR while we're at it. This will get
+ done during the second run of optimize_pass1. */
+ if((np->opcode==C_AND||np->opcode==C_OR||np->opcode==C_XOR)&&
+ (np->lval->opcode==MESH||np->lval->opcode==MESH32)&&
+ (np->rval->opcode==MESH||np->rval->opcode==MESH32))
+ {
+ OPTING(clogopfold)
+ switch(np->opcode)
+ {
+ case C_AND: np->constant = np->lval->constant & np->rval->constant; break;
+ case C_OR: np->constant = np->lval->constant | np->rval->constant; break;
+ case C_XOR: np->constant = np->lval->constant ^ np->rval->constant; break;
+ default: lose(E778, yylineno, (char*) NULL);
+ }
+ free(np->lval);
+ np->lval = (node*) NULL;
+ free(np->rval);
+ np->rval = (node*) NULL;
+ np->opcode = np->width == 16 ? MESH : MESH32;
+ }
+
+ /* Somewhat incomprehensibly, there is a 32-bit right-shift in the
+ standard library that has been done using separation into even
+ and odd bits! This code recognizes that idiom, even though
+ surely it would have been simpler to select against
+ 0xfffffffe? (This would have been optimized much earlier in this
+ function, and would also be shorter and clearer. Perhaps the
+ obfuscation is the reason that it was written in separate bits.) */
+
+ /* Selecting something with 0x55555554, then mingling with 0,
+ right-shifts the even bits onto the odd bits. */
+ if(np->opcode==MINGLE&&np->lval->opcode==SELECT&&
+ (np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==0&&np->lval->rval->opcode==MESH32&&
+ np->lval->rval->constant==0x55555554)
+ {
+ OPTING(selminglershift)
+ np->opcode = C_RSHIFT;
+ np->rval->opcode = MESH32;
+ np->rval->width = 32;
+ np->rval->constant = 0x55555554;
+ free(np->lval->rval);
+ op = np->lval->lval;
+ free(np->lval);
+ np->lval = op;
+ }
+
+ /* Since it's such a stupid idiom anyway, we'll just optimize it the
+ way round that the standard library has it. It looks like this:
+ (((a&0x55555554)>>1)|((a&0xaaaaaaaa)>>1)) */
+ if(np->opcode==C_OR&&np->lval->opcode==C_RSHIFT&&
+ np->rval->opcode==C_RSHIFT&&np->lval->rval->opcode==MESH32&&
+ np->lval->rval->constant==0x55555554&&
+ np->rval->rval->opcode==MESH32&&np->rval->rval->constant==
+ 0xaaaaaaaa&&np->lval->lval->opcode==TWOSPOT&&
+ np->rval->lval->opcode==TWOSPOT&&np->lval->lval->constant==
+ np->rval->lval->constant)
+ {
+ OPTING(sillysyslibidiom)
+ op = np->lval;
+ free(np->rval->lval);
+ free(np->rval->rval);
+ free(np->rval);
+ op->rval->constant = 0xfffffffe;
+ *np = *op;
+ free(op);
+ optuple->warn128 = 1;
+ }
+
+ /* A more useful idiom in the standard library is on the
+ internal subroutine labelled (1525). It's an 8-bit
+ left-shift. In INTERCAL, this is done with repeated
+ mingling and selection. So far, the optimiser can only
+ recognize two leftshifts in the inside, because the rest
+ of the expression is written assuming that the low-bits
+ of the result are unset (which is correct after a two-bit
+ left-shift). This code recognizes the entire idiom straight
+ off, rather than optimizing in stages, after the optimization
+ of the inside to a double-leftshift. */
+ if(np->opcode==SELECT&&np->rval->opcode==MESH32&&
+ np->rval->constant==0xaaaaff&&np->lval->opcode==MINGLE&&
+ (np->lval->rval->opcode==MESH||np->lval->rval->opcode==MESH32)&&
+ np->lval->rval->constant==0&&np->lval->lval->opcode==SELECT&&
+ np->lval->lval->rval->opcode==MESH32&&
+ np->lval->lval->rval->constant==0xaaaaaaf&&
+ np->lval->lval->lval->opcode==MINGLE&&(
+ np->lval->lval->lval->rval->opcode==MESH||
+ np->lval->lval->lval->rval->opcode==MESH32)&&
+ np->lval->lval->lval->rval->constant==0&&
+ np->lval->lval->lval->lval->opcode==C_LSHIFT2&&(
+ np->lval->lval->lval->lval->rval->opcode==MESH||
+ np->lval->lval->lval->lval->rval->opcode==MESH32)&&
+ np->lval->lval->lval->lval->rval->constant==0x3fff)
+ {
+ OPTING(lshift8)
+ /* left-shift np->lval->lval->lval->lval->lval by 8 */
+ op = np->lval->lval->lval->lval->lval;
+ free(np->lval->lval->lval->lval->rval);
+ free(np->lval->lval->lval->lval);
+ free(np->lval->lval->lval->rval);
+ free(np->lval->lval->lval);
+ free(np->lval->lval->rval);
+ free(np->lval->lval);
+ free(np->lval->rval);
+ free(np->lval);
+ np->lval = op;
+ np->opcode = C_LSHIFT8;
+ np->rval->constant = 0x00ffffff;
+ }
+
+ /* recognize an idiom for ==, != */
+ if(np->opcode == C_ISNONZERO && np->rval->opcode == C_XOR)
+ {
+ OPTING(xortoequal)
+ np->opcode = C_NOTEQUAL;
+ op = np->rval;
+ np->lval = op->lval;
+ np->rval = op->rval;
+ free(op);
+ /* So !!(a ^ b), as in 1 + !!(a^b), has become (a!=b). */
+ }
+
+ /* Some of the remaining idioms depend on active-bit analysis */
+ checknodeactbits(np);
+ /* C binary logical operations can be done in 'expanded' form, that is, on
+ just oddbits or evenbits of a 32-bit number. */
+ if((np->opcode==C_AND || np->opcode==C_LSHIFT || np->opcode == C_LSHIFT2 ||
+ np->opcode==C_LSHIFT8 || np->opcode==C_LSHIFTIN1 || np->opcode==C_NNAND)
+ && (np->rval->opcode==MESH32 || np->rval->opcode==MESH)
+ && !(np->rval->constant & 0xaaaaaaaaLU))
+ {
+ unsigned long i=iselect(np->rval->constant, 0x55555555LU);
+ if(i==iselect(i,i) && (np->lval->opcode == OR ||
+ np->lval->opcode == AND ||
+ np->lval->opcode == XOR) &&
+ np->lval->rval->opcode==C_OR)
+ {
+ if(!(np->lval->rval->lval->optdata & 0x55555555LU) &&
+ !(np->lval->rval->rval->optdata & 0xaaaaaaaaLU) &&
+ (np->lval->rval->lval->opcode == C_AND ||
+ np->lval->rval->lval->opcode == C_LSHIFT ||
+ np->lval->rval->lval->opcode == MESH ||
+ np->lval->rval->lval->opcode == MESH32))
+ { /* recognized the idiom. Swap the C_OR round so we don't have to write
+ the code for this out twice. */
+ OPTING(clogopexpswitch)
+ op=np->lval->rval->rval;
+ np->lval->rval->rval=np->lval->rval->lval;
+ np->lval->rval->lval=op;
+ }
+ if(!(np->lval->rval->lval->optdata & 0xaaaaaaaaLU) &&
+ !(np->lval->rval->rval->optdata & 0x55555555LU) &&
+ (np->lval->rval->rval->opcode == C_AND ||
+ np->lval->rval->rval->opcode == C_LSHIFT ||
+ np->lval->rval->lval->opcode == MESH ||
+ np->lval->rval->lval->opcode == MESH32))
+ {
+ OPTING(clogopexpand)
+ op = np->lval->rval;
+ switch(np->lval->opcode)
+ {
+ case AND: op->opcode = C_AND; break;
+ case OR: op->opcode = C_OR; break;
+ case XOR: op->opcode = C_XOR; break;
+ default: lose(E778, yylineno, (char*) NULL);
+ }
+ free(np->lval);
+ np->lval = op;
+ if(np->lval->rval->opcode == MESH || np->lval->rval->opcode == MESH32)
+ np->lval->rval->constant >>= 1;
+ else np->lval->rval->opcode = np->lval->rval->opcode == C_AND ?
+ C_RSHIFT : C_AND;
+ if(np->opcode == C_LSHIFT&&(np->lval->lval->opcode == C_AND ||
+ np->lval->lval->opcode == C_RSHIFT ||
+ np->lval->lval->opcode == MESH ||
+ np->lval->lval->opcode == MESH32))
+ {
+ /* Instead of doing the calculation on the evenbits, do it on the
+ oddbits; that'll save a bitshift (possibly even save two
+ bitshifts). */
+ np->opcode = C_AND;
+ if(np->lval->lval->opcode == MESH ||
+ np->lval->lval->opcode == MESH32) np->lval->lval->constant <<= 1;
+ else np->lval->lval->opcode = np->lval->lval->opcode == C_AND ?
+ C_LSHIFT : C_AND;
+ if(np->lval->rval->opcode == MESH ||
+ np->lval->rval->opcode == MESH32) np->lval->rval->constant <<= 1;
+ else np->lval->rval->opcode = np->lval->rval->opcode == C_AND ?
+ C_LSHIFT : C_AND;
+ np->rval->constant <<= 1;
+ }
+ checknodeactbits(np); /* To calculate an improved active-bits value */
+ }
+ }
+ }
+
+ /* One common situation in which the previous idiom is used is a 32-bit
+ logic operation with a constant. The distributive law will not catch
+ such cases because even bits of the constant are used on one side and
+ odd bits of the constant are used on the other side, making the
+ expressions different. In syslib, the idiom is only used with the
+ constant equal to 0x80000000, leading to another problem; the logic
+ operation may not have been written at all on one side of the
+ expression, due to one parity set of bits having no effect. The
+ following code catches three cases involving 32-bit logical operations
+ with constants. Of course, some loony could theoretically write the
+ 16-bit version like this... */
+ if(np->opcode==C_OR&&(np->lval->opcode==C_AND||np->lval->opcode==C_XOR||
+ np->lval->opcode==C_OR||np->lval->opcode==C_LSHIFT||
+ np->lval->opcode==C_RSHIFT)&&
+ (np->rval->opcode==C_AND||np->rval->opcode==C_XOR||
+ np->rval->opcode==C_OR||np->rval->opcode==C_LSHIFT||
+ np->rval->opcode==C_RSHIFT)&&
+ !(np->lval->optdata&np->rval->optdata))
+ {
+ op = np->lval;
+ op2 = np->rval;
+ /* rely on the 'constant on the right' optimization */
+ if(op->opcode!=C_LSHIFT&&op->opcode!=C_RSHIFT)
+ if(op->lval->opcode==C_AND || op->lval->opcode==C_LSHIFT)
+ if(op->rval->opcode==MESH || op->rval->opcode==MESH32) op=op->lval;
+ if(op2->opcode!=C_LSHIFT&&op2->opcode!=C_RSHIFT)
+ if(op2->lval->opcode==C_AND || op2->lval->opcode==C_LSHIFT)
+ if(op2->rval->opcode==MESH || op2->rval->opcode==MESH32) op2=op2->lval;
+ if(nodessame(op->lval,op2->lval) &&
+ (op->rval->opcode==MESH||op->rval->opcode==MESH32) &&
+ (op2->rval->opcode==MESH||op2->rval->opcode==MESH32) &&
+ !(op->rval->constant&op2->rval->constant) &&
+ (op->opcode==op2->opcode) &&
+ (op->opcode==C_AND||op->opcode==C_LSHIFT||op->opcode==C_RSHIFT)&&
+ (op2->opcode==C_AND||op2->opcode==C_LSHIFT||op2->opcode==C_RSHIFT))
+ {
+ /* Now op and op2 are & or implied & (only <<, >>, & are at all likely
+ to be here), and have the same lval. The only check left is that
+ this does actually correspond to (something32 op constant), in
+ other words that there is exactly one possibility for op. */
+ if((np->lval==op||np->rval==op2||np->lval->opcode==np->rval->opcode)
+ &&(np->lval!=op||np->rval!=op2))
+ {
+ OPTING(clogopwithconst)
+ if(np->lval!=op) temp2=np->lval->opcode;
+ if(np->rval!=op2) temp2=np->rval->opcode;
+ if(np->lval==op) temp=np->rval->rval->constant;
+ else if(np->rval==op2) temp=np->lval->rval->constant;
+ else switch(temp2)
+ {
+ case C_AND:
+ temp = np->rval->rval->constant & np->lval->rval->constant; break;
+ case C_OR:
+ temp = np->rval->rval->constant | np->lval->rval->constant; break;
+ case C_XOR:
+ temp = np->rval->rval->constant ^ np->lval->rval->constant; break;
+ default: lose(E778, yylineno, (char*)NULL);
+ }
+ np->opcode = temp2;
+ np->rval->opcode = np->width==16 ? MESH : MESH32;
+ np->rval->constant = temp;
+ temp = op->rval->constant | op2->rval->constant;
+ nodefree(np->rval->lval);
+ nodefree(np->rval->rval);
+ np->rval->lval = (node*) NULL;
+ np->rval->rval = (node*) NULL;
+ if(np->lval!=op)
+ {
+ op2 = np->lval;
+ np->lval = op;
+ free(op2);
+ }
+ np->lval->rval->constant = temp;
+ if(np->lval->rval->constant>0xffff) np->lval->rval->opcode = MESH32;
+ optimize_pass1(np->lval);
+ /* it's pretty likely that there's an & with 0xffffffff here, although
+ not guaranteed, so reoptimize it */
+ }
+ }
+ }
+
+ /* Greater than/less than. The longest idiom in syslib, it stretches over 2
+ statements. The first statement will already be optimized to
+ :a <- (:b ^ :c) or similar. At this point in the code, the second
+ statement looks like ((:c ~ :a) ~ ((? (:a ~ :a)) ^ 0x80000000)) or
+ similar. (That's a 32-bit ?.) The idiom, obviously, also could work
+ with a 16-bit ? and 0x8000. The point is, it returns the bit of :c
+ that corresponds to the most significant set bit in :a, which is the
+ most significant bit that differs between :b and :c. So if this bit is
+ a 1, it means that :c is greater; if it's a 0, it means that :b is
+ greater, or the numbers are equal. optimize_pass1 only optimizes within
+ an expression, so we're going to render it as :c > (:a ^ :c). */
+ if(np->opcode==SELECT&&np->lval->opcode==SELECT&&np->rval->opcode==C_XOR&&
+ (np->rval->rval->opcode==MESH||np->rval->rval->opcode==MESH32)&&
+ np->rval->lval->opcode==XOR&&np->rval->lval->rval->opcode==SELECT&&
+ ((np->rval->lval->width==32&&np->rval->rval->constant==0x80000000LU)||
+ (np->rval->lval->width==16&&np->rval->rval->constant==0x8000))&&
+ nodessame(np->lval->rval,np->rval->lval->rval->lval)&&
+ nodessame(np->lval->rval,np->rval->lval->rval->rval))
+ {
+ temp=np->rval->lval->width;
+ if(temp==32||(np->lval->lval->width==16&&np->lval->rval->width==16&&
+ np->rval->lval->rval->lval->width==16&&
+ np->rval->lval->rval->rval->width==16))
+ {
+ OPTING(greaterthan)
+ nodefree(np->rval);
+ op = np->lval;
+ *np=*op;
+ free(op);
+ np->opcode = C_XORGREATER;
+ np->optdata = 1;
+ }
+ }
+
+ /* Many previous optimizations generate Boolean values. In INTERCAL,
+ Boolean algebra on these will be done with the familiar mingle,
+ unary, select routine. However, in many cases the 'select' will be
+ an implied &1, which could have been computed by many of the earlier
+ optimizations. These Boolean algebra operations are caught here. */
+ if((np->opcode==C_AND1ADD1||np->opcode==C_2SUBAND1||
+ ((np->opcode==C_AND||np->opcode==C_NNAND||np->opcode==C_LSHIFT||
+ np->opcode==C_RSHIFT||np->opcode==C_LSHIFT2||np->opcode==C_LSHIFT8||
+ np->opcode==C_LSHIFTIN1)&&
+ (np->rval->opcode==MESH||np->rval->opcode==MESH32)&&
+ np->rval->constant==1)))
+ {
+ if(np->opcode==C_AND1ADD1||np->opcode==C_2SUBAND1) op = np->rval;
+ else op = np->lval;
+ if((op->opcode==AND||op->opcode==OR||op->opcode==XOR)&&
+ op->rval->opcode==MINGLE)
+ {
+ OPTING(clogopand1)
+ mingleop = op->rval;
+ switch(op->opcode)
+ {
+ case AND: mingleop->opcode = C_AND; break;
+ case OR: mingleop->opcode = C_OR; break;
+ case XOR: mingleop->opcode = C_XOR; break;
+ default: lose(E778, yylineno, (char *) NULL);
+ }
+ free(op);
+ if(np->opcode==C_AND1ADD1||np->opcode==C_2SUBAND1)
+ np->rval = mingleop;
+ else np->lval = mingleop;
+ }
+ }
+
+ /* The next optimization is aided by splitting C_NNANDs when they are
+ the argument to C_OR. Two cases. */
+
+ if(np->opcode == C_OR && np->lval->opcode == C_NNAND)
+ {
+ OPTING(splitnnandinorl)
+ op = np->lval;
+ np->lval = cons(C_ISNONZERO, (node *) NULL, op);
+ np->lval->width = np->lval->rval->width;
+ np->lval->rval->opcode = C_AND;
+ np->lval->optdata = 1;
+ }
+
+ if(np->opcode == C_OR && np->rval->opcode == C_NNAND)
+ {
+ OPTING(splitnnandinorr)
+ op = np->rval;
+ np->rval = cons(C_ISNONZERO, (node *) NULL, op);
+ np->rval->width = np->rval->rval->width;
+ np->rval->rval->opcode = C_AND;
+ np->rval->optdata = 1;
+ }
+
+ /* We can save a small amount of time, and aid further optimization,
+ by undistributing C_ISNONZERO across C_OR. This is used in some tests
+ which produce Booolean output, when testing the oddbits and
+ evenbits separately. Unfortunately, this doesn't work for C_AND. */
+ if(np->opcode == C_OR && np->lval->opcode == C_ISNONZERO &&
+ np->rval->opcode == C_ISNONZERO)
+ {
+ OPTING(distribnon0overor)
+ np->opcode = C_ISNONZERO;
+ np->rval->opcode = C_OR;
+ np->rval->lval = np->lval->rval;
+ free(np->lval);
+ np->lval = 0;
+ optimize_pass1(np->rval); /* reoptimize this */
+ }
+
+ /* Recognize a C logical operation on just the oddbits or evenbits of a
+ number. Two cases (evenbits and oddbits). */
+
+ if (np->opcode==SELECT && np->rval->opcode==MESH32 &&
+ np->rval->constant==0x55555555LU &&
+ (np->lval->opcode==AND||np->lval->opcode==OR||np->lval->opcode==XOR) &&
+ np->lval->rval->opcode == C_OR &&
+ ((np->lval->rval->lval->opcode == C_LSHIFT &&
+ np->lval->rval->rval->opcode == C_AND) ||
+ (np->lval->rval->lval->opcode == C_AND &&
+ np->lval->rval->rval->opcode == C_LSHIFT)) &&
+ np->lval->rval->lval->rval->opcode == MESH32 &&
+ np->lval->rval->rval->rval->opcode == MESH32 &&
+ np->lval->rval->lval->rval->constant == 0x55555555LU &&
+ np->lval->rval->rval->rval->constant == 0x55555555LU)
+ {
+ OPTING(clogopevenbits)
+ switch(np->lval->opcode)
+ {
+ case AND: np->lval->rval->opcode = C_AND; break;
+ case OR: np->lval->rval->opcode = C_OR; break;
+ case XOR: np->lval->rval->opcode = C_XOR; break;
+ default: lose(E778, yylineno, (char *) NULL);
+ }
+ op = np->lval->rval;
+ free(np->lval);
+ np->lval = op;
+ op = np->lval->lval->lval;
+ free(np->lval->lval->rval);
+ free(np->lval->lval);
+ np->lval->lval = op;
+ op = np->lval->rval->lval;
+ free(np->lval->rval->rval);
+ free(np->lval->rval);
+ np->lval->rval = op;
+ }
+
+ if (np->opcode==SELECT && np->rval->opcode==MESH32 &&
+ np->rval->constant==0x55555555LU &&
+ (np->lval->opcode==AND||np->lval->opcode==OR||np->lval->opcode==XOR) &&
+ np->lval->rval->opcode == C_OR &&
+ ((np->lval->rval->lval->opcode == C_RSHIFT &&
+ np->lval->rval->rval->opcode == C_AND) ||
+ (np->lval->rval->lval->opcode == C_AND &&
+ np->lval->rval->rval->opcode == C_RSHIFT)) &&
+ np->lval->rval->lval->rval->opcode == MESH32 &&
+ np->lval->rval->rval->rval->opcode == MESH32 &&
+ np->lval->rval->lval->rval->constant == 0xAAAAAAAALU &&
+ np->lval->rval->rval->rval->constant == 0xAAAAAAAALU)
+ {
+ OPTING(clogopoddbits)
+ switch(np->lval->opcode)
+ {
+ case AND: np->lval->rval->opcode = C_AND; break;
+ case OR: np->lval->rval->opcode = C_OR; break;
+ case XOR: np->lval->rval->opcode = C_XOR; break;
+ default: lose(E778, yylineno, (char *) NULL);
+ }
+ op = np->lval->rval;
+ free(np->lval);
+ np->lval = op;
+ op = np->lval->lval->lval;
+ free(np->lval->lval->rval);
+ free(np->lval->lval);
+ np->lval->lval = op;
+ op = np->lval->rval->lval;
+ free(np->lval->rval->rval);
+ free(np->lval->rval);
+ np->lval->rval = op;
+ np->rval->constant = 0xAAAAAAAALU;
+ }
+
+ /* !!(a ~ b) can be weakened to !!(a & b) */
+ if(np->opcode == C_ISNONZERO && np->rval->opcode == SELECT)
+ {
+ OPTING(non0seltonnand)
+ np->lval = np->rval->lval;
+ op = np->rval->rval;
+ free(np->rval);
+ np->rval = op;
+ np->opcode = C_NNAND;
+ }
+ return opted;
}
/*************************************************************************
"GETS",
"RESIZE",
"NEXT",
+ "GO_AHEAD", /* AIS: Added for backtracking */
+ "GO_BACK", /* AIS: Added for backtracking */
"FORGET",
"RESUME",
"STASH",
"REINSTATE",
"DISABLE",
"ENABLE",
+ "MANYFROM", /* AIS: Added ABSTAIN expr FROM gerunds */
"GIVE_UP",
"READ_OUT",
"WRITE_IN",
"COME_FROM",
+ "COMPUCOME", /* AIS: Added COMPUCOME */
+ "TRY_AGAIN", /* AIS: Added TRY AGAIN */
+ "FROM", /* AIS: ABSTAIN expr FROM LABEL */
};
assoc vartypes[] =
return((char *)NULL);
}
-static void prexpr(node *np, FILE *fp);
+/* AIS: Code for printing explanations (mixed C/INTERCAL code that lets
+ the user know what the meaning of an expression is). This is paraphrased
+ from the prexpr/prvar code lower down. It's passed to yuk so that the
+ explain ('e') command works. It's also included in the degenerated C
+ code when the option -c is used, so the person looking at the code can
+ debug both the INTERCAL and ick itself more effectively, and used by
+ -h to produce its optimizer-debug output. */
+
+unsigned long varextern(unsigned long intern, int vartype)
+{
+ atom *x;
+ if(!oblist) lose(E778, emitlineno, (char*) NULL);
+ for (x = oblist; x < obdex; x++)
+ if (x->type == vartype && x->intindex == intern)
+ return(x->extindex);
+ lose(E778, emitlineno, (char*) NULL);
+}
+
+static void explvar(node* np, FILE* fp)
+{
+ node *sp;
+ switch(np->opcode)
+ {
+ case ONESPOT:
+ (void) fprintf(fp, ".%lu", varextern(np->constant,ONESPOT));
+ break;
+ case TWOSPOT:
+ (void) fprintf(fp, ":%lu", varextern(np->constant,TWOSPOT));
+ break;
+ case TAIL:
+ (void) fprintf(fp, ",%lu", varextern(np->constant,TAIL));
+ break;
+ case HYBRID:
+ (void) fprintf(fp, ";%lu", varextern(np->constant,HYBRID));
+ break;
+ case SUB:
+ (void) fprintf(fp, "(");
+ explvar(np->lval, fp);
+ (void) fprintf(fp, " SUB ");
+ for (sp = np->rval ; sp ; sp = sp->rval)
+ explexpr(sp->lval, fp);
+ (void) fprintf(fp, ")");
+ break;
+ default:
+ lose(E778, emitlineno, (char*) NULL);
+ }
+}
+
+/* unlike prexpr, this doesn't free its operands */
+void explexpr(node* np, FILE* fp)
+{
+ if(!np) return;
+ switch (np->opcode)
+ {
+ case MINGLE:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " $ ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case SELECT:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " ~ ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case AND:
+ (void) fprintf(fp, "(& ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case OR:
+ (void) fprintf(fp, "(V ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case XOR:
+ (void) fprintf(fp, "(? ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case FIN:
+ if (Base < 3)
+ lose(E997, emitlineno, (char *)NULL);
+ (void) fprintf(fp, "(^ ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case WHIRL:
+ case WHIRL2:
+ case WHIRL3:
+ case WHIRL4:
+ case WHIRL5:
+ if (np->opcode - WHIRL + 3 > Base)
+ lose(E997, emitlineno, (char *)NULL);
+ if(np->opcode == WHIRL)
+ (void) fprintf(fp, "(@ ");
+ else
+ (void) fprintf(fp, "(%d@ ", np->opcode - WHIRL + 1);
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case MESH:
+ (void) fprintf(fp, "0x%lx", np->constant);
+ break;
+
+ case MESH32:
+ (void) fprintf(fp, "0x%lx", np->constant);
+ break;
+
+ case ONESPOT:
+ case TWOSPOT:
+ case TAIL:
+ case HYBRID:
+ case SUB:
+ explvar(np, fp);
+ break;
+
+ /* cases from here down are generated by the optimizer */
+ case C_AND:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_OR:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " | ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_XOR:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " ^ ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_NOT:
+ (void) fprintf(fp, "(~ ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_NOTEQUAL:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " != ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_NNAND:
+ (void) fprintf(fp, "(!!(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, "))");
+ break;
+
+ case C_AND1ADD1:
+ (void) fprintf(fp, "((");
+ explexpr(np->rval,fp);
+ (void) fprintf(fp, " & 0x1) + 0x1)");
+ break;
+
+ case C_1PLUS:
+ (void) fprintf(fp, "(");
+ explexpr(np->rval,fp);
+ (void) fprintf(fp, " + 0x1)");
+ break;
+
+ case C_2MINUS:
+ (void) fprintf(fp, "(0x2 - ");
+ explexpr(np->rval,fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_2SUBAND1:
+ (void) fprintf(fp, "(0x2 - (");
+ explexpr(np->rval,fp);
+ (void) fprintf(fp, " & 0x1))");
+ break;
+
+ case C_LSHIFT:
+ (void) fprintf(fp, "((");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ") << 0x1)");
+ break;
+
+ case C_LSHIFTIN1:
+ (void) fprintf(fp, "(((");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ") << 0x1) | 0x1)");
+ break;
+
+ case C_LSHIFT2:
+ (void) fprintf(fp, "((");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ") << 0x2)");
+ break;
+
+ case C_LSHIFT8:
+ (void) fprintf(fp, "((");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ") << 0x8)");
+ break;
+
+ case C_RSHIFTBY:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " >> ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_RSHIFT:
+ (void) fprintf(fp, "((");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " & ");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ") >> 0x1)");
+ break;
+
+ case C_XORGREATER:
+ (void) fprintf(fp, "(");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " > (");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, " ^ ");
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, "))");
+ break;
+
+ case C_ISNONZERO:
+ (void) fprintf(fp, "(!!");
+ explexpr(np->rval, fp);
+ (void) fprintf(fp, ")");
+ break;
+
+ case INTERSECTION:
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " + ");
+ explexpr(np->rval, fp);
+ break;
+
+ case GETS:
+ case RESIZE:
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " <- ");
+ explexpr(np->rval, fp);
+ break;
+
+ case BY:
+ explexpr(np->lval, fp);
+ (void) fprintf(fp, " BY ");
+ explexpr(np->rval, fp);
+ break;
+
+ default:
+ lose(E778, emitlineno, (char*) NULL);
+ break;
+ }
+}
+
+/* AIS: Added the third argument to prexpr and prvar. It specifies
+ whether the node should be freed or not. I added the third
+ argument in all calls of prexpr/prvar. */
+
+/* AIS: I moved prexpr's prototype higher in the file. */
-static void prvar(node *np, FILE *fp)
+static void prvar(node *np, FILE *fp, int freenode)
/* print out args to pass to storage manager for reference */
{
node *sp;
case SUB:
{
(void) fprintf(fp, "aref(");
- prvar(np->lval, fp);
+ prvar(np->lval, fp, freenode);
dim = 0;
for (sp = np->rval ; sp ; sp = sp->rval)
for (sp = np->rval ; sp ; sp = sp->rval) {
(void) fprintf(fp, ", ");
- prexpr(sp->lval, fp);
+ prexpr(sp->lval, fp, freenode);
}
(void) fprintf(fp, ")");
}
break;
+ default: /* Added by AIS */
+ lose(E778, emitlineno, (char*) NULL);
+ break;
}
}
-static void prexpr(node *np, FILE *fp)
+static void prexpr(node *np, FILE *fp, int freenode)
/* print out C-function equivalent of an expression */
{
switch (np->opcode)
{
case MINGLE:
(void) fprintf(fp, "mingle(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, freenode);
(void) fprintf(fp, ", ");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case SELECT:
(void) fprintf(fp, "iselect(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, freenode);
(void) fprintf(fp, ", ");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case AND:
(void) fprintf(fp, "and%d(", np->width);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case OR:
(void) fprintf(fp, "or%d(", np->width);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case XOR:
(void) fprintf(fp, "xor%d(", np->width);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
if (Base < 3)
lose(E997, emitlineno, (char *)NULL);
(void) fprintf(fp, "fin%d(", np->width);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
if (np->opcode - WHIRL + 3 > Base)
lose(E997, emitlineno, (char *)NULL);
(void) fprintf(fp, "whirl%d(%d, ", np->width, np->opcode - WHIRL + 1);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case TWOSPOT:
case TAIL:
case HYBRID:
- prvar(np, fp);
+ prvar(np, fp, freenode);
break;
case SUB:
(void) fprintf(fp, "*(%s*)", nameof(np->lval->opcode, typedefs));
- prvar(np, fp);
+ prvar(np, fp, freenode);
break;
/* cases from here down are generated by the optimizer */
case C_AND:
(void) fprintf(fp, "(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, freenode);
(void) fprintf(fp, " & ");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case C_OR:
(void) fprintf(fp, "(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, freenode);
(void) fprintf(fp, " | ");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
case C_XOR:
(void) fprintf(fp, "(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, freenode);
(void) fprintf(fp, " ^ ");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
(void) fprintf(fp, ")");
break;
-
+
case C_NOT:
(void) fprintf(fp, "(~");
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, freenode);
if (np->rval->width == Small_digits)
(void) fprintf(fp, " & Max_small)");
else
(void) fprintf(fp, " & Max_large)");
+ break;
+
+ /* AIS: I added the rest of the cases */
+ case C_NOTEQUAL:
+ (void) fprintf(fp, "(");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " != ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_NNAND:
+ (void) fprintf(fp, "(!!(");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, "))");
break;
+
+ case C_AND1ADD1:
+ (void) fprintf(fp, "((");
+ prexpr(np->rval,fp, freenode);
+ (void) fprintf(fp, " & 0x1) + 0x1)");
+ break;
+
+ case C_1PLUS:
+ (void) fprintf(fp, "(");
+ prexpr(np->rval,fp, freenode);
+ (void) fprintf(fp, " + 0x1)");
+ break;
+
+ case C_2MINUS:
+ (void) fprintf(fp, "(0x2 - ");
+ prexpr(np->rval,fp, freenode);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_2SUBAND1:
+ (void) fprintf(fp, "(0x2 - (");
+ prexpr(np->rval,fp, freenode);
+ (void) fprintf(fp, " & 0x1))");
+ break;
+
+ case C_LSHIFT:
+ (void) fprintf(fp, "((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ") << 0x1)");
+ break;
+
+ case C_LSHIFTIN1:
+ (void) fprintf(fp, "(((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ") << 0x1) | 0x1)");
+ break;
+
+ case C_LSHIFT2:
+ (void) fprintf(fp, "((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ") << 0x2)");
+ break;
+
+ case C_LSHIFT8:
+ (void) fprintf(fp, "((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ") << 0x8)");
+ break;
+
+ case C_RSHIFTBY:
+ (void) fprintf(fp, "((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, ") >> ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ")");
+ break;
+
+ case C_RSHIFT:
+ (void) fprintf(fp, "((");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " & ");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, ") >> 0x1)");
+ break;
+
+ case C_XORGREATER:
+ (void) fprintf(fp, "(");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " > (");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, " ^ ");
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, "))");
+ break;
+
+ case C_ISNONZERO:
+ (void) fprintf(fp, "(!!(");
+ prexpr(np->rval, fp, freenode);
+ (void) fprintf(fp, "))");
+ break;
+
+ case GETS: /* AIS: this is used only if freenode == 0 */
+ if(freenode) lose(E778, emitlineno, (char*) NULL);
+ prexpr(np->lval, fp, freenode);
+ (void) fprintf(fp, " = ");
+ prexpr(np->rval, fp, freenode);
+ break;
+
+ default: /* Added by AIS */
+ if(!freenode) break; /* Be less careful when not freeing, because
+ this is used by -hH to print out its
+ intermediate optimization stages */
+ lose(E778, emitlineno, (char*) NULL);
+ break;
}
- (void) free(np);
+ if(freenode) (void) free(np);
}
static char *nice_text(char *texts[], int lines)
(*cp++) = '\n';
(*cp++) = '\t';
}
- for (text = texts[i] ; *text ; cp++, text++) {
+ for (text = texts[i] ; text&&*text ; cp++, text++) {
if (cp>buf+MAXNICEBUF-10) goto abort;
if(*text == '"' || *text == '\\') {
(*cp++) = '\\';
static void emit_guard(tuple *tn, FILE *fp)
/* emit execution guard for giiven tuple (note the unbalanced trailing {!) */
{
+ if(tn->maybe) /* AIS */
+ {
+ if(!multithread) lose(E405, emitlineno, (char *)NULL);
+ (void) fprintf(fp, " gonebackto = setjmp(btjb); choicepoint();\n");
+ }
+ if(!flowoptimize || tn->abstainable) /* This condition by AIS */
+ {
(void) fprintf(fp, " if (");
+ if (tn->maybe) /* AIS */
+ (void) fprintf(fp, "gonebackto == !(");
if (tn->exechance < 100)
(void) fprintf(fp, "roll(%d) && ", tn->exechance);
- (void) fprintf(fp, "!abstained[%d]) {\n", (int)(tn - tuples));
+ if ((tn->type != NEXT && tn->type != GO_BACK && tn->type != COME_FROM)
+ || tn->onceagainflag == onceagain_NORMAL)
+ (void) fprintf(fp, "!abstained[%d])%s {\n", (int)(tn - tuples),
+ /* AIS */ tn->maybe?")":"");
+ else /* AIS: [NEXT, GO_BACK, COME_FROM] ONCE needs specially
+ handled abstentions */
+ (void) fprintf(fp, "!oldabstain)%s {\n",
+ /* AIS */ tn->maybe?")":"");
+ }
+ else
+ { /* AIS */
+ if(tn->maybe) lose(E778, emitlineno, (char*) NULL);
+ if(!tn->initabstain)
+ {
+ if(tn->type != COMPUCOME) (void) fprintf(fp, " {\n");
+ else (void) fprintf(fp, " if(1) {\n"); /* COMPUCOME specifically needs
+ an if() so it can have
+ an else. */
+ }
+ else (void) fprintf(fp, " if(0) {\n"); /* for exceptional cases like
+ DON'T COME FROM #1 where we
+ need a label or an else. */
+ }
+}
+
+void emittextlines(FILE *fp)
+{
+ int i=-1;
+ while(i++<yylineno)
+ {
+ (void) fprintf(fp, "\"%s\",\n",nice_text(textlines + i, 0));
+ }
}
void emit(tuple *tn, FILE *fp)
{
node *np, *sp;
int dim;
+ int generatecfjump=0; /* AIS */
+ static int pasttryagain=0; /* AIS */
/* grind out label and source dump */
if (yydebug || compile_only)
if (tn->label)
(void) fprintf(fp, "L%d:", tn->label);
if (yydebug || compile_only)
- (void) fprintf(fp, "\t/* %s */", textlines[tn->lineno]);
+ {
+ (void) fprintf(fp, "\t/* %s */", textlines[tn->lineno]);
+ /* AIS: grind out an expression explanation */
+ if (tn->type == GETS || tn->type == FORGET || tn->type == RESUME
+ || tn->type == FROM || tn->type == COMPUCOME
+ || tn->type == MANYFROM)
+ {
+ (void) fprintf(fp, "\n\t/* Expression is ");
+ explexpr(tn->type == MANYFROM ? tn->u.node->lval :
+ tn->type == GETS ? tn->u.node->rval : tn->u.node, fp);
+ (void) fprintf(fp, " */");
+ }
+ }
(void) fputc('\n', fp);
/* set up the "next" lexical line number for error messages */
emitlineno = up->lineno;
break;
}
- } else if (tn->comefrom)
- emitlineno = tuples[tn->comefrom-1].lineno;
+ } else if (tn->ncomefrom)
+ emitlineno = comefromsearch(tn,1); /* AIS: For multithreading.
+ Return the 1st if we're forking. */
else if (tn < tuples + lineno - 1)
emitlineno = tn[1].lineno;
else
emitlineno = yylineno;
(void) fprintf(fp, " lineno = %d;\n", emitlineno);
+ /* print warnings on -l */
+ if(checkforbugs)
+ {
+ if(tn->warn112) lwarn(W112, emitlineno, (char*) NULL);
+ if(tn->warn128) lwarn(W128, emitlineno, (char*) NULL);
+ if(tn->warn534) lwarn(W534, emitlineno, (char*) NULL);
+ if(tn->warn018) lwarn(W018, emitlineno, (char*) NULL);
+ if(tn->warn016) lwarn(W016, emitlineno, (char*) NULL);
+ if(tn->warn276) lwarn(W276, emitlineno, (char*) NULL);
+ if(tn->warn239) lwarn(W239, emitlineno, (char*) NULL);
+ if(tn->warn622) lwarn(W622, emitlineno, (char*) NULL);
+ }
+
+ /* emit debugging information */
+ if (yukdebug||yukprofile)
+ {
+ (void) fprintf(fp, " YUK(%d,%d);\n",
+ (int)(tn-tuples),emitlineno);
+ }
+
+ /* AIS: The +mystery option on degenerated code causes the code to
+ unexpectedly terminate after 4 billion commands are run, thus
+ preventing an infinite loop. Of course, it will enhance the fun
+ if we don't tell the user that. (This is necessary for the
+ constant-output optimizer to work properly.) */
+ (void) fprintf(fp, " MYSTERYLINE;\n");
+
+ /* AIS: If the tuple is ONCE/AGAIN flagged, we need a delayed-action
+ set of its abstention status to the AGAIN-flagged status. The
+ problem is that some statements, like COME FROM, need to set after
+ the command has finished, and some, like NEXT, need it before the
+ command has started. At the moment, only NEXT and GO_BACK have a
+ ONCE/AGAIN before it, rather than after (because neither of them
+ continue in the normal fashion). */
+ if ((tn->type == NEXT || tn->type == GO_BACK) &&
+ tn->onceagainflag != onceagain_NORMAL)
+ {
+ /* ONCE/AGAIN has already been swapped by perpetrate.c in the case
+ of a preabstained statement ('DO NOT'...). So if currently have
+ a ONCE, it means that being abstained is the attractive state,
+ and if we currently have an AGAIN, it means that being
+ reinstated is the attractive state. Semantics with computed
+ ABSTAIN: Don't change the abstention count unless necessary, in
+ which case change it to 0 or 1. */
+ fprintf(fp," oldabstain = abstained[%d];\n", (int)(tn - tuples));
+ fprintf(fp," abstained[%d] = %s;\n",
+ (int)(tn - tuples),
+ tn->onceagainflag==onceagain_ONCE ? "oldabstain ? oldabstain : 1"
+ : "0");
+ /* This test-and-set must be atomic. As all statements are atomic anyway
+ in the current version of ick, that isn't a problem, but if anyone
+ wants to try using POSIX's multithreading features, the above two
+ lines need to be a critical section. */
+ }
+
+ /* in the case of COMPUCOME, we need an extra guard */
+ if (tn->type == COMPUCOME)
+ {
+ fprintf(fp," if(0)\n {\n");
+ fprintf(fp,"CCF%d:\n",compucomecount++);
+ fprintf(fp," if(skipto==");
+ prexpr(tn->u.node, fp, 1);
+ fprintf(fp,") {\n");
+ }
+
+ /* AIS: With this block placed here, you can't even have a comment
+ after a TRY AGAIN line. Move it below the next check if this seems
+ to be undesirable behaviour. */
+ if(pasttryagain) /* AIS */
+ {
+ lose(E993, emitlineno, (char*)NULL);
+ }
+
+ if(flowoptimize && tn->initabstain && !tn->abstainable
+ && tn->type != COMPUCOME && tn->type != COME_FROM &&
+ tn->type != NEXT) /* AIS */
+ goto skipcomment; /* Look, a comment! We can completely skip all
+ degeneration of this statement (although with
+ -c, comments will appear in the degenerated
+ code in its place). The COMPUCOME condition is
+ because it is so weird. COME_FROM and NEXT are
+ exempted so labels are generated. */
+
/* emit conditional-execution prefixes */
if (tn->type != COME_FROM)
emit_guard(tn, fp);
switch(tn->type)
{
case GETS:
+ /* Start of AIS optimization */
+ np = tn->u.node;
+ if(np->lval->opcode == SUB) np = np->lval;
+ if(flowoptimize &&
+ (np->lval->opcode == TWOSPOT
+ || np->lval->opcode == HYBRID
+ || !(tn->u.node->lval->optdata & ~0xffffLU)))
+ {
+ atom* op;
+ int ignorable = 1;
+ for(op = oblist; op < obdex; op++)
+ {
+ if(op->type == np->lval->opcode &&
+ op->intindex == np->lval->constant)
+ {
+ ignorable &= op->ignorable;
+ }
+ }
+ if(!ignorable)
+ { /* Variable can't be ignored, and expression must be in range */
+ (void) fprintf(fp,"\t");
+ prexpr(tn->u.node->lval, fp, 1);
+ (void) fprintf(fp, " = ");
+ prexpr(tn->u.node->rval, fp, 1);
+ (void) fprintf(fp, ";\n");
+ break;
+ }
+ }
+ /* End of AIS optimization */
+
np = tn->u.node;
+
if (np->lval->opcode != SUB) {
sp = np->lval;
(void) fprintf(fp,"\t(void) assign((char*)&");
sp = np->lval->lval;
(void) fprintf(fp,"\t(void) assign(");
}
- prvar(np->lval, fp);
+ prvar(np->lval, fp, 1);
(void) fprintf(fp,", %s", nameof(sp->opcode, vartypes));
(void) fprintf(fp,", %s[%lu], ", nameof(sp->opcode, forgetbits),
sp->constant);
- prexpr(np->rval, fp);
+ prexpr(np->rval, fp, 1);
(void) fprintf(fp,");\n");
break;
for (sp = np->rval; sp; sp = sp->rval)
dim++;
(void) fprintf(fp, "\tresize(");
- prvar(np->lval, fp);
+ prvar(np->lval, fp, 1);
(void) fprintf(fp, ", %s[%lu]", nameof(np->lval->opcode, forgetbits),
np->lval->constant);
(void) fprintf(fp, ", %d", dim);
for (sp = np->rval; sp; sp = sp->rval) {
(void) fprintf(fp, ", ");
- prexpr(sp->lval, fp);
+ prexpr(sp->lval, fp, 1);
}
(void) fprintf(fp, ");\n");
break;
case NEXT:
+ /* Start of AIS optimization */
+ if(tn->optversion)
+ { /* optimizef has checked that this is a valid optimization */
+ (void) fprintf(fp, "\tif(1 == ");
+ prexpr(tn->u.node, fp, 1); /* frees optimizef's nodecopy */
+ (void) fprintf(fp, ") {pushnext(%d); goto N%d;} N%d:;\n",
+ (int)(tn - tuples + 1), tn->nexttarget, (int)(tn - tuples + 1));
+ break;
+ }
+ /* End of AIS optimization */
(void) fprintf(fp,
"\tpushnext(%d); goto L%d; N%d:;\n",
(int)(tn - tuples + 1), tn->u.target, (int)(tn - tuples + 1));
break;
+ case GO_BACK: /* By AIS */
+ if(!multithread) lose(E405, emitlineno, (char*) NULL);
+ (void) fprintf(fp, "\tchoiceback();\n");
+ break;
+
+ case GO_AHEAD: /* By AIS */
+ if(!multithread) lose(E405, emitlineno, (char*) NULL);
+ (void) fprintf(fp, "\tchoiceahead();\n");
+ break;
+
case RESUME:
(void) fprintf(fp, "\tskipto = resume(");
- prexpr(tn->u.node, fp);
+ prexpr(tn->u.node, fp, 1);
(void) fprintf(fp, "); goto top;\n");
break;
case FORGET:
(void) fprintf(fp, "\tpopnext(");
- prexpr(tn->u.node, fp);
+ prexpr(tn->u.node, fp, 1);
(void) fprintf(fp, ");\n");
break;
np->constant);
break;
+ /* All abstention code has been edited by AIS to allow for the new abstention rules */
case ABSTAIN:
- (void) fprintf(fp, "\tabstained[%d] = TRUE;\n", tn->u.target - 1);
+ (void) fprintf(fp, "\tif(!abstained[%d]) abstained[%d] = 1;\n", tn->u.target - 1, tn->u.target-1);
+ break;
+
+ case FROM:
+ (void) fprintf(fp, "\tabstained[%d]+=", tn->u.target-1);
+ tn->u.node->width = 32;
+ prexpr(tn->u.node,fp, 1);
+ (void) fprintf(fp, ";\n");
break;
case REINSTATE:
- (void) fprintf(fp, "\tabstained[%d] = FALSE;\n", tn->u.target - 1);
+ (void) fprintf(fp, "\tif(abstained[%d]) abstained[%d]--;\n", tn->u.target - 1, tn->u.target-1);
break;
case ENABLE:
{
(void) fprintf(fp,
"\n\tfor (i = 0; i < (int)(sizeof(linetype)/sizeof(int)); i++)\n");
- if (np->constant == ABSTAIN || np->constant == REINSTATE) {
+ if (np->constant == ABSTAIN) {
+ (void) fprintf(fp,
+ "\t if (linetype[i] == %s || linetype[i] == %s || linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2], enablers[FROM-GETS], enablers[MANYFROM-GETS]);
+ } else if (np->constant == REINSTATE) {
(void) fprintf(fp,
"\t if (linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2]);
} else {
"\t if (linetype[i] == %s)\n", enablers[np->constant-GETS]);
}
(void) fprintf(fp,
- "\t\tabstained[i] = FALSE;\n");
+ "\t\tif(abstained[i]) abstained[i]--;\n");
}
break;
{
(void) fprintf(fp,
"\n\tfor (i = 0; i < (int)(sizeof(linetype)/sizeof(int)); i++)\n");
- if (np->constant == ABSTAIN || np->constant == REINSTATE) {
+ if (np->constant == ABSTAIN) {
+ (void) fprintf(fp,
+ "\t if (linetype[i] == %s || linetype[i] == %s || linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2], enablers[FROM-GETS], enablers[MANYFROM-GETS]);
+ } else if (np->constant == REINSTATE) {
(void) fprintf(fp,
"\t if (linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2]);
} else {
"\t if (linetype[i] == %s)\n", enablers[np->constant-GETS]);
}
(void) fprintf(fp,
- "\t\tabstained[i] = TRUE;\n");
+ "\t\tif(!abstained[i]) abstained[i] = 1;\n");
}
break;
- case GIVE_UP:
- (void) fprintf(fp, "\treturn(0);\n");
+ case MANYFROM:
+ (void) fprintf(fp,
+ "\tint i;\n\tint j;\n\tj=");
+ tn->u.node->lval->width=32;
+ prexpr(tn->u.node->lval,fp, 1);
+ (void) fprintf(fp,
+ ";\n");
+ for (np = tn->u.node->rval; np; np = np->rval)
+ {
+ (void) fprintf(fp,
+ "\n\tfor (i = 0; i < (int)(sizeof(linetype)/sizeof(int)); i++)\n");
+ if (np->constant == ABSTAIN) {
+ (void) fprintf(fp,
+ "\t if (linetype[i] == %s || linetype[i] == %s || linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2], enablers[FROM-GETS], enablers[MANYFROM-GETS]);
+ } else if (np->constant == REINSTATE) {
+ (void) fprintf(fp,
+ "\t if (linetype[i] == %s || linetype[i] == %s)\n", enablers[np->constant-GETS], enablers[np->constant-GETS+2]);
+ } else {
+ (void) fprintf(fp,
+ "\t if (linetype[i] == %s)\n", enablers[np->constant-GETS]);
+ }
+ (void) fprintf(fp,
+ "\t\tabstained[i] += j;\n");
+ }
break;
+ case COMPUCOME: /* By AIS. Note that this doesn't even have balanced
+ braces; it's designed to work with COMPUCOME's
+ crazy guarding arrangements */
+ fprintf(fp,"\t;} else goto CCF%d;\n",compucomecount);
+ break;
+
+ case GIVE_UP: /* AIS: Edited to allow for yuk */
+ if(yukprofile||yukdebug) fprintf(fp, "\tYUKTERM;\n");
+ if(multithread) fprintf(fp, "\tkillthread();\n");
+ (void) fprintf(fp, "\treturn(0);\n");
+ break;
+
+ case TRY_AGAIN: /* By AIS */
+ (void) fprintf(fp, "\tgoto ick_restart;\n }\n");
+ if(yukprofile||yukdebug) fprintf(fp, " if(yukloop) goto ick_restart;\n");
+ if(yukprofile||yukdebug) fprintf(fp, " YUKTERM;\n");
+ if(multithread) fprintf(fp, "\tkillthread();\n");
+ (void) fprintf(fp, " {\n\treturn(0);\n");
+ /* because if TRY AGAIN is the last line, falling off the end isn't an error */
+ pasttryagain=1; /* flag an error if we try any more commands */
+ break;
+
case WRITE_IN:
for (np = tn->u.node; np; np = np->rval) {
if (np->lval->opcode == TAIL || np->lval->opcode == HYBRID) {
(void) fprintf(fp,"\tbinin(");
- prvar(np->lval, fp);
+ prvar(np->lval, fp, 1);
(void) fprintf(fp, ", %s[%lu]",
nameof(np->lval->opcode, forgetbits),
np->lval->constant);
sp = np->lval->lval;
(void) fprintf(fp,"\t(void) assign(");
}
- prvar(np->lval, fp);
+ prvar(np->lval, fp, 1);
(void) fprintf(fp,", %s", nameof(sp->opcode, vartypes));
(void) fprintf(fp,", %s[%lu]", nameof(sp->opcode, forgetbits),
sp->constant);
{
if (np->lval->opcode == TAIL || np->lval->opcode == HYBRID) {
(void) fprintf(fp,"\tbinout(");
- prvar(np->lval, fp);
+ prvar(np->lval, fp, 1);
(void) fprintf(fp,");\n");
}
else {
(void) fprintf(fp, "\tpout(");
- prexpr(np->lval, fp);
+ prexpr(np->lval, fp, 1);
(void) fprintf(fp, ");\n");
}
}
break;
case COME_FROM:
- (void) fprintf(fp, "C%d:\n", tn->u.target);
+ (void) fprintf(fp, "C%ld:\n", (long)(tn-tuples+1));
+ /* AIS: Changed so all COME_FROMs have unique labels even if two
+ of them aim at the same line. */
break;
default:
if (tn->type != COME_FROM)
(void) fprintf(fp, " }\n");
+ skipcomment:
+
+ if (tn->type == COMPUCOME)
+ { /* By AIS */
+ (void) fprintf(fp," else goto CCF%d;\n",compucomecount);
+ (void) fprintf(fp," ccfc++;\n");
+ /* Note that due to the semantics of setjmp, this has to be written as 2
+ separate ifs. The MULTICOME macro expands to a non-multithreaded or
+ multithreaded function for handling a COME FROM clash. */
+ (void) fprintf(fp," if(ccfc==1||MULTICOME(%d,cjb))\n"
+ "\tif(setjmp(cjb) == 0) goto CCF%d;\n",
+ emitlineno, compucomecount);
+ /* Of course, emitlineno is unlikely to be helpful! */
+ (void) fprintf(fp," }\n");
+ }
+
+ /* AIS: Before any COMING FROM this line is done, we need to sort out
+ ONCE and AGAIN situations, unless this line was a NEXT or GO_BACK.
+ COME FROM is also excluded because it acts at the suckpoint, not
+ at the place it's written in the program. */
+ if (tn->onceagainflag != onceagain_NORMAL &&
+ (tn->type != NEXT && tn->type != GO_BACK && tn->type != COME_FROM))
+ {
+ /* See my comments against the NEXT code for more information.
+ This code is placed here so COME FROM ... ONCE constructs work
+ properly (the line is abstained if the COME FROM is reached in
+ execution, or its suckpoint is reached in execution). */
+ fprintf(fp," oldabstain = abstained[%d];\n", (int)(tn - tuples));
+ fprintf(fp," abstained[%d] = %s;\n",
+ (int)(tn - tuples),
+ tn->onceagainflag==onceagain_ONCE ? "oldabstain ? oldabstain : 1"
+ : "0");
+ }
+
+ /* AIS: This is where we start the COME FROM suckpoint code. */
+
+ /* AIS: We need to keep track of how many COME FROMs are aiming here
+ at runtime, if we don't have the very simple situation of no
+ COMPUCOMEs and a single-thread program (in which case the check
+ is done at compile-time by codecheck). Even without COMPUCOME,
+ this can change in a multithread program due to abstentions. */
+ if((tn->ncomefrom && multithread) || (tn->label && compucomesused))
+ (void) fprintf(fp, " ccfc = 0;\n");
+
/*
* If the statement that was just degenerated was a COME FROM target,
* emit the code for the jump to the COME FROM.
+ * AIS: Changed most of this to allow for multithreading.
*/
- if (tn->comefrom) {
- if (yydebug || compile_only)
- (void) fprintf(fp,
- " /* line %03d is a suck point for the COME FROM at line %03d */\n",
- tn->lineno, tuples[tn->comefrom-1].lineno);
- emit_guard(tuples + tn->comefrom - 1, fp);
+ while(tn->ncomefrom) /* acts as an if if singlethreading */
+ {
+ tuple* cf; /* local to this block */
+ if(multithread || compucomesused) generatecfjump = 1;
+ cf = tuples+comefromsearch(tn,tn->ncomefrom)-1;
+ if (yydebug || compile_only)
+ (void) fprintf(fp,
+ " /* line %03d is a suck point for the COME FROM "
+ "at line %03d */\n", tn->lineno, cf->lineno);
+ if (cf->onceagainflag != onceagain_NORMAL)
+ { /* Calculate ONCE/AGAIN when the suckpoint is passed */
+ fprintf(fp," oldabstain = abstained[%d];\n", (int)(cf - tuples));
+ fprintf(fp," abstained[%d] = %s;\n",
+ (int)(cf - tuples),
+ cf->onceagainflag==onceagain_ONCE ? "oldabstain ? oldabstain : 1"
+ : "0");
+ }
+ emit_guard(cf, fp);
+ if(multithread || compucomesused)
(void) fprintf(fp,
- "\tgoto C%d;\n }\n",
- tuples[tn->comefrom-1].u.target);
+ "\tccfc++;\tif(ccfc==1||MULTICOME(%d,cjb)) "
+ "if(setjmp(cjb) == 1) goto C%ld;\n }\n",
+ emitlineno, (long)(cf-tuples+1));
+ else /* optimize for the simple case */
+ (void) fprintf(fp, "\tgoto C%ld;\n }\n", (long)(cf-tuples+1));
+ tn->ncomefrom--;
}
+
+ /* AIS: If the statement has a label, it might be a
+ computed COME FROM target. Also check the flag that says this
+ code is needed in a multithread non-COMPUCOME program.
+ If (at runtime) ccfc is nonzero, we know cjb has already been set;
+ otherwise, set it now. In the case of a multithread non-COMPUCOME
+ program, the goto will just jump to a longjmp, switching to the
+ one and only one COME FROM that hasn't been given its own thread. */
+ if ((tn->label && compucomesused) || generatecfjump)
+ {
+ if(compucomesused) (void) fprintf(fp, " skipto = %d;\n", tn->label);
+ if(generatecfjump) (void) fprintf(fp, " if(ccfc) goto CCF0;\n");
+ if(compucomesused)
+ { /* check all the COMPUCOMES */
+ (void) fprintf(fp, " %sif(setjmp(cjb) == 0) goto CCF0;\n",
+ generatecfjump?"else ":"");
+ }
+ generatecfjump = 0;
+ }
+
+ /* AIS: Now we've finished the statement, let's switch to the next
+ thread in a multithread program. */
+ if(multithread) (void) fputs(" NEXTTHREAD;\n", fp);
}
/* feh.c ends here */
extern void optimize(node *np);
extern char *nameof(int value, assoc table[]);
extern void emit(tuple *tn, FILE *fp);
+extern void emittextlines(FILE *fp);
+extern int comefromsearch(tuple *tn, unsigned int index); /* AIS */
+extern void explexpr(node* np, FILE* fp); /* AIS */
+extern void optimizef(); /* AIS */
extern char *enablers[MAXTYPES];
extern assoc vartypes[];
{
if (Base == 2) {
if (r>0xffff || s>0xffff)
- lose(E533, lineno, (char *)NULL);
+ lose(E533, lineno, (char *)NULL);
r = ((r & 0x0000ff00) << 8) | (r & 0x000000ff);
r = ((r & 0x00f000f0) << 4) | (r & 0x000f000f);
r = ((r & 0x0c0c0c0c) << 2) | (r & 0x03030303);
+$L
/* $A.c -- generated C-code file for INTERCAL program $A.i */
/* This code is explicitly *not* GPLed. Use, abuse, and redistribute freely */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
+#include <setjmp.h>
-#include <fiddle.h>
-#include <abcess.h>
-#include <lose.h>
+$M
+#include "fiddle.h"
+#include "abcess.h"
+#include "lose.h"
+$K
+
+#define OK(d) !abstained[d]
+
+extern int printflow;
int lineno;
-static int abstained[$B]$C;
+jmp_buf cjb;
+int ccfc;
+int skipto;
+
+int oldabstain;
+int abstained[$B]$C;
$D
$E
-#define OK(d) !abstained[d]
-
int main(int argc, char *argv[])
{
- int skipto = 0;
-
parseargs(argc,argv);
+ skipto = 0;
+
+ next = calloc(80, sizeof *next);
+$N
+
+#ifdef YUK
+ yuklines = $J;
+ yukcommands = $B;
+#endif
/* set seed for random error generation */
#ifdef USG
srand48(time((long *)0) + getpid());
srand(time((long *)0));
#endif /* UNIX */
+#if MULTITHREAD == 1
+ ickmtinit();
+#endif
+
/* set up stash storage */
stashinit();
$F
- /* degenerated code */
+
+ /* degenerated code */
+ ick_restart:
+ ;
+
$G
+
+#ifdef YUK
+ if(yukloop) goto ick_restart;
+#endif
lose(E633, $J, (char *)0);
$H
/* ick.h -- compilation types for intercal parser */
/* Comment this out if your version of lex automatically supplies yylineno. */
-#define YYLINENO_BY_HAND
+/*#define YYLINENO_BY_HAND*/
/* Comment this out if your version of lex doesn't use yyrestart(). */
-#define USE_YYRESTART
+/*#define USE_YYRESTART*/
+
+#define YY_NO_UNPUT
typedef int bool;
#define TRUE 1
*/
/*
- * Maximum supported statement types; should be equal to (COME_FROM - GETS + 1)
+ * Maximum supported statement types; should be equal to (FROM - GETS + 1)
+ * AIS: Changed this when I added new statements.
*/
-#define MAXTYPES 17
+#define MAXTYPES 23
+
+/* AIS: Maximum supported spark/ears nesting, divided by 32. The value given
+ allows for 256 nested spark/ears groupings, which should be enough. */
+#define SENESTMAX 8
+
+enum onceagain {onceagain_NORMAL, onceagain_ONCE, onceagain_AGAIN}; /* AIS */
typedef struct node_t
{
int opcode; /* operator or type code */
unsigned long constant; /* constant data attached */
+ unsigned long optdata; /* AIS: Temp used by the optimizer */
int width; /* is this 32-bit data? */
struct node_t *lval, *rval; /* attached expression nodes */
} node;
typedef struct tuple_t
{
unsigned int label; /* label # of this statement */
- unsigned int comefrom; /* if NZ, a COME FROM touches this */
- int exechance; /* chance of execution */
+ unsigned int ncomefrom; /* AIS: How many noncomputed COME FROMS
+ have this line as a suck-point */
+ int exechance; /* chance of execution, initial abstain,
+ (AIS) MAYBE details */
+ bool maybe; /* AIS: Where MAYBE details go when
+ exechance has been parsed */
+ bool abstainable; /* AIS: Is it possible for this line to
+ be abstained from? */
+ bool initabstain; /* AIS: Is this line initially
+ abstained from? */
+ bool nextable; /* AIS: Can this line be a NEXT
+ target? */
+ bool optversion; /* AIS: Use an optimized version? (Only
+ set if the optimizer thinks that
+ it's safe.) */
+ bool warn112:1; /* AIS: Should this line produce warning
+ 112 during degeneration? */
+ bool warn128:1, warn534:1, warn018:1, warn016:1, warn276:1, warn239:1,
+ warn622:1; /* AIS: As warn112. The warnings are a bitfield to save space. */
unsigned int type; /* statement type */
- union
- {
+ struct
+ { /* AIS: Struct, not union needed because ABSTAIN expr FROM (line) has both */
unsigned int target; /* for NEXT statements */
node *node; /* attached expression node(s) */
} u;
+ unsigned int nexttarget; /* AIS: The target tuple of a NEXT must
+ also be recorded for optimizef */
int lineno; /* source line for error messages */
bool sharedline; /* if NZ, two statements on a line */
+ enum onceagain onceagainflag; /* AIS: ONCE / AGAIN */
} tuple;
/* this maps the `external' name of a variable to an internal array index */
int type;
int extindex;
int intindex;
+ int ignorable; /* AIS: Can this variable be IGNOREd? */
}
atom;
extern tuple *tuples;
extern int tuplecount;
+extern tuple *optuple; /* AIS: The tuple currently being optimized */
+
extern char *enablers[MAXTYPES];
extern assoc vartypes[];
extern int textlinecount;
extern int yylineno;
+/* AIS: These are needed to sort out a grammar near-ambiguity */
+extern unsigned long sparkearsstack[SENESTMAX];
+extern int sparkearslev;
+
/* compilation options */
extern bool compile_only; /* just compile into C, don't run the linker */
extern bool nocompilerbug; /* set possibility of E774 to zero */
extern int politesse;
+
+/* AIS: I added these */
+extern int yukdebug; /* debug the code with yuk */
+extern int yukprofile; /* profile the code with yuk */
+extern int compucomecount; /* number of computed COME FROMs */
+extern int compucomesused; /* are computed COME FROMs used? */
+extern int multithread; /* is the program multithreaded? */
+extern int coreonerr; /* dump core on E778? */
+extern int optdebug; /* debug the optimizer */
+extern int flowoptimize; /* optimize program flow */
+extern int checkforbugs; /* check for bugs */
+extern int coopt; /* constant-output optimizer */
+
/* ick.h ends here */
DESCRIPTION
This YACC grammar parses the INTERCAL language by designed by Don R. Woods
-and James M. Lyon. There are two syntax extensions over the original
-INTERCAL-72 language; the COME FROM statement, and the prefixed forms of the
-WHIRL operator.
+and James M. Lyon. There are five syntax extensions over the original
+INTERCAL-72 language; the COME FROM statement, the prefixed forms of the
+WHIRL operator, and (AIS) the ABSTAIN <expr> FROM, COME FROM <expr>,
+and ONCE/AGAIN forms.
LICENSE TERMS
Copyright (C) 1996 Eric S. Raymond
extern int stbeginline; /* line number of last seen preamble */
static int thisline; /* line number of beginning of current statement */
+
+extern int mark112; /* AIS: Mark the tuple for W112 when it's created. */
+
static tuple *splat(void);
#define GETLINENO \
{x = newtuple(); x->type = nt; x->lineno = thisline; x->u.node = nn;}
#define TARGET(x, nt, nn) \
{x = newtuple(); x->type = nt; x->lineno = thisline; x->u.target = nn;}
-#define NEWFANGLED if (traditional) lose(E111,yylineno,(char*)NULL); else
+#define ACTARGET(x, nt, nn, nn2)\
+ {x = newtuple(); x->type = nt; x->lineno = thisline;\
+ x->u.node = nn; x->u.target = nn2;}
+/* AIS : The macro above was added for ABSTAIN expr FROM. */
+#define NEWFANGLED mark112 = 1; /* AIS: Added the mention of mark112 */ \
+ if (traditional) lose(E111,yylineno,(char*)NULL); else
+
+#define DESTACKSE1 sparkearsstack[sparkearslev--/32] >>= 1
+#define DESTACKSPARKEARS DESTACKSE1; DESTACKSE1
%}
* Don't change this statement token list gratuitously!
* Some code in feh.c depends on GETS being the least
* statement type and on the order of the ones following.
+ * AIS: Added FROM, MANYFROM, TRY_AGAIN, COMPUCOME.
+ * AIS: COME_FROM now merged with the label following it,
+ * to distinguish it from COMPUCOME, in the lexer. This changes
+ * the parser somewhat.
*/
-%token GETS RESIZE NEXT FORGET RESUME STASH RETRIEVE IGNORE REMEMBER ABSTAIN
-%token REINSTATE DISABLE ENABLE GIVE_UP READ_OUT WRITE_IN COME_FROM
+%token GETS RESIZE NEXT GO_AHEAD GO_BACK FORGET RESUME STASH RETRIEVE IGNORE
+%token REMEMBER ABSTAIN REINSTATE
+%token DISABLE ENABLE MANYFROM GIVE_UP READ_OUT WRITE_IN
+%token <numval> COME_FROM
+%token COMPUCOME TRY_AGAIN FROM
-%token DO PLEASE NOT MESH ONESPOT TWOSPOT TAIL HYBRID
-%token MINGLE SELECT SPARK EARS SUB BY BADCHAR
+/* AIS: ONCE and AGAIN added, for multithread support */
+%token MAYBE DO PLEASE NOT ONCE AGAIN MESH ONESPOT TWOSPOT TAIL HYBRID
+%token MINGLE SELECT /* AIS: SPARK EARS */ SUB BY BADCHAR
%token <numval> NUMBER UNARY OHOHSEVEN GERUND LABEL
%token <node> INTERSECTION
* will not conflict with the other tokens. It is important that
* WHIRL through WHIRL5 be a continuous sequence.
*/
-%token SPLATTERED C_AND C_OR C_XOR C_NOT AND OR XOR FIN MESH32
-%token WHIRL WHIRL2 WHIRL3 WHIRL4 WHIRL5
+/* AIS: Added new tokens for optimizer output */
+%token SPLATTERED
+%token C_AND C_OR C_XOR C_NOT C_NNAND C_ISNONZERO C_LSHIFT C_LSHIFT2
+%token C_LSHIFT8 C_LSHIFTIN1 C_RSHIFT C_AND1ADD1 C_2SUBAND1 C_1PLUS C_2MINUS
+%token C_XORGREATER C_RSHIFTBY C_NOTEQUAL
+%token AND OR XOR FIN MESH32 WHIRL WHIRL2 WHIRL3 WHIRL4 WHIRL5
%type <node> expr varlist variable constant lvalue inlist outlist
%type <node> subscr byexpr scalar array initem outitem sublist
%type <node> unambig subscr1 sublist1 oparray osubscr osubscr1
-%type <tuple> perform
+%type <tuple> perform mtperform
%type <numval> please preftype
+%nonassoc OPENEARS OPENSPARK CLOSEEARS CLOSESPARK
%nonassoc HIGHPREC
-%nonassoc EARS SPARK
+/* AIS: I reversed this precedence, to sort out the near-ambiguity */
%% /* beginning of rules section */
* followed by an optional probability, followed by the statement body.
* Negative exechance values indicate initial abstentions, and will be
* made positive before code is emitted.
+ * AIS: An exechance above 100 indicates a MAYBE situation (e.g. 4545
+ * means MAYBE DO %45 ...). This means %0 should be illegal. I modified
+ * all these to allow for MAYBE.
*/
-command : please perform
+command : please mtperform
{$2->label = 0; $2->exechance = $1 * 100;}
- | please OHOHSEVEN perform
+ | please OHOHSEVEN mtperform
{$3->label = 0; $3->exechance = $1 * $2;}
- | LABEL please perform
+ | LABEL please mtperform
{checklabel($1); $3->label = $1; $3->exechance = $2 * 100;}
- | LABEL please OHOHSEVEN perform
+ | LABEL please OHOHSEVEN mtperform
{checklabel($1); $4->label = $1; $4->exechance = $2 * $3;}
| error
{lose(E017, yylineno, (char *)NULL);}
;
+/*
+ * AIS: added for the ONCE/AGAIN qualifiers. It copies a pointer to the tuple,
+ * so command will set the values in the original tuple via the copy.
+ */
-/* There are two forms of preamble returned by the lexer */
+mtperform : perform
+ {$1->onceagainflag = onceagain_NORMAL; $$ = $1;}
+ | perform ONCE
+ {NEWFANGLED {$1->onceagainflag = onceagain_ONCE; $$ = $1;}}
+ | perform AGAIN
+ {NEWFANGLED {$1->onceagainflag = onceagain_AGAIN; $$ = $1;}}
+
+/* There are two (AIS: now four) forms of preamble returned by the lexer */
please : DO {GETLINENO; $$ = 1;}
| DO NOT {GETLINENO; $$ = -1;}
+ | MAYBE {NEWFANGLED {GETLINENO; $$ = 101;}}
+ | MAYBE NOT {NEWFANGLED {GETLINENO; $$ = -101;}}
;
/* Here's how to parse statement bodies */
| RETRIEVE varlist {ACTION($$, RETRIEVE, rlist);}
| IGNORE varlist {ACTION($$, IGNORE, rlist);}
| REMEMBER varlist {ACTION($$, REMEMBER, rlist);}
- | ABSTAIN LABEL {stbeginline=0; TARGET($$, ABSTAIN, $2);}
- | ABSTAIN gerunds {ACTION($$, DISABLE, rlist);}
+ | ABSTAIN FROM LABEL {stbeginline=0; TARGET($$, ABSTAIN, $3);}
+ | ABSTAIN FROM gerunds {ACTION($$, DISABLE, rlist);}
+ | ABSTAIN expr FROM LABEL {/* AIS */ NEWFANGLED {stbeginline=0; ACTARGET($$, FROM, $2, $4);}}
+ | ABSTAIN expr FROM gerunds {/* AIS */ NEWFANGLED {$$ = newtuple(); $$->type = MANYFROM; $$->lineno = thisline; \
+ {node* tempnode=newnode(); $$->u.node = tempnode; tempnode->lval=$2; tempnode->rval=rlist; tempnode->opcode=MANYFROM;}}}
| REINSTATE LABEL {stbeginline=0; TARGET($$, REINSTATE, $2);}
| REINSTATE gerunds {ACTION($$, ENABLE, rlist);}
| WRITE_IN inlist {ACTION($$, WRITE_IN, $2);}
| READ_OUT outlist {ACTION($$, READ_OUT, $2);}
| GIVE_UP {ACTION($$, GIVE_UP, 0);}
- | COME_FROM LABEL {NEWFANGLED {TARGET($$,COME_FROM,$2)}}
+ | GO_AHEAD {/* AIS */ NEWFANGLED {ACTION($$, GO_AHEAD, 0);}}
+ | GO_BACK {/* AIS */ NEWFANGLED {ACTION($$, GO_BACK, 0);}}
+ | TRY_AGAIN {/* AIS */ NEWFANGLED {ACTION($$,TRY_AGAIN,0);}}
+ | COME_FROM {/* AIS: Modified this */ NEWFANGLED {TARGET($$,COME_FROM,$1);}}
+ | COMPUCOME expr {/* AIS */NEWFANGLED {ACTION($$,COMPUCOME,$2); compucomesused=1;}}
| BADCHAR {yyclearin; $$ = splat();}
| error {yyclearin; $$ = splat();}
;
}
/* Now deal with the screwy unary-op interaction with grouping */
- | SPARK UNARY expr SPARK
+ /* AIS: Modified to allow for maintenance of the SPARK/EARS stack */
+ | eitherspark UNARY expr CLOSESPARK
{
$$ = newnode();
$$->opcode = $2;
$$->rval = $3;
+ DESTACKSPARKEARS;
}
- | EARS UNARY expr EARS
+ | eitherears UNARY expr CLOSEEARS
{
$$ = newnode();
$$->opcode = $2;
$$->rval = $3;
+ DESTACKSPARKEARS;
}
- | SPARK expr SPARK {$$ = $2;}
- | EARS expr EARS {$$ = $2;}
+ | eitherspark expr CLOSESPARK {$$ = $2; DESTACKSPARKEARS;}
+ | eitherears expr CLOSEEARS {$$ = $2; DESTACKSPARKEARS;}
;
+eitherspark : OPENSPARK ;
+ | CLOSESPARK ;
+ ;
+
+eitherears : OPENEARS ;
+ | CLOSEEARS ;
+ ;
+
%%
static tuple *splat(void)
tok = ' '; /* scanner must not see a NUL */
break;
}
- else if (tok == DO || tok == PLEASE || tok == LABEL) {
+ else if (tok == DO || tok == PLEASE || tok == LABEL
+ /* AIS */ || tok == MAYBE) {
re_send_token = TRUE;
break;
}
--- /dev/null
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
;; expanding some fraction of the "do" abbrevs typed to PLEASE DO.
;; The intercal-politesse-level constant is the denominator of this fraction.
+;; AIS: I corrected the READ/WRITE, IN/OUT reversal independent of the correction
+;; that happened from 0.22 to 0.24 (this code was originally based on the 0.22
+;; distribution and updated for 0.24 compatibility); this version is distributed
+;; with C-INTERCAL 0.25.
+;;
+;; I also altered the code for ( so the user didn't have to go to the beginning
+;; of the line, added C-c C-[a,c,r,s] for convenience when working with
+;; constants, and added support for TRY AGAIN, ONCE, AGAIN, and Font Lock.
+;; I added support for M-x compile so it could compile INTERCAL programs
+;; correctly (assuming that ick has been installed).
+
;; $Id: intercal.el,v 1.5 1996/11/14 04:02:00 esr Exp $
(defconst intercal-politesse-level 4
(setq intercal-mode-map (make-sparse-keymap))
(define-key intercal-mode-map "\t" 'tab-to-tab-stop)
(define-key intercal-mode-map "\r" 'intercal-return)
+ (define-key intercal-mode-map "\C-J" 'intercal-return)
+ (define-key intercal-mode-map "\C-C\C-C" 'intercal-constant-convert) ;AIS
+ (define-key intercal-mode-map "\C-C\C-R" 'intercal-constant-radix-convert) ;AIS
+ (define-key intercal-mode-map "\C-C\C-S" 'intercal-char-constant-convert) ;AIS
+ (define-key intercal-mode-map "\C-C\C-A" 'intercal-string-array-convert) ;AIS
+ (define-key intercal-mode-map "\C-C\C-U" 'intercal-lnu) ;AIS
(define-key intercal-mode-map "(" 'intercal-paren)
(define-key intercal-mode-map "*" 'intercal-splat)
(define-key intercal-mode-map "\177" 'backward-delete-char-untabify)
nil
(define-abbrev-table 'intercal-mode-abbrev-table ())
(define-abbrev intercal-mode-abbrev-table "pl" "PLEASE" nil)
+ (define-abbrev intercal-mode-abbrev-table "on" "ONCE" nil) ;AIS
+ (define-abbrev intercal-mode-abbrev-table "ag" "AGAIN" nil) ;AIS
(define-abbrev intercal-mode-abbrev-table "ne" "" 'intercal-ne-abbrev)
(define-abbrev intercal-mode-abbrev-table "fo" "" 'intercal-fo-abbrev)
(define-abbrev intercal-mode-abbrev-table "res" "" 'intercal-res-abbrev)
(define-abbrev intercal-mode-abbrev-table "wr" "" 'intercal-wr-abbrev)
(define-abbrev intercal-mode-abbrev-table "co" "" 'intercal-co-abbrev)
(define-abbrev intercal-mode-abbrev-table "do" "" 'intercal-do-abbrev)
+ (define-abbrev intercal-mode-abbrev-table "goa" "" 'intercal-goa-abbrev) ;AIS
+ (define-abbrev intercal-mode-abbrev-table "gob" "" 'intercal-gob-abbrev) ;AIS
+ (define-abbrev intercal-mode-abbrev-table "ma" "MAYBE" nil) ;AIS
+ (define-abbrev intercal-mode-abbrev-table "tr" "" 'intercal-tr-abbrev) ;AIS
+ (define-abbrev intercal-mode-abbrev-table "cal" "" 'intercal-cal-abbrev) ;AIS
)
(defun use-gerund ()
(make-intercal-abbrev intercal-rea-abbrev "READING OUT" "READ OUT")
(make-intercal-abbrev intercal-wr-abbrev "WRITING IN" "WRITE IN")
(make-intercal-abbrev intercal-co-abbrev "COMING FROM" "COME FROM")
+(make-intercal-abbrev intercal-tr-abbrev "TRYING AGAIN" "TRY AGAIN") ;AIS
+(make-intercal-abbrev intercal-cal-abbrev "CALCULATING" "cal") ;AIS
+(make-intercal-abbrev intercal-goa-abbrev "GOING AHEAD" "GO AHEAD") ;AIS
+(make-intercal-abbrev intercal-gob-abbrev "GOING BACK" "GO BACK") ;AIS
(defun intercal-do-abbrev ()
"Emit a DO (usually). Occasionally, emit PLEASE DO."
(interactive)
(if (eolp) (delete-horizontal-space))
(insert "\n")
+ (delete-horizontal-space) ;AIS
(tab-to-tab-stop)
+ (if intercal-lnu-mode (intercal-lnu)) ;AIS
)
-(defun intercal-paren ()
- "Generate an INTERCAL label."
+;; AIS: This is the old intercal-paren function, modified slightly.
+(defun intercal-paren-2 ()
+ "Generate an INTERCAL label if at start of line. Otherwise type '('."
(interactive)
(if (and (bolp) (looking-at "[ \t]\\|$"))
- (insert (format "(%d)"
- (save-restriction
- (widen)
- (save-excursion
- (beginning-of-line)
- (1+ (count-lines 1 (point))))))
- "\t")
+ (insert (format "(%d)"
+ (save-restriction
+ (widen)
+ (save-excursion
+ (beginning-of-line)
+ (1+ (count-lines 1 (point))))))
+ "\t")
(insert "(")))
+;; AIS: I wrote this as a better intercal-paren-2.
+(defun intercal-paren ()
+ "Generate an INTERCAL label or (."
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at "^[ \t]*$")
+ (delete-horizontal-space)))
+ (intercal-paren-2)
+)
+
(defun intercal-splat ()
"Begin an INTERCAL comment."
(interactive)
(insert " ")
)
+;; AIS: Added new abbreviations (marked ;AIS above), expanded the documentation.
(defun intercal-mode ()
"A major editing mode for the language Intercal.
It activates the following abbrevs (each one appropriately modified to a
gi GIVE UP ig IGNORE ne NEXT
rea READ OUT rei REINSTATE rem REMEMBER
res RESUME ret RETRIEVE st STASH
-wr WRITE IN pl PLEASE
+wr WRITE IN pl PLEASE tr TRY AGAIN
+on ONCE ag AGAIN ma MAYBE
+goa GO AHEAD gob GO BACK do DO, or sometimes PLEASE DO
+cal CALCULATING (only as a gerund)
Carriage return takes you to the first tab stop (code indent level).
Certain other single keys are bound to things which may or may not be useful.
You may consider discovering these one of the pleasures awaiting you in your
discovery of INTERCAL's unique ambience.
+Typing C-c C-c converts a constant in the form #<legal C constant> to a legal
+INTERCAL constant (such as #45 or #65280$#65280). If the answer is a mingled
+one, it is only valid in binary.
+
+For programmers who prefer TRI-INTERCAL, another constant conversion function
+is given. Typing a number in the format (say) #3r2210210011 and pressing
+C-c C-r will result in a (possibly mingled) decimal constant that works in
+base 3. This works likewise for other bases, say #6r520314 would generate a
+base-6 constant.
+
+For binary I/O, C-c C-s is provided. This takes a constant of the form
+#?<character> and converts it into a constant of the form #<character code>.
+With a prefix argument (as in C-u C-c C-s), the output has its bottom 8 bits
+reversed, and so is suitable for use with semi-standard output routines.
+
+For longer strings, C-c C-a can produce sections of programs that store
+strings in arrays. The command can give help on itself.
+
+For information about C-c C-u and LNU, see `intercal-lnu-mode'.
+
Turning on Intercal mode calls the value of the variable intercal-mode-hook
with no args, if that value is non-nil."
(interactive)
(provide 'intercal-mode)
+;; AIS: I wrote everything from here down.
+
+;; Line Number Update minor mode.
+(defvar intercal-lnu-mode nil "Whether intercal-lnu-mode is on or not.")
+(make-variable-buffer-local 'intercal-lnu-mode)
+
+(defvar intercal-lnu-mode-initialized nil "Whether intercal-lnu-mode is initialized.")
+
+(defun intercal-lnu-mode (arg)
+"Minor mode used primarily when editing INTERCAL.
+ (LNU stands for Line Number Update).
+The mode tries to ensure that all line labels below 1000 are equal to the line
+numbers of the lines they refer to. Renumbering is done when RET is pressed, the
+mode is turned on, or C-c C-u is pressed. This mode has no effect unless
+intercal-mode is also active, or its functions are called. It is inadvisable to
+turn LNU mode on in long files, because line number updates take a long time to
+run in long files. Instead, leave LNU mode off and use `intercal-lnu' (C-c C-u).
+Labels greater than or equal to 1000 are ignored because they probably indicate
+library functions."
+ (interactive "P")
+ (setq intercal-lnu-mode
+ (if (null arg) (not intercal-lnu-mode) (> (prefix-numeric-value arg) 0)))
+ (force-mode-line-update)
+ (if intercal-lnu-mode (intercal-lnu))
+ (if (not intercal-lnu-mode-initialized) (intercal-lnu-initialize))
+)
+
+(defun intercal-lnu-initialize ()
+"Initializes INTERCAL LNU mode. See `intercal-lnu-mode'."
+ (if (not intercal-lnu-mode-initialized)
+ (setq minor-mode-alist (cons '(intercal-lnu-mode " LNU") minor-mode-alist)
+ intercal-lnu-mode-initialized t))
+)
+
+(defsubst cadar (x)
+ "Return the car of the cdr of the car of X."
+ (car (cdr (car x))))
+
+(defun intercal-lnu ()
+"Updates line numbers in an INTERCAL program. See `intercal-lnu-mode'. This
+function will run even if intercal-lnu-mode is off, but intercal-mode must be
+on. Running this function manually (with C-c C-u) rather than automatically is
+a good idea in long files, which take a long time to update."
+ (interactive)
+ (if (equal major-mode 'intercal-mode)
+ (save-excursion
+ (let ((line-number-update-list nil))
+ (goto-char (point-min))
+ (while (re-search-forward "^(\\([0-9]+\\))" nil t)
+ (if (< (string-to-number (match-string-no-properties 1)) 1000)
+ (setq line-number-update-list (cons
+ (list
+ (string-to-number (match-string-no-properties 1))
+ (count-lines 1 (point)))
+ line-number-update-list))))
+ (while line-number-update-list
+ (intercal-lnu-individual (caar line-number-update-list) (cadar line-number-update-list))
+ (setq line-number-update-list (cdr line-number-update-list))))
+ (goto-char (point-min))
+ (while (search-forward "LNUChange:" nil t)
+ (replace-match "")))
+ (error "The buffer is not in intercal-mode"))
+)
+
+(defun intercal-lnu-individual (oldlabel newlabel)
+"Updates all occurrences of one label in an INTERCAL program for another."
+ (save-excursion
+ (goto-char (point-min))
+ (while (search-forward (concat "(" (number-to-string oldlabel) ")") nil t)
+ (replace-match (concat "(LNUChange:" (number-to-string newlabel) ")"))))
+)
+
+;; Font Lock settings.
+;; We use keyword-face for commands, builtin-face for gerunds, constant-face
+;; for meshes and mingle-mesh constants, and comment-face for initially
+;; abstained lines (because these are usually comments, and anyway it's good
+;; for them to stand out). Only the first line of multiline comments is marked.
+;; MAYBE lines aren't marked because that's a big giveaway that the line won't
+;; be abstained from all program.
+(defvar intercal-font-lock-keywords
+ '(("^\\(([0-9]+)\\|\\)[ \t]*\\(PLEASE DO\\|DO\\|PLEASE\\)[ \t]*\\(NOT\\|N'T\\).*$" . font-lock-comment-face)
+ ("\\<\\(ABSTAIN\\|GIVE UP\\|READ OUT\\|RESUME\\|WRITE IN\\|COME\\|FROM\\|IGNORE\\|REINSTATE\\|RETRIEVE\\|PLEASE\\|DO\\|MAYBE\\|ONCE\\|AGAIN\\|FORGET\\|NEXT\\|REMEMBER\\|STASH\\|DON'T\\|NOT\\|TRY AGAIN\\|GO AHEAD\\|GO BACK\\)\\>" . font-lock-keyword-face)
+ ("\\<\\(ABSTAINING\\|GIVING UP\\|READING OUT\\|RESUMING\\|WRITING IN\\|COMING\\|IGNORING\\|REINSTATING\\|RETRIEVING\\|FORGETTING\\|NEXTING\\|REMEMBERING\\|STASHING\\|TRYING AGAIN\\|CALCULATING\\|GOING AHEAD\\|GOING BACK\\)\\>" . font-lock-builtin-face)
+ ("[.,:;][0-9]+" . font-lock-variable-name-face)
+ ("#[0-9]+\\(\\$#[0-9]+\\|\\)" . font-lock-constant-face))
+ "Default expressions to highlight in Intercal mode.")
+
+;; Find an error message produced by ick. If the famous RESUBNIT spelling error
+;; is ever corrected, this will need to be corrected too.
+(defvar intercal-error-regexp
+ '("ICL[0-9][0-9][0-9][IW].*\n[ \t]*ON THE WAY TO \\([0-9]+\\)\n[ \t]*\\(CORRECT\\|RECONSIDER\\) SOURCE AND RESUBNIT$" nil 1)
+ "Regexp that identifies an INTERCAL error message, and the file and line number positions in it.")
+
+;; Detect the line with which ick was invoked, so the filename used can be
+;; used by Emacs' compile-mode to find the error. This will need to be changed
+;; if command-line arguments to ick other than letters are allowed.
+(defvar intercal-file-regexp '(".*ick \\(-[a-zA-Z]+ \\)*\\(.*i\\)$" 2)
+ "Regexp that identifies the line with which ick was invoked, and the filename it was used on.")
+
+;; Helper function for the binary I/O routines.
+(defun intercal-reverse-bits-if-nonnull (flag num)
+ "Returns num if flag is null, or num with bits reversed if flag is nonnull."
+ (if (null flag) num
+ (let ((ans 0) (count 8) (num1 num))
+ (while (> count 0)
+ (setq ans (* ans 2))
+ (if (= (% num1 2) 1) (setq ans (1+ ans)))
+ (setq num1 (/ num1 2))
+ (setq count (1- count)))
+ ans))
+)
+
+;; Internal memory for inter-function communication. Yes, I know it's
+;; unLispish to do this sort of thing, and breaks if the user tries to
+;; convert two strings simultaneously.
+(defvar intercal-string-array-convert-options-buffer-used nil
+ "Variable that keeps track of a buffer used to display options
+for intercal-string-array-convert.")
+
+;; Function that inputs options for intercal-string-array-convert.
+;; If the user asks for help, it pops up a help buffer and returns nil.
+;; Its documentation string is the information required to appear in
+;; the help buffer.
+(defun intercal-string-array-convert-options (opts)
+ "Options for use with intercal-string-array-convert:
+ ? Display the list of options
+ 1 Pack the string one char/element (default)
+ 2 Pack the string two chars/element (unimplemented)
+ 4 Pack the string four chars/element (unimplemented)
+ $ Pack the string in mingled format (default)
+ so \"abcd\" would become \"a$b\"$\"c$d\"
+ < Pack the string in shifted format
+ (concatentate the codes for each character)
+ R Bit-reverse each character code (default)
+ W Don't bit-reverse each character code
+ , Treat entered number as a tail array (default)
+ ; Treat entered number as a hybrid array
+ 0 Each character code is based at 0 (default)
+ + Each character code is based at the previous code (unimplemented)"
+ (interactive "sOptions: (type ?[RET] for help)")
+ (if (string= opts "?")
+ (progn
+ (setq intercal-string-array-convert-options-buffer-used t)
+ (with-output-to-temp-buffer "*Options*"
+ (princ (documentation 'intercal-string-array-convert-options)))
+ nil)
+ opts)
+)
+
+;; The displaying of the help buffer is done by
+;; intercal-string-array-convert-options, if required. This function holds
+;; tests to put the display back as it was in two possible common situations
+;; involving the user asking for help (one window active, two windows active).
+(defun intercal-string-array-convert (in arr &optional opts)
+ "Generate INTERCAL code to initialize an array with information
+that makes it suitable for use as a string. For more information,
+run the command and enter a question mark for the options."
+ (interactive "*MEnter string to convert:\nnEnter number of array required:")
+ (let ((cb (current-buffer)) (w1p (one-window-p)) (ow nil))
+ (if (null w1p) (setq ow other-window-scroll-buffer))
+ (while (null opts)
+ (setq opts (call-interactively 'intercal-string-array-convert-options)))
+ (if intercal-string-array-convert-options-buffer-used
+ (progn
+ (select-window (get-buffer-window cb))
+ (if w1p
+ (delete-other-windows)
+ (switch-to-buffer-other-window ow))))
+ (setq intercal-string-array-convert-options-buffer-used nil))
+ (let ((packing 1) (basis nil) (arrtype ",") (revbits t) (mingle t))
+ (while (> (length opts) 0)
+ (if (string= (substring opts 0 1) "1") (setq packing 1)
+ (if (string= (substring opts 0 1) "2") (error "Unimplemented") ;(setq packing 2) ;unimplemented
+ (if (string= (substring opts 0 1) "4") (error "Unimplemented") ;(setq packing 4) ;unimplemented
+ (if (string= (substring opts 0 1) "$") (setq mingle t) ;unimplemented, but has no effect on option 1
+ (if (string= (substring opts 0 1) "<") (setq mingle nil);unimplemented, but has no effect on option 1
+ (if (string= (substring opts 0 1) "R") (setq revbits t)
+ (if (string= (substring opts 0 1) "W") (setq revbits nil)
+ (if (string= (substring opts 0 1) ",") (setq arrtype ",")
+ (if (string= (substring opts 0 1) ";") (setq arrtype ";")
+ (if (string= (substring opts 0 1) "0") (setq basis nil)
+ (if (string= (substring opts 0 1) "+") (error "Unimplemented") ;(setq basis t) ;unimplemented
+ (error "Invalid option"))))))))))))
+ (setq opts (substring opts 1)))
+ (intercal-return)
+ (intercal-do-abbrev)
+ (let ((al (/ (+ (length in) packing -1) packing)))
+ (insert " " arrtype (int-to-string arr) " <- #" (int-to-string al)))
+ (let ((lastchar 0) (arrind 1))
+ (while (> (length in) 0)
+ (intercal-return)
+ (intercal-do-abbrev)
+ (insert " " arrtype (int-to-string arr) " SUB #" (int-to-string arrind))
+ (insert " <- #?" (substring in 0 1))
+ (setq in (substring in 1))
+ (intercal-char-constant-convert revbits))))
+)
+
+;; Converts char to int by subtracting ! and adding 33.
+(defun intercal-char-constant-convert (arg)
+ "Convert a constant of the form #?<character> into a legal
+INTERCAL constant representing the character's character code.
+With a prefix argument, gives bit-reversed output. This routine
+is intended for use with the binary I/O capabilities of INTERCAL."
+ (interactive "*P") ;Check prefix arg, not read-only
+ (save-excursion
+ (if (re-search-backward "#" (line-beginning-position) t)
+ (if (re-search-forward "#\\?\\(.\\)" (line-end-position) t)
+ (replace-match
+ (concat "#" (int-to-string (intercal-reverse-bits-if-nonnull arg
+ (+ 33 (- (string-to-char
+ (match-string-no-properties 1)) ?!)))))))))
+)
+
+
+;; This is simpler than the next function because we're
+;; converting from the target base, so it's simply a case
+;; of selecting every second character if we need to produce
+;; a mingled result
+(defun intercal-constant-radix-convert ()
+ "Convert a constant of the form #<base>r<integer in that base>
+to a legal TRI-INTERCAL constant in that base. If the number is
+sufficiently small, it is converted to decimal; otherwise, it is
+converted to two mingled decimal constants."
+ (interactive "*")
+ (save-excursion
+ (if (re-search-backward "#" (line-beginning-position) t)
+ (if (re-search-forward "#\\([2-7]\\)r\\([0-6]+\\)"
+ (line-end-position) t)
+ (replace-match
+ (let ((radix (string-to-number
+ (match-string-no-properties 1) 10))
+ (str (match-string-no-properties 2)) (slen 0)
+ (mingle1 "") (mingle2 "") (num1 0) (num2 0))
+ (setq slen (length str))
+ (if (or (<= (* radix slen) 32) ; Calculate max onespot length
+ (or (and (= radix 6) (= slen 6)) ;on these
+ (and (= radix 7) (= slen 5)))) ;three lines
+ (progn
+ (setq num1 (string-to-number str radix))
+ (concat "#" (number-to-string num1)))
+ (progn
+ (while (/= 0 (length str))
+ (setq mingle2 (concat (substring str -1) mingle2))
+ (setq str (substring str 0 -1))
+ (if (/= 0 (length str))
+ (progn
+ (setq mingle1 (concat (substring str -1) mingle1))
+ (setq str (substring str 0 -1)))))
+ (setq num1 (string-to-number mingle1 radix))
+ (setq num2 (string-to-number mingle2 radix))
+ (concat "#" (number-to-string num1)
+ "$#" (number-to-string num2)))))))))
+)
+
+;; The following code needs a bit of explanation. INTERCAL
+;; can handle constants up to 4294967295 (0xffffffff), but
+;; Emacs's constants max out somewhere between 100 million
+;; and 1 billion. So, when a high number is entered, the
+;; code processes the last 6 digits (in whatever base the
+;; number is entered in) separately from the rest of the
+;; number. This ensures that the arithmetic routines never
+;; overflow if the input is a valid integer in the range
+;; 0-4294967295. The calculations used do not work for
+;; higher numbers, but that doesn't matter because
+;; INTERCAL wouldn't accept them. Constants higher than
+;; 65535 are given in mingled form (e.g. #65280$#65280).
+(defun intercal-constant-convert ()
+ "Convert a constant of the form #<a valid C integer> to a
+legal INTERCAL constant (#<16-bit decimal integer> or
+#<16-bit decimal integer>$#<16-bit decimal integer>).
+Decimal (#4294967295), octal (#037777777777) and
+hex (#0xffffffff) formats are all supported."
+ (interactive "*")
+ (save-excursion
+ (if (re-search-backward "#" (line-beginning-position) t)
+ (if (re-search-forward "#\\(0?[xX]?\\)\\([0-9a-fA-F]+\\)"
+ (line-end-position) t)
+ (replace-match
+ (let ((str (match-string-no-properties 2))
+ (strhi "0") (strlow "0")
+ (base (if (string= (match-string-no-properties 1) "")
+ 10
+ (if (string= (match-string-no-properties 1) "0")
+ 8 16))))
+ (if (<= (length str) 6) (setq strlow str)
+ (setq strlow (substring str -6) strhi (substring str 0 -6)))
+ (let ((num (string-to-number strlow base))
+ (numhi (string-to-number strhi base)))
+ (if (and (<= num 65535) (string= strhi "0"))
+ (concat "#" (number-to-string num))
+ (let ((mingle1 0) (mingle2 0) (count 16) (temp 0))
+ (while (> count 0)
+ (progn
+ (setq temp (% num 4))
+ (setq num (/ num 4))
+ (if (= (% temp 2) 1) (setq mingle2 (+ mingle2 65536)))
+ (if (> temp 1) (setq mingle1 (+ mingle1 65536)))
+ (setq mingle1 (/ mingle1 2))
+ (setq mingle2 (/ mingle2 2))
+ (setq count (- count 1))
+ (if (= count 13)
+ (setq num (+ num (* (/ (expt base 6) 64) numhi))))))
+ (concat "#" (number-to-string mingle1)
+ "$#" (number-to-string mingle2))
+ ))))
+ t t))))
+)
+
+;; This wraps around compilation-parse-errors in compile, and makes sure that
+;; the first line of the compilation buffer is blank. This is to make the
+;; call of ick (which is needed to determine the source file) look like an
+;; error message rather than a compiler call.
+(defun intercal-error-wrap (limit-search find-at-least)
+ "Parse the current buffer as ick error messages. This just wraps around
+'compilation-parse-errors'. See variable 'compilation-parse-errors-function'
+for the interface it uses."
+ (save-excursion
+ (beginning-of-buffer)
+ (if (looking-at "^$") nil (newline)))
+ (compilation-parse-errors limit-search find-at-least)
+)
+
+(require 'compile) ;Now a prerequisite for intercal.el, so its variables can be
+ ;changed to INTERCAL values upon loading an INTERCAL file
+
+;; This hook changes settings in fontlock and compile, so that they
+;; recognize INTERCAL syntax and ick error messages. Default options to
+;; ick are to optimize, but I chose not to give -b as a default (because
+;; it spoils the fun). I'm slightly tempted to use -m as default, but
+;; I'm not sure I'm that evil, and I left -f out for the time being because
+;; it's something of a radical change to the output.
+(add-hook 'intercal-mode-hook
+ (function (lambda ()
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(intercal-font-lock-keywords t))
+ (make-local-variable 'compilation-error-regexp-alist)
+ (setq compilation-error-regexp-alist (cons intercal-error-regexp
+ compilation-error-regexp-alist))
+ (make-local-variable 'compilation-file-regexp-alist)
+ (setq compilation-file-regexp-alist (cons intercal-file-regexp
+ compilation-file-regexp-alist))
+ (make-local-variable 'compile-command)
+ (setq compile-command (concat "ick -O " (buffer-name)))
+ (make-local-variable 'compilation-parse-errors-function)
+ (setq compilation-parse-errors-function 'intercal-error-wrap))))
+
+;; AIS: End of section I wrote.
+
;;; intercal.el ends here
%install
[ "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"
mkdir -p "$RPM_BUILD_ROOT"%{_bindir}
-cp ick "$RPM_BUILD_ROOT"%{_bindir}
+cp ick coopt.sh "$RPM_BUILD_ROOT"%{_bindir}
mkdir -p "$RPM_BUILD_ROOT"%{_libdir}
cp libick.a "$RPM_BUILD_ROOT"%{_libdir}
+cp libickmt.a "$RPM_BUILD_ROOT"%{_libdir}
+cp libyuk.a "$RPM_BUILD_ROOT"%{_libdir}
mkdir -p "$RPM_BUILD_ROOT"%{_includedir}/intercal-@PACKAGE_VERSION@
-cp lose.h abcess.h fiddle.h "$RPM_BUILD_ROOT"%{_includedir}/intercal-@PACKAGE_VERSION@
+cp lose.h abcess.h fiddle.h yuk.h "$RPM_BUILD_ROOT"%{_includedir}/intercal-@PACKAGE_VERSION@
%files
%doc README BUGS NEWS
%{_bindir}/ick
%{_libdir}/libick.a
+%{_libdir}/libickmt.a
+%{_libdir}/libyuk.a
%{_includedir}/intercal-@PACKAGE_VERSION@/lose.h
%{_includedir}/intercal-@PACKAGE_VERSION@/abcess.h
%{_includedir}/intercal-@PACKAGE_VERSION@/fiddle.h
+%{_includedir}/intercal-@PACKAGE_VERSION@/yuk.h
%changelog
* Wed Dec 31 2003 Eric S. Raymond <esr@snark.thyrsus.com> 0.24-1
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
-#include <memory.h>
#include "ick.h"
#include "y.tab.h"
#include "lose.h"
-#define YY_NO_UNPUT
+/*#undef wchar_t*/
+/*#define wchar_t unsigned char*/
#ifndef yywrap
static int yywrap(void)
int politesse = 0;
int stbeginline = 0;
+/* AIS: Sort out a grammar near-ambiguity */
+unsigned long sparkearsstack[SENESTMAX] = {0};
+int sparkearslev = 0;
+
#ifdef FLEX_SCANNER
static char linebuf[YY_BUF_SIZE];
#else /* FLEX_SCANNER */
{if (stbeginline == 0) stbeginline = yylineno; \
else if (stbeginline < 0) stbeginline = 0;}
+/* AIS: Keep track of the spark/ears situation */
+#define STACKSPARKEARS(a) \
+ if (sparkearslev+1>=SENESTMAX*32) lose(E281, yylineno, (char*) NULL); \
+ sparkearslev++; sparkearsstack[sparkearslev/32]<<=1; \
+ sparkearsstack[sparkearslev/32]+=a
+#define CLEARSPARKEARSTACK {int i=SENESTMAX; \
+ while(i--) sparkearsstack[i] = 0;} \
+ sparkearslev = 0
+
/*
* The spectacular ugliness of INTERCAL syntax requires that the lexical
* analyzer have two levels. One, embedded in the getc() function, handles
}
else
{
- int c = fgetc(fp);
+ int c;
+ char c_char;
+ /*fprintf(stderr,"about to fgetc(\045p)",(void*)fp);*/
+
+ (void)fread(&c_char,1,1,fp);
+ c = c_char;
+ /*fputc(c,stderr);*/
+ if(feof(fp)) c=EOF;
+
+ /*fprintf(stderr,"getc input a character: %c\n",c);*/
if (feof(yyin))
{
@ {yylval.numval = WHIRL; return(UNARY);}
[2-5]{W}@ {yylval.numval = WHIRL + myatoi(yytext) - 1; return(UNARY);}
-\' {return(SPARK);}
-\" {return(EARS);}
+\' {char temp = sparkearsstack[sparkearslev/32]&1;
+ STACKSPARKEARS(0); /* AIS: I added all mentions of
+ STACKSPARKEARS, OPEN\(SPARK\|EARS\),
+ CLOSE\(SPARK\|EARS\),
+ and CLEARSPARKEARSTACK */
+ return(temp?OPENSPARK:CLOSESPARK);}
+\" {char temp = sparkearsstack[sparkearslev/32]&1;
+ STACKSPARKEARS(1);
+ return(temp?CLOSEEARS:OPENEARS);}
\({W}{D}\) {SETLINENO; yylval.numval = myatoi(yytext); return(LABEL);}
-DO {SETLINENO; return(DO);}
-FAC {SETLINENO; return(DO);}
-PLEASE {SETLINENO; politesse++; return(DO);}
-PLACET {SETLINENO; politesse++; return(DO);}
-PLEASE{W}DO {SETLINENO; politesse++; return(DO);}
-PLACET{W}FACERE {SETLINENO; politesse++; return(DO);}
+DO {SETLINENO; CLEARSPARKEARSTACK; return(DO);}
+FAC {SETLINENO; CLEARSPARKEARSTACK; return(DO);}
+PLEASE {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(DO);}
+PLACET {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(DO);}
+PLEASE{W}DO {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(DO);}
+PLACET{W}FACERE {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(DO);}
+MAYBE {SETLINENO; CLEARSPARKEARSTACK; return(MAYBE);}
+MAYBE{W}DO {SETLINENO; CLEARSPARKEARSTACK; return(MAYBE);}
+MAYBE{W}PLEASE {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(MAYBE);}
+MAYBE{W}PLEASE{W}DO {SETLINENO; CLEARSPARKEARSTACK; politesse++; return(MAYBE);
+ /* AIS: I added all the MAYBE cases. It seems that MAYBE
+ has no simple Latin synonym. */}
+
NOT {return(NOT);}
N\'T {return(NOT);}
NON {return(NOT);}
+ONCE {return(ONCE);}
+QUONDAM {return(ONCE);}
+AGAIN {return(AGAIN);}
+ITERUM {return(AGAIN);}
\%{W}{D} {yylval.numval = myatoi(yytext);
if (yylval.numval && yylval.numval < 100)
REMEMBER {return(REMEMBER);}
MEMINISSENDUM |
REMEMBERING {yylval.numval = REMEMBER; return(GERUND);}
-ABSTINERE{W}A |
-ABSTAIN{W}FROM {return(ABSTAIN);}
+ABSTINERE |
+ABSTAIN {return(ABSTAIN);}
+FROM |
+A {return(FROM);}
ABSTINENDUM |
ABSTAINING {yylval.numval = ABSTAIN; return(GERUND);}
REINSTARE |
WRITE{W}IN {return(WRITE_IN);}
SCRIBENDUM |
WRITING{W}IN {yylval.numval = WRITE_IN; return(GERUND);}
-ADVENIRE{W}DE |
-COME{W}FROM {stbeginline = -stbeginline; return(COME_FROM);}
+ADVENIRE{W}DE{W}\({W}{D}\) |
+COME{W}FROM{W}\({W}{D}\) {/* By AIS */ yylval.numval = myatoi(yytext);
+ return(COME_FROM);}
+ADVENIRE{W}DE |
+COME{W}FROM {/* By AIS */ return(COMPUCOME);}
ADVENENDUM |
COMING{W}FROM {yylval.numval = COME_FROM; return(GERUND);}
CONCEDERE |
DESPERARE |
GIVE{W}UP {return(GIVE_UP);}
+CONOR{W}ITERUM |
+TRY{W}AGAIN {return(TRY_AGAIN);}
+TRYING{W}AGAIN {yylval.numval = TRY_AGAIN; return(GERUND);}
+GO{W}BACK |
+REDIRE {return(GO_BACK);}
+GOING{W}BACK |
+REDENDUM {yylval.numval = GO_BACK; return(GERUND);}
+GO{W}AHEAD |
+GRASSOR {return(GO_AHEAD);}
+GOING{W}AHEAD {yylval.numval = GO_AHEAD; return(GERUND);
+ /* AIS: I'm having a few deponent troubles with the Latin, so
+ there are no Latin gerunds around here. Besides, the Latin
+ 'gerunds' look somewhat like gerundives to me, but that's
+ purely based on memory so I may be wrong. */}
\+ {return(INTERSECTION);}
return(tok);
}
-static int myatoi(char *text)
+static int myatoi(char *text) /* Alex edit! */
{
#define MAXTEXT 100
static char buf[MAXTEXT];
+ static char thinbuf[MAXTEXT];
+ char* bp;
+ char* tp;
register int i;
for(buf[i = 0] = '\0';*text && i < MAXTEXT;text++) {
}
}
buf[i] = '\0';
- return atoi(buf);
+ bp=buf; tp=thinbuf;
+ while(*tp++=*bp++); /* thinbuf code added by an Alex edit,
+ in case we want to work with wchar_t */
+ return atoi(thinbuf);
}
void yyerror(char *errtype)
/*LINTLIBRARY*/
#include <stdio.h>
#include <stdlib.h>
+#include <signal.h>
#include "lose.h"
+int coreonerr = 0; /* AIS */
+
+int checkforbugs; /* AIS */
+
void lose(char *m, int n, char *s)
{
+ (void) fflush(stdout); /* AIS: To stop stdout getting muddled with stderr*/
(void) fprintf(stderr,
"ICL%c%c%cI\t",
m[0], m[1], m[2]);
else
(void) fprintf(stderr, m + 4, n);
(void) fprintf(stderr, " CORRECT SOURCE AND RESUBNIT\n");
+ if(atoi(m)==778&&coreonerr) /* AIS */
+ {
+ /* AIS: Dump core. */
+ raise(SIGABRT);
+ }
exit(atoi(m));
}
-/* lose.c ends here */
-
+/* AIS: This function reports potential bugs. It's paraphrased from lose. */
+void lwarn(char *m, int n, char *s)
+{
+ if(!checkforbugs) return; /* Don't report a potential bug without -l */
+ (void) fflush(stdout);
+ (void) fprintf(stderr,
+ "ICL%c%c%cW\t",
+ m[0],m[1],m[2]);
+ if (s)
+ (void) fprintf(stderr, m + 4, s, n);
+ else
+ (void) fprintf(stderr, m + 4, n);
+ (void) fprintf(stderr, " RECONSIDER SOURCE AND RESUBNIT\n\n");
+ /* Don't exit. This is not any error except one not causing immediate
+ termination of program execution. */
+}
+/* lose.c ends here */
/* Out of stash space */
#define E222 "222 BUMMER, DUDE!\n\
ON THE WAY TO %d\n"
+/* (AIS) The spark/ears nesting is too deep. */
+#define E281 "281 THAT MUCH QUOTATION AMOUNTS TO PLAGIARISM\n\
+ ON THE WAY TO %d\n"
/* Too many variables. */
#define E333 "333 YOU CAN'T HAVE EVERYTHING, WHERE WOULD YOU PUT IT?\n\
ON THE WAY TO %d\n"
+/* (AIS, from the suggestion by Malcom Ryan)
+ GO BACK or GO AHEAD was executed without a choicepoint. */
+#define E404 "404 I'M ALL OUT OF CHOICES!\n\
+ ON THE WAY TO %d\n"
+/* (AIS) MAYBE, GO BACK, or GO AHEAD used without the -m option. */
+#define E405 "405 PROGRAM REJECTED FOR MENTAL HEALTH REASONS\n\
+ ON THE WAY TO %d\n"
/* A COME FROM statement references a non-existent line label. */
#define E444 "444 IT CAME FROM BEYOND SPACE\n\
ON THE WAY TO %d\n"
/* Illegal possession of a controlled unary operator. */
#define E997 "997 ILLEGAL POSSESSION OF A CONTROLLED UNARY OPERATOR.\n\
ON THE WAY TO %d\n"
+/* (AIS) Command found after TRY AGAIN. */
+#define E993 "993 I GAVE UP LONG AGO\n\
+ ON THE WAY TO %d\n"
+/* (AIS) Memory allocation failure during multithreading */
+#define E991 "991 YOU HAVE TOO MUCH ROPE TO HANG YOURSELF\n\
+ ON THE WAY TO %d\n"
+
+/*
+ * AIS: These errors are generated by the yuk debugger
+ */
+/* (AIS) fgets' buffer overflowed on debugger comand input. */
+#define E810 "810 ARE ONE-CHARACTER COMMANDS TOO SHORT FOR YOU?\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) Too many breakpoints. */
+#define E811 "811 PROGRAM IS TOO BADLY BROKEN TO RUN\n\
+ ON THE WAY TO %d\n"
+
+/*
+ * (AIS) Warnings produced by -l.
+ */
+
+/* (AIS) Non-INTERCAL-72 identifier used. */
+#define W112 "112 THAT RELIES ON THE NEW WORLD ORDER\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) That stupid idiom in syslib was used. */
+#define W128 "128 SYSLIB IS OPTIMIZED FOR OBFUSCATION\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) Possibly nonportable unary operator. */
+#define W534 "534 KEEP LOOKING AT THE TOP BIT\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) Expression still contains INTERCAL operators after
+ optimization. Only in binary, because this nearly always
+ happens in the higher bases. Syslib causes quite a lot of
+ these. This warning is fine on INTERCAL-like lines, but
+ flags a mistake on lines that are meant to be translations
+ of C. */
+#define W018 "018 THAT WAS MEANT TO BE A JOKE\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) Possible misplaced unary operator. At the moment, ick -l cannot
+ detect this condition (so it never comes up). It's meant to detect
+ expressions like '?"?.1~#256"$#2'~#3 (from numio.i); in this expression,
+ the second what has no effect (it changes only the msb of the immediately
+ surrounding expression, which is eventually filtered out by the select
+ against #3). But detecting this would probably require code that could
+ check which bits of a result were going to be used elsewhere in an
+ expression, which is something I haven't written yet (but would make
+ a decent optimize_pass3). */
+#define W016 "016 DON'T TYPE THAT SO HASTILY\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) Possibly overflowing assignment or mingle. Syslib causes some of
+ these too, in complicated situations where the bugcatcher can't figure
+ out what's happening, and also in a few blatant statements in the mould
+ of DO .3 <- :3, which are quite clearly possible overflows. Strangely
+ enough, there's a commented-out section of code in feh.c that suggests
+ that someone tried to make this an error (using a more general check
+ which would have caught more correct code involving GETS, but none
+ involving $). As a middle ground, I've made it an -l warning. */
+#define W276 "276 YOU CAN'T EXPECT ME TO CHECK BACK THAT FAR\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) The two following warnings are both compile-time traps for
+ near-certain runtime errors. As such, they have similar numbers
+ and similar messages. In fact, they're a shameless ripoff of the
+ originals, but should serve as a reminder for anyone aware of the
+ original messages. */
+/* (AIS) Dimension given for an array will come out as #0. */
+#define W239 "239 WARNING HANDLER PRINTED SNIDE REMARK\n\
+ ON THE WAY TO %d\n"
+
+/* (AIS) RESUME argument will come out as #0. */
+#define W622 "622 WARNING TYPE 622 ENCOUNTERED\n\
+ ON THE WAY TO %d\n"
extern int lineno;
extern void lose(char *m, int n, char *s);
+extern void lwarn(char *m, int n, char *s);
+
/* lose.h ends here */
#ifndef ICKLIBDIR
#define ICKLIBDIR "/usr/local/share"
#endif
+#ifndef ICKBINDIR
+#define ICKBINDIR "/usr/local/bin"
+#endif
#ifndef CC
#define CC "gcc"
#endif
#ifdef USE_YYRESTART
/* function supplied by lex */
extern void yyrestart(FILE*);
+
#endif /* USE_YYRESTART */
/* function created by yacc */
bool compile_only; /* just compile into C, don't run the linker */
bool traditional; /* insist on strict INTERCAL-72 conformance */
bool nocompilerbug; /* disable error E774 */
+int yukdebug; /* AIS: Use the yuk debugger. */
+int yukprofile; /* AIS: Use the yuk profiler. */
+extern int coreonerr; /* AIS: Dump core on E778. (defined in lose.c) */
+int multithread; /* AIS: Allow multithreading and backtracking. */
+int cdebug; /* AIS: Pass -g to our C compiler, and leave C code. */
+int optdebug; /* AIS: Debug the optimizer. Value is 0, 1, 2, or 3. */
+int flowoptimize; /* AIS: Do flow optimizations (in INTERCAL!). */
+int coopt; /* AIS: The constant-output optimization. This should
+ mean that INTERCAL will beat any other language at
+ many benchmark programs (!) */
+extern int checkforbugs;/* AIS: Try to find possible bugs in the source code */
+
+int compucomecount=0; /* AIS: Computed COME FROM count */
+int compucomesused=0; /* AIS: Are computed COME FROMs used? */
static bool dooptimize; /* do optimizations? (controlled by -O) */
static bool clockface; /* set up output to do IIII for IV */
tuple *tuples = NULL;
int tuplecount = 0;
+tuple *optuple = NULL; /* AIS: Tuple being optimized */
+
+static int myfgetc(FILE* in)
+{
+ char c;
+ fread(&c,1,1,in);
+ if(feof(in)) return EOF;
+ return (int)c;
+}
+
+
static void abend(int signim)
{
lose(E778, yylineno, (char *)NULL);
fprintf(stderr,"Usage: %s [-%s] <file> [<file> ... ]\n",prog,options);
fprintf(stderr,"\t-b\t:reduce the probability of E774 to zero\n");
fprintf(stderr,"\t-c\t:compile INTERCAL to C, but don't compile C\n");
- fprintf(stderr,"\t-d\t:print debugging information (implies -c)\n");
+ fprintf(stderr,"\t-d\t:print yacc debugging information (implies -c)\n");
fprintf(stderr,"\t-t\t:traditional mode, accept only INTERCAL-72\n");
fprintf(stderr,"\t-C\t:clockface output (e.g. use IIII instead of IV)\n");
- fprintf(stderr,"\t-O\t:attempt to optimize generated code\n");
+ fprintf(stderr,"\t-O\t:optimize expresssions in generated code\n");
+ /* AIS: Changed the help message for the previous line (because the
+ function of -O has changed). I wrote the next group of options. */
+ fprintf(stderr,"\t-f\t:optimize control flow in generated code "
+ "(prevents -yp)\n");
+ fprintf(stderr,"\t-F\t:optimize everything in generated code for\n"
+ "\t\tspeed, regardless of how slow the compiler becomes or how\n"
+ "\t\tlarge the object file becomes. Implies -fO,\n"
+ "\t\tprevents -cdghpyH\n");
+ fprintf(stderr,"\t-h\t:print optimizer debugging information "
+ "(implies -cO)\n");
+ fprintf(stderr,"\t-H\t:print verbose optimizer debugging information "
+ "(implies -cO)\n");
+ fprintf(stderr,"\t-hH\t:print optimizer debugging information in a\n"
+ "\t\tdifferent form (implies -cO)\n");
+ fprintf(stderr,"\t-y\t:run the yuk debugger on the code (prevents -fm)\n");
+ fprintf(stderr,"\t-p\t:run the yuk profiler on the code (prevents -fm)\n");
+ fprintf(stderr,"\t-m\t:allow multithreading and backtracking "
+ "(prevents -yp)\n");
+ fprintf(stderr,"\t-U\t:dump core on E778 rather than printing an error\n");
+ fprintf(stderr,"\t-g\t:compile to both debuggable executable and C\n");
+ fprintf(stderr,"\t-l\t:attempt to report likely bugs "
+ "and nonportabilities (implies -O)\n");
+ /* AIS: End of options I added. */
fprintf(stderr,"\t<file>\tINTERCAL source file(s) (use extension .i)\n");
fprintf(stderr,"\t\teach file produces a separate output program.\n");
}
+/* AIS: This function looks for the skeleton and syslib, searching first the
+ path they should be in, then the current directory, then argv[0]'s
+ directory (if one was given). This function avoids possible buffer
+ overflows, instead truncating filenames (and if that manages to find them,
+ I'll be incredibly surprised). */
+static FILE* findandfopen(char* file, char* guessdir, char* mode, char* argv0)
+{
+ char buf2[BUFSIZ], *fileiter;
+ int i = 0, j;
+ FILE* ret;
+ while(*guessdir&&i<BUFSIZ-2) buf2[i++] = *guessdir++;
+ buf2[i++] = '/';
+ fileiter = file;
+ while(*fileiter&&i<BUFSIZ-1) buf2[i++] = *fileiter++;
+ buf2[i] = 0;
+ ret = fopen(buf2,mode); /* where it ought to be */
+ if(ret) return ret;
+ ret = fopen(file,mode); /* current dir */
+ if(ret) return ret;
+ if(!strchr(argv0,'/')) return 0; /* argv[0] has no dir specified */
+ i = j = 0;
+ while(*argv0&&i<BUFSIZ-2) {buf2[i++] = *argv0++; if(*argv0=='/') j = i;}
+ i = j + 1;
+ while(*file&&i<BUFSIZ-1) buf2[i++] = *file++;
+ buf2[i] = 0;
+ ret = fopen(buf2,mode); /* argv[0]'s dir */
+ return ret; /* just return 0 if even this failed */
+}
+
+/* AIS: The same, looking for an executable */
+static char* findandtestopen(char* file, char* guessdir, char* mode,
+ char* argv0)
+{
+ static char buf2[BUFSIZ], *fileiter;
+ int i = 0, j;
+ FILE* ret;
+ while(*guessdir&&i<BUFSIZ-2) buf2[i++] = *guessdir++;
+ buf2[i++] = '/';
+ fileiter = file;
+ while(*fileiter&&i<BUFSIZ-1) buf2[i++] = *fileiter++;
+ buf2[i] = 0;
+ ret = fopen(buf2,mode); /* where it ought to be */
+ if(ret) {fclose(ret); return buf2;}
+ ret = fopen(file,mode); /* current dir */
+ if(ret) {fclose(ret); return buf2;}
+ if(!strchr(argv0,'/')) return 0; /* argv[0] has no dir specified */
+ i = j = 0;
+ while(*argv0&&i<BUFSIZ-2) {buf2[i++] = *argv0++; if(*argv0=='/') j = i;}
+ i = j + 1;
+ while(*file&&i<BUFSIZ-1) buf2[i++] = *file++;
+ buf2[i] = 0;
+ ret = fopen(buf2,mode); /* argv[0]'s dir */
+ if(ret) {fclose(ret); return buf2;}
+ return 0;
+}
+
+/* AIS: The same thing, but with freopen */
+static FILE* findandfreopen(char* file, char* guessdir, char* mode,
+ char* argv0, FILE* over)
+{
+ char buf2[BUFSIZ], *fileiter;
+ int i = 0, j;
+ FILE* ret;
+ while(*guessdir&&i<BUFSIZ-2) buf2[i++] = *guessdir++;
+ buf2[i++] = '/';
+ fileiter = file;
+ while(*fileiter&&i<BUFSIZ-1) buf2[i++] = *fileiter++;
+ buf2[i] = 0;
+ ret = freopen(buf2,mode,over); /* where it ought to be */
+ if(ret) return ret;
+ ret = freopen(file,mode,over); /* current dir */
+ if(ret) return ret;
+ if(!strchr(argv0,'/')) return 0; /* argv[0] has no dir specified */
+ i = j = 0;
+ while(*argv0&&i<BUFSIZ-2) {buf2[i++] = *argv0++; if(*argv0=='/') j = i;}
+ i = j + 1;
+ while(*file&&i<BUFSIZ-1) buf2[i++] = *file++;
+ buf2[i] = 0;
+ ret = freopen(buf2,mode,over); /* argv[0]'s dir */
+ return ret; /* just return 0 if even this failed */
+}
+
int main(int argc, char *argv[])
{
extern int optind; /* set by getopt */
- char buf[BUFSIZ], buf2[BUFSIZ], *chp, *strrchr();
+ char buf[BUFSIZ], buf2[BUFSIZ], *chp; /* AIS: , *strrchr(); */
tuple *tp;
atom *op;
int c, i;
- char *includedir, *libdir, *getenv();
+ char *includedir, *libdir; /* AIS: , *getenv(); */
+ char *bindir, *cooptsh;
FILE *ifp, *ofp;
int maxabstain, nextcount, bugline;
bool needsyslib, firstfile;
includedir = ICKINCLUDEDIR;
if (!(libdir = getenv("ICKLIBDIR")))
libdir = ICKLIBDIR;
+ if (!(bindir = getenv("ICKBINDIR"))) /* AIS */
+ bindir = ICKBINDIR;
if (!(compiler = getenv("CC")))
compiler = CC;
- while ((c = getopt(argc, argv, "bcdtOC@")) != EOF)
+ while ((c = getopt(argc, argv, "bcdfghlmptyCFHOU@")) != EOF)
{
switch (c)
{
case 'c':
compile_only = TRUE;
+ /* AIS */ coopt = FALSE;
break;
case 'd':
yydebug = compile_only = TRUE;
+ /* AIS */ coopt = FALSE;
break;
case 'C':
case 't':
traditional = TRUE;
+ if(multithread) lose(E111, 1, (char*) NULL);
break;
case 'O':
dooptimize = TRUE;
break;
+ case 'f': /* By AIS */
+ flowoptimize = TRUE;
+ yukdebug = yukprofile = FALSE;
+ break;
+
+ case 'F': /* By AIS */
+ coopt = flowoptimize = dooptimize = TRUE;
+ yukdebug = yukprofile = yydebug =
+ compile_only = cdebug = FALSE;
+ break;
+
+ case 'h': /* By AIS */
+ optdebug|=1;
+ compile_only=dooptimize=TRUE;
+ coopt=FALSE;
+ break;
+
+ case 'H': /* By AIS */
+ optdebug|=2;
+ compile_only=dooptimize=TRUE;
+ coopt=FALSE;
+ break;
+
+ case 'y': /* By AIS */
+ yukdebug=TRUE;
+ multithread=flowoptimize=coopt=FALSE;
+ break;
+
+ case 'p': /* By AIS */
+ yukprofile=TRUE;
+ multithread=flowoptimize=coopt=FALSE;
+ break;
+
+ case 'm': /* By AIS */
+ multithread=TRUE;
+ yukprofile=FALSE;
+ yukdebug=FALSE;
+ if(traditional) lose(E111, 1, (char*) NULL);
+ break;
+
+ case 'l': /* By AIS */
+ checkforbugs=TRUE;
+ dooptimize=TRUE;
+ break;
+
+ case 'U': /* By AIS */
+ coreonerr=TRUE;
+ break;
+
+ case 'g': /* By AIS */
+ cdebug=TRUE;
+ coopt=FALSE;
+ break;
+
case '?':
default:
case '@':
- print_usage(argv[0],"bcdtCO");
+ print_usage(argv[0],"bcdfghlmptyCFHOU@");
exit(1);
break;
}
#ifdef SIGBUS
(void) signal(SIGBUS, abend);
#endif /* SIGBUS */
-
+
if (!nocompilerbug) {
#ifdef USG
srand48(time(NULL) + getpid());
#endif /* UNIX */
}
- (void) sprintf(buf2,"%s/%s",libdir,SKELETON);
-
+ /* AIS: New function for enhanced file-finding */
+ if ((ifp = findandfopen(SKELETON, libdir, "r", argv[0])) == 0)
+ lose(E999, 1, (char *)NULL);
+
/* now substitute in tokens in the skeleton */
- if ((ifp = fopen(buf2, "r")) == (FILE *)NULL)
- lose(E999, 1, (char *)NULL);
+
buf[strlen(buf) - 2] = '\0';
for (firstfile = TRUE; optind < argc; optind++, firstfile = FALSE)
Large_digits = 2 * Small_digits;
Max_small = maxsmalls[Base];
if (Max_small == 0xffff)
- Max_large = 0xffffffff;
+ Max_large = 0xffffffffLU;
else
Max_large = (Max_small + 1) * (Max_small + 1) - 1;
}
tp->u.target <= 1999)
needsyslib = TRUE;
}
- if ( needsyslib ) {
- if (Base == 2)
- (void) sprintf(buf2, "%s/%s.i", libdir, SYSLIB);
+ if ( needsyslib ) { /* AIS: modified to use findandfreopen */
+ if (Base == 2) /* see code for opening the skeleton */
+ (void) sprintf(buf2, "%s.i", SYSLIB);
else
- (void) sprintf(buf2, "%s/%s.%di", libdir, SYSLIB, Base);
- if ( freopen(buf2, "r", stdin) == (FILE*) NULL ) {
+ (void) sprintf(buf2, "%s.%di", SYSLIB, Base);
+ if (findandfreopen(buf2, libdir, "r", argv[0], stdin) == 0)
lose(E127, 1, (char*) NULL);
- }
+
#ifdef USE_YYRESTART
yyrestart(stdin);
#endif /* USE_YYRESTART */
* deducible type of the operand.
*/
for (tp = tuples; tp->type; tp++)
+ {
if (tp->type == GETS || tp->type == RESIZE
- || tp->type == WRITE_IN || tp->type == READ_OUT
- || tp->type == FORGET || tp->type == RESUME)
- typecast(tp->u.node);
+ || tp->type == WRITE_IN || tp->type == READ_OUT
+ || tp->type == FROM || tp->type == MANYFROM
+ || tp->type == FORGET || tp->type == RESUME
+ || tp->type == COMPUCOME)
+ typecast(tp->type == MANYFROM ? tp->u.node->lval : tp->u.node);
+ if (tp->type == WRITE_IN) coopt = 0; /* AIS: may as well do
+ this here */
+ }
codecheck(); /* check for compile-time errors */
-
+ /* AIS: And importantly, sort out line number references */
+
/* perform optimizations */
if (dooptimize)
for (tp = tuples; tp->type; tp++)
- if (tp->type == GETS || tp->type == RESIZE
- || tp->type == FORGET || tp->type == RESUME)
- optimize(tp->u.node);
+ {
+ optuple = tp;
+ if (tp->type == GETS || tp->type == RESIZE
+ || tp->type == FORGET || tp->type == RESUME
+ || tp->type == FROM || tp->type == COMPUCOME)
+ optimize(tp->u.node);
+ if (tp->type == MANYFROM) optimize(tp->u.node->lval);
+ } /* AIS: Added FROM and MANYFROM support. */
+
+ /* AIS: perform flow optimizations */
+ if (flowoptimize) optimizef();
/* decide if and where to place the compiler bug */
#ifdef USG
fseek(ifp,0L,0); /* rewind skeleton file */
- while ((c = fgetc(ifp)) != EOF)
+ /* AIS: Before changing argv[0], locate coopt.sh. */
+ cooptsh = findandtestopen("coopt.sh", bindir, "rb", argv[0]);
+
+ /* AIS: Remove the filename from argv[0], leaving only a directory.
+ If this would leave it blank, change argv[0] to '.'.
+ This is so gcc can find the includes/libraries the same way that
+ findandfreopen does. */
+ if(strchr(argv[0],'/')) *(strrchr(argv[0],'/')) = 0;
+ else strcpy(argv[0],".");
+
+ (void) sprintf(buf2,
+ "%s %s%s-I%s -I%s -L%s -L%s -o %s -lick%s%s",
+ compiler, buf, yukdebug||yukprofile?" -lyuk ":" ",
+ includedir, argv[0], libdir, argv[0],
+ argv[optind], multithread?"mt":"", cdebug?" -g":"");
+ /* AIS: Possibly link in the debugger yuk and/or libickmt.a here. */
+ /* AIS: Added -g support. */
+ /* AIS: Added argv[0] to the -I, -L settings. */
+
+ while ((c = myfgetc(ifp)) != EOF)
if (c != '$')
(void) fputc(c, ofp);
- else switch(fgetc(ifp))
+ else switch(myfgetc(ifp))
{
case 'A': /* source name stem */
(void) fputs(argv[optind], ofp);
break;
case 'C': /* initial abstentions */
+ /* AIS: Modified to check for coopt */
maxabstain = 0;
for (tp = tuples; tp->type; tp++)
- if (tp->exechance <= 0 && tp - tuples + 1 > maxabstain)
+ if (((tp->exechance <= 0 || tp->exechance >= 101)
+ && tp - tuples + 1 > maxabstain) || coopt)
maxabstain = tp - tuples + 1;
if (maxabstain)
{
(void) fprintf(ofp, " = {");
for (tp = tuples; tp < tuples + maxabstain; tp++)
+ {
+ if(tp->exechance != 100 && tp->exechance != -100)
+ { /* AIS: The double-oh-seven operator prevents
+ coopt working. However, syslib contains a
+ double-oh-seven. feh.c has checked that that
+ isn't referenced; if it isn't, we can allow
+ one double-oh-seven if syslib was
+ automagically inclulded. */
+ if(needsyslib) needsyslib = 0; else coopt = 0;
+ }
if (tp->exechance > 0)
(void) fprintf(ofp, "0, ");
else {
(void) fprintf(ofp, "1, ");
tp->exechance = -tp->exechance;
+ /* AIS: If the line was abstained, we need to
+ swap ONCEs and AGAINs on it round, to suit
+ the code degenerator. */
+ if(tp->onceagainflag == onceagain_ONCE)
+ tp->onceagainflag = onceagain_AGAIN;
+ else if(tp->onceagainflag == onceagain_AGAIN)
+ tp->onceagainflag = onceagain_ONCE;
+ }
+ if(tp->exechance >= 101)
+ {
+ /* AIS: This line has a MAYBE */
+ tp->maybe = 1;
+ tp->exechance /= 100;
}
+ else tp->maybe = 0;
+ }
(void) fprintf(ofp, "}");
}
break;
case 'D': /* linetypes array for abstention handling */
maxabstain = 0;
for (tp = tuples; tp->type; tp++)
- if (tp->type == ENABLE || tp->type == DISABLE)
+ if (tp->type == ENABLE || tp->type == DISABLE || tp->type == MANYFROM)
maxabstain++;
if (maxabstain)
{
(void) fprintf(ofp, "int linetype[] = {\n");
for (tp = tuples; tp->type; tp++)
- if (tp->type >= GETS && tp->type <= COME_FROM)
+ if (tp->type >= GETS && tp->type <= FROM) /* AIS: FROM added */
(void) fprintf(ofp,
" %s,\n",
enablers[tp->type - GETS]);
Max_small);
(void) fprintf(ofp,"unsigned int Max_large = 0x%x;\n",
Max_large);
+ if (yukprofile || yukdebug || multithread)
+ { /* AIS: yuk.c, multithreading require all these to exist */
+ if(!nonespots) nonespots = 1;
+ if(!ntwospots) ntwospots = 1;
+ if(!ntails) ntails = 1;
+ if(!nhybrids) nhybrids = 1;
+ }
+ /* AIS: I de-staticed all these so they could be accessed by
+ yuk and cesspool, and added all the mentions of yuk and
+ multithread. Then I changed it so the variables would be
+ allocated dynamically, to speed up multithreading. (It's
+ an O(1) change to the speed of ordinary programs, so I
+ thought I could get away with it. The order is wrt the
+ number of lines in the program. The change is O(n) wrt
+ the number of variables, but again I hope that doesn't
+ matter, and I won't get the entire INTERCAL community
+ angry with me for daring to implement an extension that
+ slows down existing programs.) */
if (nonespots)
{
(void) fprintf(ofp,
- "static type16 onespots[%d];\n",
- nonespots);
+ "type16* onespots;\n");
(void) fprintf(ofp,
- "static bool oneforget[%d];\n",
- nonespots);
+ "bool* oneforget;\n");
+ if(yukprofile || yukdebug)
+ {
+ (void) fprintf(ofp,
+ "type16 oneold[%d];\n",
+ nonespots);
+ (void) fprintf(ofp,
+ "signed char onewatch[%d];\n",
+ nonespots);
+ }
+ if(multithread)
+ {
+ (void) fprintf(ofp,
+ "int onespotcount = %d;\n",
+ nonespots);
+ }
}
if (ntwospots)
{
(void) fprintf(ofp,
- "static type32 twospots[%d];\n",
- ntwospots);
+ "type32* twospots;\n");
(void) fprintf(ofp,
- "static bool twoforget[%d];\n",
- ntwospots);
+ "bool* twoforget;\n");
+ if(yukprofile || yukdebug)
+ {
+ (void) fprintf(ofp,
+ "type32 twoold[%d];\n",
+ ntwospots);
+ (void) fprintf(ofp,
+ "signed char twowatch[%d];\n",
+ ntwospots);
+ }
+ if(multithread)
+ {
+ (void) fprintf(ofp,
+ "int twospotcount = %d;\n",
+ ntwospots);
+ }
}
if (ntails)
{
(void) fprintf(ofp,
- "static array tails[%d];\n",
- ntails);
+ "array* tails;\n");
(void) fprintf(ofp,
- "static bool tailforget[%d];\n",
- ntails);
+ "bool* tailforget;\n");
+ if(multithread)
+ {
+ (void) fprintf(ofp,
+ "int tailcount = %d;\n",
+ ntails);
+ }
}
if (nhybrids)
{
(void) fprintf(ofp,
- "static array hybrids[%d];\n",
- nhybrids);
+ "array* hybrids;\n");
(void) fprintf(ofp,
- "static bool hyforget[%d];\n",
- nhybrids);
+ "bool* hyforget;\n");
+ if(multithread)
+ {
+ (void) fprintf(ofp,
+ "int hybridcount = %d;\n",
+ nhybrids);
+ }
}
if (yydebug || compile_only)
for (op = oblist; op < obdex; op++)
nameof(op->type, vartypes),
op->extindex,
op->intindex);
+ if (yukdebug || yukprofile)
+ { /* AIS: drop intern to extern map into the program */
+ (void) fprintf(ofp, "\nyukvar yukvars[]={\n");
+ for (op = oblist; op < obdex; op++)
+ (void) fprintf(ofp," {%s,%d,%d},\n",
+ nameof(op->type, vartypes),
+ op->extindex,
+ op->intindex);
+ (void) fprintf(ofp," {YUKEND,0,0}};\n");
+ }
break;
case 'F': /* set clockface option? */
}
break;
- case 'H': /* dispatching for resumes */
+ case 'H': /* COMPUCOME, and dispatching for resumes */
+ /* AIS: Added COMPUCOME here. This line must be fully guarded
+ to prevent a longjmp to an uninitialised buffer (it's
+ guarded by a lose() in ick-wrap.c.) Also checks for
+ multithread; programs that mix normal and computed COME
+ FROM need to use the same conventions for both, so even
+ if no computed COME FROMs are used, the normal ones need
+ this line so that COME FROMs can be handled consistently.*/
+ if(compucomesused || multithread)
+ {
+ (void) fprintf(ofp, "CCF%d: longjmp(cjb,1);\n",
+ compucomecount);
+ }
nextcount = 0;
for (tp = tuples; tp->type; tp++)
if (tp->type == NEXT)
case 'J': /* # of source file lines */
(void) fprintf(ofp, "%d", yylineno);
break;
+
+ case 'K': /* AIS: yuk information (or not) */
+ if(yukdebug||yukprofile)
+ {
+ (void) fprintf(ofp, "#include \"yuk.h\"\n\n");
+ (void) fprintf(ofp, "char* textlines[] = {\n");
+ emittextlines(ofp); /* from feh.c */
+ (void) fprintf(ofp, "\"\"};\n\n");
+ (void) fprintf(ofp, "char* yukexplain[] = {\n");
+ for (tp = tuples; tp->type; tp++)
+ {
+ if (tp->type == GETS || tp->type == FORGET || tp->type == RESUME
+ || tp->type == FROM || tp->type == COMPUCOME
+ || tp->type == MANYFROM)
+ {
+ (void) fprintf(ofp, "\"");
+ explexpr(tp->type == MANYFROM ? tp->u.node->lval :
+ tp->type == GETS ? tp->u.node->rval : tp->u.node, ofp);
+ (void) fprintf(ofp, "\",\n");
+ }
+ else (void) fprintf(ofp, "0,");
+ }
+ (void) fprintf(ofp, "0};\n\n");
+ (void) fprintf(ofp, "int lineofaboff[] = {\n");
+ for (tp = tuples; tp->type; tp++)
+ {
+ fprintf(ofp,"%d,",tp->lineno);
+ }
+ (void) fprintf(ofp, "-1};\n\n");
+ (void) fprintf(ofp, "int yukopts = %d;\n", yukprofile+yukdebug*2);
+ (void) fprintf(ofp, "yptimer ypexectime[%d];\n", lineno);
+ (void) fprintf(ofp, "ypcounter ypexecount[%d];\n",lineno);
+ (void) fprintf(ofp, "ypcounter ypabscount[%d];\n",lineno);
+ }
+ break;
+
+ case 'L': /* AIS: increase Emacs compatibility */
+ (void) fprintf(ofp,
+ "/* -*- mode:c; compile-command:\"%s\" -*- */"
+ ,buf2);
+ break;
+
+ case 'M': /* AIS: place a multithreading define in program */
+ /* This is needed even in a non-multithread program, to let
+ the header files know it's non-multithread */
+ (void) fprintf(ofp, "#define MULTITHREAD %d", multithread);
+ break;
+
+ case 'N': /* allocate variables */
+ /* AIS: I de-staticed all these so they could be accessed by
+ yuk and cesspool, and added all the mentions of yuk and
+ multithread. Then I changed it so the variables would be
+ allocated dynamically, to speed up multithreading (it's
+ an O(1) change to the speed of ordinary programs, so I
+ thought I could get away with it). At this point, the
+ 'E' case must already have been done. calloc sets all
+ the integer values to 0, as before. In the case of
+ arrays, it will not zero pointers, but the number-of-
+ dimensions value will become 0, which can serve as a
+ 'deallocated' flag. */
+ if (nonespots)
+ {
+ (void) fprintf(ofp,
+ " onespots = calloc("
+ "%d, sizeof *onespots);\n",
+ nonespots);
+ (void) fprintf(ofp,
+ " oneforget = calloc("
+ "%d, sizeof *oneforget);\n",
+ nonespots);
+ }
+ if (ntwospots)
+ {
+ (void) fprintf(ofp,
+ " twospots = calloc("
+ "%d, sizeof *twospots);\n",
+ ntwospots);
+ (void) fprintf(ofp,
+ " twoforget = calloc("
+ "%d, sizeof *twoforget);\n",
+ ntwospots);
+ }
+ if (ntails)
+ {
+ (void) fprintf(ofp,
+ " tails = calloc("
+ "%d, sizeof *tails);\n",
+ ntails);
+ (void) fprintf(ofp,
+ " tailforget = calloc("
+ "%d, sizeof *tailforget);\n",
+ ntails);
+ }
+ if (nhybrids)
+ {
+ (void) fprintf(ofp,
+ " hybrids = calloc("
+ "%d, sizeof *hybrids);\n",
+ nhybrids);
+ (void) fprintf(ofp,
+ " hyforget = calloc("
+ "%d, sizeof *hyforget);\n",
+ nhybrids);
+ }
+ break;
}
(void) fclose(ofp);
/* OK, now sic the C compiler on the results */
- if (!compile_only)
+ if (!compile_only&&!yukdebug&&!yukprofile)
{
- (void) sprintf(buf2,
- "%s %s -I%s -L%s -lick -o %s",
- compiler, buf, includedir, libdir,
- argv[optind]);
- (void) system(buf2);
- (void) unlink(buf);
+ /* AIS: buf2 now assigned elsewhere so $L works */
+ (void) system(buf2);
+ /* AIS: no unlink if cdebug */ if(!cdebug) (void) unlink(buf);
+ }
+ else if(!compile_only)
+ { /* AIS: run, then delete all output but yuk.out */
+ /* Note that the output must be deleted for copyright
+ reasons (so as not to GPL a non-GPL file automatically) */
+ (void) system(buf2);
+ (void) freopen("/dev/tty", "r", stdin);
+ /* stdin has got seriously muddled, what with
+ it being redirected so much. Let's set it
+ to the keyboard (the only reasonable place
+ for input to a debugger anyway). If the user
+ wants to use the profiler with data from a file,
+ this won't work, so this code probably needs
+ changing. But the original value of stdin seems
+ to have been lost, and we need to redirect from
+ somewhere. */
+ (void) system(argv[optind]);
+ (void) unlink(buf);
+ (void) unlink(argv[optind]);
+ }
+ if(coopt) /* AIS */
+ {
+ /* The constant-output optimizer is a form of post-processor.
+ IMPORTANT NOTE: This MUST NOT be run if the input program
+ takes any input or is affected in any way by the state of
+ the system, as the degenerated program may be wrong. At the
+ moment, the only INTERCAL command that takes input is
+ WRITE IN. */
+ if(cooptsh)
+ {
+ sprintf(buf2,"sh %s %s", cooptsh, argv[optind]);
+ (void) system(buf2); /* replaces the output executable if
+ neccesary */
+ }
}
}
}
}
/* perpetrate.c ends here */
+
lib/syslib-orig.i Standard library (original buggy version)
by Jon Blow <jon@sampo.com>
- sink.i Simple test program
+ tests/sink.i Simple test program
random.i Random number program
lib/plus.i Increment .1
rot13.i Prints ROT-13 of its input
by Jan-Pieter Cornet <johnpc@xs4all.nl>
- hail_mary.3i Print 1,000,000 Hail Marys
- count.3i Count from 1 to 10 in TriINTERCAL
- iogerunds.i Demonstrate gerund abstention
+ hail_mary.3i Print 1,000,000 Hail Marys
+ tests/count.3i Count from 1 to 10 in TriINTERCAL
+ tests/iogerunds.i Demonstrate gerund abstention
by Clemens Meier <clmeier@lili.uni-bielefeld.de>
rot13b.i Another ROT-13 program
compiler.
by David Moews
- test1.i Prints DO THIS TEST HAS BEEN SUCCESSFULLY COMPLETED
- test2.i Reads in two numbers and multiplies their product
+ tests/test1.i Prints DO THIS TEST HAS BEEN SUCCESSFULLY COMPLETED
+ tests/test2.i Reads in two numbers and multiplies their product
David Moews wrote of the latter (test2.i):
the INTERCAL subroutine library is present in the posted manual, and
that portion is full of typos.)
+by Alex Smith
+ tests/ais1.i A very simple test program
+ tests/ais2.i A demonstration of computed ABSTAIN's power
+ tests/compucome.i A program to test computed COME FROM
+ tests/onceagain.i A single-threaded program testing ONCE and AGAIN
+ tests/arrtest.i A program to test some changes I made to the grammar
+ tests/arrtest.doc The history behind those changes
+ tests/permute.i A permutation-printing program to test backtracking
+ tests/permute.doc Information about the permutation-printer
+ sort.i An insertion-sort program testing computed ABSTAIN
+
+by Malcom Ryan
+ tests/testonce.i A single-threaded program testing ONCE and AGAIN
+ pass.i A multithread program illustrating communications
+ between threads
+
The programs test16bit.i, testarray.i, testcf.i, testlib2.i, mult.i,
limits.{i,3i}, testops.{3i,5i}, testsplat.i, were all written by Louis
Howell. Of these, testcf.i might be considered an interesting
+++ /dev/null
- DO ,1 <- #16
- DO :2 <- #6490$#55022
- PLEASE DO (44) NEXT
- DO :2 <- #5631$#54733
- PLEASE DO (44) NEXT
- DO :2 <- #14637$#40039
- PLEASE DO (44) NEXT
- DO :2 <- #58550$#53112
- PLEASE DO (44) NEXT
- DO .1 <- #1
- PLEASE DO (99) NEXT
- DO GIVE UP
-(44) DO REINSTATE COMING FROM
-(19) DO COME FROM (68)
- DO ABSTAIN FROM (19)
-(31) DO COME FROM (34)
- DO ABSTAIN FROM (31)
-(88) DO COME FROM (65)
- PLEASE ABSTAIN FROM (88)
- DO COME FROM (44)
- PLEASE DO (123) NEXT
- DO .3 <- ':2~"#4$#13"'
- DO :2 <- ':2~"#29520$#29511"'
- DO ,1 SUB .1 <- .3
-(65) DON'T GIVE UP
-(34) PLEASE DON'T GIVE UP
-(68) DO NOTE THAT THIS FUNNY CODE ACTUALLY WORKS
- PLEASE RESUME #1
-(99) DO COME FROM (69)
- DO READ OUT ,1
- DO ,1 SUB #1 <- #180
- DO READ OUT .1
- DO .2 <- "?.1$#10"~"#0$#29524"
- PLEASE DO (15) NEXT
-(69) PLEASE DO (123) NEXT
-(42) DO RESUME .9
-(123) PLEASE .8 <- #1
- DO COME FROM (81)
- DO .9 <- '?"V!1~.8'$#1"~#1'~#1
- DO .1 <- "^.1$.8"~"#0$#29524"
- PLEASE DO (42) NEXT
-(81) DO .8 <- !8$#0'~"#9841$#1"
-(15) PLEASE RESUME '?"!2~.2'~#2"$#1'~#1
+++ /dev/null
-
-From: johnpc@xs4all.nl (Jan-Pieter Cornet)
-Newsgroups: comp.lang.misc,comp.lang.perl.misc,comp.lang.tcl,comp.lang.c,comp.lang.java,alt.lang.intercal,alt.test
-Subject: Re: Readable Perl (was: Re: Relative Speed of Perl vs. Tcl vs. C)
-Date: 27 Feb 1996 02:44:19 GMT
-Organization: XS4ALL Internet
-Message-ID: <4gtr64$s7h@news.xs4all.nl>
-Summary: hit "n" now! quick!
-
-In article <4ge7bk$4vq@news.ox.ac.uk>,
-David Hopwood <lady0065@sable.ox.ac.uk> wrote:
->In article <4gb3kp$lu7@gaia.ns.utk.edu>,
->Matthew B. Kennel <kennel@msr.epm.ornl.gov> wrote:
->>Randal L. Schwartz (merlyn@stonehenge.com) wrote:
->>: >>>>> "John" == John Viega <jtv2j@mamba.cs.virginia.edu> writes:
->>
->>: John> People bitch about the readability of Perl non-stop. In fact, I have
->>: John> heard the joke, "Perl, the only language you can uuencode, and not
->>: John> notice" twice this week around the department.
->>
->>: OK, now which do you find most readable...
->
->This (Haskell):
->
->cancount n = "I can count to "++(show n)++"\n"
->concat (map cancount [1..10])
-
-No, you got it all totally wrong. I think this is the best readable
-(in Tri-INTERCAL):
-
-[Program moved to .3i file.]
-
-Now, I think the advantages of this are pretty clear. First, this is
-clearly a write-only language. There are only few people insane enough
-to actually understand the above drivel, and they wouldn't bother
-touching your petty code, as they are too busy filling bathtubs with
-brightly colored machine tools.
-
-Anyone else will simply be too scared to touch this code. So you can be
-pretty sure nobody changes it behind your back.
-
-In fact, you can be pretty sure you won't change it either after you
-wrote it, because you will probably have forgotten how the program
-works 5 minutes after you wrote it. So any luser nagging for extra
-features afterwards, is SOL.
-
-The other major advantage is... the above code took me about 3 hours
-to write. Compare this to the 10 to 30 seconds it takes to write a
-similar program in perl, BASIC, Haskell or what have you. But... that
-means that when you programmed it in that other language, you'd have to
-spend 2 hours 59 minutes and somewhere between 30 and 50 seconds
-answering the phone talking to clueless lusers, changing backup tapes,
-or doing other boring stuff. While you could have been programming
-Intercal instead! Just think about that!
-
-And last, but certainly not least, is: the above code is likely to
-impress your boss. Bosses are wont to be impressed by incomprehensible
-things. They won't be impressed by a three line perl program that anyone
-not wearing a diaper can understand.
-
-So that pretty much proves it.
-
-PS: this article contains some strange usage of the words "best readable"
-that you probably weren't previously aware of :)
-
---
-Jan-Pieter Cornet <johnpc@xs4all.net>
-Actual quote: "Linux was made by foreign terrorists to steal money from true
- AMERICAN companies like Microsoft who invented computing as we
- know it, and are being punished for their success..."
-Linux -- "It's computing, Jim, but not as we know it"
+++ /dev/null
- DO ,1 <- #13
- PLEASE DO ,1SUB#1 <- #234
- DO ,1SUB#2 <- #112
- DO ,1SUB#3 <- #112
- DO ,1SUB#4 <- #0
- DO ,1SUB#5 <- #64
- DO ,1SUB#6 <- #194
- DO ,1SUB#7 <- #48
- PLEASE DO ,1SUB#8 <- #22
- DO ,1SUB#9 <- #248
- DO ,1SUB#10 <- #168
- DO ,1SUB#11 <- #24
- DO ,1SUB#12 <- #16
- DO ,1SUB#13 <- #214
- PLEASE READ OUT ,1
- PLEASE GIVE UP
+++ /dev/null
-Jan-Pieter Cornet <cornet@OTech.fgg.EUR.nl> writes:
-
-You might want to try the following program (I've just been hacking this up,
-and it costed me considerable more time than adding the gerund I/O things.
-But that's the power of intercal...) This program will ask for a number
-and might print it then, except that it doesn't ask the first time but
- _
-assumes ONE TWO THREE. Oh and it never prints but just exits in case that
-would've been printed (I did my best to make that part as unreadable as
-possible. did it work? :)
+++ /dev/null
- DO .1 <- #123
- DO ABSTAIN FROM WRITING IN
- DO COME FROM (123)
-(100) DO WRITE IN .1
- PLEASE .2 <- #1
- DO %50 .2 <- !2$#0'
- PLEASE DO (42) NEXT
- DO ABSTAIN FROM READING OUT
- PLEASE COME FROM (69)
- DO READ OUT .1
- DO REINSTATE READING OUT
-(123) PLEASE REINSTATE (100)
-(42) DO (43) NEXT
- DO FORGET #1
- DO (105) NEXT
- PLEASE GIVE UP
-(105) DO (106) NEXT
-(69) DON'T GIVE UP
-(106) PLEASE DO RESUME "'?"!1~.1'~#1"$#1'~#1"$'".1~.1"~#1'
-(43) DO RESUME .2
--- /dev/null
+(10) DO NOTHING
+
+ PLEASE NOTE: Process 1 reads from stdin & copies to the channel
+
+ PLEASE COME FROM (10)
+ PLEASE COME FROM (20)
+(20) PLEASE (100) NEXT
+
+ PLEASE NOTE: Process 2 reads from the channel & copies to stdout
+
+ PLEASE COME FROM (10)
+ PLEASE COME FROM (30)
+(30) PLEASE (200) NEXT
+
+(100) PLEASE NOTE: Write a message to the message box.
+
+ DO STASH .1 + .2
+ DO (101) NEXT
+ PLEASE COME FROM (104)
+(101) DO FORGET #1
+ DO .2 <- #1
+(102) DO .2 <- #2 ONCE
+(103) DO (104) NEXT
+(104) DO (105) NEXT
+(105) DO RESUME .2
+
+ PLEASE COME FROM (103)
+
+ DO WRITE IN .1
+
+ PLEASE NOTE: If .1 is zero, kill both threads
+ DO .2 <- '?"'#0$.1'~'#0$.1'"$#1'~#3
+(1) DO (2) NEXT
+(2) DO (105) NEXT
+
+ PLEASE COME FROM (1)
+
+ DO .2 <- '?"'&.1$#1'~'#0$#1'"$#1'~#3
+ DO (106) NEXT
+ DO REINSTATE (210)
+ DO (107) NEXT
+(106) DO (105) NEXT
+ DO ABSTAIN FROM (210)
+
+(107) DO .2 <- '?"'&.1$#2'~'#0$#2'"$#1'~#3
+ DO (108) NEXT
+ DO REINSTATE (211)
+ DO (109) NEXT
+(108) DO (105) NEXT
+ PLEASE ABSTAIN FROM (211)
+
+(109) DO .2 <- '?"'&.1$#4'~'#0$#4'"$#1'~#3
+ DO (110) NEXT
+ DO REINSTATE (212)
+ DO (111) NEXT
+(110) DO (105) NEXT
+ PLEASE ABSTAIN FROM (212)
+
+(111) DO .2 <- '?"'&.1$#8'~'#0$#8'"$#1'~#3
+ DO (112) NEXT
+ DO REINSTATE (213)
+ DO (113) NEXT
+(112) DO (105) NEXT
+ PLEASE ABSTAIN FROM (213)
+
+(113) DO .2 <- '?"'&.1$#16'~'#0$#16'"$#1'~#3
+ DO (114) NEXT
+ DO REINSTATE (214)
+ DO (115) NEXT
+(114) DO (105) NEXT
+ PLEASE ABSTAIN FROM (214)
+
+(115) DO .2 <- '?"'&.1$#32'~'#0$#32'"$#1'~#3
+ DO (116) NEXT
+ DO REINSTATE (215)
+ DO (117) NEXT
+(116) DO (105) NEXT
+ PLEASE ABSTAIN FROM (215)
+
+(117) DO .2 <- '?"'&.1$#64'~'#0$#64'"$#1'~#3
+ DO (118) NEXT
+ DO REINSTATE (216)
+ DO (119) NEXT
+(118) DO (105) NEXT
+ PLEASE ABSTAIN FROM (216)
+
+(119) DO .2 <- '?"'&.1$#128'~'#0$#128'"$#1'~#3
+ DO (120) NEXT
+ DO REINSTATE (217)
+ DO (121) NEXT
+(120) DO (105) NEXT
+ PLEASE ABSTAIN FROM (217)
+
+(121) DO .2 <- '?"'&.1$#256'~'#0$#256'"$#1'~#3
+ DO (122) NEXT
+ DO REINSTATE (218)
+ DO (123) NEXT
+(122) DO (105) NEXT
+ PLEASE ABSTAIN FROM (218)
+
+(123) DO .2 <- '?"'&.1$#512'~'#0$#512'"$#1'~#3
+ DO (124) NEXT
+ DO REINSTATE (219)
+ DO (125) NEXT
+(124) DO (105) NEXT
+ PLEASE ABSTAIN FROM (219)
+
+(125) DO .2 <- '?"'&.1$#1024'~'#0$#1024'"$#1'~#3
+ DO (126) NEXT
+ DO REINSTATE (220)
+ DO (127) NEXT
+(126) DO (105) NEXT
+ PLEASE ABSTAIN FROM (220)
+
+(127) DO .2 <- '?"'&.1$#2048'~'#0$#2048'"$#1'~#3
+ DO (128) NEXT
+ DO REINSTATE (221)
+ DO (129) NEXT
+(128) DO (105) NEXT
+ PLEASE ABSTAIN FROM (221)
+
+(129) DO .2 <- '?"'&.1$#4096'~'#0$#4096'"$#1'~#3
+ DO (130) NEXT
+ DO REINSTATE (222)
+ DO (131) NEXT
+(130) DO (105) NEXT
+ PLEASE ABSTAIN FROM (222)
+
+(131) DO .2 <- '?"'&.1$#8192'~'#0$#8192'"$#1'~#3
+ DO (132) NEXT
+ DO REINSTATE (223)
+ DO (133) NEXT
+(132) DO (105) NEXT
+ PLEASE ABSTAIN FROM (223)
+
+(133) DO .2 <- '?"'&.1$#16384'~'#0$#16384'"$#1'~#3
+ DO (134) NEXT
+ DO REINSTATE (224)
+ DO (135) NEXT
+(134) DO (105) NEXT
+ PLEASE ABSTAIN FROM (224)
+
+(135) DO .2 <- '?"'&.1$#32768'~'#0$#32768'"$#1'~#3
+ DO (136) NEXT
+ DO REINSTATE (225)
+ DO (137) NEXT
+(136) DO (105) NEXT
+ PLEASE ABSTAIN FROM (225)
+
+(137) DO REINSTATE (202)
+ DO RETRIEVE .1 + .2
+ PLEASE RESUME #17
+
+(200) PLEASE NOTE: Read from a message box
+
+ DO STASH .1 + .2
+
+ DO (201) NEXT
+ PLEASE COME FROM (204)
+(201) DO FORGET #1
+ DO .2 <- #1
+(202) DO NOT .2 <- #2 AGAIN
+(203) DO (204) NEXT
+(204) DO (205) NEXT
+(205) DO RESUME .2
+
+ PLEASE COME FROM (203)
+
+ DO .1 <- #0
+(210) DO .1 <- 'V.1$#1'~'#0$#65535'
+(211) DO .1 <- 'V.1$#2'~'#0$#65535'
+(212) DO .1 <- 'V.1$#4'~'#0$#65535'
+(213) DO .1 <- 'V.1$#8'~'#0$#65535'
+(214) DO .1 <- 'V.1$#16'~'#0$#65535'
+(215) DO .1 <- 'V.1$#32'~'#0$#65535'
+(216) DO .1 <- 'V.1$#64'~'#0$#65535'
+(217) DO .1 <- 'V.1$#128'~'#0$#65535'
+(218) DO .1 <- 'V.1$#256'~'#0$#65535'
+(219) DO .1 <- 'V.1$#512'~'#0$#65535'
+(220) DO .1 <- 'V.1$#1024'~'#0$#65535'
+(221) DO .1 <- 'V.1$#2048'~'#0$#65535'
+(222) DO .1 <- 'V.1$#4096'~'#0$#65535'
+(223) DO .1 <- 'V.1$#8192'~'#0$#65535'
+(224) DO .1 <- 'V.1$#16384'~'#0$#65535'
+(225) DO .1 <- 'V.1$#32768'~'#0$#65535'
+
+ DO READ OUT .1
+ DO RETRIEVE .1 + .2
+ DO REINSTATE (102)
+ PLEASE RESUME #1
+
+PLEASE NOTE: Giving up
+
+ PLEASE COME FROM (2)
+ DO REINSTATE (3)
+(3) DO NOT COME FROM (202)
+ PLEASE GIVE UP
+++ /dev/null
-(1999) PLEASE DO (1999) NEXT
-
-Sink.i: A program I wrote just to see if the guy who wrote the compiler
- was faithful. :)
- (blojo@ocf.berkeley.edu)
+++ /dev/null
-(1999) PLEASE DO (1999) NEXT
- DO NOTE THAT YOU CAN'T GET HERE FROM THERE
- DO ANYTHING YOU WANT ON THIS LINE, IT WON'T HAPPEN ANYWAY
--- /dev/null
+ PLEASE NOTE THAT THIS PROGRAM SORTS AN ENTERED LIST OF NUMBERS
+ NUMBERS ARE ENTERED UNTIL A ZERO IS RECEIVED, THEN THE SORTED
+ LIST IS OUTPUT, USING INSERTION SORT ALGORITHM
+
+ PLEASE NOTE THAT THIS PROGRAM USES COMPUTED ABSTAIN, TRY AGAIN,
+ BUT NO NEXTING, COMING FROM, OR ARRAYS
+
+ PLEASE NOTE .5 .6 .7 .8 ARE ALL TEMPORARIES
+ PLEASE NOTE .1 AND .4 ARE STASHED TO ACT LIKE ARRAYS
+
+(8) DO .1 <- #0
+(9) DO STASH .1
+(10) DO .2 <- #0
+(13) DO .4 <- #0
+(14) DO STASH .4
+ PLEASE NOTE .2 HOLDS CURRENT STATE OF PROGRAM; .2 IS #0 DURING
+ INPUT, #1 WHEN INSERTING A VALUE, #3 WHEN RESETTING THE STASH,
+ #7 WHEN OUTPUTTING THE SORTED VALUES
+ DO REINSTATE (10)
+ DO REINSTATE (13)
+ DO REINSTATE (14)
+ DO REINSTATE (10)
+ DO REINSTATE (13)
+ DO REINSTATE (14)
+ DO ABSTAIN FROM (8)
+ DO ABSTAIN FROM (9)
+ DO ABSTAIN FROM (10)
+ PLEASE DO ABSTAIN FROM (13)
+ DO ABSTAIN FROM (14)
+ PLEASE NOTE THE ABOVE LINES ENSURE 10+13+14 ARE ABSTAINED FROM EXACTLY ONCE
+
+ PLEASE NOTE WRITING IN AN ELEMENT IFF .2 IS #0
+ DO ABSTAIN FROM (15)
+ DO ABSTAIN "!2~.2'~#1"$#1 FROM (15)
+ PLEASE NOTE LINE 15 ABSTAINED FROM 2 OR 4 TIMES
+ DO REINSTATE (15)
+ DO REINSTATE (15)
+(15) DO WRITE IN .3
+ DO REINSTATE (15)
+ DO REINSTATE (15)
+
+ PLEASE NOTE SETTING LSB OF .2
+ DO .2 <- 'V.2$#1'~"#0$#65535"
+
+ PLEASE NOTE INSERTING .3 INTO OUR STASH IF .2 IS #1
+ DO .8 <- '?.2$#1'~"#0$#65535"
+ DO .8 <- !8~.8'~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO ABSTAIN FROM (33)
+ DO ABSTAIN .8$#1 FROM (33)
+ DO REINSTATE (33)
+ DO REINSTATE (33)
+(33) DO ABSTAIN #1 FROM STASHING + RETRIEVING + CALCULATING + ABSTAINING + READING OUT
+ DO REINSTATE (33)
+ DO REINSTATE (33)
+ DO RETRIEVE .1
+ PLEASE NOTE IF .1 IS LESS THAN OR EQUAL TO .3, WE STASH .3 ON STASH .4 AND SET .2 TO #3
+ PLEASE NOTE IF .1 IS GREATER THAN .3, WE STASH .1 ON STASH .4 AND LEAVE .2 AS IT IS
+ PLEASE NOTE IF .1 IS #0, THIS NEEDS THE SAME ACTIONS AS IF .1 WAS LOWER
+ PLEASE NOTE ADDING .1 TO THE COMPLEMENT OF .3, STORING THE RESULT IN .8, OVERFLOW IN .7
+ DO .8 <- '?.3$#65535'~"#0$#65535"
+ DO .5 <- .1
+ DO .7 <- #0
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE DO .6<-"&!8$.5'"~'#0$#65535' DO .8<-"?!8$.5'"~'#0$#65535' DO .5<-!6$#0'~"#32767$#1" DO .7<-'V.7$".6~#32768"'~"#0$#65535"
+ PLEASE NOTE THAT IF .1 IS GREATER THAN .3, .7 WILL BE 1; OTHERWISE .7 WILL BE 0
+ PLEASE NOTE .4 MUST BECOME .1 IF .7 IS 1 OR .3 IF .7 IS 0
+ DO .7 <- '.7$.7'$".7$.7"
+ DO .7 <- '.7$.7'$".7$.7"
+ PLEASE NOTE .7 IS NOW 65535 OR 0, SO WE WANT .4 <- (.1 & .7)|(.3 & ~.7)
+ DO .5 <- '&.1$.7'~"#0$#65535"
+ PLEASE DO .6 <- '?.7$#65535'~"#0$#65535"
+ DO .6 <- '&.3$.6'~"#0$#65535"
+ DO .4 <- 'V.5$.6'~"#0$#65535"
+ DO STASH .4
+ PLEASE NOTE SETTING BIT 1 OF .2 IFF .7 IS #0
+ PLEASE DO .7 <- '?.7$#65535'~"#0$#65535"
+ DO .7 <- '&.7$#2'~"#0$#65535"
+ PLEASE DO .2 <- 'V.2$.7'~"#0$#65535"
+ DO ABSTAIN FROM (1)
+(1) DO REINSTATE STASHING + RETRIEVING + CALCULATING + ABSTAINING + READING OUT
+ DO REINSTATE (1)
+ PLEASE NOTE END OF CODE FOR .2 = #1
+
+ PLEASE NOTE .9 KEEPS TRACK OF WHAT .2 WAS
+ DO .9 <- .2
+
+ PLEASE NOTE THAT IF .3 IS #0 AND .2 IS #3 THEN .2 SHOULD BECOME #7
+ DO .8 <- '?.2$#3'~"#0$#65535"
+ DO .8 <- 'V.3$.8'~"#0$#65535"
+ DO .8 <- ".8~.8"~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO .8 <- .8$!8$.8'
+ DO .2 <- 'V.2$.8'~"#0$#65535"
+
+ PLEASE NOTE THAT IF .9 != .2 WE MUST POP A #0 OFF .4'S STASH
+ DO .8 <- '?.2$.9'~"#0$#65535"
+ DO .8 <- !8~.8'~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO ABSTAIN FROM (113)
+ DO ABSTAIN .8$#1 FROM (113)
+ DO REINSTATE (113)
+ DO REINSTATE (113)
+(113) DO RETRIEVE .4
+ DO REINSTATE (113)
+ DO REINSTATE (113)
+
+ PLEASE NOTE OUTPUTTING SORTED LIST IF .2 IS #7
+ DO ABSTAIN FROM (125)
+ DO .8 <- '?.2$#7'~"#0$#65535"
+ DO .8 <- !8~.8'~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO ABSTAIN FROM (54)
+ DO ABSTAIN .8$#1 FROM (54)
+ DO REINSTATE (54)
+ DO REINSTATE (54)
+(54) DO ABSTAIN #1 FROM CALCULATING + ABSTAINING + READING OUT + RETRIEVING
+ DO REINSTATE (54)
+ DO REINSTATE (54)
+ DO ABSTAIN FROM (60)
+ DO ABSTAIN FROM (133)
+ DO RETRIEVE .4
+ PLEASE NOTE IF .4 IS #0 THEN END PROGRAM
+ DO .8 <- !4~.4'~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO ABSTAIN .8$#1 FROM (125)
+(60) PLEASE DO REINSTATE CALCULATING + ABSTAINING + RETRIEVING
+ DO REINSTATE (60)
+ DO REINSTATE (125)
+ DO REINSTATE (125)
+(125) DO ABSTAIN FROM (999)
+ DO REINSTATE (125)
+ DO REINSTATE (125)
+(999) DO ABSTAIN FROM RETRIEVING + CALCULATING + ABSTAINING + REINSTATING + TRYING AGAIN + READING OUT
+ DO REINSTATE (999)
+ DO READ OUT .4
+(133) DO REINSTATE READING OUT
+ DO REINSTATE (133)
+ PLEASE NOTE END OF CODE FOR .2 = #7
+
+ PLEASE NOTE MOVING STASH .4 BACK TO STASH .1 IF .2 IS #3
+ DO .8 <- '?.2$#3'~"#0$#65535"
+ DO .8 <- !8~.8'~#1
+ DO .8 <- '?.8$#1'~"#0$#65535"
+ DO ABSTAIN FROM (34)
+ DO ABSTAIN .8$#1 FROM (34)
+ DO REINSTATE (34)
+ DO REINSTATE (34)
+(34) DO ABSTAIN #1 FROM STASHING + RETRIEVING + CALCULATING + ABSTAINING
+ DO REINSTATE (34)
+ DO REINSTATE (34)
+ PLEASE DO RETRIEVE .4
+ DO STASH .1
+ DO .1 <- .4
+ PLEASE NOTE THAT IF .1 IS NOW #0, WE NEED TO SET .2 BACK TO #0 AND STASH A #0 BACK IN STASH .4
+ THIS IS ACCOMPLISHED BY ABSTAINING ONCE OR THREE TIMES FROM 10+13+14
+ PLEASE DO .7 <- !1~.1'~#1
+ DO ABSTAIN .7$#1 FROM (10)
+ PLEASE DO ABSTAIN .7$#1 FROM (13)
+ DO ABSTAIN .7$#1 FROM (14)
+ DO ABSTAIN FROM (104)
+ PLEASE DO ABSTAIN FROM (110)
+ PLEASE DO ABSTAIN FROM (111)
+ DO ABSTAIN FROM (112)
+(104) DO REINSTATE STASHING + RETRIEVING + CALCULATING + ABSTAINING
+ DO REINSTATE (104)
+ PLEASE NOTE ABSTAINING #3 FROM 10+13+14 IF .2 != #3
+(110) DO ABSTAIN #3 FROM (10)
+(111) DO ABSTAIN #3 FROM (13)
+(112) PLEASE DO ABSTAIN #3 FROM (14)
+ DO REINSTATE (110)
+ DO REINSTATE (111)
+ DO REINSTATE (112)
+ PLEASE DO REINSTATE (10)
+ PLEASE DO REINSTATE (13)
+ DO REINSTATE (14)
+ DO REINSTATE (10)
+ DO REINSTATE (13)
+ DO REINSTATE (14)
+ PLEASE NOTE END OF CODE FOR .2 = #3
+
+ PLEASE TRY AGAIN
--- /dev/null
+ PLEASE KNOCK BEFORE ENTERING
+
+ (1000) PLEASE IGNORE .4
+ PLEASE ABSTAIN FROM (1005)
+ (1009) DO STASH .1 + .2 + .5 + .6
+ DO .4 <- #1
+ DO (1004) NEXT
+ (1004) PLEASE FORGET #1
+ DO .3 <- '?.1$.2'~'#0$#65535'
+ DO .6 <- '&.1$.2'~'#0$#65535'
+ PLEASE DO .5 <- "?!6~#32768'$#1"~#3
+ DO (1002) NEXT
+ DO .4 <- #2
+ (1005) DO (1006) NEXT
+ (1999) DOUBLE OR SINGLE PRECISION OVERFLOW
+ (1002) DO (1001) NEXT
+ (1006) PLEASE FORGET #1
+ DO .5 <- '?"!6~.6'~#1"$#1'~#3
+ DO (1003) NEXT
+ DO .1 <- .3
+ DO .2 <- !6$#0'~'#32767$#1'
+ DO (1004) NEXT
+ (1003) DO (1001) NEXT
+ DO REINSTATE (1005)
+ (1007) PLEASE RETRIEVE .1 + .2 + .5 + .6
+ DO REMEMBER .4
+ PLEASE RESUME #2
+ (1001) DO RESUME .5
+ (1010) DO STASH .1 + .2 + .4
+ DO .4 <- .1
+ DO .1 <- '?.2$#65535'~'#0$#65535'
+ DO (1020) NEXT
+ PLEASE DO .2 <- .4
+ PLEASE DO (1009) NEXT
+ DO RETRIEVE .1 + .2 + .4
+ PLEASE RESUME #1
+ (1020) DO STASH .2 + .3
+ DO .2 <- #1
+ PLEASE DO (1021) NEXT
+ (1021) DO FORGET #1
+ DO .3 <- "?!1~.2'$#1"~#3
+ PLEASE DO .1 <- '?.1$.2'~'#0$#65535'
+ DO (1022) NEXT
+ DO .2 <- !2$#0'~'#32767$#1'
+ DO (1021) NEXT
+ (1023) PLEASE RESUME .3
+ (1022) DO (1023) NEXT
+ PLEASE RETRIEVE .2 + .3
+ PLEASE RESUME #2
+ (1030) DO ABSTAIN FROM (1033)
+ PLEASE ABSTAIN FROM (1032)
+ (1039) DO STASH :1 + .5
+ DO (1530) NEXT
+ DO .3 <- :1~#65535
+ PLEASE DO .5 <- :1~'#65280$#65280'
+ DO .5 <- '?"!5~.5'~#1"$#1'~#3
+ DO (1031) NEXT
+ (1032) DO (1033) NEXT
+ DO (1999) NEXT
+ (1031) DO (1001) NEXT
+ (1033) DO .4 <- .5
+ DO REINSTATE (1032)
+ PLEASE REINSTATE (1033)
+ DO RETRIEVE :1 + .5
+ PLEASE RESUME #2
+ (1040) PLEASE STASH .1 + .2 + .2 + :1 + :2 + :3
+ DO .2 <- #0
+ DO (1520) NEXT
+ DO STASH :1
+ PLEASE RETRIEVE .2
+ DO .1 <- .2
+ DO .2 <- #0
+ PLEASE DO (1520) NEXT
+ DO :2 <- :1
+ DO RETRIEVE .1 + .2 + :1
+ DO (1550) NEXT
+ PLEASE DO .3 <- :3
+ DO RETRIEVE :1 + :2 + :3
+ DO RESUME #1
+ (1050) PLEASE STASH :2 + :3 + .5
+ DO :2 <- .1
+ PLEASE DO (1550) NEXT
+ DO .5 <- :3~'#65280$#65280'
+ DO .5 <- '?"!5~.5'~#1"$#1'~#3
+ DO (1051) NEXT
+ DO (1999) NEXT
+ (1051) DO (1001) NEXT
+ DO .2 <- :3
+ PLEASE RETRIEVE :2 + :3 + .5
+ DO RESUME #2
+ (1500) PLEASE ABSTAIN FROM (1502)
+ PLEASE ABSTAIN FROM (1506)
+ (1509) PLEASE STASH :1 + .1 + .2 + .3 + .4 + .5 + .6
+ DO .1 <- :1~#65535
+ PLEASE DO .2 <- :2~#65535
+ DO (1009) NEXT
+ DO .5 <- .3
+ PLEASE DO .6 <- .4
+ DO .1 <- :1~'#65280$#65280'
+ DO .2 <- :2~'#65280$#65280'
+ DO (1009) NEXT
+ DO .1 <- .3
+ PLEASE DO (1503) NEXT
+ DO .6 <- .4
+ DO .2 <- #1
+ DO (1009) NEXT
+ DO .1 <- .3
+ DO (1501) NEXT
+ (1504) PLEASE RESUME .6
+ (1503) DO (1504) NEXT
+ (1501) DO .2 <- .5
+ DO .5 <- '?"'&.6$.4'~#1"$#2'~#3
+ DO (1505) NEXT
+ (1506) DO (1502) NEXT
+ PLEASE DO (1999) NEXT
+ (1505) DO (1001) NEXT
+ (1502) DO :4 <- .5
+ DO (1520) NEXT
+ DO :3 <- :1
+ PLEASE RETRIEVE :1 + .1 + .2 + .3 + .4 + .5 + .6
+ DO REINSTATE (1502)
+ DO REINSTATE (1506)
+ PLEASE RESUME #3
+ (1510) DO STASH :1 + :2 + :4
+ DO :1 <- "'?":2~'#65535$#0'"$#65535'~'#0$#65535'"$
+ "'?":2~'#0$#65535'"$#65535'~'#0$#65535'"
+ DO :2 <- #1
+ DO (1509) NEXT
+ PLEASE RETRIEVE :1
+ DO :2 <- :3
+ PLEASE DO (1509) NEXT
+ DO RETRIEVE :2 + :4
+ PLEASE RESUME #1
+ (1520) PLEASE STASH .3 + .4
+ DO .3 <- .1~#43690
+ DO (1525) NEXT
+ PLEASE DO .4 <- 'V.3$".2~#43690"'~'#0$#65535'
+ DO .3 <- .1~#21845
+ PLEASE DO (1525) NEXT
+ DO :1 <- .4$"'V.3$".2~#21845"'~'#0$#65535'"
+ PLEASE RETRIEVE .3 + .4
+ DO RESUME #1
+ (1525) DO .3 <- '"'"'"!3$#0'~'#32767$#1'"$#0'~'#32767$
+ #1'"$#0'~'#16383$#3'"$#0'~'#4095$#15'
+ PLEASE RESUME #1
+ (1530) DO STASH :2 + :3 + .3 + .5
+ DO :1 <- #0
+ DO :2 <- .2
+ DO .3 <- #1
+ DO (1535) NEXT
+ (1535) PLEASE FORGET #1
+ DO .5 <- "?!1~.3'$#1"~#3
+ DO (1531) NEXT
+ DO (1500) NEXT
+ DO :1 <- :3
+ PLEASE DO (1533) NEXT
+ (1531) PLEASE DO (1001) NEXT
+ (1533) DO FORGET #1
+ DO .3 <- !3$#0'~'#32767$#1'
+ DO :2 <- ":2~'#0$#65535'"$"'":2~'#32767$#0'"$
+ #0'~'#32767$#1'"
+ PLEASE DO .5 <- "?!3~.3'$#1"~#3
+ DO (1532) NEXT
+ DO (1535) NEXT
+ (1532) DO (1001) NEXT
+ PLEASE RETRIEVE :2 + :3 + .3 + .5
+ DO RESUME #2
+ (1540) PLEASE ABSTAIN FROM (1541)
+ DO ABSTAIN FROM (1542)
+ (1549) PLEASE STASH :1 + :2 + :4 + :5 + .1 + .2 + .5
+ DO .1 <- :1~#65535
+ PLEASE DO .2 <- :2~'#65280$#65280'
+ DO .5 <- :1~'#65280$#65280'
+ DO (1530) NEXT
+ DO :3 <- :1
+ DO .2 <- :2~#65535
+ PLEASE DO (1530) NEXT
+ DO :5 <- :1
+ DO .1 <- .5
+ DO (1530) NEXT
+ DO :4 <- :1
+ PLEASE DO :1 <- ":3~'#65280$#65280'"$":4~'#65280$
+ #65280'"
+ DO .5 <- ':1~:1'~#1
+ DO .2 <- :2~'#65280$#65280'
+ DO (1530) NEXT
+ PLEASE DO .5 <- '"':1~:1'~#1"$.5'~#3
+ DO .1 <- :3~#65535
+ DO .2 <- #0
+ DO (1520) NEXT
+ PLEASE DO :2 <- :1
+ PLEASE DO .1 <- :4~#65535
+ DO (1520) NEXT
+ DO (1509) NEXT
+ DO .5 <- !5$":4~#3"'~#15
+ DO :1 <- :3
+ DO :2 <- :5
+ DO (1509) NEXT
+ PLEASE DO .5 <- !5$":4~#3"'~#172
+ DO .5 <- '?"!5~.5'~#1"$#1'~#3
+ PLEASE RETRIEVE :4
+ (1541) DO :4 <- .5
+ DO (1543) NEXT
+ (1542) DO (1544) NEXT
+ PLEASE DO (1999) NEXT
+ (1543) DO (1001) NEXT
+ (1544) DO REINSTATE (1541)
+ PLEASE REINSTATE (1542)
+ PLEASE RETRIEVE :1 + :2 + :5 + .1 + .2 + .5
+ DO RESUME #2
+ (1550) DO STASH :1 + :4 + :5 + .5
+ DO :3 <- #0
+ DO .5 <- '?"':2~:2'~#1"$#1'~#3
+ PLEASE DO (1551) NEXT
+ DO :4 <- #1
+ PLEASE DO (1553) NEXT
+ (1553) DO FORGET #1
+ DO .5 <- '?":2~'#32768$#0'"$#2'~#3
+ DO (1552) NEXT
+ DO :2 <- ":2~'#0$#65535'"$"'":2~'#32767$#0'"$#
+ 0'~'#32767$#1'"
+ PLEASE DO :4 <- ":4~'#0$#65535'"$"'":4~'#32767
+ $#0'"$#0'~'#32767$#1'"
+ DO (1553) NEXT
+ (1552) DO (1001) NEXT
+ (1556) PLEASE FORGET #1
+ DO :5 <- "'?":1~'#65535$#0'"$":2~'#65535$#0'"'
+ ~'#0$#65535'"$"'?":1~'#0$#65535'"$":2~'#0$
+ #65535'"'~'#0$#65535'"
+ DO .5 <- '?"'&"':2~:5'~'"'?"'?":5~:5"~"#65535$
+ #65535"'~'#65535$#0'"$#32768'~'#0$#65535'"
+ $"'?":5~:5"~"#65535$#65535"'~'#0$#65535'"'
+ "$"':5~:5'~#1"'~#1"$#2'~#3
+ DO (1554) NEXT
+ DO :5 <- :3
+ DO (1510) NEXT
+ PLEASE DO :1 <- :3
+ DO :3 <- "'V":4~'#65535$#0'"$":5~'#65535$#0'"'
+ ~'#0$#65535'"$"'V":4~'#0$#65535'"$":5~'#0$
+ #65535'"'~'#0$#65535'"
+ DO (1555) NEXT
+ (1554) PLEASE DO (1001) NEXT
+ (1555) DO FORGET #1
+ DO .5 <- "?':4~#1'$#2"~#3
+ DO (1551) NEXT
+ DO :2 <- ":2~'#0$#65534'"$":2~'#65535$#0'"
+ DO :4 <- ":4~'#0$#65534'"$":4~'#65535$#0'"
+ PLEASE DO (1556) NEXT
+ (1551) DO (1001) NEXT
+ PLEASE RETRIEVE :1 + :4 + :5 + .5
+ PLEASE RESUME #2
+ (1900) DO STASH .2 + .3 + .5
+ DO .1 <- #0
+ DO .2 <- #1
+ PLEASE DO (1901) NEXT
+ (1901) DO FORGET #1
+ DO %50 .1 <- 'V.1$.2'~'#0$#65535'
+ DO .2 <- !2$#0'~'#32767$#1'
+ PLEASE DO .5 <- "?!2~.2'$#1"~#3
+ DO (1902) NEXT
+ DO (1901) NEXT
+ (1902) DO (1001) NEXT
+ DO RETRIEVE .2 + .3 + .5
+ PLEASE RESUME #2
+ (1910) PLEASE STASH .1 + .3 + .5 + :1 + :2 + :3
+ DO .3 <- #65524
+ DO :1 <- #6
+ DO (1911) NEXT
+ PLEASE NOTE THAT YOU CAN'T GET THERE FROM HERE
+ (1912) DO (1001) NEXT
+ (1911) DO FORGET #1
+ PLEASE DO (1900) NEXT
+ DO :2 <- .1
+ DO (1500) NEXT
+ PLEASE DO :1 <- :3
+ DO .1 <- .3
+ DO (1020) NEXT
+ PLEASE DO .3 <- .1
+ DO .5 <- '?"!3~.3'~#1"$#2'~#3
+ DO (1912) NEXT
+ DO .1 <- #12
+ PLEASE DO (1050) NEXT
+ DO RETRIEVE .1
+ DO (1530) NEXT
+ DO :2 <- #32768
+ DO (1500) NEXT
+ PLEASE DO .2 <- :3~'#65280$#65280'
+ PLEASE RETRIEVE .3 + .5 + :1 + :2 + :3
+ DO RESUME #1
--- /dev/null
+ DO COME FROM (4)
+ DO WRITE IN .1
+ DO READ OUT .1
+(4) DO (5) NEXT
+(5) DO (7) NEXT
+ PLEASE GIVE UP
+(7) PLEASE .2 <- "?'"!1~.1'~#1"$#1'"~#3
+ DON'T READ OUT .2
+ PLEASE RESUME .2
--- /dev/null
+ PLEASE NOTE THIS PROGRAM USES NO NEXTING + FORGETTING + RESUMING
+
+(5) DO .1 <- #0
+(6) DO .2 <- #1
+(7) DO .9 <- #1
+ DON'T .1 <- .2
+ DON'T .2 <- .3
+ DON'T READ OUT .1
+ DON'T WRITE IN .9
+ PLEASE NOTE THAT WE EXIT IF WE READ ZERO
+ DO REINSTATE (15)
+ DO REINSTATE (14)
+(14) DO ABSTAIN FROM (16)
+(15) DO ABSTAIN '"'.9~.9'~#1"$#1'~#3 FROM (16)
+ PLEASE NOTE THAT LINE 16 IS NOW ABSTAINED FROM TWICE OR FOUR TIMES
+ DO REINSTATE (16)
+ DO REINSTATE (16)
+(16) DON'T ABSTAIN FROM CALCULATING + REINSTATING + ABSTAINING + TRYING AGAIN
+ DO REINSTATE (16)
+ DO REINSTATE (16)
+
+(10) PLEASE DO REINSTATE CALCULATING + READING OUT + WRITING IN
+ DO ABSTAIN FROM (5)
+ DO ABSTAIN FROM (6)
+ DO ABSTAIN FROM (7)
+ DO ABSTAIN FROM (10)
+ DO ABSTAIN FROM ABSTAINING
+
+ DO .3 <- .1
+ DO .4 <- .2
+
+ PLEASE NOTE THAT WE ARE PERFORMING .3 <- .3 (arithmetic +) .4
+ NOTE ALSO THAT THIS CAN BE SUPRESSED BY IGNORING .3
+ AND ALSO THAT .5, .6 ARE USED AS TEMPORARIES
+ AND THAT THIS DISCARDS THE HIGH BIT ON OVERFLOW
+ DON'T FORGET THAT THIS CONTAINS 16 REPETITIONS OF THE SAME LINE
+ DO .5 <- .4
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+ PLEASE DO .6 <- "&!3$.5'"~'#0$#65535' DO .3 <- "?!3$.5'"~'#0$#65535' DO .5 <- !6$#0'~"#32767$#1"
+
+ PLEASE TRY AGAIN
+
--- /dev/null
+arrtest.i is a program I wrote to test my correction to a nasty
+ambiguity in grammar that was rendering many programs incompilable.
+
+The problem is:
+
+sublist1 : unambig _
+sublist : unambig _ sublist
+sublist : unambig _ sublist1
+
+Token received: SPARK or EARS.
+
+Shift/reduce conflict.
+
+This is an example from numio.i:
+
+DO .5 <- '?"'#65535~"'?.7$",2SUB.1"'~#21845"'~#1"$#1'~#3
+ ^
+ ambiguity
+
+The problem is that it's unclear whether the spark/ears is the end of
+an expression around the array reference (reduce), or whether it's the
+start of a new subscript (shift).
+
+In this case, the reduction is wanted. With the shift taking priority,
+there seems to be no way to write this statement without splitting
+it. The grammar as of INTERCAL 0.24 uses the shift by default. This is
+because multidimensional arrays may do this sort of thing:
+
+DO .1 <- ',2SUB.1".2~.3"'~#1
+
+where the shift is needed to parse the ".2~.3" construct. In the first
+case, there is no information within the next two characters that
+indicates that it was the shift that was wanted; in the second case,
+the fact that it's an ears, not a spark, indicates to humans that the
+reduce is needed, but yacc/bison cannot determine this as they don't
+have information about whether the current spark/ears level was
+introduced with sparks or ears.
+
+At first I thought that scanning past all spark/ears to find the first
+non-sparkears character could solve the problem, even if it could not
+be coded in yacc, but the following code shows the problem:
+
+DO .1 <- ,3SUB",2SUB.1".2 (reduce required)
+
+(It could be the start of this statement:
+
+DO .1 <- ,3SUB",2SUB.1".2~.3"".4 (shift required))
+
+The two statements above are the same for several tokens after the
+ambiguity, and are even the same for 2 tokens after the forward
+scan. This sort of problem is probably why the original manual
+suggested alternating sparks and ears in various levels of expression
+grouping. The only solution I can think of is:
+
+Determine somehow whether we are on a spark level or an ears level
+
+Force alternation of sparks and ears (constraint on the programmer)
+at different levels of expression grouping when dealing with
+near-ambiguous expressions involving spark/ears and arrays, like the
+ones above (so the fourth statement above would be illegal)
+
+Look at whether we see a spark or an ears to determine whether to
+shift or reduce
+
+In other words, reduce whenever it would be a legal way to close the
+current spark/ears level, otherwise shift.
+
+So how to determine whether we're on a spark level or an ears level?
+The solution is for the lexer to place all the sparks and ears it
+encounters on a spark/ears stack, and for the parser to pop two
+sparkears off the stack whenever it reduces a SPARK [unary] <expr>
+SPARK or EARS [unary] <expr> EARS.
+
+Once the determination is in place, all that is required is a way of
+determining whether to shift or reduce based on a variable in the
+program, rather than just a priority (which wouldn't work). This
+doesn't seem to fit into yacc's syntax, so it's possible that after
+all, yacc can't work with the INTERCAL syntax. But there is a solution
+(one that I used to determine COMPUCOME from COME_FROM): syntax
+analysis in the lexer! The idea is that legal closing spark/ears have
+different tokens from illegal closing spark/ears, so that the reduce
+is impossible in situations where it would be illegal (the production
+looks something like eitherspark <expr> CLOSESPARK), and the default
+in all other situations (sort of like 'auto' in C, which noone ever
+uses, because it's the default everywhere it isn't illegal).
+
+The solution I've used places a limit on the maximum nesting depth of
+an expression. Strangely, it also limits the number of sparks and ears
+that can be written into a 'comment' to 31. As care has to be taken
+anyway that malformed abstained statements don't look sufficiently
+like real statements to cause errors, this should be a trivial extra
+addition.
+
+(Incidentally, I strongly suspect this sort of fix was used in the
+original INTERCAL-72 compiler, because there is a very similar
+restriction documented in the manual. Besides, it's needed to make
+INTERCAL into an LALR(1) language.)
+
+The program arrtest.i will not actually run, but it will compile as
+far as degenerating C code. I don't believe every line would have come
+out as a valid statement in any version of INTERCAL 0.24 or earlier
+(except the one labeled as invalid, which would have come out as valid
+but is really bad style anyway).
\ No newline at end of file
--- /dev/null
+PLEASE NOTE THIS PROGRAM TESTS SOME GRAMMAR NEAR-AMBIGUITIES
+DO .5 <- '?"'#65535~"'?.7$",2SUB.1"'~#21845"'~#1"$#1'~#3
+DO .1 <- ',2SUB.1".2~.3"'~#1
+DO .1 <- ,3SUB",2SUB.1'.2~.3'".4
+PLEASE NOTE THE NEXT LINE IS TOO UNCLEAR TO PARSE
+DOXXX .1 <- ,3SUB",2SUB.1".2~.3"".4
+THE PREVIOUS LINE CAUSES ERROR ICL017I
--- /dev/null
+ PLEASE NOTE THIS PROGRAM TESTS COMPUTED COME FROM
+ DO .2 <- #2
+(1) DO .1 <- #1
+(3) DO READ OUT #5
+ DO COME FROM .1
+(256) DO READ OUT #2
+ DO .2 <- '.2$#0'~#43691
+(5) DO READ OUT #3
+ DO READ OUT #4
+ DO .1 <- #5
+ PLEASE DO (3) NEXT
+ PLEASE COME FROM .2
+ DO WRITE IN .1
+ DO WRITE IN .2
+(999) DO NOTHING
+ PLEASE GIVE UP
--- /dev/null
+ DO ,1 <- #16
+ DO :2 <- #6490$#55022
+ PLEASE DO (44) NEXT
+ DO :2 <- #5631$#54733
+ PLEASE DO (44) NEXT
+ DO :2 <- #14637$#40039
+ PLEASE DO (44) NEXT
+ DO :2 <- #58550$#53112
+ PLEASE DO (44) NEXT
+ DO .1 <- #1
+ PLEASE DO (99) NEXT
+ DO GIVE UP
+(44) DO REINSTATE COMING FROM
+(19) DO COME FROM (68)
+ DO ABSTAIN FROM (19)
+(31) DO COME FROM (34)
+ DO ABSTAIN FROM (31)
+(88) DO COME FROM (65)
+ PLEASE ABSTAIN FROM (88)
+ DO COME FROM (44)
+ PLEASE DO (123) NEXT
+ DO .3 <- ':2~"#4$#13"'
+ DO :2 <- ':2~"#29520$#29511"'
+ DO ,1 SUB .1 <- .3
+(65) DON'T GIVE UP
+(34) PLEASE DON'T GIVE UP
+(68) DO NOTE THAT THIS FUNNY CODE ACTUALLY WORKS
+ PLEASE RESUME #1
+(99) DO COME FROM (69)
+ DO READ OUT ,1
+ DO ,1 SUB #1 <- #180
+ DO READ OUT .1
+ DO .2 <- "?.1$#10"~"#0$#29524"
+ PLEASE DO (15) NEXT
+(69) PLEASE DO (123) NEXT
+(42) DO RESUME .9
+(123) PLEASE .8 <- #1
+ DO COME FROM (81)
+ DO .9 <- '?"V!1~.8'$#1"~#1'~#1
+ DO .1 <- "^.1$.8"~"#0$#29524"
+ PLEASE DO (42) NEXT
+(81) DO .8 <- !8$#0'~"#9841$#1"
+(15) PLEASE RESUME '?"!2~.2'~#2"$#1'~#1
--- /dev/null
+
+From: johnpc@xs4all.nl (Jan-Pieter Cornet)
+Newsgroups: comp.lang.misc,comp.lang.perl.misc,comp.lang.tcl,comp.lang.c,comp.lang.java,alt.lang.intercal,alt.test
+Subject: Re: Readable Perl (was: Re: Relative Speed of Perl vs. Tcl vs. C)
+Date: 27 Feb 1996 02:44:19 GMT
+Organization: XS4ALL Internet
+Message-ID: <4gtr64$s7h@news.xs4all.nl>
+Summary: hit "n" now! quick!
+
+In article <4ge7bk$4vq@news.ox.ac.uk>,
+David Hopwood <lady0065@sable.ox.ac.uk> wrote:
+>In article <4gb3kp$lu7@gaia.ns.utk.edu>,
+>Matthew B. Kennel <kennel@msr.epm.ornl.gov> wrote:
+>>Randal L. Schwartz (merlyn@stonehenge.com) wrote:
+>>: >>>>> "John" == John Viega <jtv2j@mamba.cs.virginia.edu> writes:
+>>
+>>: John> People bitch about the readability of Perl non-stop. In fact, I have
+>>: John> heard the joke, "Perl, the only language you can uuencode, and not
+>>: John> notice" twice this week around the department.
+>>
+>>: OK, now which do you find most readable...
+>
+>This (Haskell):
+>
+>cancount n = "I can count to "++(show n)++"\n"
+>concat (map cancount [1..10])
+
+No, you got it all totally wrong. I think this is the best readable
+(in Tri-INTERCAL):
+
+[Program moved to .3i file.]
+
+Now, I think the advantages of this are pretty clear. First, this is
+clearly a write-only language. There are only few people insane enough
+to actually understand the above drivel, and they wouldn't bother
+touching your petty code, as they are too busy filling bathtubs with
+brightly colored machine tools.
+
+Anyone else will simply be too scared to touch this code. So you can be
+pretty sure nobody changes it behind your back.
+
+In fact, you can be pretty sure you won't change it either after you
+wrote it, because you will probably have forgotten how the program
+works 5 minutes after you wrote it. So any luser nagging for extra
+features afterwards, is SOL.
+
+The other major advantage is... the above code took me about 3 hours
+to write. Compare this to the 10 to 30 seconds it takes to write a
+similar program in perl, BASIC, Haskell or what have you. But... that
+means that when you programmed it in that other language, you'd have to
+spend 2 hours 59 minutes and somewhere between 30 and 50 seconds
+answering the phone talking to clueless lusers, changing backup tapes,
+or doing other boring stuff. While you could have been programming
+Intercal instead! Just think about that!
+
+And last, but certainly not least, is: the above code is likely to
+impress your boss. Bosses are wont to be impressed by incomprehensible
+things. They won't be impressed by a three line perl program that anyone
+not wearing a diaper can understand.
+
+So that pretty much proves it.
+
+PS: this article contains some strange usage of the words "best readable"
+that you probably weren't previously aware of :)
+
+--
+Jan-Pieter Cornet <johnpc@xs4all.net>
+Actual quote: "Linux was made by foreign terrorists to steal money from true
+ AMERICAN companies like Microsoft who invented computing as we
+ know it, and are being punished for their success..."
+Linux -- "It's computing, Jim, but not as we know it"
--- /dev/null
+ DO ,1 <- #13
+ PLEASE DO ,1SUB#1 <- #234
+ DO ,1SUB#2 <- #112
+ DO ,1SUB#3 <- #112
+ DO ,1SUB#4 <- #0
+ DO ,1SUB#5 <- #64
+ DO ,1SUB#6 <- #194
+ DO ,1SUB#7 <- #48
+ PLEASE DO ,1SUB#8 <- #22
+ DO ,1SUB#9 <- #248
+ DO ,1SUB#10 <- #168
+ DO ,1SUB#11 <- #24
+ DO ,1SUB#12 <- #16
+ DO ,1SUB#13 <- #214
+ PLEASE READ OUT ,1
+ PLEASE GIVE UP
--- /dev/null
+Jan-Pieter Cornet <cornet@OTech.fgg.EUR.nl> writes:
+
+You might want to try the following program (I've just been hacking this up,
+and it costed me considerable more time than adding the gerund I/O things.
+But that's the power of intercal...) This program will ask for a number
+and might print it then, except that it doesn't ask the first time but
+ _
+assumes ONE TWO THREE. Oh and it never prints but just exits in case that
+would've been printed (I did my best to make that part as unreadable as
+possible. did it work? :)
--- /dev/null
+ DO .1 <- #123
+ DO ABSTAIN FROM WRITING IN
+ DO COME FROM (123)
+(100) DO WRITE IN .1
+ PLEASE .2 <- #1
+ DO %50 .2 <- !2$#0'
+ PLEASE DO (42) NEXT
+ DO ABSTAIN FROM READING OUT
+ PLEASE COME FROM (69)
+ DO READ OUT .1
+ DO REINSTATE READING OUT
+(123) PLEASE REINSTATE (100)
+(42) DO (43) NEXT
+ DO FORGET #1
+ DO (105) NEXT
+ PLEASE GIVE UP
+(105) DO (106) NEXT
+(69) DON'T GIVE UP
+(106) PLEASE DO RESUME "'?"!1~.1'~#1"$#1'~#1"$'".1~.1"~#1'
+(43) DO RESUME .2
--- /dev/null
+ PLEASE ABSTAIN FROM (1)
+(1) DON KNUTH'S IMPLEMENTATION OF TPK IN INTERCAL
+ (C) MARCH 2003
+ REFERENCE --- THE EARLY HISTORY OF PROGRAMMING
+ LANGUAGES, BY D E KNUTH AND L TRABB PARDO
+
+ NOTA BENE: THE INPUT AND OUTPUT DATA ARE SCALED
+ DECIMAL NUMBERS WITH SIX DIGITS TO THE RIGHT OF
+ THE DECIMAL POINT; THUS AN INPUT OF
+ THREE ONE FOUR ONE FIVE NINE THREE
+ DENOTES 3.141593, AND THAT VALUE WOULD BE OUTPUT AS
+ ______
+ MMMCXLMDXCIII
+
+ VARIABLE NAMES AND SUBROUTINE NAMES USE THE CLASSIC
+ 5-BIT TELEPRINTER CODE IN LETTER-SHIFT MODE, NAMELY
+ / E @ A : S I U 1/4 D R J N F C K T Z L W H Y P Q O B G " M X V $
+ (WHICH ALAN TURING ADVISED EVERY PROGRAMMER TO LEARN)
+
+ DO GIVE UP
--- /dev/null
+(1) DO NOTHING
+ PLEASE COME FROM (13) ONCE
+ PLEASE COME FROM #11 ONCE
+ DO COME FROM (1)
+ DO READ OUT #1 ONCE
+(6) DO READ OUT #2 AGAIN
+ DO READ OUT #3
+ DO ABSTAIN FROM (6) ONCE
+ DON'T READ OUT #4 ONCE
+(10) DON'T READ OUT #5 AGAIN
+(11) DO REINSTATE (10) ONCE
+ DO READ OUT #6
+(13) DON'T READ OUT #7
+ DO REINSTATE (17)
+(15) DO (19) NEXT ONCE
+(16) PLEASE READ OUT #8
+(17) DON'T (15) NEXT AGAIN
+ PLEASE GIVE UP
+(19) PLEASE READ OUT #9
+ DO (16) NEXT
+
--- /dev/null
+permute.i prints the permutations of the set {1,2,3,4,5,6}, using
+backtracking (and therefore must be compiled with the -m compiler
+option). The following is the program translated into a mix of Prolog
+and C, with some INTERCAL operations (gets, stash, retrieve, giveup)
+scattered throughout the program.
+
+goal :- gets(.1, #0),
+ gennumber,
+ checklist,
+ gennumber,
+ checklist,
+ gennumber,
+ checklist,
+ gennumber,
+ checklist,
+ gennumber,
+ checklist,
+ gennumber,
+ checklist,
+ readout(.1),
+ retrieve(.1),
+ readout(.1),
+ retrieve(.1),
+ readout(.1),
+ retrieve(.1),
+ readout(.1),
+ retrieve(.1),
+ readout(.1),
+ retrieve(.1),
+ readout(.1),
+ readout(#30),
+ fail.
+goal :- giveup.
+
+gennumber :- stash(.1), gets(.1, #1).
+gennumber :- stash(.1), gets(.1, #2).
+gennumber :- stash(.1), gets(.1, #3).
+gennumber :- stash(.1), gets(.1, #4).
+gennumber :- stash(.1), gets(.1, #5).
+gennumber :- stash(.1), gets(.1, #6).
+
+checklist :- gets(.2, .1),
+ while(.1 != #0)
+ {
+ retrieve(.1),
+ if(.1 == .2) {!, fail.}
+ },
+ fail.
+checklist.
+
+The backtracking reverses all the stashing and retrieving that is
+done, so that at the end of the program .1 is #0 again and there is no
+stash on .1. The INTERCAL has a somewhat Prolog-like attitude: it
+never uses GO BACK to remove a choicepoint except when GOING BACK to
+an earlier choicepoint (just like Prolog). The checklist. at the end
+of the pseudo-Prolog source is actually an attempt to replicate the
+semantics of MAYBE COME FROM; MAYBE COME FROM...GO BACK continues as
+if nothing had happened, except for leaving a stale choicepoint on the
+stack (but the program runs GO BACK in a loop whenever there is a risk
+of encountering a stale choicepoint on top of the stack), but MAYBE
+COME FROM...GO AHEAD, GO BACK causes the line that was come from to
+fail. (The GO AHEAD, GO BACK was translated as !, fail in the
+pseudo-Prolog above, as it has a similar effect). The program clearly
+shows that INTERCAL's variables are more general than Prolog's (you
+can rebind a variable in INTERCAL, and the rebinding is undone on
+backtracking), especially when stashes are taken into account. On the
+other hand, the program couldn't work as written in C, because
+checklist destroys all the information about the permutations so far!
+(In both the Prolog source above and in the INTERCAL, this destruction
+is always cancelled out by backtracking past it). This program
+probably could be translated into Prolog, but there would be a lot
+more passing-around of variables, and probably more predicates
+involved (I think gets, stash, and retrieve might be possible in terms
+of assert/retract). However, I think that the INTERCAL source is the
+clearest available implementation of the exact program flow above.
+Note also the way that I translated the if() and while() into
+INTERCAL.
+
+if(<1 or 2>==1) something
+becomes
+DO ABSTAIN <1 or 2> FROM (label)
+DO REINSTATE (label)
+(label) DO something AGAIN
+which is the shortest way to do an if() statement in INTERCAL that I
+have discovered (yes! ABSTAIN and REINSTATE have a purpose again!).
+
+do {block} while(<0 or 1>) becomes
+
+DO COME FROM <0 or 1>$label
+most of block
+(1$label) last statement of block
+
+which is pretty clear when written like this, but amazingly confusing
+to track in the INTERCAL, and also prevents the user using 0$label as
+a line number, without any obvious clue to this effect in the source
+code. while() can often be transformed into do..while(), and even in
+situations where it can't, an extra COME FROM does the trick.
+
+This program uses a large crosssection of INTERCAL control structures;
+computed COME FROM, ordinary COME FROM, ABSTAIN/REINSTATE, AGAIN,
+NEXT, and MAYBE/GO AHEAD/GO BACK are all used. Only ONCE (which is
+implied in the program due to the abstention/reinstatement of an AGAIN
+line) and IGNORE are left unused (at least until someone invents a new
+even nastier control structure). Unusually, it only contains three
+nontrivial expressions (those other than a single constant or a single
+variable).
\ No newline at end of file
--- /dev/null
+ PLEASE NOTE THIS IS A BACKTRACKING PERMUTATION PROGRAM
+ MAYBE DON'T GIVE UP
+ DO .1 <- #0
+(3) DO (24) NEXT
+(4) DO (24) NEXT
+(5) DO (24) NEXT
+(6) DO (24) NEXT
+(7) DO (24) NEXT
+(8) DO (24) NEXT
+ DO READ OUT .1
+ PLEASE RETRIEVE .1
+ DO READ OUT .1
+ PLEASE RETRIEVE .1
+ DO READ OUT .1
+ PLEASE RETRIEVE .1
+ DO READ OUT .1
+ PLEASE RETRIEVE .1
+ DO READ OUT .1
+ PLEASE RETRIEVE .1
+ DO READ OUT .1
+ DO READ OUT #30
+ DO COME FROM (22)
+(22) DO GO BACK
+
+(24) PLEASE NOTE THIS RETURNS #1 TO #6 ON DIFFERENT BACKTRACKS
+ DO STASH .1
+(26) DO .1 <- #1
+(27) DO .1 <- #2
+(28) DO .1 <- #3
+(29) DO .1 <- #4
+(30) DO .1 <- #5
+ DO .1 <- #6
+ DO RESUME #1
+ MAYBE COME FROM (26)
+ PLEASE RESUME #1
+ MAYBE COME FROM (27)
+ PLEASE RESUME #1
+ MAYBE COME FROM (28)
+ PLEASE RESUME #1
+ MAYBE COME FROM (29)
+ PLEASE RESUME #1
+ MAYBE COME FROM (30)
+ PLEASE RESUME #1
+
+ PLEASE NOTE THIS BACKTRACKS IF .1 IS NONUNIQUE IN ITS STASH
+ MAYBE COME FROM (3)
+ MAYBE COME FROM (4)
+ MAYBE COME FROM (5)
+ MAYBE COME FROM (6)
+ MAYBE COME FROM (7)
+ MAYBE COME FROM (8)
+ PLEASE DO .2 <- .1
+ DO .3 <- #1
+ DO COME FROM '"?"!3~.3'~#1"$#2"~#1'$#15
+ PLEASE DO RETRIEVE .1
+ DO ABSTAIN "?"!1~.1'~#1"$#1"~#3 FROM (55)
+ DO REINSTATE (55)
+(55) DO GO BACK AGAIN
+(87) PLEASE DO .3 <- '?.1$.2'~#21845
+ DO GO AHEAD
+ DO COME FROM (61)
+(61) PLEASE DO GO BACK
--- /dev/null
+(1999) PLEASE DO (1999) NEXT
+
+Sink.i: A program I wrote just to see if the guy who wrote the compiler
+ was faithful. :)
+ (blojo@ocf.berkeley.edu)
--- /dev/null
+(1999) PLEASE DO (1999) NEXT
+ DO NOTE THAT YOU CAN'T GET HERE FROM THERE
+ DO ANYTHING YOU WANT ON THIS LINE, IT WON'T HAPPEN ANYWAY
--- /dev/null
+ PLEASE COME FROM (30) ONCE
+ PLEASE COME FROM (20) ONCE
+ PLEASE COME FROM (10) ONCE
+ DO .1 <- #1
+(1) DO .1 <- #2 ONCE
+(10) DO READ OUT .1
+(20) DO NOTHING
+(30) DO REINSTATE (1)
+
+ PLEASE COME FROM (40) ONCE
+ PLEASE COME FROM (50) ONCE
+ PLEASE COME FROM (60) ONCE
+ DO .1 <- #1
+(2) DO NOT .1 <- #2 ONCE
+(40) DO READ OUT .1
+(50) DO NOTHING
+(60) DO ABSTAIN FROM (2)
+
+ DO COME FROM (70) ONCE
+ DO COME FROM (80) ONCE
+ DO COME FROM (90) ONCE
+ DO .1 <- #1
+(3) DO .1 <- #2 AGAIN
+(70) DO READ OUT .1
+(80) DO ABSTAIN FROM (3) ONCE
+(90) DO NOTHING
+
+ DO COME FROM (100) ONCE
+ DO COME FROM (110) ONCE
+ DO COME FROM (120) ONCE
+ DO .1 <- #1
+(4) DO NOT .1 <- #2 AGAIN
+(100) DO READ OUT .1
+(110) DO REINSTATE (4) ONCE
+(120) DO NOTHING
+
+ PLEASE GIVE UP
--- /dev/null
+#!/bin/sh
+
+version=$1
+
+cat <<EOF
+Name: intercal
+Version: ${version}
+Release: 1
+URL: http://www.catb.org/~esr/intercal/
+Source: intercal-${version}.tar.gz
+License: GPL
+Group: Development/Languages
+Summary: the language that kills the weak and drives mad the strong
+
+%description
+An implementation of the language INTERCAL, legendary for
+its perversity and horribleness (this version adds COME FROM
+for extra flavor). Comes with language manual and examples
+including possibly the entire extant body of INTERCAL code.
+Now supports i18n and l14n (to Ancient Roman locale only)
+Now with fix patch by Donald Knuth.
+
+%prep
+%setup -q
+
+%build
+configure --prefix=/usr
+make
+
+%install
+rm -fr /usr/share/intercal-${version}/*
+make install
+
+%files
+/usr/bin/ick
+/usr/lib/libick.a
+/usr/lib/libickmt.a
+/usr/lib/libyuk.a
+/usr/include/intercal-${version}/lose.h
+/usr/include/intercal-${version}/abcess.h
+/usr/include/intercal-${version}/fiddle.h
+/usr/include/intercal-${version}/yuk.h
+/usr/share/intercal-${version}/ick-wrap.c
+/usr/share/intercal-${version}/
+%doc README BUGS NEWS
+EOF
+#find pit -type f -print | sed -e "/^/s//\/usr\/share\/intercal-${version}\//" -e '/RCS/d'
+
+
--- /dev/null
+/*****************************************************************************
+
+NAME
+ unravel.c -- multithreading and backtracking support for C-INTERCAL
+
+LICENSE TERMS
+ Copyright (C) 2006 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.
+
+***************************************************************************/
+
+/* Notes about authorship. This entire file was written by Alex Smith (AIS),
+ but with reference to an earlier implementation of Threaded INTERCAL written
+ by Malcom Ryan. I have not reused any of his C code (two of his INTERCAL
+ programs are in the pit), but it was a useful source of inspiration, even
+ though I did it a completely different and less efficient way (I think we
+ handled mutiple COME FROM recognition in much the same way). This file only
+ contains functions necessary for multithreading; some of the code is stored
+ in feh.c (stored in strings), or in perpetrate.c (again stored in strings).
+ The information about the required syntax is in ick.y and lexer.l.
+ A small amount of the multithread code is in ick-wrap.c, although as that
+ file is copied almost verbatim (although it's quite a big 'almost') into
+ all ick output, it's guarded there by #if...#endif. The whole multithread
+ idea started on alt.lang.intercal when it was noticed that multiple COME
+ FROMs aiming at the same line were hard to interpret, but I would like
+ to thank Malcom Ryan for drafting the Threaded Intercal standard and a
+ reference compiler, and for turning the idea into a concrete set of rules.
+ (The standard itself carries a note saying that a revision (use of AGAIN)
+ was inspired by Kyle Dean, so I'd like to mention that here too, and I also
+ revised it (so that ABSTAIN/REINSTATE were preserved through backtracking).)
+ In terms of the quality of the code, Malcom Ryan's code was clearly better
+ for multithread programs, but required rewriting most of the compiler. As
+ clearly it would be unfair to subject the INTERCAL community at large to
+ the risk of silent multithreading by default, I decided multithreading
+ should be off by default (but ONCE/AGAIN should be legal). So this code is
+ designed to interfere as little as possible with non-multithreaded output.
+ There are two versions of libick compiled by the Makefile in this
+ distribution: libick.a, the non-multithread version, and libickmt.a, the
+ multithread version. The only difference between them is this file,
+ unravel.c, which is multithread only, so it seemed a good place for this
+ comment. To see what the multithreading looks like in the object code,
+ see degenerated code or feh.c. */
+
+/* This file also implements Backtracking INTERCAL, which is turned on with
+ the same command-line option (-m). This implementation differs from
+ Malcom Ryan's standard in that abstention stati are not restored upon
+ GOING BACK. As far as I know, this is the only Backtracking INTERCAL
+ implementation currently available, although the code depends on the
+ multithreading code (which is why -m is neccesary). */
+
+/* Note about control structures: Crazy INTERCAL control structures call for
+ crazy C control structures. setjmp/longjmp is probably C's weirdest
+ control structure (it's sort of like a time-reversed computed COME FROM).
+ I've used them to implement both multithreading and computed COME FROMming.
+
+ Worried that this code might actually be copied by a casual C programmer, I
+ have the following warning:
+
+ setjmp/longjmp is worse than goto in terms of spaghettification of code.
+ It is strictly to be used only when neccesary, or when writing INTERCAL
+ compilers. They also lead to weird portability problems when you don't obey
+ all the restrictions put on them by the C standard. For instance,
+ if(setjmp(cjb)!=0) puts("Jumped"); is portable, but
+ if(setjmp(cjb)) puts("Jumped"); is not, despite seeming to mean exactly the
+ same thing. Also, the address of setjmp can't be taken. Semantically,
+ setjmp/longjmp lets you do the same crazy things like goto, like jump into
+ the middle of a loop, except in this case the loop can be in a different
+ function, or even in a different file. unravel.c has no qualms about
+ jumping straight into the middle of an if statement in a degenerated C
+ program, even if said degenerated C program didn't exist when libickmt.a was
+ compiled. */
+
+/* LINTLIBRARY */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+
+#define MULTITHREAD 1
+
+#include "sizes.h"
+#include "abcess.h"
+#include "lose.h"
+
+int gonebackto; /* Is the choicepoint reached by GOING BACK? */
+static int choicing = 0; /* Is a multithread function being used to do
+ backtracking processing? */
+jmp_buf btjb; /* The backtracking jmp_buf */
+static ickthread* topchoice; /* Top of the choicepoint stack */
+extern int lineno; /* Keep track of error-message lines */
+
+extern int printflow; /* from arrgghh.c; a debug option */
+
+/**********************************************************************
+ *
+ * This functions deal with choicepoints, which are implemented as
+ * ickthread objects. choicepoint creates a choicepoint or marks a
+ * choicepoint as stale; choiceahead eliminates a choicepoint;
+ * choiceback eliminates a stale choicepoint or returns to a fresh
+ * choicepoint.
+ *
+ *********************************************************************/
+
+void choicepoint(void)
+{
+ ickthread* oldprev, *oldtc;
+ if(gonebackto)
+ { /* Create a stale choicepoint */
+ if(printflow) printf("(back)");
+ oldtc = topchoice;
+ topchoice = (ickthread*) malloc(sizeof(ickthread));
+ if(!topchoice) lose(E991, lineno, (char*) NULL);
+ topchoice->next = oldtc;
+ topchoice->stale = 1;
+ topchoice->refcount = 1; /* At the moment, this is the only
+ thread looking at this choicepoint */
+ return;
+ }
+ else
+ { /* Create a new choicepoint */
+ if(printflow) printf("(maybe)");
+ oldprev = ickmt_prev;
+ choicing = 1;
+ multicome1(lineno,btjb); /* Duplicate data */
+ choicing = 0;
+ oldprev->next = ickmt_cur;
+ ickmt_prev->choicepoint = topchoice;
+ topchoice = ickmt_prev;
+ ickmt_prev = oldprev;
+ topchoice->stale = 0;
+ topchoice->refcount = 1;
+ /* So in other words, we've duplicated the current execution
+ environment, except for the choicepoint stack, changed the
+ duplicate from a thread into a choicepoint, and pushed it
+ on top of the choicepoint stack. Its pc is the point in the
+ degenerated program where choicepoint was called. */
+ }
+}
+
+void choiceahead(void)
+{
+ ickthread* tempthread;
+ jmp_buf fakepc;
+
+ if(printflow) printf("(ahead)");
+
+ if(!topchoice) lose(E404, lineno, (char*) NULL); /* That's what E404's for */
+ /* GO AHEAD with multithreading requires care. The choicepoint should only
+ be removed from this thread. topchoice = topchoice->next almost works, but
+ is a memory leak. So most of this is garbage-collection. */
+
+ /* If other threads are using the choicepoint, don't free it. */
+ if(topchoice->refcount > 1)
+ {
+ topchoice->refcount--;
+ topchoice = topchoice->choicepoint;
+ return;
+ }
+
+ /* The top choicepoint is not being used by other threads; free it. */
+
+ /* Freeing a stale choicepoint (which contains no data) is easy. */
+ if(topchoice->stale)
+ {
+ tempthread = topchoice;
+ topchoice = topchoice->choicepoint;
+ free(tempthread);
+ return;
+ }
+
+ /* This code works by converting topchoice back to a thread and placing it
+ just before the current thread, and then killing it. First, the data from
+ this thread, apart from the choicepoint stack, must be saved. */
+ choicing = 1;
+ if(setjmp(fakepc) == 0)
+ {
+ memcpy(ickmt_cur->pc,fakepc,sizeof(jmp_buf));
+ nextthread(fakepc, -1, 5);
+ }
+ choicing = 0;
+ /* That's saved the current thread's data. Now to convert topchoice to a
+ thread. */
+ tempthread = topchoice->choicepoint;
+ ickmt_prev->next = topchoice;
+ topchoice->next = ickmt_cur;
+ ickmt_cur = topchoice;
+ topchoice = tempthread;
+ /* Let's load the backtracking data... */
+ choicing = 1;
+ if(setjmp(fakepc) == 0)
+ {
+ memcpy(ickmt_cur->pc,fakepc,sizeof(jmp_buf));
+ nextthread(fakepc, -1, 6);
+ }
+ /* only to destroy it! Mwahahahahah! */
+ if(setjmp(fakepc) == 0)
+ {
+ memcpy(ickmt_cur->next->pc,fakepc,sizeof(jmp_buf));
+ killthread();
+ }
+ choicing = 0;
+ /* So we've reloaded the original current thread, the original previous
+ thread is still correct, topchoice has become topchoice->choicepoint,
+ and the original topchoice has disappeared. Mission accomplished. */
+}
+
+void choiceback(void)
+{
+ if(!topchoice) lose(E404, lineno, (char *) NULL);
+ if(topchoice->stale) {if(printflow) printf("(back=)"); choiceahead(); return;}
+ /* That's two simple cases out of the way (at least once choiceahead's
+ been implemented). What we need to do to backtrack is to change
+ topchoice to a thread after the current thread (rather than before
+ as in the previous two functions), and then kill the current thread.
+ (It amuses me that destroying a choicepoint, as in choiceahead(),
+ is more complicated than either visiting a choicepoint or creating a
+ choicepoint. That's how much work it can take to avoid a memory leak.)
+ In this case, choiceback won't return in the normal fashion. */
+ if(topchoice->refcount > 1)
+ {
+ /* The Threaded INTERCAL standard states that if other threads are using
+ the choicepoint, a GO BACK should cause the thread it's in to be
+ killed. (Of course, if it's stale, it should just have been removed.)*/
+ killthread();
+ return;
+ }
+ topchoice->next = ickmt_cur->next;
+ ickmt_cur->next = topchoice;
+ topchoice = topchoice->choicepoint;
+ if(ickmt_cur==ickmt_prev) ickmt_prev = ickmt_cur->next;
+ choicing = 2; /* Tells killthread to set it back to 0 */
+ killthread();
+}
+
+/**********************************************************************
+ *
+ * This function is called when two COME FROMs reference the same
+ * line at runtime. multicome1 is used in a multithread
+ * program; it forks the program. For multicome0, see cesspool.c.
+ *
+ *********************************************************************/
+
+int multicome1(int errlineno, jmp_buf pc)
+{
+ /* Make a new thread just before the current one. Fake a PC in the
+ current thread within this function, change to the new thread, then
+ call nextthread. The upshot of all this is that all this thread's
+ data is stored in the new thread's state. Then, we have to copy
+ all this thread's current data to new locations. */
+ static ickthread* newthread;
+ jmp_buf fakepc;
+ stashbox *isb, *isb2, *isbprev;
+ void* tvp;
+ array* a;
+ int prod, i, j;
+ newthread = malloc(sizeof(ickthread));
+ if(!newthread) lose(E991, errlineno, (char *) NULL);
+ ickmt_prev->next = newthread;
+ newthread->next = ickmt_cur;
+ ickmt_cur = newthread;
+
+ if(printflow && !choicing) printf("(fork)");
+
+ if(setjmp(fakepc) == 0)
+ {
+ memcpy(newthread->next->pc,fakepc,sizeof(jmp_buf));
+ nextthread(pc, -1, 1);
+ }
+ /* So on the previous line: Save the value of pc as the program
+ counter of the new thread, and give a fake value for the
+ program value of the current thread (so it returns here,
+ not anywhere in the degenerated program). All that remains
+ is to duplicate all the data stored through pointers in the 'old'
+ thread (nextthread has changed ickmt_cur to point at the 'old'
+ thread). The original memory pointed to by these pointers is in
+ use storing the values in the 'new' thread, so the 'old' thread
+ needs new copies that it can modify independently. */
+
+ /* duplicate variables, forget indicators */
+ i = onespotcount;
+ tvp = onespots;
+ onespots = malloc(i * sizeof *onespots);
+ if(!onespots) lose(E991, errlineno, (char *) NULL);
+ memcpy(onespots, tvp, i * sizeof *onespots);
+ i = twospotcount;
+ tvp = twospots;
+ twospots = malloc(i * sizeof *twospots);
+ if(!twospots) lose(E991, errlineno, (char *) NULL);
+ memcpy(twospots, tvp, i * sizeof *twospots);
+ i = tailcount;
+ tvp = tails;
+ tails = malloc(i * sizeof *tails);
+ if(!tails) lose(E991, errlineno, (char *) NULL);
+ memcpy(tails, tvp, i * sizeof *tails);
+ i = hybridcount;
+ tvp = hybrids;
+ hybrids = malloc(i * sizeof *hybrids);
+ if(!hybrids) lose(E991, errlineno, (char *) NULL);
+ memcpy(hybrids, tvp, i * sizeof *hybrids);
+ i = onespotcount;
+ tvp = oneforget;
+ oneforget = malloc(i * sizeof *oneforget);
+ if(!oneforget) lose(E991, errlineno, (char *) NULL);
+ memcpy(oneforget, tvp, i * sizeof *oneforget);
+ i = twospotcount;
+ tvp = twoforget;
+ twoforget = malloc(i * sizeof *twoforget);
+ if(!twoforget) lose(E991, errlineno, (char *) NULL);
+ memcpy(twoforget, tvp, i * sizeof *twoforget);
+ i = tailcount;
+ tvp = tailforget;
+ tailforget = malloc(i * sizeof *tailforget);
+ if(!tailforget) lose(E991, errlineno, (char *) NULL);
+ memcpy(tailforget, tvp, i * sizeof *tailforget);
+ i = hybridcount;
+ tvp = hyforget;
+ hyforget = malloc(i * sizeof *hyforget);
+ if(!hyforget) lose(E991, errlineno, (char *) NULL);
+ memcpy(hyforget, tvp, i * sizeof *hyforget);
+
+ /* duplicate NEXT stack */
+ tvp = next;
+ next = malloc(MAXNEXT * sizeof *next);
+ if(!next) lose(E991, errlineno, (char *) NULL);
+ memcpy(next, tvp, MAXNEXT * sizeof *next);
+
+ /* duplicate data stored in arrays */
+ j = tailcount;
+ while(j--)
+ {
+ a = tails+j; /* &(tails[j]) */
+ if(!a->rank||!a->dims) continue; /* don't duplicate a deallocated array */
+ tvp = a->dims;
+ /* Much of this code is paraphrased from the stashbox-copying code below,
+ which was in turn paraphrased from a section in cesspool.c I didn't
+ write. So any errors in this code are probably mine, but the algorithm
+ isn't. */
+ a->dims = malloc(a->rank * sizeof(unsigned int));
+ memcpy(a->dims, tvp, a->rank * sizeof(unsigned int));
+ prod = !!a->rank;
+ i = a->rank;
+ while(i--) prod *= a->dims[i];
+ tvp = a->data.tail;
+ a->data.tail = malloc(prod * sizeof(type16));
+ if(!a->data.tail) lose(E991, errlineno, (char *) NULL);
+ memcpy(a->data.tail, tvp, prod * sizeof(type16));
+ }
+ j = hybridcount;
+ while(j--)
+ {
+ a = hybrids+j; /* &(hybrids[j]) */
+ if(!a->rank||!a->dims) continue; /* don't duplicate a deallocated array */
+ tvp = a->dims;
+ /* Much of this code is paraphrased from the stashbox-copying code below,
+ which was in turn paraphrased from a section in cesspool.c I didn't
+ write. So any errors in this code are probably mine, but the algorithm
+ isn't. */
+ a->dims = malloc(a->rank * sizeof(unsigned int));
+ memcpy(a->dims, tvp, a->rank * sizeof(unsigned int));
+ prod = !!a->rank;
+ i = a->rank;
+ while(i--) prod *= a->dims[i];
+ tvp = a->data.hybrid;
+ a->data.hybrid = malloc(prod * sizeof(type32));
+ if(!a->data.hybrid) lose(E991, errlineno, (char *) NULL);
+ memcpy(a->data.hybrid, tvp, prod * sizeof(type32));
+ }
+
+ /* allow for multithreading with choicepoints on the stack */
+ if(!choicing && topchoice)
+ {
+ ickthread* icktp = topchoice;
+ while(icktp)
+ {
+ icktp->refcount++;
+ icktp = icktp->choicepoint; /* next choicepoint on the stack */
+ }
+ /* The old thread's and new thread's choicepoint stack share
+ memory. This is pretty much necessary to handle backtracking
+ past a fork correctly. */
+ }
+
+ /* duplicate stashbox */
+ isb2 = first;
+ isbprev = (stashbox*)NULL;
+ while(isb2)
+ {
+ isb = (stashbox*)malloc(sizeof(stashbox));
+ if(!isb) lose(E991, errlineno, (char *) NULL);
+ memcpy(isb,isb2,sizeof(stashbox));
+ if(isbprev) isbprev->next = isb;
+ isbprev = isb;
+ if(isb2==first) first = isb; /* change first only the first time round */
+ if(isb->type == ONESPOT || isb->type == TWOSPOT)
+ { /* all copying already done */
+ isb2 = isb->next;
+ continue;
+ }
+ /* Copy the stashed array. Much of this code is paraphrased from some
+ code in cesspool.c. In fact, it's the same, with a few idioms added
+ and variable names changed. So, although it's in this file, I can't
+ take the credit for it. */
+ isb->save.a = (array*)malloc(sizeof(array));
+ if(!isb->save.a) lose(E991, errlineno, (char *) NULL);
+ isb->save.a->rank = isb2->save.a->rank;
+ isb->save.a->dims = (unsigned int*)malloc(isb2->save.a->rank *
+ sizeof(unsigned int));
+ if(!isb->save.a->dims) lose(E991, errlineno, (char *) NULL);
+ memcpy(isb->save.a->dims, isb2->save.a->dims,
+ isb2->save.a->rank * sizeof(unsigned int));
+ prod = !!isb2->save.a->rank; /* I use this idiom often enough in the
+ code produced by my optimizer that I
+ may as well use it here. */
+ i = isb2->save.a->rank;
+ while(i--) prod *= isb2->save.a->dims[i];
+ if(isb2->type == TAIL)
+ {
+ isb->save.a->data.tail = (type16*)malloc(prod * sizeof(type16));
+ if(!isb->save.a->data.tail) lose(E991, errlineno, (char *) NULL);
+ memcpy(isb->save.a->data.tail, isb2->save.a->data.tail,
+ prod * sizeof(type16));
+ }
+ else
+ {
+ isb->save.a->data.hybrid = (type32*)malloc(prod * sizeof(type32));
+ if(!isb->save.a->data.hybrid) lose(E991, errlineno, (char *) NULL);
+ memcpy(isb->save.a->data.hybrid, isb2->save.a->data.hybrid,
+ prod * sizeof(type32));
+ }
+ isb2 = isb->next;
+ }
+ return 1; /* Tell the degenerated program to look for yet
+ another COME FROM */
+}
+
+/**********************************************************************
+ *
+ * These functions do the multithreading, using setjmp and longjmp
+ * to save the program counter. ickmtinit sets up the first
+ * thread, and nextthread changes to the next thread in the
+ * sequence. (Note that nextthread rarely actually returns). The
+ * code makes each command atomic, so that ONCE and AGAIN appear
+ * to the user to be atomic operations.
+ *
+ *********************************************************************/
+
+ickthread* ickmt_cur; /* define ickmt_cur */
+ickthread* ickmt_prev; /* define ickmt_prev */
+
+void ickmtinit(void)
+{
+ ickmt_cur = malloc(sizeof(ickthread));
+ if(!ickmt_cur) lose(E991, 1, (char *) NULL);
+ ickmt_prev = ickmt_cur;
+ ickmt_cur->next = ickmt_cur;
+ topchoice = (ickthread*) NULL; /* No choicepoints */
+}
+
+/* Destroys the current thread, and switches to the next thread.
+ If there are no threads left, terminates the program using exit(0). */
+void killthread(void)
+{
+ static jmp_buf dummy;
+ stashbox* isb, *isbi;
+ int i;
+
+ if(printflow&&!choicing) printf("(kill)");
+
+ /* Deallocate the current thread's data */
+ i=tailcount;
+ while(i--)
+ { /* free tail data */
+ if(!tails[i].rank||!tails[i].dims) continue; /* already free */
+ free(tails[i].dims);
+ free(tails[i].data.tail);
+ }
+ i=hybridcount;
+ while(i--)
+ { /* free hybrid data */
+ if(!hybrids[i].rank||!hybrids[i].dims) continue; /* already free */
+ free(hybrids[i].dims);
+ free(hybrids[i].data.hybrid);
+ }
+ free(onespots); free(twospots); free(tails); free(hybrids);
+ free(oneforget); free(twoforget); free(tailforget); free(hyforget);
+ free(next); /* Free NEXT stack */
+ if(!choicing) while(topchoice) choiceahead();
+ /* The above line will mark each of the choicepoints as no longer being
+ used by this thread, and free them if neccesary. */
+ isbi = first;
+ while(isbi) /* Free stash */
+ {
+ isb=isbi->next;
+ if(isbi->type == TAIL || isbi->type == HYBRID)
+ {
+ free(isbi->save.a->dims);
+ if(isbi->type == TAIL)
+ free(isbi->save.a->data.tail);
+ else
+ free(isbi->save.a->data.hybrid);
+ }
+ free(isbi);
+ isbi=isb;
+ }
+
+ ickmt_prev->next = ickmt_cur->next;
+ if(ickmt_cur->next == ickmt_cur)
+ {
+ free(ickmt_cur);
+ exit(0);
+ }
+ else
+ {
+ /* We need to run about half of nextthread. So we pass in a 2 for
+ flags and tell it to skip the first half. */
+ free(ickmt_cur);
+ ickmt_cur = ickmt_prev;
+ nextthread(dummy, -1, 2); /* dummy is not used by nextthread */
+ lose(E778, -1, (char *) NULL); /* nextthread does not return */
+ }
+}
+
+/* This function does not return in the normal fashion, but by a nonlocal
+ goto to a mysterious location, possibly in multicome1 but possibly in
+ the degenerated code. From the point of view of libickmt.a, we're going
+ to a piece of code that doesn't even exist yet! The general ugliness of
+ INTERCAL multithreading pulls out all the stops when it comes to using
+ unusual and confusing C control structures. It is important to remember
+ that longjmp clobbers all auto variables that have changed since the
+ corresponding setjmp. */
+
+/* In this Threaded INTERCAL implementation, data is saved in a linked ring
+ of threads. A thread runs for a command, then all the data pointers are
+ changed, saving the old ones. This is an improvement on an earlier attempt
+ of mine in which the values themselves were copied, but is still less
+ efficient than Malcom Ryan's method (which didn't involve copying things
+ about except when forking). However, I justify this by saying that it leaves
+ as much existing code as possible untouched, which is helpful for single-
+ thread compatibility, modifying the code in feh.c without an understanding
+ of multithread issues, and because I'm lazy. It also makes the rest of the
+ program shorter. */
+void nextthread(jmp_buf pc, int errlineno, int flags)
+{ /* flags | 1 means save this thread.
+ flags | 2 means load the next thread.
+ flags | 4 means don't change thread. */
+ if(errlineno > -1 && ickmt_cur->next == ickmt_cur && !choicing) longjmp(pc,1);
+ /* If we only have 1 thread, just continue with it. Otherwise: */
+
+ if(!(flags&1)) goto advancethread;
+ /* OK, so I've spaghettified this procedure slightly by using goto
+ instead of if. But I was so deep into figuring out setjmp/longjmp,
+ a goto seemed crystal-clear by comparison. */
+
+ /* save variables */
+ ickmt_cur->varforget[0] = onespots;
+ ickmt_cur->varforget[1] = twospots;
+ ickmt_cur->varforget[2] = tails;
+ ickmt_cur->varforget[3] = hybrids;
+ ickmt_cur->varforget[4] = oneforget;
+ ickmt_cur->varforget[5] = twoforget;
+ ickmt_cur->varforget[6] = tailforget;
+ ickmt_cur->varforget[7] = hyforget;
+
+ /* save NEXT stack */
+ ickmt_cur->nextstack = next;
+ ickmt_cur->nextpointer = nextindex;
+
+ /* save stashbox */
+ ickmt_cur->sb = first;
+
+ /* save choicepoints */
+ if(!choicing) ickmt_cur->choicepoint = topchoice;
+
+ /* save comefrom information */
+ memcpy(ickmt_cur->cjb, cjb, sizeof(jmp_buf));
+ ickmt_cur->ccfc = ccfc;
+ ickmt_cur->skipto = skipto;
+
+ /* save program counter */
+ memcpy(ickmt_cur->pc, pc, sizeof(jmp_buf));
+ /* And another thing about setjmp/longjmp. A jmp_buf
+ acts like a structure that passes itself around by
+ reference. However, it cannot be assigned, although
+ just about everything else in C can be, although it
+ can be copied with memcpy (what I'm doing in the line
+ above - remember it passes itself around by reference).
+ Generally speaking, it's some sort of array,
+ even though some implementors use a 1-element array.
+ The exact representation of jmp_buf is one of the most
+ implementation-dependent things in C (I've seen both
+ a 1-element array of structure and an int[12].) */
+
+ advancethread:
+ /* change thread */
+ if(!(flags&4))
+ {
+ ickmt_prev = ickmt_cur;
+ ickmt_cur = ickmt_cur->next;
+ }
+
+ if(!(flags&2)) goto returnjmp;
+
+ /* load variables */
+ onespots = ickmt_cur->varforget[0];
+ twospots = ickmt_cur->varforget[1];
+ tails = ickmt_cur->varforget[2];
+ hybrids = ickmt_cur->varforget[3];
+ oneforget = ickmt_cur->varforget[4];
+ twoforget = ickmt_cur->varforget[5];
+ tailforget = ickmt_cur->varforget[6];
+ hyforget = ickmt_cur->varforget[7];
+
+ /* load NEXT stack */
+ next = ickmt_cur->nextstack;
+ nextindex = ickmt_cur->nextpointer;
+
+ /* load choicepoints */
+ if(!choicing) topchoice = ickmt_cur->choicepoint;
+
+ /* load stashbox */
+ first = ickmt_cur->sb;
+
+ /* load comefrom information */
+ memcpy(cjb, ickmt_cur->cjb, sizeof(jmp_buf));
+ ccfc = ickmt_cur->ccfc;
+ skipto = ickmt_cur->skipto;
+
+ returnjmp:
+ /* return to the new current thread's program counter */
+ if(choicing==2) choicing = 0;
+ longjmp(ickmt_cur->pc, 1);
+}
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<link rev="made" href="mailto:esr@snark.thyrsus.com" />
-<link rel="stylesheet" href="/~esr/sitestyle.css" type="text/css" />
-<meta name="description" content="Escape now before the madness takes you!" />
-<meta name="keywords" content="" />
-<meta name="MSSmartTagsPreventParsing" content="TRUE" />
-<title>The INTERCAL Resources Page</title>
-</head>
-<body>
-
-<div id="Header">
-<table width="100%" cellpadding="0" summary="Canned page header">
-<tr>
-<td>
-The INTERCAL Resources Page
-</td>
-<td align="right">
-<script language="JavaScript" src="/~esr/datestamp.js"></script>
-</td>
-</tr>
-</table>
-</div>
-
-<div id="Menu">
- <hr/>
- <a href="/~esr" title="My home page">Home Page</a><br />
- <a href="/~esr/sitemap.html" title="Map of the site">Site Map</a><br />
- <a href="/~esr/software.html" title="Software I maintain">Software</a><br />
- <a href="/~esr/projects.html" title="My projects">Projects</a><br />
- <a href="/~esr/faqs/" title="My FAQ documents">HOWTOs</a><br />
- <a href="/~esr/writings/" title="Essays and ruminations">Essays</a><br />
- <a href="/~esr/personal.html" title="Portrait of the author">Personal</a><br />
- <a href="http://www.ibiblio.org/esrblog/">Weblog</a><br/>
- <a href="/~esr/netfreedom/">Freedom!</a><br />
- <a href="/~esr/guns/">Firearms!</a><br />
- <hr/>
-</div>
-
-<div id="Content">
-
-<p>Beware! If you aren't a hard-core hacker, you'd best surf right
-back where you came from <em>now</em>. Nothing but twisted
-technical yuks and an inexorable descent into brain-sucking
-obsession awaits beyond this point. <strong>You have been
-warned.</strong></p>
-
-<h1 class="c1">Abandon All Sanity, Ye Who Enter Here</h1>
-
-<p>So, you think you've seen it all, eh?</p>
-
-<p>OK. You've coded in C. You've hacked in LISP. Fortran and BASIC
-hold no terrors for you. You write Emacs modes for fun. You eat
-assemblers for breakfast. You're fluent in half a dozen languages
-nobody but a handful of übergeeks have ever heard of. You grok
-TECO. Possibly you even know <i><shudder></i> COBOL.</p>
-
-<p>Maybe you're ready for the ultimate challenge...INTERCAL.</p>
-
-<p>INTERCAL. The language designed to be Turing-complete but as
-fundamentally unlike any existing language as possible. Expressions
-that look like line noise. Control constructs that will make you
-gasp, make you laugh, and possibly make you hurl. Data structures?
-We don't need no steenking data structures!</p>
-
-<p>INTERCAL. Designed very early one May morning in 1972 by two
-hackers who are still trying to live it down. Initially implemented
-on an IBM 360 running batch SPITBOL. Described by a manual that
-circulated for years after the short life of the first
-implementation, reducing strong men to tears (of laughter). Revived
-in 1990 by the C-INTERCAL compiler, and now the center of an
-international community of technomasochists.</p>
-
-<p>INTERCAL. Now you, too, can be a part of the madness.</p>
-
-<p>Read what <a href="nelson.html">Ted Nelson</a> had to say...)</p>
-
-<h1 class="c1">INTERCAL Resources</h1>
-
-<h2>Documentation</h2>
-
-<p>You can download either a <a
-href="intercal.ps.gz">Postscript</a> or <a
-href="http://www.catb.org/~esr/intercal/intercal.txt.gz">flat
-text</a> version of the Revised INTERCAL Manual here. Postscript is
-recommended, as the manual now includes figures and diagrams until
-recently unseen by any but the small handful with paper copies.</p>
-
-<h2>An INTERCAL paper</h2>
-
-<p>Alexander Garrett wrote a <a href="paper.html">paper</a> on
-INTERCAL for his Spring 1997 Programming Languages: Theory and
-Design class. Alexander writes:</p>
-
-<blockquote class="c2">The obvious choice was INTERCAL (I'm still
-quite surprised that I'm the only one who picked it -- most people
-did Java??). Anyway, it was not favourably received...when [the
-professor] handed it back, he said, "Ah. I see you're someone with
-a sense of humour. Unfortunately for you, I'm not."</blockquote>
-
-<p>We have corrected two typos (misspellings of "Malvernite" and
-"compiler") in this copy.</p>
-
-<h2>Implementations</h2>
-
-<p>You can download the latest version of the <a
-href="http://www.catb.org/~esr/intercal/intercal-0.23.tar.gz">C-INTERCAL
-distribution</a> here (includes the manual and sample programs).
-Requires either bison or yacc and flex or lex. Builds and runs
-nicely under any ANSI/POSIX platform, including Linux and the free
-BSD versions.</p>
-
-<p>You can download a binary archive of William Walter Patterson's
-<a href="ick15d12.zip">port of INTERCAL 0.15 for DOS</a>, which
-finally has the programming language it truly deserves.</p>
-
-<p>There is a Java implementation of INTERCAL with COME FROM -- see
-the <a
-href="http://studwww.ira.uka.de/~s_sperli/jintercal/">J-INTERCAL</a>
-project page.</p>
-
-<h2>Other Tools</h2>
-
-<p>Jonathan Ferro has written an <a
-href="calc-intercal.el">Intercal calculator mode</a> for Emacs.</p>
-
-<p>You can find out more about Kevin Stock's implementation of <a
-href="iperl.html">INTERCAL functions for PERL</a>.</p>
-
-<p>Alexander Garrett has written a <a
-href="http://www.demiurge.org/alex/computer/index.html">Java class
-implementing the INTERCAL math library</a>.</p>
-
-<h2>Home Pages</h2>
-
-<p>Louis Howell, possibly the most accomplished C-INTERCAL hacker
-not yet permanently institutionalized, has his own INTERCAL page,
-<a href="http://www.webcom.com/nazgul/intercal.html">The
-Pit</a>.</p>
-
-<p>Brian Raiter, who edited the revised version of the INTERCAL
-manual available in HTML above, maintains a good <a
-href="http://www.muppetlabs.com/~breadbox/intercal">INTERCAL
-page</a>.</p>
-
-<p>Jacob Mandelson also has an <a
-href="http://www.ugcs.caltech.edu/~jlm/intercal.html">INTERCAL
-Page</a>.</p>
-
-<p>(The code from all of these home pages has been folded into the
-INTERCAL distribution.)</p>
-
-<h2>Other Resources</h2>
-
-<p>There is an <a
-href="news:alt.lang.intercal">alt.lang.intercal</a> Usenet
-newsgroup.</p>
-
-<p>INTERCAL has even shown up once in the print media. Here's a
-transcript of an <a href="stross.html">article by Charles
-Stross.</a>.</p>
-
-<h1>Extension Proposals</h1>
-
-<p>There have been various proposals to extend INTERCAL to support
-various trendy modern programming concepts. Of these, perhaps the
-most impressively gaga is Malcolm Ryan's proposal for <a
-href="http://www.cse.unsw.edu.au/~malcolmr/threaded_intercal.html">Threaded
-Intercal</a>.</p>
-
-<p>Andrew Arensburger is developing a proposal for <a
-href="overloading.html">operand overloading</a> in INTERCAL.</p>
-
-<p>The fine folks at <a href="http://www.assurdo.com/">Assurdo
-Technologies</a> have released an INTERCAL implementation in Perl.
-One of them writes ``[We're] gearing up for a manifesto. Our goal
-is to position CLC-INTERCAL as the logical successor to Java.
-(After all, it's faster, more functional, and provides better job
-security for programmers!) But first we have to get the editor
-environment (TECO) sorted out, write an ORB, and provide some
-mechanism for generating XML (probably via custom obfuscated troff
-macros).''</p>
-
-<h1>Other Interesting Languages</h1>
-
-<ul>
-<li><a href="http://www.catseye.mb.ca/esoteric/">Befunge</a> --
-Computer Programming in multiple Directions, Dimensions, and
-Topologies.</li>
-
-<li><a href="http://www.catseye.mb.ca/esoteric/bf/">BrainF***</a>
--- An 8-instruction Turing-complete computer language.</li>
-
-<li><a
-href="http://www.mines.edu/students/b/bolmstea/malbolge/index.html">
-Malebolge</a> -- Programming from Hell.</li>
-
-<li><a
-href="http://www.eleves.ens.fr:8080/home/madore/programs/unlambda/">
-Unlambda</a> -- functional programming taken to a horrifying
-extreme.</li>
-</ul>
-
-<h1 class="c1">Related Links</h1>
-
-<p>If INTERCAL interests you, you may want to check out the <a
-href="http://www.catb.org/jargon">Jargon File</a> and the <a
-href="http://www.catb.org/retro">Retrocomputing Museum</a>. Both
-these pages and this one are maintained by <a
-href="http://www.catb.org/~esr">Eric S. Raymond</a>, who also
-maintains a large collection of open-source software you may find
-stimulating.</p>
-
-</div>
-</body>
-</html>
-<!--
-Local Variables:
-compile-command: "(cd ~/WWW; upload intercal/index.html)"
-End:
--->
-
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta name="generator"
-content="HTML Tidy for Linux/x86 (vers 1st February 2002), see www.w3.org" />
-<title>iperl - INTERCAL in Perl</title>
-<meta name="description" content="INTERCAL in Perl. The horror. The horror..." />
-<style type="text/css">
-/*<![CDATA[*/
- div.c1 {text-align: center}
-/*]]>*/
-</style>
-</head>
-<body>
-<table width="100%" cellpadding="0" summary="Canned page header">
-<tr>
-<td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
-<td width="30%" align="center">Up to <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:24:24 $</td>
-</tr></table>
-<hr />
-<h1 class="c1">Using INTERCAL in Perl</h1>
-
-<p><a href="mailto:KStock@Unforgettable.Com">Kevin Stock</a> posted
-the following to comp.sources.misc (Feb 1991):</p>
-
-<blockquote>
-<p>I guess I must be cracking up. I've been trying to learn how to
-use the usersubs stuff in Perl, and also how to program in
-INTERCAL. Anyway, I ended up combining the two!</p>
-
-<p>The following shar file is an instant mix package (just add
-Perl) for Iperl, which is Perl plus the INTERCAL operators. There's
-even a manual page - what more could you want?</p>
-</blockquote>
-
-<p>Here is the contents of the README (from the archive):</p>
-
-<blockquote>
-<p>I think this belongs somewhere alongside such films as "Abbot
-and Costello meet Frankenstein's Monster". But, here it is anyway
-...</p>
-
-<p>PERL MEETS INTERCAL.</p>
-
-<p>In this archive, you will find the usersubs stuff to add
-INTERCAL functions to Perl. Unshar it somewhere (/dev/null would
-probably do), and run make. (You may need to alter SRC in the
-Makefile).</p>
-
-<p>The resulting binary, iperl, will work just like perl with the
-addition of the following INTERCAL functions:</p>
-
-<ul>
-<li>and16</li>
-
-<li>or16</li>
-
-<li>xor16</li>
-
-<li>and32</li>
-
-<li>or32</li>
-
-<li>xor32</li>
-
-<li>mingle</li>
-
-<li>select</li>
-</ul>
-
-<p>The test file, op.ical, will run tests to ensure that the
-functions work. This may be done using "make test".</p>
-
-<p>The program iperlsh just reads in perl expressions (one per
-line) and evaluates them.</p>
-</blockquote>
-
-<p><a href="iperl.tar.gz">Download iperl.tar.gz.</a></p>
-
-<p>Or, here is the <a
-href="http://src.doc.ic.ac.uk/public/pub/usenet/comp.sources.misc/volume16/intercal.pl/part01.gz">
-Or, original shar</a> from the usenet archives.</p>
-
-<p><a href="index.html">Return to the INTERCAL Resources
-Page.</a></p>
-
-<hr />
-<table width="100%" cellpadding="0" summary="Canned page footer">
-<tr>
-<td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
-<td width="30%" align="center">Up to <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:24:24 $</td>
-</tr></table>
-
-<br clear="left"/>
-<address>Eric S. Raymond <a
-href="mailto:esr@thyrsus.com"><esr@snark.thyrsus.com></a></address>
-</body>
-</html>
-
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<link rev="made" href="mailto:esr@snark.thyrsus.com" />
-<meta name="description" content="" />
-<meta name="keywords" content="" />
-<meta name="MSSmartTagsPreventParsing" content="TRUE" />
-<title>Ted Nelson comments....</title>
-<style type="text/css">
-/*<![CDATA[*/
- div.c1 {text-align: center}
-/*]]>*/
-</style>
-</head>
-<body>
-<table width="100%" cellpadding="0" summary="Canned page header">
-<tr>
-<td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:35:36 $</td>
-</tr>
-</table>
-<hr />
-<h1 class="c1">Ted Nelson Comments...</h1>
-
-<pre>
-From ted@xanadu.net Wed Dec 2 11:50:17 1998
-Return-Path: <ted@xanadu.net>
-Received: from localhost (esr@localhost [127.0.0.1])
- by snark.thyrsus.com (8.8.7/8.8.7) with ESMTP id LAA27208
- for <esr@localhost>; Wed, 2 Dec 1998 11:50:15 -0500
-Received: from imap.ccil.org
- by localhost with IMAP (fetchmail-4.6.9)
- for esr@localhost (multi-drop); Wed, 02 Dec 1998 16:50:15 +0000 (UTC)
-Received: from mail.sfc.keio.ac.jp (mail.sfc.keio.ac.jp [133.27.4.120])
- by locke.ccil.org (8.8.5/8.8.5) with ESMTP id MAA28871
- for <esr@thyrsus.com>; Wed, 2 Dec 1998 12:13:54 -0500 (EST)
-Received: from servix.sfc.keio.ac.jp (servix [133.27.104.66])
- by mail.sfc.keio.ac.jp (8.9.1a/3.6Wbeta7-SFC) with SMTP id BAA15833;
- Thu, 3 Dec 1998 01:43:37 +0900 (JST)
-Message-Id: <3.0.3.32.19981203012655.01d68d20@mail.sfc.keio.ac.jp>
-X-Sender: ted@mail.sfc.keio.ac.jp
-X-Mailer: QUALCOMM Windows Eudora Light Version 3.0.3 (32)
-Date: Thu, 03 Dec 1998 01:26:55 +0900
-To: "Eric S. Raymond" <esr@thyrsus.com>
-From: Ted Nelson <ted@xanadu.net>
-Subject: COME FROM statement considered asymmetrical (CFasym.d6
-Cc: ted@sfc.keio.ac.jp, marlene@xanadu.net, erik@xanadu.net, xanni@xanadu.net,
- eharter@din.or.jp, markm@ricochet.net,
- drexler@imm.org (K. Eric Drexler), john@iecc.com, margy@iecc.com,
- jordan@iecc.com, Nat Kuhn <nat@iecc.com>,
- Carol Baroudi <carol@iecc.com>, sw@tiac.net,
- Charles Harris <xchar@worldnet.att.net>, fen@comedia.com,
- "John Pettitt" <jpp@beyond.com>, scriven@aol.com, colias@ascii.co.jp,
- DickHeiser@aol.com, braun@sfo.com, penrose@sfc.keio.ac.jp,
- jpost@earthlink.net (Jonathan Vos Post), farber@cis.upenn.edu
-Mime-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Status: RO
-Content-Length: 2980
-Lines: 64
-
-Hi Eric--
-
-I consider it marvelous that you have enhanced the world's
- most obscure computer language, Intercal, by adding
- Peter Ingerman's COME FROM statement.
-
-However, I should point out that COME FROM is not
- a precise inverse of the GO TO statement. True,
- they are similar when each is one-to-one,
- i.e. when each GOTO target/sink is pointed to by
- only one GO TO, and each COME FROM receiver
- is the unique recipient of its antecedent donor routine.
-
-But the many-to-one case is asymmetrical: a number of
- different GOTOs can have the same target, but a
- COME FROM statement can only have a unique source.
- And conversely: in the case of the GO TO, it is the antecedent
- routine which can have only one target but can share it
- with others; while in the case of the COME FROM,
- it is the successor routines which can only share a single source.
-
-This *could* be considered to be a deeper symmetry:
- the possible many-to-one relation of the GO TO could be seen
- as remapping into the possible one-to-many use of the COME FROM.
-
-But the asymmetry is stronger than that, being temporal
- (and in some sense causative-- but this discussion must
- skirt theology, and we know that A Programmer exists)--:
- GO TO may only be temporally one-to-one or many-to-one,
- while COME FROM may only be temporally one-to-one
- or one-to-many. If we took sexual behavior as an analogy,
- the possible many-to-one relation of the GO TO is like being
- gang-banged, with a relatively small variety of possible outcomes
- (progeny), while the COME FROM is more like a bee going
- from... oh, never mind.
-
-I hope this brings some measure of analytic rigor to a hitherto,
- and justifiably, unknown problem area, where such rigor may
- hitherto have been, and still may perhaps be, unwelcome.
-
-Best regards, Ted
-Gee, maybe I should submit this to Communications of the ACM...
-
-
-____________________________________________________
-Theodor Holm Nelson, Visiting Professor of Environmental Information
- Keio University, Shonan Fujisawa Campus, Fujisawa, Japan
- Home Fax from USA: 011-81-466-46-7368 (If in Japan, 0466-46-7368)
-http://www.sfc.keio.ac.jp/~ted/ (Professorial page)
-_____________________________________________________
-Permanent: Project Xanadu, 3020 Bridgeway #295, Sausalito CA 94965
- Tel. 415/ 331-4422, fax 415/332-0136
-http://www.xanadu.net (see also Professorial page, above)
-PERMANENT E-MAIL: ted@xanadu.net
-_____________________________________________________
-Quotation of the day, 98.12.02:
-Mike McNally, president of the Air Traffic Controllers Union, yesterday
-assured the press that air traffic controllers can take over from computers
-in case Y2K bugs hit the system.
- "I'm not trying to indicate that when our computers shut down that
-everything is hunky-dory. There is a major transition period where the
-heart is beating and things are happening fast, and people are yelling and
-screaming to try to get a handle on it," he said. (cnn.com, dateline
-98.12.01)
-
-</pre>
-
-
-<hr />
-<table width="100%" cellpadding="0" summary="Canned page footer">
-<tr>
-<td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:35:36 $</td>
-</tr>
-</table>
-
-<br clear="left" />
-<address>Eric S. Raymond <a
-href="mailto:esr@thyrsus.com"><esr@thyrsus.com></a></address>
-</body>
-</html>
-
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta name="generator"
-content="HTML Tidy for Linux/x86 (vers 1st February 2002), see www.w3.org" />
-<link rev="made" href="mailto:esr@snark.thyrsus.com" />
-<meta name="description"
-content="Overloading proposal for INTERCAL" />
-<meta name="keywords" content="INTERCAL" />
-<title>Overloading proposal for INTERCAL</title>
-<style type="text/css">
-/*<![CDATA[*/
- h1.c1 {text-align: center}
-/*]]>*/
-</style>
-</head>
-<body>
-<table width="100%" cellpadding="0" summary="Canned page header">
-<tr>
-<td width="30%">Back to <a href="index.html">Intercal Home
-Page</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:30:43 $</td>
-</tr>
-</table>
-
-<hr />
-<h1 class="c1">Operand Overloading in INTERCAL</h1>
-
-<p>Andrew Arensburger <arensb@cfar.umd.edu> writes:</p>
-
-<p>While rereading the INTERCAL reference manual, it occurred to me
-that INTERCAL is a bit dated, since the languages whose features it
-avoids (Fortran, COBOL, etc.) are pretty much dead. Shouldn't
-INTERCAL start avoiding features found in some more modern
-languages, like C++, Java and Perl?</p>
-
-<p>In this vein, let me suggest a direction for future development:
-overloaded operands. I suggest the following syntax:</p>
-
-<pre>
- <var>/<expr>
- <expr1>\<expr2>
-</pre>
-
-<p>In the first form, <var> is a variable (16- or 32-bit,
-scalar or array). Subsequently, any time it appears as an operand
-to $ , ~ , & , V , or ? , it will be silently replaced by
-<expr>. Thus,</p>
-
-<pre>
- DO .7/#&77
- DO :8<-.7
-</pre>
-
-<p>will have the same effect as</p>
-
-<pre>
- DO :8<-#&77
-</pre>
-
-<p>In the second form, <expr1> is a 32-bit expression,
-divided into two 16-bit numbers (high 16 bits and low 16 bite).
-This defines a range. Any time a variable whose number is in the
-range thus defined appears as an operand, it is replaced with the
-value of <expr2>.</p>
-
-<p>Furthermore, any time the special token ) appears in
-<expr2>, it is replaced with the number of the variable being
-affected. Thus,</p>
-
-<pre>
- DO #196608\#99
-</pre>
-
-<p>will affect variables .3 through .10, :3 through :10, ,3 through
-,10 , and ;3 through ;10 , replacing them with #99 whenever they
-appear as an operand to $ , ~ , & , V , or ? .</p>
-
-<pre>
- DO #196608\;)SUB".&)"
- DO :1<-.9
-</pre>
-
-<p>has the same effect as</p>
-
-<pre>
- DO :1<-;9SUB".&9"
-</pre>
-
-<p>Since overloading is not indicated by a keyword, there can be no
-PLEASE ABSTAIN FROM OVERLOADING directive, but overloading can be
-undone by mapping variable numbers back to their original
-values.</p>
-
-<p>There are, of course, various issues that still need to be
-ironed out, but it seems to me that operand overloading can be a
-powerful technique, on a par with Perl closures or Java's
-on-the-fly class definitions.</p>
-
-<hr />
-<table width="100%" cellpadding="0" summary="Canned page footer">
-<tr>
-<td width="30%">Back to <a href="index.html">INTERCAL Home
-Page</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:30:43 $</td>
-</tr>
-</table>
-
-<br clear="left" />
-<address>Eric S. Raymond <a
-href="mailto:esr@thyrsus.com"><esr@snark.thyrsus.com></a></address>
-</body>
-</html>
-
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>Abstraction and Modularity in INTERCAL</title>
-<style type="text/css">
-/*<![CDATA[*/
- body {
- background-color: #FFFFFF;
- }
- span.c1 {font-size: 80%}
-/*]]>*/
-</style>
-</head>
-<body>
-<br />
-<br />
-<br />
-<blockquote>
-<p><tt><img src="notfunny.png" align="right" alt="Not Funny!" />
-Abstraction and Modularity in INTERCAL<br />
-D. Alexander Garrett<br />
-CS-538: Theory and Design of Programming Languages.<br
-clear="all" />
-</tt></p>
-
-<p><tt>"<em>And remember, when you look into the pit, the pit looks
-back into you.</em>"<br />
-         -- Anonymous
-INTERCAL hacker</tt></p>
-
-<p><tt>On May 26, 1972, two students at Princeton University took
-the programming community if not by storm, at least by mild
-sprinkle when they released INTERCAL[<a href="#note1">1</a>]. They
-were summarily dismissed from Princeton and forced to flee to a
-small banana republic where they refine the finer points of the
-language on political prisoners. This is, of course, strictly
-against the Geneva Convention, but as you will see, INTERCAL
-strives to be an unconventional language.</tt></p>
-
-<p><tt>Eighteen years later, while suffering from a paralytic
-attack of ennui, the Mad Malvernite J. Lapin perpetrated a hack of
-untold consequences upon the world by rereleasing INTERCAL under
-UN*X, which he renamed C-INTERCAL. Unfortunately, J. Lapin appears
-to be a pseudonym, so nobody can determine upon whose shoulders the
-blame should rest for such malfeasance. However, some people
-suspect that the rerelease of INTERCAL heralds the time when the
-Old Ones shall wake from their sleep deep beneath the sea and shall
-rule over the earth for 2^32 years, befuddling men's minds and
-forcing them to use buggy overpriced software[<a
-href="#note2">2</a>].</tt></p>
-
-<p><tt>But I'm not here to talk about eschatology, I'm here to talk
-about modularity and abstraction. Well, believe me, you couldn't
-have designed a language more abstract than INTERCAL. To begin
-with, one of the most important aspects of abstraction is
-information hiding. Information hiding is a time honoured tradition
-of computer programmers, although sometimes it goes by its other
-name, "job security". The idea is to make your code as obscure as
-possible, hiding any possible information, so your employer
-couldn't fire you and hire some junior birdman mailboy to maintain
-your code. INTERCAL doesn't only hide information it actively
-distorts it. For example, the easiest way to store the value of
-65536 in a 32-bit INTERCAL variable is:</tt></p>
-
-<blockquote><tt>DO:1<-#0$#256</tt></blockquote>
-
-<p><tt>If that's the easiest way, imagine the power at your
-fingertips if you're trying to be deliberately obscure! To further
-demonstrate, if you were to write a program in INTERCAL which reads
-in 32-bit unsigned integers, treats them as signed 2's complement
-numbers, and prints out their absolute values, it would take about
-22 lines of code and between 15 and 30 minutes to write, whereas
-the same program could be written in a single line of SNOBOL or APL
-requiring about a minute to write both[<a href="#note3">3</a>]. So
-not only does INTERCAL allow the programmer to generate twenty
-times as much code as most other languages, making the programmer
-appear much more productive than his colleagues forced to program
-in a terse language, an INTERCAL program also takes much longer to
-write, allowing for more Quake-breaks. And as an added bonus, when
-the programmer is done, the information is so cleverly hidden that
-not even Sparky the Wonder Dog could find it, and she can find
-gravy in a cesspool! This allows the programmer to take even more
-Quake-breaks, as management doesn't dare fire such an important
-asset to the company.</tt></p>
-
-<p><tt>In addition to information hiding, multinational support is
-also an important part of abstraction. As information exchange
-causes the globe to shrink,[<a href="#note4">4</a>] it's important
-that programming languages are able to support a wide variety of
-different cultures. To that end, INTERCAL took the obvious step.
-Since the number systems of different countries are different from
-other different countries where the relationship between the
-different countries can be symmetric or transitive, it cannot, for
-obvious reasons, be reflexive, INTERCAL has implemented a different
-number system. Instead of using numerals, all input is done by
-typing in the name of the number. For example, if you wanted to
-feed the value of 523 to an INTERCAL program, the input would look
-like "FIVE TWO THREE."[<a href="#note5">5</a>] Additionally,
-INTERCAL will also accept the value of OH for zero and NINER for 9.
-Recognising that INTERCAL would have multicultural scope, the
-implementors implemented number support for input digits in
-Sanskrit, Basque, Tagalog, Classical Nahuatl, Georgian, Kwakiutl,
-and Volapuk.</tt></p>
-
-<p><tt>Until the new INTERCAL compiler with better RYM[<a
-href="#note6">6</a>] access comes out, the old compiler has no way
-of knowing which language you are familiar with and thus it doesn't
-know what language to produce its output in[<a
-href="#note7">7</a>]. INTERCAL elegantly solves this problem by
-producing its output in Roman numerals, under the assumption that
-when Rome was at the height of its strength, half the world was
-under its dominion, so the comprehension of Roman numerals is part
-of our racial memory.</tt></p>
-
-<p><tt>In addition to being a versatile and truly international
-language, INTERCAL is also very simple. For example, in most
-languages the logical operators AND, OR, and XOR are binary, i.e.,
-they require two operands to operate on. In INTERCAL, AND, OR, and
-XOR are unary operators, thereby halving the potential for
-pernicious logical errors. AND is represented by the ampersand
-(&), OR by the inverted, baseless isoceles triangle (V) and XOR
-by the what[<a href="#note8">8</a>] (?). The way the unary
-operators work is to perform the required operation on adjacent
-bits in the variable. Thus, #&77 (binary = 1001101) is binary
-0000000000000100 = 4, #V77 is binary 1000000001101111 = 32879, and
-#?77 is binary 1000000001101011 = 32875.[<a
-href="#note9">9</a>]</tt></p>
-
-<p><tt>Ever since Dijkstra's seminal paper "Use of GOTO Considered
-Harmful" was published in Communications of the ACM, there has been
-a hue and cry against the use of GOTO. INTERCAL recognises the
-importance of structured programming and rebukes the GOTO, saying
-<em>retro me iad</em>[<a href="#note10">10</a>]. In fact, the
-implementors of INTERCAL feel so strongly about the poor
-programming habits that GOTO encourages, that they implemented
-GOTO's opposite number, COME FROM. Thus if you had a program which
-looked similar to below:</tt></p>
-
-<blockquote><tt>(1) PLEASE <YOUR STATEMENT HERE><br />
-</tt>
-
-<blockquote>.<br />
- .<br />
- .</blockquote>
-
-<tt>(2) DO COME FROM (1)</tt></blockquote>
-
-<p><tt>anytime the program executed the statement at label 1, it
-would immediately jump to the statement at label 2 without
-executing any of the intervening statements. This is very difficult
-to follow and requires considerable expertise to use correctly and
-makes the code almost impossible to follow. That's right, baby --
-information hiding.</tt></p>
-
-<p><tt>One of the big changes to C that Stroustroup made when he
-created C++ was the use of const data types, which kept the
-programmer from inadvertently changing the values of variables
-which shouldn't.[<a href="#note11">11</a>] The creators of INTERCAL
-recognised the need for this way before Stroustroup became Mr.
-Fancy Pants and so they put the IGNORE statement into the language.
-Any variables or arrays named in a list following the DO IGNORE
-directive will effectively become read-only. Their value can be
-used in operations and assigned to other variables, but any attempt
-to assign a value to a variable being IGNOREd will be met with a
-contempt so profound that the compiler will pass over it in utter
-silence. Of course, there may be a time when you want to cast away
-the constancy of variable, and in that case, you would use the
-REMEMBER directive. Any variable which is REMEMBERed will stay so
-until it is IGNORED. Future versions of the language may have a
-SNUB directive which when used upon a variable will cause it to
-IGNORE any attempts to write to it, even if it is REMEMBERed. The
-only way to make a SNUBbed variable writeable again is through the
-use of the APOLOGIZE statement which has roughly a fifty percent
-chance of working[<a href="#note12">12</a>]. The DON'T BE LIKE
-THAT. YOU REMIND ME OF MY MOTHER statement is currently a valid
-statement in INTERCAL though if used upon an IGNOREd variable will
-not cause a change of state in that variable, i.e., it will still
-be IGNOREd.[<a href="#note13">13</a>]</tt></p>
-
-<p><tt>INTERCAL is not even vaguely modular and nothing I can say
-would persuade you that it was.</tt></p>
-
-<p><tt>INTERCAL is a very dynamic, constantly evolving[<a
-href="#note14">14</a>] language which shows much promise for future
-generations of programmers. With languages like Visual Basic and
-Java out there which allow people who can hardly tie their shoes to
-write complicated GUI WWW browsers, people will begin to think that
-programmers aren't wizards and should be earning less than that
-nice young man at the local fast food joint who asks them if they'd
-like fries with that. Hmmm... as long as I have a couple of
-paragraphs left, I may as well mention that INTERCAL is fully
-portable, as the INTERCAL compiler first generates native C code
-and then compiles that. The INTERCAL compiler, itself, is written
-in C and is easily portable. There's even an INTERCAL major mode
-for emacs which will help you maintain the proper balance of
-PLEASE, DO, and PLEASE DO statements.[<a
-href="#note15">15</a>]</tt></p>
-
-<p><tt>References</tt><br />
-</p>
-
-<blockquote><tt>THE INTERCAL PROGRAMMING LANGUAGE REVISED REFERENCE
-MANUAL, Woods, Donald R. and Lyon, James M. Revised by Howell,
-Louis and Raymond, Eric S.<br />
- My pineal gland.</tt></blockquote>
-
-<p><tt>Afterword</tt><br />
-</p>
-
-<blockquote><tt>The author of this paper is currently residing in a
-home for the criminally insane after attempting to rewrite the
-Linux kernel in Object Disoriented INTERCAL.</tt></blockquote>
-
-<br />
-<br />
-<br />
-<hr width="30%" />
-<span class="c1"><tt>[<a id="note1" name="note1">1</a>] which
-stands for "Compiler Language With No Pronouncable Acronym",
-obviously.<br />
-[<a id="note2" name="note2">2</a>] There's a small sect of
-Billyites who, pointing to Microsoft, claim that this has already
-happened.<br />
-[<a id="note3" name="note3">3</a>]These examples shamelessly
-cribbed from THE INTERCAL PROGRAMMING LANGUAGE REVISED REFERENCE
-MANUAL, page 2.<br />
-[<a id="note4" name="note4">4</a>]It has been demonstrated that
-information exchange causes the release of a virtual particle
-called a metron. As the metron leaves the local system it was
-originally a part of, the system shrinks by an arbitrary amount
-which is directly proportional to the tightness of Tom Jones'
-pants. As more and more information is exchanged, an increasing
-number of metrons are released, and as Tom Jones' pants keep
-getting tighter and tighter, the local system, in this case, the
-planet, is shrinking without bound. What does this mean to you? Not
-much, really. Actually, I'm kind of sorry I brought it up. Just
-forget I mentioned it.<br />
-[<a id="note5" name="note5">5</a>]It might also look different,
-depending on the font your terminal uses.<br />
-[<a id="note6" name="note6">6</a>]Read Your Mind<br />
-[<a id="note7" name="note7">7</a>]True, it could a) look at your
-input and produce output that matches the language or b) you could
-include compiler directives mandating an output language. Well, a)
-would require doubling the size of the system library which is
-definitely the Wrong Thing and b) would require adding more to the
-compiler which is definitely the Wrong Thing.<br />
-[<a id="note8" name="note8">8</a>]Which due to the popularity of
-the movie, The Usual Suspects, may have its name changed to the
-"what the fuh", pending the creation of an ANSI committee to look
-into the matter, cubic cubits upon cubic cubits of jargonised
-deliberations interspersed with sheets of paper saying, "this page
-intensionally left blank", and at least one best selling pulp
-novelisation of the process written either by Jackie Collins or
-Donald Knuth (or both).<br />
-[<a id="note9" name="note9">9</a>]You may be wondering about the
-splat (#) in front of each number. That's good. It shows that you
-have a curious mind. However, I'm not going to tell you what it
-means. That's called "information hiding".<br />
-[<a id="note10" name="note10">10</a>]"get thee behind me, GOTO,"
-obviously<br />
-[<a id="note11" name="note11">11</a>]Somebody's law of programming
-seen on fortune: "Constants aren't; Variables don't."<br />
-[<a id="note12" name="note12">12</a>]The surest way to get a
-SNUBbed variable to listen to you, again, is to offer it hot dogs
-without any buns. Hail Eris!<br />
-[<a id="note13" name="note13">13</a>]Incidentally, INTERCAL is
-fully compliant with the military's view of female officers and
-supports the DON'T ASK, DON'T TELL ME YOU DON'T WANT IT, BABY
-statement.<br />
-[<a id="note14" name="note14">14</a>]"constantly evolving" is a
-characteristic shared by most things that you put in a dark, cool
-place and pretend they don't exist, vide my refrigerator.<br />
-[<a id="note15" name="note15">15</a>]Confused? Good. Information
-hiding.<br />
-</tt></span></blockquote>
-
-<br />
-<br />
-<br />
-</body>
-</html>
-
+++ /dev/null
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta name="generator"
-content="HTML Tidy for Linux/x86 (vers 1st February 2002), see www.w3.org" />
-<link rev="made" href="mailto:esr@snark.thyrsus.com" />
-<meta name="description"
-content="Charlie Stross's article about INTERCAL" />
-<meta name="keywords" content="humor, satire, parody" />
-<title>INTERCAL -- the Language From Hell</title>
-<style type="text/css">
-/*<![CDATA[*/
- p.c2 {font-style: italic}
- h1.c1 {text-align: center}
-/*]]>*/
-</style>
-</head>
-<body>
-<table width="100%" cellpadding="0" summary="Canned page header">
-<tr>
-<td width="30%">Back to <a href="index">Intercal Resources</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:39:23 $</td>
-</tr>
-</table>
-
-<hr />
-<em>The following article appeared in Computer Shopper (the British
-magazine of that name, not the Ziff-Davis title) around September
-1992.</em>
-
-<h1 class="c1">Intercal -- the Language From Hell</h1>
-
-<p class="c2">Where would we be without effective programming
-languages?</p>
-
-<p>Wait, don't turn the page; that was a rhetorical question. (The
-answer isn't: word-processing on slide rules.) Every once in a
-while it's worth thinking about the matter. Most of us (the lucky
-ones, that is) don't come within spitting distance of programming
-from one day to the next. Those who do, usually don't give any
-thought to them: it's time to write that function so do it, in C or
-Cobol or dBase whatever comes to hand. We don't waste time
-contemplating the deeper significance of the tools we use to do the
-job. But what would we do without well-designed, efficient
-programming languages?</p>
-
-<p>Go back to slide rules, maybe.</p>
-
-<p>A computer, in a very real sense, is its language. The processor
-speaks in a native tongue, its own machine code: unreadable by
-humans and next to impossible to program in, but nevertheless
-essential. It's the existence of this language which makes the
-computer such a general purpose tool; a hardware platform upon
-which we layer the abstractions, the virtual machines, of our
-operating systems. Which are, when you stop to think about it,
-simply a set of grammatically correct expressions in the computer's
-internal language. Take the humble 386 PC for example. Feed it one
-set of instructions and it pretends to be a cute little Windows
-machine; feed it another set, and something hairy happens -- it
-turns into a big, bad file server and starts demanding passwords
-and issuing threats.</p>
-
-<p>This flexibility is not an accident. Almost from the start, the
-feature which distinguished computers from their complex
-calculating predecessors was the fact that they were programmable
--- indeed, universally programmable, capable of tackling any
-computationally tractable problem. Strip away the programmability
-of the machine and you lose the universality. Not to mention the
-usefulness.</p>
-
-<p>Programming languages, as any fule kno, originated in the
-nineteen-fifties as a partial solution to a major difficulty;
-machine code is difficult to write and maintain and next to
-impossible to move (or port) from one computer to another of a
-different type. Assemblers, which allowed the programmers to write
-machine code using relatively simple mnemonic commands (which were
-then "assembled" into machine code) were an early innovation, but
-still failed to address the portability issue. The solution that
-finally took off was the concept of an abstract "high level"
-language: and the first to achieve widespread use was Fortran.</p>
-
-<p>A high level language is an artificial language with a rigidly
-specified grammar, which can be translated into machine code via a
-program called a "compiler". Statements in the high level language
-may correspond to individual statements, or whole series of
-statements, in the machine language ofthe computer. Indeed, the
-only thing that makes compilation practical is the fact that all
-computer language systems are effectively equivalent; any algorithm
-which can be expressed in one language can be solved in any other,
-in principle. So why are there so many languages?</p>
-
-<h2>A load of old cobol'ers</h2>
-
-<p>There are several answers to the question of language
-proliferation. Besides the facetious (some of us don't like Cobol)
-and the obvious (designing languages looks like a Fun Thing to a
-certain type of warped personality), there's the pragmatic reason.
-Simply put, some languages are excellent for expressing certain
-types of problem, but are lousy at dealing with other situations.
-Take Prolog, for example. Prolog is a brilliant language for
-resolving formal logic propositions expressable in the first order
-predicate calculus, but you'd need your head examining if you tried
-to write an operating system in it. (The Japanese MITI tried to do
-something similar with their Fifth Generation Project, and when was
-the last time you heard of them? Right.) Alternatively, take C. C
-is a wonderful language. It combines the flexibility and speed of
-raw machine code with the readability of ... er. Yes, you can
-re-jig a C compiler to run on anything. You can fine-tune it to
-produce tight, fast machine code that will execute on your toaster.
-Yes, you can write wonderful device drivers in it. But, again,
-you'd need your head examining if you set out to write a humongous
-database application in it. That's what Cobol is for; or SQL. So to
-the point of this article ... INTERCAL.</p>
-
-<h2>An icky mess</h2>
-
-<p>INTERCAL is a programming language which is to other languages
-as elephants are to deep-sea fishing -- it has nothing whatsoever
-to do with them. Nothing ... except that it's a programming
-language. And it serves as a wonderful example of the fact that,
-despite their theoretical, abstract interchangeability, not all
-languages are born equal. Here's a potted history of the
-offender:</p>
-
-<p>INTERCAL is short for "Computer Language With No Readily
-Pronouncable Acronym". It was not so much designed as perpetrated
-at Princeton University, on the morning of May 26th, 1972, by
-Donald R. Woods and James M. Lyon. They have been trying to live it
-down ever since. The current implementation, C-INTERCAL, was
-written by Eric S. Raymond (also the author of The New Hacker's
-Dictionary), and -- god help us -- runs on anything that supports C
-(and the C programming tools lex and yacc).</p>
-
-<p>INTERCAL is, in its own terms, elegant, simple and concise. It
-is also flexible and forgiving; if the compiler (called,
-appropriately enough, ick) encounters something it doesn't
-understand it simply ignores it and carries on. In order to insert
-a comment, just type in something that ick thinks is wrong; but be
-careful not to embed any valid INTERCAL code in your comments, or
-ick will get all excited and compile it. There are only two
-variable types: 16-bit integers, and 32-bit integers, denoted by .1
-(for the 16-bit variable called "1") or :1 (for the 32-bit variable
-named "1"); note that .1 is not equivalent to :1 and definitely has
-nothing to do with 0.1 (unless it happens to be storing a value of
-0.1).</p>
-
-<p>INTERCAL supports two unique bitwise operators, interleave (or
-mingle) and select, denoted by the "^" and "~" symbols
-respectively. You interleave two variables by alternating the bits
-in the two operands; you select two variables by taking from the
-first operand whichever bits correspond to 1's in the second
-operand, then pack these bits to the right in the result. There are
-also numerous unary bitwise operators, and in order to resolve
-matters of precedence the pedantic may use sparks (') or
-rabbit-ears (") to group expressions (Don't blame me for the silly
-names: INTERCAL has a character set which is best described as
-creative.) It is not surprising that these operators are unique to
-INTERCAL; the parlous readability of C would not be enhanced by the
-addition of syntax like:</p>
-
-<p><tt>PLEASE DO IGNORE .1
-<-".1^C'&:51~"#V1^C!12~;&75SUB"V'V.1~</tt></p>
-
-<p>Like any other language, INTERCAL has flow-of-control statements
-and input and output statements. To write something or other into a
-variable, you need the WRITE IN list statement, where list is a
-string of variables and/or array elements. The format of the input
-data should be as numbers, the digits of which are spelt out in
-english in the range ZERO (or OH) to FOUR TWO NINE FOUR NINE SIX
-SEVEN TWO NINE FIVE. To output some information, you need the READ
-OUT list statement, where list again consists of variables. Numbers
-are printed, by default, in the form of "extended" Roman numerals
-(the syntax of which I will draw a merciful veil over), although
-the scholarly may make use of the standard library, which contains
-routines for formatting output in Sanskrit.</p>
-
-<p>Like FORTRAN, INTERCAL uses line numbers which are optional and
-follow in no particular order. Unlike FORTRAN, INTERCAL has no
-evil, unspeakable GOTO command, and not even an IF statement.
-However, you would be wrong to ascribe this to INTERCAL being
-designed for structured programming; it is actually because
-C-INTERCAL is the only known language that implements the legendary
-COME FROM ... control statement (originally described by R. L.
-Clark in "A Linguistic contribution to GOTO-less programming",
-Comm. ACM 27 (1984), pp. 349-350). For many years the GOTO
-statement -- once the primary means of controlling the sequence of
-execution of a program -- has been reviled as contributing to
-unreadable, unpredictable code that is virtually impossible to
-follow because it jumps about the place like a kangaroo on
-amphetamines. The COME FROM statement enables INTERCAL to do away
-with nasty GOTO's, while still preserving for the programmer that
-sense of warm self-esteem and achievement that comes from
-successfully writing a really nasty piece of self-modifying code
-involving computed GOTO's in FORTRAN (Or, for the terminally hip
-and hacker-ish, involving a triple-indirect pointer to a union of
-UNIX kernel data structures in C. Capisce?) Basically, the COME
-FROM statement specifies a line, or lines, which -- when the
-program executes them -- will jump to the COME FROM: effectively
-the opposite of GOTO.</p>
-
-<p>Because INTERCAL contains no equivalent of the NEXT statement
-for controlling whether or not some statement is executed, it
-provides a creative, endearing and unique substitute; abstention.
-For example, you can abstain from executing a given line of code
-with the ABSTAIN FROM (label) form of the command. Alternatively,
-and more uselessly, you can abstain from executing all statements
-of a specified type; for example, you can say</p>
-
-<p><tt>PLEASE ABSTAIN FROM IGNORING + FORGETTING</tt></p>
-
-<p>or</p>
-
-<p><tt>DO ABSTAIN FROM ABSTAINING</tt></p>
-
-<p>The abstention command is revoked by the REINSTATE statement. It
-is a Bad Idea to ABSTAIN FROM REINSTATING. It is also worth noting
-that the ABSTAIN syntax is rather confusing; for example, DO
-ABSTAIN FROM GIVING UP is not accepted, although a valid synonym
-for this is DON'T GIVE UP. (GIVE UP is the statement that
-terminates execution of a program. You are encouraged to use this
-statement at every opportunity. It is your only hope of
-escape.)</p>
-
-<p>The designers of the INTERCAL language believed that source code
-should be easy to understand or, failing that, friendly; in
-extremis, good old-fashioned politeness will do. Consequently, the
-syntax of the language looks a bit odd at first. After the line
-label (if any) there should be a statement identifier; this can be
-one of DO, PLEASE, or PLEASE DO. Programs which are insufficiently
-polite to the compiler may be rejected with the error message
-PROGRAMMER IS INSUFFICIENTLY POLITE; likewise, programs which spend
-too much time grovelling to the compiler will be terminated with
-extreme prejudice. The DO, PLEASE or PLEASE DO is then followed by
-(optionally) one of NOT, N'T, or %n, then a statement: the NOT or
-N'T's meaning should be self-evident, while the %n is merely the
-percentage probability that the following statement will be
-executed.</p>
-
-<p>Of course, with only two binary and three unary operators, it is
-rather difficult for programmers to get to grips with the language.
-Therefore, in a fit of quite uncharacteristic generosity, the
-designers have supplied -- and even partially documented -- a
-library of rather outre subroutines that carry out such esoteric
-operations as addition, subtraction, logical comparison, and
-generation of random numbers. The subroutines will be charmingly
-familiar to those PDP-11 assembly-language hackers among you who
-are also fluent in FORTRAN and SPITBOL.</p>
-
-<h2>Why you should program in Intercal</h2>
-
-<p>INTERCAL, despite being afflicted with these unique features
-(which, arguably, should remain that way) has survived for twenty
-years and is indeed thriving. The relatively recent C-INTERCAL
-dialect (which introduced the COME FROM statement, among other
-things) has spread it far beyond its original domain; the infamy
-continues, transmitted like a malign influence across the Internet.
-It is a matter of record that no computer language has ever
-succeeded in gaining widespread acceptance on the basis of
-elegance, comprehensibility or necessity. Look at FORTRAN, Cobol or
-C; all of them spread despite the fact that better alternatives
-were available. In fact, there are reasons to believe that INTERCAL
-is the language of the future.</p>
-
-<p>Firstly, INTERCAL creates jobs. Yes, it's true. In general, if a
-particular programming tool is unfriendly, ugly, and absolutely
-essential, the response of management is to throw more programmers
-at it instead of replacing it. INTERCAL is so monumentally
-difficult to use for anything sensible that it is surely destined
-to be the cause of full employment, massive increases in the DP
-budget of every company where it is used, and general prosperity
-for programmers.</p>
-
-<p>Secondly, once you have learned INTERCAL you will be able to win
-friends and influence people. As the authors point out, if you were
-to state that the simplest way to store a value of 65536 in a
-32-bit variable is</p>
-
-<p><tt>DO :1 <- #0$#256</tt></p>
-
-<p>any sensible programmer would say that this was absurd. Since
-this is indeed the simplest way of doing this, they'd be made to
-look like a fool in front of their boss (who, by Murphy's law,
-would have turned up at just that moment). This will have a
-devastating effect on their ego and simultaneously make you look
-brilliant (until they realise that you cribbed this example from
-the manual, like me. Deep shame.)</p>
-
-<p>Thirdly, INTERCAL helps sell hardware. There's been a lot of
-fuss recently about big corporations inventing gigantic, bloated
-windowing and operating systems that require monstrously powerful
-computers to run on; some cynics suggest that this is because
-personal computers are now so powerful that they can already do
-anything any reasonable individual would want them to, and it's
-necessary to invent warm furry buttons that soak up millions of
-processor cycles in order to sell new equipment. With INTERCAL, you
-no longer need Windows or OS/2 to slow your 486 PC to a crawl! A
-Sieve of Eratosthenes benchmark (that computes all the prime
-numbers less than 65536), when coded in INTERCAL, clocked over
-seventeen hours on a SPARCStation-1. The same program, in C, took
-less than 0.5 seconds -- thus proving, quite clearly, that INTERCAL
-software is so slow that you absolutely must buy a CRAY-3 or
-equivalent in order to have any hope of getting any work out of
-it.</p>
-
-<p>Consequently, it is quite clear that INTERCAL represents a major
-alternative to conventional programming languages. Anyone who
-learns this language is going to go far -- at least as far as the
-nearest psychiatric institution. Rumour has it that INTERCAL was
-not entirely unrelated to the collapse of the Soviet Union and the
-success of the Apollo missions. It is even reported to improve your
-sex life and restore hair loss! So we warmly advise you to take
-this utterly unbiased report at face value and go forth and get
-your friendly neighbourhood software company to switch to INTERCAL,
-wherever or whatever they may be using right now. You know it makes
-sense ...</p>
-
-<hr />
-<table width="100%" cellpadding="0" summary="Canned page footer">
-<tr>
-<td width="30%">Back to <a href="index">Intercal Resources</a></td>
-<td width="30%" align="center">Up to <a
-href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2002-07-30 23:39:23 $</td>
-</tr>
-</table>
-
-<br clear="left" />
-<address>Eric S. Raymond <a
-href="mailto:esr@thyrsus.com"><esr@snark.thyrsus.com></a></address>
-</body>
-</html>
-
--- /dev/null
+/****************************************************************************
+
+NAME
+ yuk.c -- C-INTERCAL debugger and profiler code, linked into programs.
+
+DESCRIPTION
+ File linked into programs as a debugger or profiler.
+
+LICENSE TERMS
+ Copyright (C) 2006 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.
+
+****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <setjmp.h>
+
+#define YUKDEBUG 1
+
+#include "yuk.h"
+#include "lose.h"
+#include "sizes.h"
+#include "abcess.h"
+
+#if YPTIMERTYPE == 4
+#include <sys/times.h>
+#endif
+
+extern signed char onewatch[];
+extern signed char twowatch[];
+extern type16 oneold[];
+extern type32 twoold[];
+
+int yuklines = 0;
+int yukloop = 0;
+int yukcommands = 0; /* these 3 lines because externs must be defined
+ somewhere */
+/* Global variable storage types:
+ static: limited to the file
+ unadorned: defining an extern
+ extern: defined elsewhere (unless initialised) */
+
+static char buf[20];
+
+static sig_atomic_t singlestep = 1; /* if 0, run until a breakpoint */
+static sig_atomic_t writelines = 1; /* whether to display executed lines onscreen */
+static int breakpoints[80]; /* initialised to all 0s. Breakpoint locations */
+static int nbreakpoints = 1; /* how many breakpoints we have */
+static int monitors[80]; /* monitors give a message when program flow passes them */
+static int nmonitors = 0;
+static int untilnext = -1; /* NEXTING level to break the program at */
+static int firstrun = 1; /* first time an interactive command point is reached */
+static int yukerrcmdg = -1; /* the aboff that indicates an error in the 'g' command */
+
+static yptimer tickcount; /* yptimer of last run */
+static int lastaboff = 0; /* last value of aboff */
+
+void handlesigint(int i)
+{ /* this is a signal handler, so can't do much */
+ singlestep = 1;
+ writelines = 1;
+ (void) i; /* we're ignoring our argument */
+}
+
+#if YPTIMERTYPE==1 || YPTIMERTYPE==2
+yptimer yukgettimeofday()
+{
+ static struct timeval tp;
+ yptimer temp;
+ gettimeofday(&tp,0);
+ temp=(yptimer)tp.tv_usec +
+ (yptimer)tp.tv_sec * (yptimer)1000000LU;
+ /* here we make use of unsigned wraparound. In the case
+ YPTIMERTYPE == 1, it seems quite likely that we're going
+ to wraparound, but because everything is cast to the
+ unsigned integral type yptimer, we get a value that will
+ wraparound in such a way that - will give us the correct
+ time interval. */
+ return temp;
+}
+#elif YPTIMERTYPE == 4
+yptimer yuktimes()
+{
+ static struct tms tp;
+ times(&tp);
+ return tp.tms_utime + tp.tms_stime;
+}
+#endif /* YPTIMERTYPE 4 */
+
+void yukterm(void)
+{
+ int i,lastline,thisline,inrow;
+ yptimer avgtime,avgtime2;
+ if(yukopts==2) puts("Program ended without error.");
+ if(!(yukopts&1)) return;
+ /* Print profiling information */
+ puts("Profiling information saved to \"yuk.out\".");
+ freopen("yuk.out","w",stdout);
+ i=-1;
+ lastline=-1;
+ while(++i<yukcommands)
+ {
+ thisline=lineofaboff[i];
+ if(thisline==lastline) inrow++; else
+ {
+ inrow=1;
+ printf("%5d:\t%s\n",thisline,textlines[thisline]);
+ }
+ lastline=thisline;
+ avgtime=ypexecount[i]+ypabscount[i];
+ if(avgtime) avgtime=ypexectime[i]/avgtime;
+ avgtime2=0;
+ if(ypexecount[i]) avgtime2=ypexectime[i]/ypexecount[i];
+ printf("C%d: Time%4" YPTIMERTFORMAT ".%0" YPTIMERTFORMATD
+ ", Avg%2" YPTIMERTFORMAT ".%0" YPTIMERTFORMATD ", "
+ "Avg Exec%2" YPTIMERTFORMAT ".%0" YPTIMERTFORMATD
+ ", Exec%8" YPCOUNTERTFORMAT ", Abs%8" YPCOUNTERTFORMAT "\n",
+ inrow,ypexectime[i]/YPTIMERSCALE, ypexectime[i]%YPTIMERSCALE,
+ avgtime/YPTIMERSCALE, avgtime%YPTIMERSCALE,
+ avgtime2/YPTIMERSCALE, avgtime2%YPTIMERSCALE,
+ ypexecount[i],ypabscount[i]);
+ }
+}
+
+void yukline(int aboff,int emitlineno)
+{ /* this runs every time a source line is encountered */
+ int i;
+ int broken; /* hit a breakpoint, monitorpoint, viewbreak, until */
+ int keeplooping;
+ int templine;
+ int tempcmd;
+ int temp;
+ yptimer temptick;
+ char* text=textlines[lineofaboff[aboff]];
+ if(!yukopts) return;
+ if(yukopts & 1)
+ { /* profile */
+ temptick=YPGETTIME;
+ if(lastaboff) ypexectime[lastaboff]+=temptick-tickcount;
+ tickcount=temptick;
+ if(abstained[aboff]) ypabscount[aboff]++;
+ else ypexecount[aboff]++;
+ lastaboff=aboff;
+ }
+ if(yukopts & 2)
+ { /* debug */
+ if(firstrun)
+ {
+ /* GNU GPL requires a copyright notice at this point */
+ puts("yuk debugger Copyright (C) 2006 Alex Smith.");
+ puts("The yuk debugger is covered by the GNU GPL and can");
+ puts("be redistributed freely, but comes with ABSOLUTELY");
+ puts("NO WARRANTY. For more information, type *<RET>.\n");
+ puts("For help on yuk, type ?<RET>.\n");
+ }
+ i=nbreakpoints;
+ broken=0;
+ while(i--) broken|=breakpoints[i]==lineofaboff[aboff];
+ if(yukloop&&broken&&*breakpoints!=lineofaboff[aboff]) broken=0;
+ if(broken)
+ {
+ if(*breakpoints!=lineofaboff[aboff])
+ printf("Breakpoint hit at line %d:\n",lineofaboff[aboff]);
+ singlestep=1;
+ }
+ else
+ {
+ i=nmonitors;
+ while(i--) broken|=monitors[i]==lineofaboff[aboff];
+ if(yukloop) broken=0;
+ if(broken) printf("Command flowed past line %d:\n",lineofaboff[aboff]);
+ }
+ if(nextindex <= untilnext)
+ {
+ broken = 1;
+ singlestep = 1;
+ }
+ if(!broken&&yukerrcmdg==aboff)
+ {
+ singlestep = 1;
+ puts("There are no commands on that line.");
+ /* To the user, nothing will have happened but the error message! */
+ }
+ i=-1;
+ while(++i,1)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if(yukvars[i].vartype==ONESPOT)
+ {
+ if(onewatch[yukvars[i].intername])
+ {
+ if(onespots[yukvars[i].intername]!=oneold[yukvars[i].intername]&&
+ onewatch[yukvars[i].intername]>1)
+ {
+ oneold[yukvars[i].intername]=onespots[yukvars[i].intername];
+ if(onewatch[yukvars[i].intername]==2||!onespots[yukvars[i].intername])
+ {
+ printf(onewatch[yukvars[i].intername]==2?
+ "Variable .%d changed.\n":"Variable .%d became 0.\n",
+ yukvars[i].extername);
+ broken=1; singlestep=1;
+ }
+ }
+ if(writelines||broken)
+ {
+ printf(".%d is:\n",yukvars[i].extername);
+ pout(onespots[yukvars[i].intername]);
+ }
+ }
+ }
+ if(yukvars[i].vartype==TWOSPOT)
+ {
+ if(twowatch[yukvars[i].intername])
+ {
+ if(twospots[yukvars[i].intername]!=twoold[yukvars[i].intername]&&
+ twowatch[yukvars[i].intername]>1)
+ {
+ twoold[yukvars[i].intername]=twospots[yukvars[i].intername];
+ if(twowatch[yukvars[i].intername]==2||!twospots[yukvars[i].intername])
+ {
+ printf(twowatch[yukvars[i].intername]==2?
+ "Variable :%d changed.\n":"Variable :%d became 0.\n",
+ yukvars[i].extername);
+ broken=1; singlestep=1;
+ }
+ }
+ if(writelines||broken)
+ {
+ printf(":%d is:\n",yukvars[i].extername);
+ pout(twospots[yukvars[i].intername]);
+ }
+ }
+ }
+ }
+ if(writelines||broken)
+ {
+ /* write line that we're on */
+ printf("%5d:\t%s\n",lineofaboff[aboff],text);
+ /* write command within line that we're on */
+ tempcmd=aboff;
+ while(tempcmd&&lineofaboff[--tempcmd]==lineofaboff[aboff]);
+ printf("On C%d: Abstained %d time%s\n",aboff?aboff-tempcmd:1,
+ abstained[aboff]-yukloop,abstained[aboff]-yukloop==1?".":"s.");
+ }
+ if(singlestep)
+ {
+ signal(SIGINT,handlesigint); /* placing this line here means that a rapid
+ ^C^C will terminate the program, if it's
+ stuck in a loop somewhere */
+ keeplooping = 1;
+ breakpoints[0] = 0; /* breakpoints[0] goes whenever a breakpoint is hit */
+ untilnext = -1;
+ if(yukloop)
+ { /* reverse the abstentions that g caused */
+ i = -1;
+ while(++i<yukcommands) abstained[i]--;
+ }
+ yukloop = 0;
+ yukerrcmdg = -1;
+ do
+ {
+ printf("yuk007 "); /* this is our prompt, a sort of reverse
+ INTERCAL version of % */
+ fgets(buf,20,stdin); /* input a command */
+ if(!strchr(buf,'\n'))
+ {
+ lose(E810,emitlineno,(char*)NULL);
+ }
+ templine=0;
+ switch(*buf)
+ {
+ case '?':
+ case '@':
+ puts("a<line>\tabstain once from all non-abstained commands on <line>");
+ puts("b<line>\tset breakpoint at <line>");
+ puts("c\tcontinue execution until a breakpoint is reached");
+ puts("d<line>\tdelete breakpoint at <line>");
+ puts("e<line>\texplain the main expression on <line>");
+ puts("f<line>\tstop producing messages when commands on <line> are run");
+ puts("g<line>\tchange currently executing command to the first command");
+ puts("\ton <line> or the next command if already on <line>");
+ puts("h\tlist 10 lines either side of the current line");
+ puts("i<var>\tignore a variable");
+ puts("j<var>\tremember a variable");
+ puts("k\tcontinue until we RESUME back to the current nexting level");
+ puts("\t(that is, step unless we are on a NEXT, in which case execute");
+ puts("\tuntil a RESUME or FORGET back to the same or smaller NEXT stack)");
+ puts("l<line>\tlist 10 lines either side of <line>");
+ puts("m<line>\tproduce a message every time a command on <line> is run");
+ puts("n\tshow the NEXT stack");
+ puts("o\tcontinue until we RESUME/FORGET below the current nexting level");
+ puts("\tie until the NEXT stack becomes smaller than it is at present");
+ puts("p\tdisplay the values of all onespot and twospot variables");
+ puts("q\tabort execution");
+ puts("r<line>\treinstate once all abstained commands on <line>");
+ puts("s\tstep to the next line of code");
+ puts("t\tcontinue until a breakpoint, displaying all lines executed");
+ puts("u<line>\texecute until just before <line> is reached");
+ puts("v<var>\tshow value of variable every time a command is printed");
+ puts("w\tshow the current line and current command");
+ puts("x<var>\tremove a variable view, breakchange, or breakzero");
+ puts("y<var>\tview variable every displayed line, and break on change");
+ puts("z<var>\tview variable every displayed line, and break on zero");
+ puts("<var>\tview the value of a onespot or twospot variable");
+ puts("<<var>\tset the value of a onespot or twospot variable");
+ puts("*\tview the GNU General Public Licence");
+ puts("?\tview this help screen");
+ puts("@\tview this help screen");
+ puts("Line numbers refer to lines of source code, not line labels.");
+ puts("Listings have (Axxxxxx) at the start of each line: this shows");
+ puts("the abstention status of each command on that line.");
+ puts("The values of variables must be input in proper INTERCAL");
+ puts("notation (i.e. ONE TWO THREE), and are output as butchered");
+ puts("Roman numerals.");
+ puts("You can press ^C to break an executing program.");
+ break;
+ case 'q':
+ exit(0);
+ break;
+ case 'n':
+ i=nextindex;
+ if(!i)
+ {
+ puts("The NEXT stack is empty.");
+ }
+ else
+ {
+ puts("Commands NEXTED from:");
+ while(i--)
+ {
+ /* write NEXT line */
+ printf("%5d:\t%s\n",lineofaboff[next[i]-1],
+ textlines[lineofaboff[next[i]-1]]);
+ /* write NEXT command within line */
+ tempcmd=next[i];
+ while(tempcmd&&lineofaboff[--tempcmd]==lineofaboff[next[i]-1]);
+ printf("NEXTED from command C%d: Abstained %d time%s\n",next[i]-1?
+ next[i]-1-tempcmd:1,abstained[next[i]-1],
+ abstained[next[i]-1]==1?".":"s.");
+ }
+ }
+ break;
+ case 'w':
+ /* write line that we're on */
+ printf("%5d:\t%s\n",lineofaboff[aboff],text);
+ /* write command within line that we're on */
+ tempcmd=aboff;
+ while(tempcmd&&lineofaboff[--tempcmd]==lineofaboff[aboff]);
+ printf("On C%d: Abstained %d time%s\n",aboff?aboff-tempcmd:1,abstained[aboff],
+ abstained[aboff]==1?".":"s.");
+ break;
+ case 'p':
+ i=-1;
+ while(++i,1)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if(yukvars[i].vartype==ONESPOT)
+ {
+ printf("Variable .%d is:\n",yukvars[i].extername);
+ pout(onespots[yukvars[i].intername]);
+ }
+ if(yukvars[i].vartype==TWOSPOT)
+ {
+ printf("Variable :%d is:\n",yukvars[i].extername);
+ pout(twospots[yukvars[i].intername]);
+ }
+ }
+ break;
+ case '.':
+ case ':':
+ sscanf(buf+1,"%d",&templine);
+ if(templine<1)
+ {
+ puts("Don't know which variable you mean.");
+ break;
+ }
+ i=-1;
+ temp=0;
+ while(++i,!temp)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if((*buf=='.'&&yukvars[i].vartype==ONESPOT)||
+ (*buf==':'&&yukvars[i].vartype==TWOSPOT))
+ {
+ if(yukvars[i].extername==templine)
+ {
+ temp=1;
+ if(yukvars[i].vartype==ONESPOT)
+ {
+ pout(onespots[yukvars[i].intername]);
+ puts(oneforget[yukvars[i].intername]?
+ "This variable is currently ignored.":
+ "This variable is currently remembered.");
+ }
+ if(yukvars[i].vartype==TWOSPOT)
+ {
+ pout(twospots[yukvars[i].intername]);
+ puts(twoforget[yukvars[i].intername]?
+ "This variable is currently ignored.":
+ "This variable is currently remembered.");
+ }
+ }
+ }
+ }
+ if(temp) break;
+ puts("That variable is not in the program.");
+ break;
+ case 'v':
+ case 'x':
+ case 'y':
+ case 'z':
+ if(buf[1]!='.'&&buf[1]!=':')
+ {
+ puts("This command only works on onespot and twospot variables.");
+ break;
+ }
+ sscanf(buf+2,"%d",&templine);
+ if(templine<1)
+ {
+ puts("Don't know which variable you mean.");
+ break;
+ }
+ i=-1;
+ temp=0;
+ while(++i,!temp)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if(yukvars[i].extername==templine)
+ {
+ if(buf[1]=='.'&&yukvars[i].vartype==ONESPOT)
+ {
+ if(*buf=='v') onewatch[yukvars[i].intername]=1;
+ if(*buf=='x') onewatch[yukvars[i].intername]=0;
+ if(*buf=='y') onewatch[yukvars[i].intername]=2;
+ if(*buf=='z') onewatch[yukvars[i].intername]=3;
+ oneold[yukvars[i].intername]=onespots[yukvars[i].intername];
+ temp=1;
+ }
+ if(buf[1]==':'&&yukvars[i].vartype==TWOSPOT)
+ {
+ if(*buf=='v') twowatch[yukvars[i].intername]=1;
+ if(*buf=='x') twowatch[yukvars[i].intername]=0;
+ if(*buf=='y') twowatch[yukvars[i].intername]=2;
+ if(*buf=='z') twowatch[yukvars[i].intername]=3;
+ twoold[yukvars[i].intername]=twospots[yukvars[i].intername];
+ temp=1;
+ }
+ }
+ }
+ if(!temp)
+ {
+ puts("That variable is not in the program.");
+ break;
+ }
+ if(*buf=='v') puts("Set a normal variable view.");
+ if(*buf=='x') puts("Removed all views from that variable.");
+ if(*buf=='y') puts("Set a breakchange variable view.");
+ if(*buf=='z') puts("Set a breakzero variable view.");
+ break;
+ case 'i':
+ case 'j':
+ if(buf[1]!='.'&&buf[1]!=':'&&buf[1]!=','&&buf[1]!=';')
+ {
+ puts("That isn't a real sort of variable.");
+ break;
+ }
+ sscanf(buf+2,"%d",&templine);
+ if(templine<1)
+ {
+ puts("Don't know which variable you mean.");
+ break;
+ }
+ i=-1;
+ temp=0;
+ while(++i,!temp)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if((buf[1]=='.'&&yukvars[i].vartype==ONESPOT)||
+ (buf[1]==':'&&yukvars[i].vartype==TWOSPOT)||
+ (buf[1]==','&&yukvars[i].vartype==TAIL)||
+ (buf[1]==';'&&yukvars[i].vartype==HYBRID))
+ {
+ if(yukvars[i].extername==templine)
+ {
+ temp=1;
+ if(yukvars[i].vartype==ONESPOT)
+ oneforget[yukvars[i].intername]=*buf=='i';
+ if(yukvars[i].vartype==TWOSPOT)
+ twoforget[yukvars[i].intername]=*buf=='i';
+ if(yukvars[i].vartype==TAIL)
+ tailforget[yukvars[i].intername]=*buf=='i';
+ if(yukvars[i].vartype==HYBRID)
+ hyforget[yukvars[i].intername]=*buf=='i';
+ }
+ }
+ }
+ if(temp)
+ {
+ if(*buf=='i')
+ puts("Variable ignored.");
+ else
+ puts("Variable remembered.");
+ break;
+ }
+ puts("That variable is not in the program.");
+ break;
+ case '<':
+ if(buf[1]!='.'&&buf[1]!=':')
+ {
+ puts("You cannot set that sort of variable (if it exists at all).");
+ break;
+ }
+ sscanf(buf+2,"%d",&templine);
+ if(templine<1)
+ {
+ puts("Don't know which variable you mean.");
+ break;
+ }
+ i=-1;
+ temp=0;
+ while(++i,!temp)
+ {
+ if(yukvars[i].vartype==YUKEND) break;
+ if((buf[1]=='.'&&yukvars[i].vartype==ONESPOT)||
+ (buf[1]==':'&&yukvars[i].vartype==TWOSPOT))
+ {
+ if(yukvars[i].extername==templine)
+ {
+ temp=1;
+ if(yukvars[i].vartype==ONESPOT)
+ onespots[yukvars[i].intername]=pin();
+ if(yukvars[i].vartype==TWOSPOT)
+ twospots[yukvars[i].intername]=pin();
+ /* note that when debugging, you can set an
+ ignored variable */
+ }
+ }
+ }
+ if(temp) break;
+ puts("That variable is not in the program.");
+ break;
+ case 'g':
+ sscanf(buf+1,"%d",&templine);
+ if(!templine)
+ {
+ puts("Don't know which line you mean.");
+ break;
+ }
+ breakpoints[0] = templine;
+ yukloop = 1;
+ /* This is implemented by incrementing all ABSTAIN counts,
+ even the normally immutable ones on GIVE UP lines, setting
+ a temporary breakpoint ([0]) on the line given, and running the
+ program. When the breakpoint is hit singlestep will see that
+ yukloop is set (its purpose is to cause the program to go back
+ to the start when it reaches the end) and decrement all ABSTAIN
+ counts, putting the commands back the way they were. We set an error
+ breakpoint on this line in case the user is trying to jump to a
+ line with no commands (although this debugger command is called
+ 'g', would I dare to describe this as a GOTO?) */
+ i = -1;
+ while(++i<yukcommands) abstained[i]++;
+ yukerrcmdg = aboff;
+ singlestep = 0;
+ writelines = 0;
+ keeplooping = 0; /* to break out of the loop in the debugger! */
+ break;
+ case 'a':
+ case 'r':
+ sscanf(buf+1,"%d",&templine);
+ if(!templine)
+ {
+ puts("Don't know which line you mean.");
+ break;
+ }
+ i=-1;
+ tempcmd=1;
+ while(++i<yukcommands)
+ {
+ if(lineofaboff[i]==templine)
+ {
+ temp=abstained[i];
+ if(*buf=='a') if(!temp) abstained[i]=1;
+ if(*buf=='r') if(temp) abstained[i]--;
+ printf("Command %d on line %d was abstained %d time%s, "
+ "now abstained %d time%s.\n",tempcmd,templine,
+ temp,temp==1?"":"s",abstained[i],
+ abstained[i]==1?"":"s");
+ tempcmd++;
+ }
+ }
+ if(tempcmd==1) puts("No commands start on this line.");
+ break;
+ case 'k':
+ case 'o':
+ untilnext=nextindex-(*buf=='o');
+ /* no break;! */
+ case 'c':
+ singlestep=0;
+ writelines=0;
+ keeplooping=0;
+ break;
+ case 'b':
+ sscanf(buf+1,"%d",&templine);
+ if(templine)
+ {
+ printf("Breakpoint set at line %d.\n",templine);
+ breakpoints[nbreakpoints++]=templine;
+ if(nbreakpoints>=80) lose(E811,emitlineno,(char*)NULL);
+ }
+ else
+ puts("Don't know which line you mean.");
+ break;
+ case 'd':
+ sscanf(buf+1,"%d",&templine);
+ if(templine)
+ {
+ printf("All breakpoints removed from line %d.\n",templine);
+ i=nbreakpoints;
+ while(i--) if(templine==breakpoints[i])
+ {
+ memmove(breakpoints+i,breakpoints+i+1,sizeof(int)*(nbreakpoints-i));
+ nbreakpoints--;
+ }
+ }
+ else
+ puts("Don't know which line you mean.");
+ break;
+ case 'm':
+ sscanf(buf+1,"%d",&templine);
+ if(templine)
+ {
+ printf("Monitor set at line %d.\n",templine);
+ monitors[nmonitors++]=templine;
+ if(nmonitors>=80) lose(E811,emitlineno,(char*)NULL);
+ }
+ else
+ puts("Don't know which line you mean.");
+ break;
+ case 'f':
+ sscanf(buf+1,"%d",&templine);
+ if(templine)
+ {
+ printf("All monitors removed from line %d.\n",templine);
+ i=nmonitors;
+ while(i--) if(templine==monitors[i])
+ {
+ memmove(monitors+i,monitors+i+1,sizeof(int)*(nmonitors-i));
+ nmonitors--;
+ }
+ }
+ else
+ puts("Don't know which line you mean.");
+ break;
+ case 's':
+ singlestep=1;
+ writelines=1;
+ keeplooping=0;
+ break;
+ case 't':
+ singlestep=0;
+ writelines=1;
+ keeplooping=0;
+ break;
+ case 'u':
+ sscanf(buf+1,"%d",&templine);
+ if(templine)
+ {
+ breakpoints[0]=templine;
+ singlestep=0;
+ writelines=0;
+ keeplooping=0;
+ }
+ else
+ puts("Don't know which line you mean.");
+ break;
+ case 'e':
+ sscanf(buf+1,"%d",&templine);
+ if(!templine)
+ {
+ puts("Don't know which line you mean.");
+ break;
+ }
+ tempcmd=-1;
+ temp=0;
+ i=0;
+ while(++tempcmd<yukcommands)
+ {
+ if(lineofaboff[tempcmd]==templine)
+ {
+ if(!yukexplain[tempcmd]) ++i;
+ else
+ {
+ printf("C%d: Expression is %s\n",++i,yukexplain[tempcmd]);
+ temp++;
+ }
+ }
+ }
+ if(!temp) puts("No expressions on that line.");
+ break;
+ case 'l':
+ sscanf(buf+1,"%d",&templine);
+ if(!templine)
+ {
+ puts("Don't know which line you mean.");
+ break;
+ }
+ /* no break;! */
+ case 'h':
+ if(!templine) templine=lineofaboff[aboff];
+ templine-=10;
+ if(templine+21>=yuklines) templine=yuklines-22;
+ if(templine<1) templine=1;
+ i=templine;
+ while(i<templine+21&&i<yuklines)
+ {
+ buf[6]=0;
+ buf[0]=buf[1]=buf[2]=buf[3]=buf[4]=buf[5]=' ';
+ tempcmd=-1;
+ temp=0;
+ while(++tempcmd<yukcommands)
+ {
+ if(lineofaboff[tempcmd]==i)
+ {
+ buf[temp++]='0'+abstained[tempcmd];
+ if(abstained[tempcmd]>9) buf[temp-1]='!';
+ if(temp==6) break;
+ }
+ }
+ printf("(A%s)%5d:\t%s\n",buf,i,textlines[i]);
+ i++;
+ }
+ break;
+ case '*':
+ system("more < " YUKCOPYLOC); /* display the GNU GPL copying conditions */
+ break;
+ default:
+ puts("Not sure what you mean. Try typing ?<RET>.");
+ break;
+ }
+ } while(keeplooping);
+ }
+ }
+ firstrun=0;
+}
--- /dev/null
+/* yuk.h - header file for yuk.c and debugging versions of ick-wrap.c */
+/* Copyright (C) Alex Smith 2006. See yuk.c for copyright conditions.
+ This file is GPL'd, and so can be freely redistributed but has
+ absolutely no warranty. */
+
+#include <time.h>
+#define YUK(t,u) yukline(t,u)
+#define YUKTERM yukterm()
+
+#define YUKEND 5
+
+extern void yukline(int,int);
+extern void yukterm(void);
+
+extern int abstained[];
+extern int yukopts;
+extern int lineno;
+extern int yuklines;
+extern int yukcommands;
+extern char *textlines[];
+extern int lineofaboff[];
+extern char *yukexplain[];
+
+extern int yukloop;
+
+/* Defines that change the functions used for profiling */
+#define YPTIMERTYPE 2
+/* 0 to use clock(), 1 to use gettimeofday() and long,
+ 2 to use gettimeofday() and long long, 3 to use gethrtime()
+ 4 to use times() */
+/* Note: On many systems, 0's resolution is too low to produce any output
+ 1 and 2 produce the same output; use 2 if your system can handle
+ long long because the overflow is dealt with more simply
+ 3 is a system-specific function. If there are more system-specific
+ functions around that return more accurate times than the others
+ used here, it would improve the profiler on those systems. */
+
+#if YPTIMERTYPE == 0
+#define YPTIMERTFORMAT "lu"
+#define YPCOUNTERTFORMAT "lu"
+#define YPTIMERTFORMATD "6" YPTIMERTFORMAT
+#define YPTIMERSCALE CLOCKS_PER_SEC
+#define YPGETTIME clock()
+typedef unsigned long yptimer;
+typedef unsigned long ypcounter;
+
+#elif YPTIMERTYPE == 1
+#define YPTIMERTFORMAT "lu"
+#define YPCOUNTERTFORMAT "lu"
+#define YPTIMERTFORMATD "6" YPTIMERTFORMAT
+#define YPTIMERSCALE 1000000LU
+#define YPGETTIME yukgettimeofday()
+typedef unsigned long yptimer;
+typedef unsigned long ypcounter;
+
+#elif YPTIMERTYPE == 2
+#define YPTIMERTFORMAT "llu"
+#define YPCOUNTERTFORMAT "lu"
+#define YPTIMERTFORMATD "6" YPTIMERTFORMAT
+#define YPTIMERSCALE 1000000LU
+#define YPGETTIME yukgettimeofday()
+typedef unsigned long long yptimer;
+typedef unsigned long ypcounter;
+
+#elif YPTIMERTYPE == 3
+#define YPTIMERTFORMAT "llu"
+#define YPCOUNTERTFORMAT "lu"
+#define YPTIMERTFORMATD "9" YPTIMERTFORMAT
+#define YPTIMERSCALE 1000000000LLU
+#define YPGETTIME gethrtime()
+typedef unsigned long long yptimer;
+typedef unsigned long ypcounter;
+
+#elif YPTIMERTYPE == 4
+#define YPTIMERTFORMAT "lu"
+#define YPCOUNTERTFORMAT "lu"
+#define YPTIMERTFORMATD "6" YPTIMERTFORMAT
+#define YPTIMERSCALE CLK_TCK
+#define YPGETTIME yuktimes()
+typedef unsigned long yptimer;
+typedef unsigned long ypcounter;
+
+#else
+#error Invalid YPTIMERTYPE in yuk.h
+
+#endif /* YPTIMERTYPE cases */
+
+extern yptimer ypexectime[];
+extern ypcounter ypexecount[];
+extern ypcounter ypabscount[];
+
+typedef struct yukvar_tag
+{
+ int vartype;
+ int extername;
+ int intername;
+} yukvar;
+
+extern yukvar yukvars[];