Prepare for the winners of **IOCCC28**. > However these are not the 2024 droids you are looking for. :-) The HTML menu (both JavaScript and non-JavaScript) has been updated. The `Status -> Rules and guidelines' have been replaced with two separate menus `Status -> IOCCC rules` and `Status -> IOCCC guidelines`. Added a new top level `social.html` page: built from a new `social.md`. Sorted rules for building specific web pages in the top level `Makefile`. Added `make social` to make the `social.html` page from `social.md`. The `bin/gen-top-html.sh` now is able to process a argument of **social** to process the new top level `social.html` page. Changed `bin/gen-top-html.sh` VERSION from "2.0.0 2025-03-13" to "2.0.1 2025-07-25". Below `About -> Home page` a new `About -> IOCCC social media` menu item as added. Because the menu change touched every HTML file, we changed the general copyright date range for HTML files from "1984-2024" to "1984-2025" due to the extensive changes made for **IOCCC28**. Those markdown files that were modified in 2025 had their copyright date range also changed from "1984-2024" to "1984-2025". Rebuilt tarballs and sitemap due to the extensive HTML rebuilding. Ran `make update` to perform the above.
314 lines
10 KiB
Markdown
314 lines
10 KiB
Markdown
## To build:
|
|
|
|
``` <!---sh-->
|
|
make
|
|
```
|
|
|
|
The following bit of perl may help determine the values you need:
|
|
|
|
``` <!---sh-->
|
|
perl -MConfig -e 'print "$Config{archlibexp}/CORE\n"'
|
|
```
|
|
|
|
... just in case the Makefile does not figure this out for you.
|
|
|
|
|
|
### Bugs and (Mis)features:
|
|
|
|
The current status of this entry is:
|
|
|
|
> **STATUS: INABIAF - please DO NOT fix**
|
|
|
|
For more detailed information see [2000/dlowe in bugs.html](../../bugs.html#2000_dlowe).
|
|
|
|
|
|
## To use:
|
|
|
|
``` <!---sh-->
|
|
./dlowe [file ...]
|
|
```
|
|
|
|
|
|
## Try:
|
|
|
|
``` <!---sh-->
|
|
./try.sh
|
|
```
|
|
|
|
|
|
## Judges' remarks:
|
|
|
|
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 author,
|
|
[David Lowe](../../authors.html#J_David_Lowe) continues to inflict the highest
|
|
quality "`poot`" on the Judges.
|
|
|
|
The program also contains an undocumented command for Chad and Chongo (Landon).
|
|
The judges' remarks contain a clue to the hidden command :-).
|
|
|
|
* The IOCCC uses an anonymous judging process which keeps the identity
|
|
of the submitters hidden until all winning entries have been selected.
|
|
|
|
|
|
## Author's remarks:
|
|
|
|
### Usage
|
|
|
|
```
|
|
./dlowe [file ...]
|
|
```
|
|
|
|
### Synopsis
|
|
|
|
This is a [Reverse Polish
|
|
calculator](https://en.wikipedia.org/wiki/Reverse_Polish_notation), 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 data types, 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 mis-configurations 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](https://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 also 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!
|
|
|
|
|
|
### Auto defend
|
|
|
|
0. Isn't this the obfuscated C contest? What's this Perl `$#_&&$_`?
|
|
|
|
1. 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.
|
|
|
|
2. Perl isn't portable enough, or ubiquitous enough.
|
|
|
|
3. 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.
|
|
|
|
|
|
<!--
|
|
|
|
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
|
|
|
You are free to share and adapt this file under the terms of this license:
|
|
|
|
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
|
|
|
For more information, see:
|
|
|
|
https://creativecommons.org/licenses/by-sa/4.0/
|
|
|
|
-->
|