fix Makefile, README.md and bash script for 2001/herrmann1
This commit is contained in:
1 parent
7621291e2f
commit
bad0cd868f
3 files changed
+556
-469
No files matched your search
+258
-169
@@ -1,18 +1,9 @@
|
|||||||
#!/usr/bin/env make
|
#!/usr/bin/env make
|
||||||
#
|
#
|
||||||
# IOCCC 2001 entry Makefile
|
# IOCCC 2001 winning entry - herrmann1
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# An Historical Makefile NOTE:
|
|
||||||
#
|
|
||||||
# The orig.Makefile, if it exits, is the original Makefile before this IOCCC
|
|
||||||
# year directory was reworked so that entries are in separate directories.
|
|
||||||
# This also applies to any orig.ansi.mk and orig.common.mk files.
|
|
||||||
#
|
|
||||||
# Several Makefiles were modified / formed in 2022, and as such it may have
|
|
||||||
# elements that are not historically compatible with way entries were built.
|
|
||||||
#
|
|
||||||
# Regarding individual entries:
|
# Regarding individual entries:
|
||||||
#
|
#
|
||||||
# IOCCC winning entry code may not work on your system. Even with standards,
|
# IOCCC winning entry code may not work on your system. Even with standards,
|
||||||
@@ -45,192 +36,290 @@
|
|||||||
# See: http://creativecommons.org/licenses/by-sa/3.0/
|
# See: http://creativecommons.org/licenses/by-sa/3.0/
|
||||||
|
|
||||||
|
|
||||||
SHELL= /bin/sh
|
#############################
|
||||||
CAT= cat
|
# shell used by this Makefile
|
||||||
RM= rm
|
#############################
|
||||||
SED= sed
|
|
||||||
TRUE= true
|
|
||||||
#CINCLUDE= -I ${HOMEBREW_PREFIX}/include/SDL2
|
|
||||||
|
|
||||||
# optimization
|
|
||||||
#
|
#
|
||||||
# Most compiles will safely use -O2. Some can use only -O.
|
SHELL= bash
|
||||||
# A few compilers have broken optimizers and thus you may
|
|
||||||
# not want anything.
|
#######################
|
||||||
|
# common tool locations
|
||||||
|
#######################
|
||||||
|
#
|
||||||
|
include ../../var.mk
|
||||||
|
|
||||||
|
# Set X11_LIBDIR to the directory where the X11 library resides
|
||||||
|
#
|
||||||
|
#X11_LIBDIR= /usr/X11R6/lib
|
||||||
|
#X11_LIBDIR= /usr/X11/lib
|
||||||
|
X11_LIBDIR= /opt/X11/lib
|
||||||
|
|
||||||
|
# Set X11_INCLUDEDIR to the directory where the X11 include files reside
|
||||||
|
#
|
||||||
|
#X11_INCDIR= /usr/X11R6/include
|
||||||
|
#X11_INCDIR= /usr/X11/include
|
||||||
|
X11_INCDIR= /opt/X11/include
|
||||||
|
|
||||||
|
# Common C compiler warnings to silence
|
||||||
|
#
|
||||||
|
CSILENCE=
|
||||||
|
#CSILENCE= -Wno-implicit-int
|
||||||
|
|
||||||
|
# Common C compiler warning flags
|
||||||
|
#
|
||||||
|
#CWARN= ${CSILENCE}
|
||||||
|
#CWARN= -Wall ${CSILENCE}
|
||||||
|
#CWARN= -Wall -Wextra ${CSILENCE}
|
||||||
|
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
|
||||||
|
|
||||||
|
# Compiler standard
|
||||||
|
#
|
||||||
|
#CSTD=
|
||||||
|
#CSTD= -ansi
|
||||||
|
CSTD= -std=gnu99
|
||||||
|
|
||||||
|
# Compiler bit architecture
|
||||||
|
#
|
||||||
|
# Some entries require 32-bitness:
|
||||||
|
# ARCH= -m32
|
||||||
|
#
|
||||||
|
# Some entries require 64-bitness:
|
||||||
|
# ARCH= -m64
|
||||||
|
#
|
||||||
|
# By default we assume nothing:
|
||||||
|
#
|
||||||
|
ARCH=
|
||||||
|
|
||||||
|
# Defines that are needed to compile
|
||||||
|
#
|
||||||
|
CDEFINE=
|
||||||
|
#CDEFINE= -DIOCCC
|
||||||
|
|
||||||
|
# Include files that are needed to compile
|
||||||
|
#
|
||||||
|
CINCLUDE=
|
||||||
|
#CINCLUDE= -include stdlib.h
|
||||||
|
#CINCLUDE= -include stdio.h
|
||||||
|
#CINCLUDE= -include stdlib.h -include stdio.h
|
||||||
|
#CINCLUDE= -I ${X11_INCDIR} -I ${X11_INCDIR}/X11
|
||||||
|
#CINCLUDE= `${SDL2_CONFIG} --cflags`
|
||||||
|
|
||||||
|
# Optimization
|
||||||
|
#
|
||||||
|
# Most compiles will safely use -O2. Some can use only -O1 or -O.
|
||||||
|
# A few compilers have broken optimizers or this entry make break
|
||||||
|
# under those buggy optimizers and thus you may not want anything.
|
||||||
|
# Reasonable compilers will allow for -O3.
|
||||||
#
|
#
|
||||||
#OPT=
|
#OPT=
|
||||||
#OPT= -O
|
#OPT= -O
|
||||||
OPT= -O2
|
#OPT= -O1
|
||||||
|
#OPT= -O2
|
||||||
|
OPT= -O3
|
||||||
|
|
||||||
# flags for ANSI compiles
|
# Default flags for ANSI C compilation
|
||||||
#
|
#
|
||||||
# NOTE: Some ANSI compilers make use of -Xa to turn on ANSI mode,
|
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
|
||||||
# others such as gcc may want -ansi, others (Compaq Tru64 Unix)
|
|
||||||
# want -std1, and others may want nothing at all.
|
|
||||||
# Adjust the CFLAGS line as needed.
|
|
||||||
#
|
|
||||||
# NOTE: Some compilers cannot optimize, or optimize some entries
|
|
||||||
# incorrectly. You might want to turn on -O to see if your
|
|
||||||
# compiler can handle them.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#CFLAGS= -Xa ${OPT}
|
|
||||||
#CFLAGS= -std1 $(OPT)
|
|
||||||
CFLAGS= -ansi ${OPT}
|
|
||||||
|
|
||||||
# NOTE: On some systems, the library path does not include the location
|
# Libraries needed to build
|
||||||
# of the X11 libraries. You might need to use a -L/path/to/X11/lib/dir
|
|
||||||
# in order to compile with these libs.
|
|
||||||
#
|
#
|
||||||
X11CCFLAGS= -I/usr/X11R6/include -I/usr/X11R6/include/X11 -I/usr/include/X11
|
LIBS=
|
||||||
#X11CCFLAGS=
|
#LIBS= -lm
|
||||||
X11LDFLAGS= -L/usr/X11R6/lib -Wl,-R/usr/X11R6/lib
|
#LIBS= -L ${X11_LIBDIR} -lX11
|
||||||
#X11LDFLAGS=
|
#LIBS= `${SDL2_CONFIG} --libs`
|
||||||
|
|
||||||
# ANSI compiler
|
# C compiler to use
|
||||||
#
|
|
||||||
# Set CC to the name of your ANSI compiler.
|
|
||||||
#
|
|
||||||
# Some entries seem to need gcc. If you have gcc, set
|
|
||||||
# both CC and MAY_NEED_GCC to gcc.
|
|
||||||
#
|
|
||||||
# If you do not have gcc, set CC to the name of your ANSI compiler, and
|
|
||||||
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
|
|
||||||
# to disable such programs.
|
|
||||||
#
|
#
|
||||||
CC= cc
|
CC= cc
|
||||||
MAY_NEED_GCC= gcc
|
#CC=clang
|
||||||
|
#CC=gcc
|
||||||
|
|
||||||
# winners that compile under ANSI C
|
# Compiler add-ons or replacements for clang only
|
||||||
#
|
#
|
||||||
WINNERS= anonymous bellard bellard.otccex cheong coupard \
|
ifeq ($(CC),clang)
|
||||||
ctk dgbeards herrmann1 herrmann2 jason kev ollinger rosten \
|
|
||||||
schweikh westley williams
|
|
||||||
ALT_NAMES= westley.orig
|
|
||||||
DATA_FILES= anonymous_files bellard_files herrmann1_files herrmann2_files
|
|
||||||
|
|
||||||
|
|
||||||
all: ${WINNERS}
|
|
||||||
|
|
||||||
# Most likely to amaze
|
|
||||||
#
|
#
|
||||||
anonymous: anonymous.c
|
#CSILENCE+=
|
||||||
magic='${MAY_NEED_GCC} -O1'; \
|
|
||||||
X='-DA(X)=#X'; \
|
|
||||||
warning='-pedantic -Dprocessor'; \
|
|
||||||
$$magic $$warning -Dmagic= $$X "-DX=A($$magic \"$$X\")" \
|
|
||||||
-o anonymous anonymous.c
|
|
||||||
|
|
||||||
anonymous_files: anonymous.ten.c
|
|
||||||
|
|
||||||
# Best abuse of the rules
|
|
||||||
#
|
#
|
||||||
bellard: bellard.c
|
CWARN+= -Weverything
|
||||||
${CC} -rdynamic ${CFLAGS} bellard.c -o bellard -ldl
|
|
||||||
|
|
||||||
bellard_files: bellard.otccex.c
|
|
||||||
|
|
||||||
# Best short program
|
|
||||||
#
|
#
|
||||||
cheong: cheong.c
|
endif
|
||||||
${CC} ${CFLAGS} cheong.c -o cheong
|
|
||||||
|
|
||||||
# Most obfuscated sound
|
# Specific add-ons or replacements for gcc only
|
||||||
#
|
#
|
||||||
coupard: coupard.c
|
ifeq ($(CC),gcc)
|
||||||
${CC} ${CFLAGS} -o coupard coupard.c
|
|
||||||
|
|
||||||
# Worst Driver
|
|
||||||
#
|
#
|
||||||
ctk: ctk.c
|
#CSILENCE+=
|
||||||
${CC} ${CFLAGS} -o ctk ctk.c
|
|
||||||
|
|
||||||
# Worst AI
|
|
||||||
#
|
#
|
||||||
dgbeards: dgbeards.c
|
#CWARN+=
|
||||||
${CC} ${CFLAGS} -DE=break -DF=char -DK=case -DP=int -DR=return \
|
|
||||||
-DI=0xFFFF dgbeards.c -o dgbeards
|
|
||||||
|
|
||||||
# Best abuse of the C preprocessor
|
|
||||||
#
|
#
|
||||||
herrmann1: herrmann1.c herrmann1.sh
|
endif
|
||||||
@echo "NOTE: $@ must be built/run using the script $@.sh"
|
|
||||||
${SHELL} ./herrmann1.sh
|
|
||||||
|
|
||||||
herrmann1_files: herrmann1.gcd herrmann1.sh herrmann1.times2
|
|
||||||
|
|
||||||
# Most eye-crossing
|
##############################
|
||||||
|
# Special flags for this entry
|
||||||
|
##############################
|
||||||
#
|
#
|
||||||
# This entry requires the GCC -include feature.
|
ENTRY= herrmann1
|
||||||
|
PROG= ${ENTRY}
|
||||||
#
|
#
|
||||||
herrmann2: herrmann2.c
|
OBJ= ${PROG}.o
|
||||||
${MAY_NEED_GCC} ${CFLAGS} herrmann2.c -o herrmann2 \
|
DATA= herrmann1.gcd herrmann1.sh herrmann1.times2
|
||||||
-include /usr/include/stdlib.h -include /usr/include/stdio.h \
|
TARGET= ${PROG}
|
||||||
-include /usr/include/time.h -include /usr/include/unistd.h
|
|
||||||
|
|
||||||
herrmann2_files: herrmann2.cup herrmann2.ioccc
|
|
||||||
|
|
||||||
# Best Of Show
|
|
||||||
#
|
#
|
||||||
jason: jason.c
|
ALT_OBJ=
|
||||||
${CC} ${CFLAGS} -o jason jason.c
|
ALT_TARGET=
|
||||||
|
|
||||||
# Best Curses Game
|
|
||||||
|
#################
|
||||||
|
# build the entry
|
||||||
|
#################
|
||||||
#
|
#
|
||||||
kev: kev.c
|
all: data ${TARGET}
|
||||||
${CC} ${CFLAGS} -DPORT=5455 -DSPEED=50 -o kev kev.c \
|
|
||||||
-lcurses -ltermcap \
|
|
||||||
-Dl_="socket(il.sin_family=AF_INET,SOCK_STREAM,0)"
|
|
||||||
|
|
||||||
# Best primal ASCII graphics
|
|
||||||
#
|
|
||||||
ollinger: ollinger.c
|
|
||||||
${CC} ${CFLAGS} ollinger.c -o ollinger
|
|
||||||
|
|
||||||
# Best abuse of the user
|
|
||||||
#
|
|
||||||
rosten: rosten.c
|
|
||||||
${CC} ${CFLAGS} rosten.c ${X11CCFLAGS} ${X11LDFLAGS} -pedantic -lX11 \
|
|
||||||
-o rosten
|
|
||||||
|
|
||||||
# Best one-liner
|
|
||||||
#
|
|
||||||
schweikh: schweikh.c
|
|
||||||
${CC} ${CFLAGS} schweikh.c -o schweikh
|
|
||||||
|
|
||||||
# Best position-independant code
|
|
||||||
#
|
|
||||||
westley: westley.c
|
|
||||||
${CC} ${CFLAGS} westley.c -o westley
|
|
||||||
|
|
||||||
westley.orig: westley.orig.c
|
|
||||||
${CC} ${CFLAGS} westley.orig.c -o westley.orig
|
|
||||||
|
|
||||||
# Best position-independant code
|
|
||||||
#
|
|
||||||
williams: williams.c
|
|
||||||
${CC} williams.c ${X11CCFLAGS} ${X11LDFLAGS} -lX11 -o williams
|
|
||||||
|
|
||||||
everything: ${WINNERS} ${ALT_NAMES} ${DATA_FILES}
|
|
||||||
|
|
||||||
love:
|
|
||||||
@echo 'not war?'
|
|
||||||
|
|
||||||
haste:
|
|
||||||
${MAKE} waste
|
|
||||||
|
|
||||||
waste:
|
|
||||||
@echo 'waste'
|
|
||||||
|
|
||||||
clean:
|
|
||||||
${RM} -f *.o a.out core ${WINNERS}
|
|
||||||
|
|
||||||
clobber: clean
|
|
||||||
${RM} -f ${WINNERS}
|
|
||||||
${RM} -f ${ALT_NAMES}
|
|
||||||
|
|
||||||
nuke: clobber
|
|
||||||
@${TRUE}
|
@${TRUE}
|
||||||
|
|
||||||
install: all
|
.PHONY: all alt data everything clean clobber install \
|
||||||
${CAT} ${WINNERS} ${ALT_NAMES} > /dev/null
|
love haste waste maker easter_egg sandwich \
|
||||||
|
supernova deep_magic magic charon pluto
|
||||||
|
|
||||||
|
${PROG}: ${PROG}.c ${PROG}.sh
|
||||||
|
${SHELL} ./herrmann1.sh
|
||||||
|
|
||||||
|
# alternative executable
|
||||||
|
#
|
||||||
|
alt: data ${ALT_TARGET}
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
# data files
|
||||||
|
#
|
||||||
|
data: ${DATA}
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
# both all and alt
|
||||||
|
#
|
||||||
|
everything: all alt
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
# utility rules
|
||||||
|
###############
|
||||||
|
#
|
||||||
|
clean:
|
||||||
|
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||||
|
@-if [ -f indent.c ]; then \
|
||||||
|
echo ${RM} -f indent.c; \
|
||||||
|
${RM} -f indent.c; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clobber: clean
|
||||||
|
${RM} -f ${TARGET} ${ALT_TARGET}
|
||||||
|
@-if [ -e sandwich ]; then \
|
||||||
|
${RM} -f sandwich; \
|
||||||
|
echo 'ate sandwich'; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
install:
|
||||||
|
@echo "Dr. Spock says that is not logical!"
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
# you may be able to misunderstand the source by reading indent.c
|
||||||
|
#
|
||||||
|
indent.c: ${PROG}.c
|
||||||
|
@if which "${GINDENT}" >/dev/null 2>&1; then \
|
||||||
|
echo ${RM} -f $@; \
|
||||||
|
${RM} -f $@; \
|
||||||
|
echo "${GINDENT} < $< > $@"; \
|
||||||
|
${GINDENT} < $< > $@; \
|
||||||
|
elif which "${INDENT}" >/dev/null 2>&1; then \
|
||||||
|
echo ${RM} -f $@; \
|
||||||
|
${RM} -f $@; \
|
||||||
|
echo "${INDENT} < $< > $@"; \
|
||||||
|
${INDENT} < $< > $@; \
|
||||||
|
else \
|
||||||
|
echo "no intent tool found, ident $< yourself, sorry"; \
|
||||||
|
echo "exit 1"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##################
|
||||||
|
# 133t hacker rulz
|
||||||
|
##################
|
||||||
|
#
|
||||||
|
love:
|
||||||
|
@echo 'not war?'
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
haste:
|
||||||
|
$(MAKE) waste
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
waste:
|
||||||
|
@echo 'haste'
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
maker:
|
||||||
|
@echo 'Participate in a maker faire'
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
easter_egg:
|
||||||
|
@echo "you expected to often misunderstand this $${RANDOM} magic"
|
||||||
|
@echo "chongo '<was here>' /\\oo/\\"
|
||||||
|
@echo "Eggy"
|
||||||
|
|
||||||
|
sandwich: easter_egg
|
||||||
|
@if [ `id -u` -eq 0 ]; then \
|
||||||
|
echo 'Okay.'; \
|
||||||
|
echo "$${RANDOM}`date +%s`$${RANDOM}" > $@; \
|
||||||
|
else \
|
||||||
|
echo 'What? Make it yourself.'; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Understand the history of the Homebrew Computer Club
|
||||||
|
# as well as the West Coast Computer Faire and
|
||||||
|
# you might be confused different. :-)
|
||||||
|
#
|
||||||
|
supernova: sandwich
|
||||||
|
@-if [ -r .code_anal ]; then \
|
||||||
|
${RM} -f .code_anal_v6; \
|
||||||
|
else \
|
||||||
|
echo "planet deniers, like some members of the IAU, are so cute when they try to defend their logic"; \
|
||||||
|
fi
|
||||||
|
@echo "A $@ helps ${MAKE} the elements that help form planets"
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
deep_magic: supernova
|
||||||
|
@-if [ -r .code_anal ]; then \
|
||||||
|
ccode_analysis --deep_magic 7889066cdbdf09b0408021754586e895be641cc9be29e7eafd3ca65359541f17 \
|
||||||
|
--FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
|
||||||
|
else \
|
||||||
|
echo "Wrong! Do it again!"; \
|
||||||
|
sleep 2; \
|
||||||
|
echo "Wrong! Do it again!"; \
|
||||||
|
sleep 2; \
|
||||||
|
echo "Wrong! Do it again!"; \
|
||||||
|
fi
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
magic: deep_magic
|
||||||
|
@-if [ -r .code_anal ]; then \
|
||||||
|
ccode_analysis --level 20003 --mode 5717175 --FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
|
||||||
|
else \
|
||||||
|
echo "If you don't eat yer meat, you can't have any pudding!"; \
|
||||||
|
echo "How can you have any pudding if you don't eat yer meat?!"; \
|
||||||
|
fi
|
||||||
|
@${TRUE}
|
||||||
|
|
||||||
|
# The IOCCC resident astronomer states
|
||||||
|
#
|
||||||
|
charon: magic
|
||||||
|
@echo "$@ is a dwarf planet"
|
||||||
|
@echo "dwarf is a type of planet"
|
||||||
|
@echo "therefore IAU, $@ is a planet"
|
||||||
|
|
||||||
|
pluto: charon
|
||||||
|
${MAKE} charon
|
||||||
|
@echo "$@ is a dwarf planet"
|
||||||
|
@echo "dwarf is a type of planet"
|
||||||
|
@echo "therefore, $@ is a planet"
|
||||||
|
@echo "having lots of planets is good feature because supernovae can help ${MAKE} a lot of them"
|
||||||
+297
-299
@@ -1,4 +1,4 @@
|
|||||||
Best abuse of the C preprocessor:
|
# Best abuse of the C preprocessor:
|
||||||
|
|
||||||
Immanuel Herrmann
|
Immanuel Herrmann
|
||||||
University of Freiburg, Germany
|
University of Freiburg, Germany
|
||||||
@@ -8,356 +8,354 @@ Best abuse of the C preprocessor:
|
|||||||
|
|
||||||
http://pcpool.mathematik.uni-freiburg.de/~immi/
|
http://pcpool.mathematik.uni-freiburg.de/~immi/
|
||||||
|
|
||||||
|
# To build:
|
||||||
|
|
||||||
Judges' Comments:
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
To build:
|
### To run:
|
||||||
|
|
||||||
Running and building are combined for this entry.
|
```sh
|
||||||
|
./herrmann1.sh 'prg=file'
|
||||||
|
```
|
||||||
|
|
||||||
Try:
|
### Try:
|
||||||
./herrmann1.sh 'prg=herrmann1.times2'
|
|
||||||
-or-
|
|
||||||
./herrmann1.sh 'prg=herrmann1.gcd'
|
|
||||||
|
|
||||||
There are some clear hints in the source code as to the
|
```sh
|
||||||
purpose of this program. Perhaps the only way to figure out what is
|
./herrmann1.sh 'prg=herrmann1.times2'
|
||||||
going on is to look at the differences between the runs of the C
|
```
|
||||||
preprocessor! Computer Science students should recognize what is going
|
|
||||||
on.
|
|
||||||
|
|
||||||
|
-or-
|
||||||
|
|
||||||
Selected Author's Comments:
|
```sh
|
||||||
|
./herrmann1.sh 'prg=herrmann1.gcd'
|
||||||
|
```
|
||||||
|
|
||||||
Many cool things have been done with the preprocessor,
|
## Judges' comments:
|
||||||
e. g. calculation of prime numbers or the tower of Hanoi. However,
|
|
||||||
up to now, no one proved that the preprocessor is Turing complete,
|
|
||||||
and I wondered why. Well, the answer is simply that the
|
|
||||||
preprocessor is _not_ Turing complete, at least not if the program
|
|
||||||
is preprocessed only once. This is true even if the program is
|
|
||||||
allowed to include itself. (The reason being that for a given
|
|
||||||
program, the preprocessor has only a finite number of states, plus
|
|
||||||
a stack consisting of the places which the file has been included
|
|
||||||
from. This is only a push-down automaton.)
|
|
||||||
|
|
||||||
Well, this entry _is_ a Turing machine implemented in the
|
There are some clear hints in the source code as to the
|
||||||
preprocessor; so of course, it has to be preprocessed several
|
purpose of this program. Perhaps the only way to figure out what is
|
||||||
times. Here are the main features:
|
going on is to look at the differences between the runs of the C
|
||||||
|
preprocessor! Computer Science students should recognize what is going
|
||||||
|
on.
|
||||||
|
|
||||||
- Easy to program: Write your own Turing programs in a nice
|
## Author's comments:
|
||||||
syntax.
|
|
||||||
|
|
||||||
- Easy to debug: (some) errors in the Turing machine program will
|
Many cool things have been done with the preprocessor,
|
||||||
be reported nicely. (That's something which is not often seen in
|
e. g. calculation of prime numbers or the tower of Hanoi. However,
|
||||||
IOCCC programs.)
|
up to now, no one proved that the preprocessor is Turing complete,
|
||||||
|
and I wondered why. Well, the answer is simply that the
|
||||||
|
preprocessor is _not_ Turing complete, at least not if the program
|
||||||
|
is preprocessed only once. This is true even if the program is
|
||||||
|
allowed to include itself. (The reason being that for a given
|
||||||
|
program, the preprocessor has only a finite number of states, plus
|
||||||
|
a stack consisting of the places which the file has been included
|
||||||
|
from. This is only a push-down automaton.)
|
||||||
|
|
||||||
- Ultra-fast: The resulting C program will print the output in
|
Well, this entry _is_ a Turing machine implemented in the
|
||||||
time O(n), where n is the length of the output. This means for
|
preprocessor; so of course, it has to be preprocessed several
|
||||||
example that you can solve NP hard problems in polynomial time!
|
times. Here are the main features:
|
||||||
;-)
|
|
||||||
|
|
||||||
- And best of all: During the preprocessing, watch the animated
|
- Easy to program: Write your own Turing programs in a nice
|
||||||
Turing machine running over the tape and doing its work in your
|
syntax.
|
||||||
terminal!
|
|
||||||
|
|
||||||
|
- Easy to debug: (some) errors in the Turing machine program will
|
||||||
|
be reported nicely. (That's something which is not often seen in
|
||||||
|
IOCCC programs.)
|
||||||
|
|
||||||
|
- Ultra-fast: The resulting C program will print the output in
|
||||||
|
time O(n), where n is the length of the output. This means for
|
||||||
|
example that you can solve NP hard problems in polynomial time!
|
||||||
|
;-)
|
||||||
|
|
||||||
How to use it
|
- And best of all: During the preprocessing, watch the animated
|
||||||
=============
|
Turing machine running over the tape and doing its work in your
|
||||||
|
terminal!
|
||||||
|
|
||||||
For the impatient
|
### How to use it
|
||||||
-----------------
|
|
||||||
|
|
||||||
The info files "herrmann1.turing" and "herrmann1.gcd" are sample
|
For the impatient
|
||||||
programs for the Turing machine. For example, type
|
-----------------
|
||||||
|
|
||||||
./herrmann1.sh 'prg=herrmann1.times2'
|
The info files "herrmann1.turing" and "herrmann1.gcd" are sample
|
||||||
|
programs for the Turing machine. For example, type
|
||||||
|
|
||||||
and watch the animated Turing machine multiply 8 by two (in
|
```sh
|
||||||
unary representation). Here's a screen shot during compilation:
|
./herrmann1.sh 'prg=herrmann1.times2'
|
||||||
|
```
|
||||||
|
|
||||||
/*
|
and watch the animated Turing machine multiply 8 by two (in
|
||||||
*
|
unary representation). Here's a screen shot during compilation:
|
||||||
* State: st2.
|
|
||||||
*
|
|
||||||
* _ _ _ _ _ * _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
||||||
* ... O O I I I I I O I I I I I O O ...
|
|
||||||
* ~ ~ ~ ~ ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
(As on real videos, you'll see a bit of "white noise" at the
|
/*
|
||||||
beginning and at the end.;-) After compilation has terminated,
|
*
|
||||||
type ./prog to see the final result. The output will be
|
* State: st2.
|
||||||
|
*
|
||||||
|
* _ _ _ _ _ * _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
* ... O O I I I I I O I I I I I O O ...
|
||||||
|
* ~ ~ ~ ~ ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
Final tape:
|
(As on real videos, you'll see a bit of "white noise" at the
|
||||||
|
beginning and at the end.;-) After compilation has terminated,
|
||||||
|
type ./prog to see the final result. The output will be
|
||||||
|
|
||||||
*
|
Final tape:
|
||||||
..OOIIIIIIIIIIIIIIIIOOOO..
|
|
||||||
*
|
|
||||||
|
|
||||||
(Note that the last frame of the animation is _not_ the final
|
*
|
||||||
result.)
|
..OOIIIIIIIIIIIIIIIIOOOO..
|
||||||
|
*
|
||||||
|
|
||||||
|
(Note that the last frame of the animation is _not_ the final
|
||||||
|
result.)
|
||||||
|
|
||||||
In the previous example, the Turing machine started on the default
|
|
||||||
tape of the program "times2.turing". To provide your own tape, type
|
|
||||||
(for example)
|
|
||||||
|
|
||||||
./build prg=times2.turing tape="O O O I I I O O O"
|
In the previous example, the Turing machine started on the default
|
||||||
|
tape of the program "times2.turing". To provide your own tape, type
|
||||||
|
(for example)
|
||||||
|
|
||||||
(The O's and I's are letters, not digits.) You might prefer to
|
./build prg=times2.turing tape="O O O I I I O O O"
|
||||||
provide only a finite portion of the tape, like I did above. In
|
|
||||||
this case, the remainder of the tape is filled with O's. ;-)
|
|
||||||
|
|
||||||
If you just type
|
(The O's and I's are letters, not digits.) You might prefer to
|
||||||
./build
|
provide only a finite portion of the tape, like I did above. In
|
||||||
and run the program, you'll get a usage message (and the return
|
this case, the remainder of the tape is filled with O's. ;-)
|
||||||
code will be 2).
|
|
||||||
|
|
||||||
Note: To get a really nice animation, you'll need a terminal which
|
If you just type:
|
||||||
is able to scroll fast enough. (xterm is not very good. The
|
|
||||||
kde terminal "konsole" or the text console under linux are much
|
|
||||||
better. Simply try some out.)
|
|
||||||
|
|
||||||
|
```
|
||||||
|
./build
|
||||||
|
```
|
||||||
|
|
||||||
|
and run the program, you'll get a usage message (and the return
|
||||||
|
code will be 2).
|
||||||
|
|
||||||
Writing your own programs
|
Note: To get a really nice animation, you'll need a terminal which
|
||||||
-------------------------
|
is able to scroll fast enough. (xterm is not very good. The
|
||||||
|
kde terminal "konsole" or the text console under linux are much
|
||||||
|
better. Simply try some out.)
|
||||||
|
|
||||||
Now, let's assume you want to write a program which adds 1 to a
|
### Writing your own programs
|
||||||
number in unary representation. (That is, a row of I's is
|
|
||||||
expected, and one more I is appended to the row.) Let's call it
|
|
||||||
"plus1.turing". Here's what it could look like:
|
|
||||||
|
|
||||||
/* Search beginning of number. */
|
Now, let's assume you want to write a program which adds 1 to a
|
||||||
#define start_O O, right, start
|
number in unary representation. (That is, a row of I's is
|
||||||
/* Number found. Move one step to the left. */
|
expected, and one more I is appended to the row.) Let's call it
|
||||||
#define start_I I, left, st2
|
"plus1.turing". Here's what it could look like:
|
||||||
/* Write a I and stop */
|
|
||||||
#define st2_O I, left, stop
|
|
||||||
|
|
||||||
Some explanations:
|
/* Search beginning of number. */
|
||||||
- The tape alphabet is always O and I.
|
#define start_O O, right, start
|
||||||
- The states can be anything starting with "st". "start" and
|
/* Number found. Move one step to the left. */
|
||||||
"stop" are the start and stop states, respectively.
|
#define start_I I, left, st2
|
||||||
- to define a state, use two lines: one for each letter on the
|
/* Write a I and stop */
|
||||||
tape. You may omit one of the lines if the Turing machine will
|
#define st2_O I, left, stop
|
||||||
never enter the state reading that letter. (In the example, the
|
|
||||||
line defining st2_I has been left out.)
|
|
||||||
- The order of the lines is irrelevant.
|
|
||||||
- You may use c-style comments. (Would you have guessed it?)
|
|
||||||
|
|
||||||
Now, the program can be used with
|
Some explanations:
|
||||||
|
- The tape alphabet is always O and I.
|
||||||
|
- The states can be anything starting with "st". "start" and
|
||||||
|
"stop" are the start and stop states, respectively.
|
||||||
|
- to define a state, use two lines: one for each letter on the
|
||||||
|
tape. You may omit one of the lines if the Turing machine will
|
||||||
|
never enter the state reading that letter. (In the example, the
|
||||||
|
line defining st2_I has been left out.)
|
||||||
|
- The order of the lines is irrelevant.
|
||||||
|
- You may use c-style comments. (Would you have guessed it?)
|
||||||
|
|
||||||
./herrmann1.sh 'prg=plus1.turing' 'tape="I I I"'
|
Now, the program can be used with
|
||||||
|
|
||||||
But what happens if no tape is provided? Up to now, the Turing
|
```sh
|
||||||
machine would start on an empty tape (that is, a tape filled with
|
./herrmann1.sh 'prg=plus1.turing' 'tape="I I I"'
|
||||||
O's). For many programs, this doesn't make much sense (as is
|
```
|
||||||
the case for "plus1.turing"). So you might want to provide a
|
|
||||||
default tape by adding a line like
|
|
||||||
|
|
||||||
#define tape O O O O O I I I I
|
But what happens if no tape is provided? Up to now, the Turing
|
||||||
|
machine would start on an empty tape (that is, a tape filled with
|
||||||
|
O's). For many programs, this doesn't make much sense (as is
|
||||||
|
the case for "plus1.turing"). So you might want to provide a
|
||||||
|
default tape by adding a line like
|
||||||
|
|
||||||
to your program.
|
#define tape O O O O O I I I I
|
||||||
|
|
||||||
|
to your program.
|
||||||
|
|
||||||
|
### Debugging
|
||||||
|
|
||||||
|
When writing long programs, the most common errors are to forget
|
||||||
|
to define a state or to misspell one. Let's assume you forgot the
|
||||||
|
line
|
||||||
|
|
||||||
|
#define start_I I, left, st2
|
||||||
|
|
||||||
|
Remove it and type
|
||||||
|
|
||||||
|
./herrmann1 'prg=plus1.turing'
|
||||||
|
|
||||||
|
The output will be
|
||||||
|
|
||||||
|
Undefined state start.
|
||||||
|
|
||||||
|
Tape:
|
||||||
|
|
||||||
Debugging
|
*
|
||||||
---------
|
..OOOOOOOOIIIIOO..
|
||||||
|
*
|
||||||
|
|
||||||
When writing long programs, the most common errors are to forget
|
and the return code will be 1. As you can see, the Turing machine
|
||||||
to define a state or to misspell one. Let's assume you forgot the
|
moved over the O's, but when it arrived at the I (still in state
|
||||||
line
|
start), the error occurred.
|
||||||
|
|
||||||
#define start_I I, left, st2
|
Note that other kinds of errors can cause compilation to fail.
|
||||||
|
If this happens, the build script will write the error message of
|
||||||
|
gcc into a file called "error" and then exit.
|
||||||
|
|
||||||
Remove it and type
|
### What the build script does
|
||||||
|
|
||||||
./herrmann1 'prg=plus1.turing'
|
In principle, the build script simply runs the preprocessor over
|
||||||
|
and over again, until nothing changes anymore; then, the program
|
||||||
|
is compiled. After each preprocessing step, the script outputs the
|
||||||
|
beginning of the program; this is where the animation takes place
|
||||||
|
(except in the first and last few steps).
|
||||||
|
|
||||||
|
However, there's a technical problem to overcome: Some compilers
|
||||||
|
(including gcc) insert a lot of white space during the
|
||||||
|
preprocessing. This is bad for two reasons. First, the animated
|
||||||
|
picture won't look right. And second, after some time, the file
|
||||||
|
will grow too big for your hard disk. (The amount of white space
|
||||||
|
grows exponentially.) So after each preprocessing, the first thing
|
||||||
|
the build script does is remove all the unnecessary white space
|
||||||
|
using sed.
|
||||||
|
|
||||||
|
(gcc would even insert #line directives if I didn't suppress
|
||||||
|
them with the -P option.)
|
||||||
|
|
||||||
|
### Some more details
|
||||||
|
|
||||||
|
- The arguments passed to the build script are passed on to gcc
|
||||||
|
with a "-D" before. I had a slight technical problem doing this
|
||||||
|
(especially with the spaces that can appear within the tape
|
||||||
|
argument). That made the build script a bit longer.
|
||||||
|
|
||||||
|
- It would be enough to pass the defines in the first
|
||||||
|
preprocessing. The program then "remembers" them. However, it
|
||||||
|
doesn't matter if they are passed in all preprocessings. (This
|
||||||
|
doesn't sound very impressive, but it has required some extra
|
||||||
|
lines of code.)
|
||||||
|
|
||||||
|
- During the preprocessing, intermediate files "herrmann1-1.c" and
|
||||||
|
"herrmann1-2.c" are generated.
|
||||||
|
|
||||||
|
- Also, a file "error" is generated. This file is removed after
|
||||||
|
the compilation, except if gcc produced an error; then it contains
|
||||||
|
the error message. (I can't let gcc output all its messages
|
||||||
|
directly, because the warnings would clobber the animation. I
|
||||||
|
could have made the compile script output the error file in case
|
||||||
|
of an error, but I didn't want to make it yet longer.)
|
||||||
|
|
||||||
The output will be
|
### Some technical details / obfuscations
|
||||||
|
|
||||||
Undefined state start.
|
- The program is compressed. In the first three preprocessing
|
||||||
|
passes, it uncompresses itself and initializes the
|
||||||
|
"variables". So if you want to understand how it works, the best
|
||||||
|
thing is to preprocess it three times and then look at it
|
||||||
|
again. (However, I wouldn't have wasted three passes if they
|
||||||
|
weren't needed anyway to initialize the tape in certain
|
||||||
|
cases. Find out why.)
|
||||||
|
|
||||||
Tape:
|
- The first problem I had to solve when writing this program was
|
||||||
|
to write a preprocessor program which outputs itself. Of course,
|
||||||
|
each program which doesn't contain any preprocessor directives
|
||||||
|
is such a program, but that's not what I needed. In fact, to do
|
||||||
|
this, the program has to include itself, but even then, it's not
|
||||||
|
easy.
|
||||||
|
|
||||||
*
|
- The next problem to solve was how to pass results of a
|
||||||
..OOOOOOOOIIIIOO..
|
calculation of one preprocessing to the next one. This is done
|
||||||
*
|
by outputting #defines with the result. But there's a problem
|
||||||
|
with this: it is impossible to output a "#define result xxx",
|
||||||
|
where xxx depends on the previous value of result. Try it if you
|
||||||
|
don't believe it. And find out what I did instead.
|
||||||
|
|
||||||
and the return code will be 1. As you can see, the Turing machine
|
- What's a useful way to store information, especially the content
|
||||||
moved over the O's, but when it arrived at the I (still in state
|
of the tape? Of course, a "#define tape OOIOOIOIIIIO" contains
|
||||||
start), the error occurred.
|
the information, but then, how do you access the information?
|
||||||
|
(For example, you won't be able to write preprocessor code which
|
||||||
|
replaces the first O by I.) My answer looks very much like the
|
||||||
|
way a stack would have been implemented in lambda calculus. (The
|
||||||
|
tape is implemented as two stacks, to be exact.) And still,
|
||||||
|
there were some technical problems to solve. Look at the program
|
||||||
|
for more details.
|
||||||
|
|
||||||
Note that other kinds of errors can cause compilation to fail.
|
- There are many other interesting things to look at, e.g. the way
|
||||||
If this happens, the build script will write the error message of
|
to access the information in the user-provided program, the way
|
||||||
gcc into a file called "error" and then exit.
|
a non-defined state is detected, the way the picture is
|
||||||
|
produced, etc. If you want a real challenge, try to understand
|
||||||
|
what the line "w j k(P ## x)" does.
|
||||||
|
|
||||||
|
- Due to the fact that our alphabet has only 53 ;-) letters, I had
|
||||||
What the build script does
|
to use many variables more than once.
|
||||||
==========================
|
|
||||||
|
- I couldn't refrain from doing a little bit of nasty stuff like
|
||||||
In principle, the build script simply runs the preprocessor over
|
|
||||||
and over again, until nothing changes anymore; then, the program
|
#define a 0&0
|
||||||
is compiled. After each preprocessing step, the script outputs the
|
#if !a
|
||||||
beginning of the program; this is where the animation takes place
|
|
||||||
(except in the first and last few steps).
|
Of course, it is a bit more subtle, and even useful.
|
||||||
|
|
||||||
However, there's a technical problem to overcome: Some compilers
|
- The layout of the source code..., well, let's call it the
|
||||||
(including gcc) insert a lot of white space during the
|
"modern art of programming" - a mixture of program-like
|
||||||
preprocessing. This is bad for two reasons. First, the animated
|
indenting and modern art. There are even some comments...
|
||||||
picture won't look right. And second, after some time, the file
|
|
||||||
will grow too big for your hard disk. (The amount of white space
|
### Compatibility
|
||||||
grows exponentially.) So after each preprocessing, the first thing
|
|
||||||
the build script does is remove all the unnecessary white space
|
- It works with many versions of gcc. I tested it with versions
|
||||||
using sed.
|
2.7.2.1, 2.8.1, 2.95.2, and ecgs-2.91.66. However, an old version
|
||||||
|
of gcc produced "internal compiler errors" (obviously not my
|
||||||
(gcc would even insert #line directives if I didn't suppress
|
fault).
|
||||||
them with the -P option.)
|
|
||||||
|
- The only warnings I get tell me that I'm undefining __FILE__ and
|
||||||
|
that preprocessing directives are not recognized within macro
|
||||||
Some more details
|
args. My answer to this is "yes, I know this and it's all
|
||||||
-----------------
|
right". With "-Wall", I also get some warnings about "/*"
|
||||||
|
inside comments (Well, _I_ like some well-placed "/*/*/".) as
|
||||||
- The arguments passed to the build script are passed on to gcc
|
well as some suggestions where to place some more parentheses
|
||||||
with a "-D" before. I had a slight technical problem doing this
|
(as if I didn't know the operator precedence).
|
||||||
(especially with the spaces that can appear within the tape
|
|
||||||
argument). That made the build script a bit longer.
|
- Different versions of cc all produced only rubbish. Apparently,
|
||||||
|
the preprocessors didn't really work. (I don't feel guilty
|
||||||
- It would be enough to pass the defines in the first
|
there, either. Even with very simple programs, they produced
|
||||||
preprocessing. The program then "remembers" them. However, it
|
mysterious output.)
|
||||||
doesn't matter if they are passed in all preprocessings. (This
|
|
||||||
doesn't sound very impressive, but it has required some extra
|
- For Mac-Users: It works with the C compiler of Codewarrior (an
|
||||||
lines of code.)
|
old version). This compiler even leaves out all that unnecessary
|
||||||
|
white space, so that no clean-up is needed. (It would be useful
|
||||||
- During the preprocessing, intermediate files "herrmann1-1.c" and
|
to write a kind of script which does the equivalent to the build
|
||||||
"herrmann1-2.c" are generated.
|
script, so that one does not have to choose "preprocess" from
|
||||||
|
the menu over and over again. I leave this as an exercise to the
|
||||||
- Also, a file "error" is generated. This file is removed after
|
experienced Mac programmer.)
|
||||||
the compilation, except if gcc produced an error; then it contains
|
|
||||||
the error message. (I can't let gcc output all its messages
|
- In the build script, I passed the -P option to gcc to suppress
|
||||||
directly, because the warnings would clobber the animation. I
|
the insertion of #line directives. If your compiler doesn't
|
||||||
could have made the compile script output the error file in case
|
support this option (and does insert #line directives), you
|
||||||
of an error, but I didn't want to make it yet longer.)
|
should change the call to sed to remove them, too: Add
|
||||||
|
|
||||||
|
-e "/^#line/ d"
|
||||||
|
|
||||||
|
to the sed parameters. Or, if your #line directives look like
|
||||||
Some technical details / obfuscations
|
|
||||||
====================================
|
# 15 "filename"
|
||||||
|
|
||||||
- The program is compressed. In the first three preprocessing
|
add
|
||||||
passes, it uncompresses itself and initializes the
|
|
||||||
"variables". So if you want to understand how it works, the best
|
-e "/^# [0-9]/ d"
|
||||||
thing is to preprocess it three times and then look at it
|
|
||||||
again. (However, I wouldn't have wasted three passes if they
|
instead.
|
||||||
weren't needed anyway to initialize the tape in certain
|
|
||||||
cases. Find out why.)
|
- First, I had "-ansi -pedantic" turned on, but on some systems,
|
||||||
|
the stdio.h is not compatible to that, so I turned it back off.
|
||||||
- The first problem I had to solve when writing this program was
|
|
||||||
to write a preprocessor program which outputs itself. Of course,
|
- The build script probably needs a bash to run in. So perhaps you
|
||||||
each program which doesn't contain any preprocessor directives
|
have to add "#!/bin/bash" or something like this at the
|
||||||
is such a program, but that's not what I needed. In fact, to do
|
beginning.
|
||||||
this, the program has to include itself, but even then, it's not
|
|
||||||
easy.
|
- On SunOS, I had to remove the "-q" option from diff in the build
|
||||||
|
script.
|
||||||
- The next problem to solve was how to pass results of a
|
|
||||||
calculation of one preprocessing to the next one. This is done
|
|
||||||
by outputting #defines with the result. But there's a problem
|
|
||||||
with this: it is impossible to output a "#define result xxx",
|
|
||||||
where xxx depends on the previous value of result. Try it if you
|
|
||||||
don't believe it. And find out what I did instead.
|
|
||||||
|
|
||||||
- What's a useful way to store information, especially the content
|
|
||||||
of the tape? Of course, a "#define tape OOIOOIOIIIIO" contains
|
|
||||||
the information, but then, how do you access the information?
|
|
||||||
(For example, you won't be able to write preprocessor code which
|
|
||||||
replaces the first O by I.) My answer looks very much like the
|
|
||||||
way a stack would have been implemented in lambda calculus. (The
|
|
||||||
tape is implemented as two stacks, to be exact.) And still,
|
|
||||||
there were some technical problems to solve. Look at the program
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
- There are many other interesting things to look at, e.g. the way
|
|
||||||
to access the information in the user-provided program, the way
|
|
||||||
a non-defined state is detected, the way the picture is
|
|
||||||
produced, etc. If you want a real challenge, try to understand
|
|
||||||
what the line "w j k(P ## x)" does.
|
|
||||||
|
|
||||||
- Due to the fact that our alphabet has only 53 ;-) letters, I had
|
|
||||||
to use many variables more than once.
|
|
||||||
|
|
||||||
- I couldn't refrain from doing a little bit of nasty stuff like
|
|
||||||
|
|
||||||
#define a 0&0
|
|
||||||
#if !a
|
|
||||||
|
|
||||||
Of course, it is a bit more subtle, and even useful.
|
|
||||||
|
|
||||||
- The layout of the source code..., well, let's call it the
|
|
||||||
"modern art of programming" - a mixture of program-like
|
|
||||||
indenting and modern art. There are even some comments...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Compatibility
|
|
||||||
=============
|
|
||||||
|
|
||||||
- It works with many versions of gcc. I tested it with versions
|
|
||||||
2.7.2.1, 2.8.1, 2.95.2, and ecgs-2.91.66. However, an old version
|
|
||||||
of gcc produced "internal compiler errors" (obviously not my
|
|
||||||
fault).
|
|
||||||
|
|
||||||
- The only warnings I get tell me that I'm undefining __FILE__ and
|
|
||||||
that preprocessing directives are not recognized within macro
|
|
||||||
args. My answer to this is "yes, I know this and it's all
|
|
||||||
right". With "-Wall", I also get some warnings about "/*"
|
|
||||||
inside comments (Well, _I_ like some well-placed "/*/*/".) as
|
|
||||||
well as some suggestions where to place some more parentheses
|
|
||||||
(as if I didn't know the operator precedence).
|
|
||||||
|
|
||||||
- Different versions of cc all produced only rubbish. Apparently,
|
|
||||||
the preprocessors didn't really work. (I don't feel guilty
|
|
||||||
there, either. Even with very simple programs, they produced
|
|
||||||
mysterious output.)
|
|
||||||
|
|
||||||
- For Mac-Users: It works with the C compiler of Codewarrior (an
|
|
||||||
old version). This compiler even leaves out all that unnecessary
|
|
||||||
white space, so that no clean-up is needed. (It would be useful
|
|
||||||
to write a kind of script which does the equivalent to the build
|
|
||||||
script, so that one does not have to choose "preprocess" from
|
|
||||||
the menu over and over again. I leave this as an exercise to the
|
|
||||||
experienced Mac programmer.)
|
|
||||||
|
|
||||||
- In the build script, I passed the -P option to gcc to suppress
|
|
||||||
the insertion of #line directives. If your compiler doesn't
|
|
||||||
support this option (and does insert #line directives), you
|
|
||||||
should change the call to sed to remove them, too: Add
|
|
||||||
|
|
||||||
-e "/^#line/ d"
|
|
||||||
|
|
||||||
to the sed parameters. Or, if your #line directives look like
|
|
||||||
|
|
||||||
# 15 "filename"
|
|
||||||
|
|
||||||
add
|
|
||||||
|
|
||||||
-e "/^# [0-9]/ d"
|
|
||||||
|
|
||||||
instead.
|
|
||||||
|
|
||||||
- First, I had "-ansi -pedantic" turned on, but on some systems,
|
|
||||||
the stdio.h is not compatible to that, so I turned it back off.
|
|
||||||
|
|
||||||
- The build script probably needs a bash to run in. So perhaps you
|
|
||||||
have to add "#!/bin/bash" or something like this at the
|
|
||||||
beginning.
|
|
||||||
|
|
||||||
- On SunOS, I had to remove the "-q" option from diff in the build
|
|
||||||
script.
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
name=herrmann1
|
name=herrmann1
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user