diff --git a/2000/dlowe/Makefile b/2000/dlowe/Makefile index 25524921d..680771740 100644 --- a/2000/dlowe/Makefile +++ b/2000/dlowe/Makefile @@ -1,215 +1,331 @@ -#!/bin/make -# 2000 makefile +#!/usr/bin/env make # -# Copyright (C) Simon Cooper, Landon Curt Noll, Peter Seebach -# and Leonid A. Broukhis, 2000. -# All Rights Reserved. Permission for personal, educational or non-profit -# use is granted provided this this copyright and notice are included in its -# entirety and remains unaltered. All other uses must receive prior permission -# from the contest judges. +# IOCCC 2000 winning entry - dlowe -SHELL= /bin/sh -CAT= cat -RM= rm -SED= sed -TRUE= true -#CINCLUDE= -I ${HOMEBREW_PREFIX}/include/SDL2 - -# optimization +################################################################################ # -# Most compiles will safely use -O2. Some can use only -O. -# A few compilers have broken optimizers and thus you may -# not want anything. +# Regarding individual entries: +# +# IOCCC winning entry code may not work on your system. Even with standards, +# conditions and build environments change, especially when it comes to more +# extreme code such you might find in an IOCCC winner. Moreover, what was +# allowed and liked in one IOCCC contest may no longer be liked/allowed in +# later IOCCC years. +# +# Corrections on winning author and fixing typos in remarks are VERY WELCOME. +# +# GitHub pull requests are welcome: +# +# If you have a patch that might make running an entry work in modern Unix-like +# environments, please create a GitHub pull request for the IOCCC judges to +# consider. +# +# Suggestions and corrections regarding Makefiles, winning author information, +# fixing typos in remarks, and code patches are welcome via opening a GitHub +# issue or better yet, by creating a GitHub pull request for the IOCCC judges +# to consider. To form a GitHub issue or GitHub pull, please visit: +# +# https://github.com/ioccc-src/winner +# +################################################################################ + +# This work by Landon Curt Noll and Leonid A. Broukhis is licensed under: +# +# Creative Commons Attribution-ShareAlike 3.0 Unported License. +# +# See: http://creativecommons.org/licenses/by-sa/3.0/ + + +############################# +# shell used by this Makefile +############################# +# +SHELL= bash + +####################### +# 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-gnu-statement-expression -Wno-unused-parameter + +# 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= -Dna=0 + +# 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} +#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= -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, -# 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} +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} -NO_ANSI_CFLAGS= -#NO_ANSI_CFLAGS= +# Libraries needed to build +# +LIBS= +#LIBS= -lm +#LIBS= -L ${X11_LIBDIR} -lX11 +#LIBS= `${SDL2_CONFIG} --libs` -# NOTE: On some systems, the library path does not include the location -# 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 -#X11CCFLAGS= -X11LDFLAGS= -L/usr/X11R6/lib -#X11LDFLAGS= - -# Perl -# -PERL= perl -#PERL= perl5 - -# ANSI compiler -# -# 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. +# C compiler to use # 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= anderson schneiderwent primenum bellard bmeyer briddlebane dhyang \ - dmy2jd jarijyrki dlowe natori rince robison thadgavin tomx -ALT_NAMES= schneiderwent.orig briddlebane.orig thadgavin.orig -DATA_FILES= schneiderwent_files bmeyer_files jarijyrki_files - - -all: ${WINNERS} - -# Best use of flags +ifeq ($(CC),clang) # -anderson: anderson.c - ${CC} ${CFLAGS} $? -o $@ - -# Most Timely Output +CSILENCE+= -Wno-cast-align -Wno-cast-qual -Wno-comma -Wno-float-equal \ + -Wno-implicit-int-conversion -Wno-missing-prototypes -Wno-padded \ + -Wno-poison-system-directories -Wno-shadow -Wno-shorten-64-to-32 \ + -Wno-sign-conversion -Wno-strict-prototypes -Wno-switch-enum \ + -Wno-undef -Wno-used-but-marked-unused # -schneiderwent: schneiderwent.c - ${CC} ${CFLAGS} $? -o $@ - -schneiderwent_files: schneiderwent.data - -schneiderwent.orig: schneiderwent.orig.c - ${CC} ${CFLAGS} $? -o $@ - -# Best Abuse of CPP +CWARN+= -Weverything # -primenum: primenum.c - ${CC} ${CFLAGS} $? -o $@ +endif -# Most Specific Output +# Specific add-ons or replacements for gcc only # -bellard: bellard.c - ${CC} ${CFLAGS} $? -o $@ +ifeq ($(CC),gcc) +# +#CSILENCE+= +# +#CWARN+= +# +endif -# Best Utility -# -# machines operating in 64 bit mode: -# -bmeyer: bmeyer.c - ${CC} -DY= -O6 $? -o $@ -lm -# -# linux/x86, glibc 2.0, libc4/5: -# -# bmeyer: bmeyer.c -# ${CC} -DY="__setfpucw(0x127f)" -O6 $? -o $@ -lm -# -# linux/x86, glibc 2.1: -# -# bmeyer: bmeyer.c -# ${MAY_NEED_GCC} -DY='int x=0x127f; __asm__ ("fldcw %0" : : "m" (*&x))' \ -# -O6 $? -o $@ -lm -bmeyer_files: lavabus.pgm lenna.glic michael.pgm - -# Best Abuse of User +############################## +# Special flags for this entry +############################## # -briddlebane: briddlebane.c - ${CC} ${CFLAGS} $? -o $@ -lm - -briddlebane.orig: briddlebane.orig.c - ${CC} ${CFLAGS} $? -o $@ -lm - -# Best Layout +ENTRY= dlowe +PROG= ${ENTRY} # -dhyang: dhyang.c - ${CC} ${CFLAGS} $? -o $@ - -dmy2jd: dmy2jd.c - ${CC} ${CFLAGS} $? -o $@ - -# Best of Show +OBJ= ${PROG}.o +DATA= +TARGET= ${PROG} # -jarijyrki: jarijyrki.c - ${CC} ${X11CCFLAGS} ${CFLAGS} -DNeedFunctionPrototypes \ - -DU=40 -DT=98 '-Dz=(T+1)*U*U' -DQ=80 -DS=20 -DN=10 -DB=5 -DG=23 \ - -Dp=7 '-DM=((p+1)*Q)+S' '-DH=(G*S)+S+S' -DC=XK_Up -DL=XK_Down \ - -DO=XK_Left -DV=XK_Right -DR=XK_Escape -D_=XK_BackSpace \ - $? -o $@ ${X11LDFLAGS} -lX11 +ALT_OBJ= +ALT_TARGET= -jarijyrki_files: sheet1.info -# Worst Abuse of the Rules +################# +# build the entry +################# # -# NOTE: You will need to adjust this path to the place where Perl has been -# installed on your system. Running "perl -V" may help you locate -# this place. -# -# The following bit of perl may help determining the values you need: -# -# perl -MConfig -e 'print "$Config{archlibexp}/CORE\n"' -# -# -dlowe: dlowe.c - ${CC} ${NO_ANSI_CFLAGS} -DPERL_POLLUTE \ - `${PERL} -MExtUtils::Embed -e ccopts` $? -o $@ \ - `${PERL} -MExtUtils::Embed -e ldopts` - -# Best Small Program -# -natori: natori.c - ${CC} ${CFLAGS} $? -o $@ -lm - -# Astronomically Obfuscated -# -rince: rince.c - ${CC} ${X11CCFLAGS} ${CFLAGS} -DM_PI=3.14159265358979323846 \ - $? -o $@ -lm ${X11LDFLAGS} -lX11 - -# Best game -# -robison: robison.c - ${CC} ${CFLAGS} $? -o $@ - -# Most Portable Output -# -thadgavin: thadgavin.c - ${CC} ${CFLAGS} $? -o $@ -lcurses -lm - -thadgavin.orig: thadgavin.orig.c - ${CC} ${CFLAGS} $? -o $@ -lncurses -lm - -# Most Complete Program -# -tomx: tomx.c - ${CC} ${CFLAGS} $? -o $@ - -everything: ${WINNERS} ${ALT_NAMES} ${DATA_FILES} - -clean: - ${RM} -f *.o a.out core ${WINNERS} - -clobber: clean - ${RM} -f ${WINNERS} - ${RM} -f ${ALT_NAMES} - -nuke: clobber +all: data ${TARGET} @${TRUE} -install: all - ${CAT} ${WINNERS} ${ALT_NAMES} > /dev/null +.PHONY: all alt data everything clean clobber install \ + love haste waste maker easter_egg sandwich \ + supernova deep_magic magic charon pluto + +${PROG}: ${PROG}.c + ${CC} ${CDEFINE} ${CSILENCE} -DPERL_POLLUTE \ + `${PERL} -MExtUtils::Embed -e ccopts` $? -o $@ \ + `${PERL} -MExtUtils::Embed -e ldopts` + +# 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 '' /\\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" diff --git a/2000/dlowe/README.md b/2000/dlowe/README.md index 1b53c17d8..f4778cc7f 100644 --- a/2000/dlowe/README.md +++ b/2000/dlowe/README.md @@ -1,247 +1,269 @@ -Worst Abuse of the Rules: +# Worst Abuse of the Rules: - David Lowe - 1224 11th Avenue - San Francisco, California, 94122 - USA +David Lowe +1224 11th Avenue +San Francisco, California, 94122 +USA - http://pootpoot.com/~dlowe/ +http://pootpoot.com/~dlowe/ + +## To build: + +```sh +make +``` + +The following bit of perl may help determining the values you need: + +```sh +perl -MConfig -e 'print "$Config{archlibexp}/CORE\n"' +``` + +### To run: + +```sh +./dlowe [file ...] +``` + +### Try: + +```sh +echo "13 14 15 16 17 + - * / p" | ./dlowe +``` + +## Judges' comments: + +When this entry was submitted the rules of the IOCCC did not prohibit +the use of embedded language interpreters. The judges considered +disqualifying this entry because of the use of perl, but on the other +hand it qualifies as the Worst Abuse of the Rules. As a previous winner +(*) David Lowe continues to inflict the highest quality "poot" on the +Judges. + +The program also contains an undocumented command for Chad and Chongo. +The judges' comments contain a clue to the hidden command :-). + +(*) The IOCCC uses an anonymous judging process which keeps the identity +of the submitters hidden until all the prize winners have been selected. + +## Author's comments: + +### Usage: + +./dlowe [file ...] + +### Synopsis: + +This is a reverse polish calculator, loosely based on the dc(1) unix +calculator. + +# Syntax: + +This program understands the following dc(1) commands: + + p prints the top stack value without altering the stack. + P prints the top stack value, removing it from the stack, and + doesn't print a trailing newline. + f prints the contents of the stack, one number per line, + without modifying it. + c clears the stack. + d pushes a copy of the top stack value onto the stack. + r reverses the order of the top two stack values. + +And the following arithmetic operators are supported: + + + Pops 2 values and pushes their sum. + - Pops 2 values and pushes the result of subtracting the first + from the second. + * Pops 2 values and pushes their product. + / Pops 2 values and pushes the result of dividing the second + by the first. + ^ Pops 2 values and pushes the result of raising the second + to the power of the first. + % Pops 2 values and pushes the remainder of the division that + / would do. + +The precision and range are double, like it or not, except that the +modulus operator actually returns (p1 - (p2 * (p1 / p2))), but with +the innermost division calculated at integer precision. This is +usually what you expect (e.g. echo "12 8 % p" | ./dlowe == 4) + +Commands are read from stdin or from a list of files named on +the command line. Unlike dc(1), multiple commands on the same line +must be space separated. Commands are only executed when a newline +or EOF is encountered. + +### Diagnostics: + +``` +"stack empty" Not enough on the stack for the requested command +"divide by zero" Attempt to divide by zero +"unimplemented" Invalid input +Floating point exception (core dumped) (or something to that effect) + Bug in Perl_sv_upgrade causes this in some cases when + the results of an operation are really huge (> 10^308) + This bug appears to be fixed in perl5.6.0 + +``` + +### Examples: + +```sh +$ echo "12 13 14 15 16 + + + + f" | ./dlowe +70 +$ echo "12 13 14 15 16 17 + - * / p" | ./dlowe +-0.0515873015873016 +$ echo "+" | ./dlowe +stack empty +$ echo "999999999999999 1 + p" | ./dlowe +1e+15 +$ echo "99999999999999 1 + p" | ./dlowe +100000000000000 +$ echo "12.5 9 % 10 * 15 + f" | ./dlowe +50 +$ echo "7 P 6 d P P 8 p" | ./dlowe | tr 876 tpo +poot +``` + +### Code Concept: + +We all know that Perl and other VHLLs (very high level languages) +are particularly well-suited for (among other things) string +handling, I/O, and powerful built-in datatypes, and (relatively) +poorly suited for number crunching and other processor-intensive +tasks - areas where C is strongest. This program takes this +knowledge to its extreme conclusion, using each language for its +strengths. Thus, it uses Perl to read and parse input, for output, +and for the easy-to-use list primitive, and uses C for mathematical +operations. Since the rules of this contest state that the program +must be generated by an ANSI C compiler, of course, the outer Perl +layer is wrapped with a thin layer of C. + +In case that wasn't clear, in a nutshell: this program is C, calling +embedded Perl (contained in a C string), which in turn calls back to +C, which performs math on Perl data types and calls Perl functions for +error reporting. + +### Requirements: + +Unfortunately, Perl is an evolving beast - that includes the +embedding API and the XS API. The code was developed under +Perl 5.005_03, successfully tested against Perl 5.6.0, Perl 5.005_02 +and Perl 5.004_04, and according to the version delta documentation, +should work as-is with Perl 5.002 and later (which has been around +since February 1996). To clarify - it's not the Perl code itself +that may be non-portable, it's the C code for embedding Perl and for +calling C from Perl. + +It is also important that Perl be installed cleanly and correctly. +You may have problems linking if, for example, you have multiple +overlapping versions of Perl installed (which might not be a problem +for scripts, but causes problems with embedding the interpreter). +More commonly, you may get non-fatal warnings from the linker, caused +by slight misconfigurations of Perl on your system. + +Some compilers also complain that "third argument of `main' is +deprecated" or something to that effect. But in Perl prior to +5.6.0, the header file "proto.h" actually had a prototype for main, +so applications which embed Perl must use the three argument form +of main. + +### Aside: history... + +Larry Wall wrote the original Perl in 1986-87, the same two successive +years he won the IOCCC. I hope this program helps you to realize that +this was no fluke - that Perl and Obfuscation are as inseparable as, +say, camels and humps. + +### Obfuscated? + +. Reverse polish notation is pretty strange, in and of itself. + +. The layout of the program is three roughly symmetrical "stacks" +of code. This layout is quite sensitive in places - my C indenter +actually breaks the code by inserting spaces in certain places. + +. Anyone who has ever programmed in Perl can attest to the fact that +it is particularly well-suited to obfuscation; thus, the Perl is +obfuscated. (Here's my favorite legal Perl from this program: +'_:$_=<>;' - but '$SS[$#SS]-=$SS[$#SS-1]' isn't bad, either). + +. I've eschewed traditional branch and loop structures such as +'if' and 'for', in favor of their oft-neglected cousins, 'goto' +and '?:', in both the Perl and C code. + +. I've used some highly magical Perl incantations, such as symbolic +references, the 'goto &NAME' syntax, AUTOLOAD for exception handling, +and abuse of the default scalar ($_). + +. I've also deliberately used Perl syntax that is very much unlike +C syntax: the &NAME rather than NAME() function calling syntax, +leaving off parentheses wherever possible, using print() instead +of printf(), and using the English style logic operators 'and' and +'or' rather than '&&' and '||', for example. + +. The fact that all the Perl code is in double-quotes doesn't lend +any readability to the regular expressions and quoted strings +therein. + +. The points and ways in which C and Perl connect are *really* +obscure. They're also incredibly poorly documented, as they're +primarily used in machine-generated code. However, there's a +wealth of example code on CPAN (www.cpan.org). + +. The Perl API functions are almost all macros, so you will probably +find that preprocessor expansion will only make things worse. They +also have helpful, verbose names like SvNV, SvIV, and newSVpv. I +couldn't have done better myself! + +. Figuring out how the mathematical C functions get called is a bit +tricky. Note the lack of explicit switching based on command +input. + +. Because of the "interesting" way that commands are interpreted, +all of the commands have synonyms. For example, if you find it +easier to remember, '=' is synonymous with 'd'. This is makes it +possible to write (even more) obfuscated reverse polish commands +(I figure this explanation moves the synonyms from 'bug' to +'feature'!) + +. The first IOCCC entry with an "easter egg"?... -Judges' Comments: - - To build: - - make dlowe - - To run: - - echo "13 14 15 16 17 + - * / p" | ./dlowe - - When this entry was submitted the rules of the IOCCC did not prohibit - the use of embedded language interpreters. The judges considered - disqualifying this entry because of the use of perl, but on the other - hand it qualifies as the Worst Abuse of the Rules. As a previous winner - (*) David Lowe continues to inflict the highest quality "poot" on the - Judges. - - The program also contains an undocumented command for Chad and Chongo. - The judges' comments contain a clue to the hidden command :-). - - (*) The IOCCC uses an anonymous judging process which keeps the identity - of the submitters hidden until all the prize winners have been selected. +Aside: on unobfuscated Perl +My original intent was to write obfuscated C and crystal-clear Perl, +to highlight my bending of the rules. Unfortunately, Perl really +doesn't lend itself to crystal-clear code... -Selected Author's Comments: +Bending the rules? +Well, the rules never state that you can't embed another programming +language, but on the other hand, knowing Perl probably isn't high on +the list of qualifications for judges... Oh dear, I guess your C +beautifier won't help too much, either ;) - Usage: - dlowe [file ...] +If you don't change the rules, it'll be embedded Ada next year! +### AutoDefend - Synopsis: - This is a reverse polish calculator, loosely based on the dc(1) unix - calculator. +A. Isn't this the obfuscated C contest? What's this Perl $#_&&$_? +D. Hey, this program *is* 100% C, and does not exec an external Perl +interpreter. It simply links against the Perl language library. +The "Perl code" is just a C string constant. - Syntax: - This program understands the following dc(1) commands: - p prints the top stack value without altering the stack. - P prints the top stack value, removing it from the stack, and - doesn't print a trailing newline. - f prints the contents of the stack, one number per line, - without modifying it. - c clears the stack. - d pushes a copy of the top stack value onto the stack. - r reverses the order of the top two stack values. +A. Perl isn't portable enough, or ubiquitous enough. - And the following arithmetic operators are supported: - + Pops 2 values and pushes their sum. - - Pops 2 values and pushes the result of subtracting the first - from the second. - * Pops 2 values and pushes their product. - / Pops 2 values and pushes the result of dividing the second - by the first. - ^ Pops 2 values and pushes the result of raising the second - to the power of the first. - % Pops 2 values and pushes the remainder of the division that - / would do. +D. I'd argue that it is more portable than X. According to the Perl +folks, it runs on the following platforms: Acorn, AIX, Amiga, AS/400, +BeOS, Concurrent, Debian, DEC OSF/1, Digital UNIX, EPOC, FreeBSD, +Guardian, HP-UX, IRIX, LinuxPPC, LynxOS, MacOS, MachTen, Minix, MPE/iX, +MS-DOS, MVS, NetBSD, Netware, NextStep, OpenBSD, OpenLinux, ODT, OpenVMS, +OS/2, OS390, OSR, PowerMAX, Psion, QNX, Redhat, Reliant UNIX, RISCOS, +SCO, SGI, SINIX, Slackware, Solaris, Sun, SuSE, Tandem, Tru64, UNIX, +U/WIN, Unixware, VMS, Win31, Win32, Windows 3.1, and Windows 95/98/NT/2K. +Granted, embeddable Perl isn't quite so portable, but still... - The precision and range are double, like it or not, except that the - modulus operator actually returns (p1 - (p2 * (p1 / p2))), but with - the innermost division calculated at integer precision. This is - usually what you expect (e.g. echo "12 8 % p" | ./dlowe == 4) - - Commands are read from stdin or from a list of files named on - the command line. Unlike dc(1), multiple commands on the same line - must be space separated. Commands are only executed when a newline - or EOF is encountered. - - - Diagnostics: - "stack empty" Not enough on the stack for the requested command - "divide by zero" Attempt to divide by zero - "unimplemented" Invalid input - Floating point exception (core dumped) (or something to that effect) - Bug in Perl_sv_upgrade causes this in some cases when - the results of an operation are really huge (> 10^308) - This bug appears to be fixed in perl5.6.0 - - - Examples: - $ echo "12 13 14 15 16 + + + + f" | ./dlowe - 70 - $ echo "12 13 14 15 16 17 + - * / p" | ./dlowe - -0.0515873015873016 - $ echo "+" | ./dlowe - stack empty - $ echo "999999999999999 1 + p" | ./dlowe - 1e+15 - $ echo "99999999999999 1 + p" | ./dlowe - 100000000000000 - $ echo "12.5 9 % 10 * 15 + f" | ./dlowe - 50 - $ echo "7 P 6 d P P 8 p" | ./dlowe | tr 876 tpo - poot - - - Code Concept: - We all know that Perl and other VHLLs (very high level languages) - are particularly well-suited for (among other things) string - handling, I/O, and powerful built-in datatypes, and (relatively) - poorly suited for number crunching and other processor-intensive - tasks - areas where C is strongest. This program takes this - knowledge to its extreme conclusion, using each language for its - strengths. Thus, it uses Perl to read and parse input, for output, - and for the easy-to-use list primitive, and uses C for mathematical - operations. Since the rules of this contest state that the program - must be generated by an ANSI C compiler, of course, the outer Perl - layer is wrapped with a thin layer of C. - - In case that wasn't clear, in a nutshell: this program is C, calling - embedded Perl (contained in a C string), which in turn calls back to - C, which performs math on Perl data types and calls Perl functions for - error reporting. - - - Requirements: - Unfortunately, Perl is an evolving beast - that includes the - embedding API and the XS API. The code was developed under - Perl 5.005_03, successfully tested against Perl 5.6.0, Perl 5.005_02 - and Perl 5.004_04, and according to the version delta documentation, - should work as-is with Perl 5.002 and later (which has been around - since February 1996). To clarify - it's not the Perl code itself - that may be non-portable, it's the C code for embedding Perl and for - calling C from Perl. - - It is also important that Perl be installed cleanly and correctly. - You may have problems linking if, for example, you have multiple - overlapping versions of Perl installed (which might not be a problem - for scripts, but causes problems with embedding the interpreter). - More commonly, you may get non-fatal warnings from the linker, caused - by slight misconfigurations of Perl on your system. - - Some compilers also complain that "third argument of `main' is - deprecated" or something to that effect. But in Perl prior to - 5.6.0, the header file "proto.h" actually had a prototype for main, - so applications which embed Perl must use the three argument form - of main. - - - Aside: history... - Larry Wall wrote the original Perl in 1986-87, the same two successive - years he won the IOCCC. I hope this program helps you to realize that - this was no fluke - that Perl and Obfuscation are as inseparable as, - say, camels and humps. - - - Obfuscated? - . Reverse polish notation is pretty strange, in and of itself. - - . The layout of the program is three roughly symmetrical "stacks" - of code. This layout is quite sensitive in places - my C indenter - actually breaks the code by inserting spaces in certain places. - - . Anyone who has ever programmed in Perl can attest to the fact that - it is particularly well-suited to obfuscation; thus, the Perl is - obfuscated. (Here's my favorite legal Perl from this program: - '_:$_=<>;' - but '$SS[$#SS]-=$SS[$#SS-1]' isn't bad, either). - - . I've eschewed traditional branch and loop structures such as - 'if' and 'for', in favor of their oft-neglected cousins, 'goto' - and '?:', in both the Perl and C code. - - . I've used some highly magical Perl incantations, such as symbolic - references, the 'goto &NAME' syntax, AUTOLOAD for exception handling, - and abuse of the default scalar ($_). - - . I've also deliberately used Perl syntax that is very much unlike - C syntax: the &NAME rather than NAME() function calling syntax, - leaving off parentheses wherever possible, using print() instead - of printf(), and using the English style logic operators 'and' and - 'or' rather than '&&' and '||', for example. - - . The fact that all the Perl code is in double-quotes doesn't lend - any readability to the regular expressions and quoted strings - therein. - - . The points and ways in which C and Perl connect are *really* - obscure. They're also incredibly poorly documented, as they're - primarily used in machine-generated code. However, there's a - wealth of example code on CPAN (www.cpan.org). - - . The Perl API functions are almost all macros, so you will probably - find that preprocessor expansion will only make things worse. They - also have helpful, verbose names like SvNV, SvIV, and newSVpv. I - couldn't have done better myself! - - . Figuring out how the mathematical C functions get called is a bit - tricky. Note the lack of explicit switching based on command - input. - - . Because of the "interesting" way that commands are interpreted, - all of the commands have synonyms. For example, if you find it - easier to remember, '=' is synonymous with 'd'. This is makes it - possible to write (even more) obfuscated reverse polish commands - (I figure this explanation moves the synonyms from 'bug' to - 'feature'!) - - . The first IOCCC entry with an "easter egg"?... - - - Aside: on unobfuscated Perl - My original intent was to write obfuscated C and crystal-clear Perl, - to highlight my bending of the rules. Unfortunately, Perl really - doesn't lend itself to crystal-clear code... - - - Bending the rules? - Well, the rules never state that you can't embed another programming - language, but on the other hand, knowing Perl probably isn't high on - the list of qualifications for judges... Oh dear, I guess your C - beautifier won't help too much, either ;) - - If you don't change the rules, it'll be embedded Ada next year! - - - AutoDefend - A. Isn't this the obfuscated C contest? What's this Perl $#_&&$_? - - D. Hey, this program *is* 100% C, and does not exec an external Perl - interpreter. It simply links against the Perl language library. - The "Perl code" is just a C string constant. - - A. Perl isn't portable enough, or ubiquitous enough. - - D. I'd argue that it is more portable than X. According to the Perl - folks, it runs on the following platforms: Acorn, AIX, Amiga, AS/400, - BeOS, Concurrent, Debian, DEC OSF/1, Digital UNIX, EPOC, FreeBSD, - Guardian, HP-UX, IRIX, LinuxPPC, LynxOS, MacOS, MachTen, Minix, MPE/iX, - MS-DOS, MVS, NetBSD, Netware, NextStep, OpenBSD, OpenLinux, ODT, OpenVMS, - OS/2, OS390, OSR, PowerMAX, Psion, QNX, Redhat, Reliant UNIX, RISCOS, - SCO, SGI, SINIX, Slackware, Solaris, Sun, SuSE, Tandem, Tru64, UNIX, - U/WIN, Unixware, VMS, Win31, Win32, Windows 3.1, and Windows 95/98/NT/2K. - Granted, embeddable Perl isn't quite so portable, but still... - - Also, Perl 5 is bundled with the following OS distributions: AIX 4.3.3+, - FreeBSD 3.0+, IRIX 6.4+, every Linux distribution, NetBSD, OpenBSD, and - DEC Tru64 5.0+, again according to the Perl people. +Also, Perl 5 is bundled with the following OS distributions: AIX 4.3.3+, +FreeBSD 3.0+, IRIX 6.4+, every Linux distribution, NetBSD, OpenBSD, and +DEC Tru64 5.0+, again according to the Perl people.