Merge pull request #1705 from xexyl/burton2
This commit is contained in:
27 files changed
+648
-400
No files matched your search
+31
-33
@@ -4,6 +4,10 @@
|
||||
make
|
||||
```
|
||||
|
||||
To use this entry requires, in some invocations, a sound processing program.
|
||||
This can be ALSA or SoX but we recommend the latter. See [FAQ 3.10 - How do I
|
||||
compile and use an IOCCC winner that requires sound?](/faq.md#faq3_10).
|
||||
|
||||
|
||||
### Bugs and (Mis)features:
|
||||
|
||||
@@ -19,31 +23,16 @@ For more detailed information see [2018 algmyr in bugs.md](/bugs.md#2018-algmyr)
|
||||
## To use:
|
||||
|
||||
```sh
|
||||
cat prog.c | ./prog # Printing garbage might break your font
|
||||
cat prog.c | ./prog # Print garbage: might mess up your terminal
|
||||
./prog <file1> <file2> > out.raw
|
||||
./prog -d 2 0 out.raw # Decode the first (0th) channel out of two
|
||||
```
|
||||
|
||||
NOTE: this entry will crash if a file specified cannot be opened.
|
||||
|
||||
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
./prog -h | ./prog -d 1 0
|
||||
|
||||
# Who needs cat?
|
||||
./prog prog.c | ./prog -d 1 0
|
||||
|
||||
# Assuming ALSA:
|
||||
echo '<<<<<< /\_/\_/\ _-_-_-_ !!!!! :.:.:.: >>>>>> ****** ~~~~~~~' |
|
||||
./prog | aplay -c1 -fFLOAT_LE -r44100
|
||||
|
||||
# Assuming sox:
|
||||
echo -n ' MENE MENE TEKEL UPHARSIN ' | ./prog |\
|
||||
sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 - -n spectrogram -d 10 -X 300
|
||||
|
||||
# now open spectrogram.png with a graphics viewer or editor
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -55,11 +44,13 @@ or at least a handy and well-tested volume knob.
|
||||
Pixels are numbered, amplitudes are weighed, frequencies are divided,
|
||||
and the message can be displayed in fiery letters, but don't be alarmed.
|
||||
|
||||
How does decoding of the waveform work? Can you encode an arbitrary text in a sound sample?
|
||||
How does decoding of the waveform work? Can you encode an arbitrary text in a
|
||||
sound sample?
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
|
||||
### What is this?
|
||||
|
||||
To put it brief, this entry is akin to a sound based cat. It takes characters as
|
||||
@@ -67,18 +58,20 @@ input and outputs them into frequency space as audio. The entry also supports
|
||||
decoding the produced waveforms using the `-d` flag. Usage instructions is
|
||||
output if run with the `-h` flag, albeit not in an immediately legible format.
|
||||
|
||||
|
||||
### Details
|
||||
|
||||
In normal operation, the entry reads characters from one or more sources. If the
|
||||
`-h` flag is given, usage instructions is used as a source. Else if file paths
|
||||
are present as arguments those will be used. Else stdin is used.
|
||||
are present as arguments those will be used. Else `stdin` is used.
|
||||
|
||||
If a character is part of the supported subset of ASCII `{10, 32-126}` then that
|
||||
character is output into frequency space of an audio signal (44.1 kHz single
|
||||
precision float, endianness should depend on system endianness) through `stdout`.
|
||||
Any other character will be interpreted and outputted as a space.
|
||||
|
||||
Characters are printed using a (slightly modified) pixel font based on [gohufont](https://github.com/hchargois/gohufont).
|
||||
Characters are printed using a (slightly modified) pixel font based on
|
||||
[gohufont](https://github.com/hchargois/gohufont).
|
||||
Pixels are drawn using crosses in frequency space, achieved by simultaneous up
|
||||
and down chirps.
|
||||
|
||||
@@ -93,12 +86,13 @@ characters.
|
||||
|
||||
See image [spoiler.png](spoilers.png) for an example spectrogram.
|
||||
|
||||
|
||||
### Limitations
|
||||
|
||||
There is no error checking done when opening files, so expect segfaults if you
|
||||
provide the wrong path to a file.
|
||||
|
||||
This program is bound to misbehave if int is less than 32 bits.
|
||||
This program is bound to misbehave if `int` is less than 32 bits.
|
||||
|
||||
Flags will only be interpreted correctly if they are the first argument. Reading
|
||||
a file named `-d` or `-h` is fully possible if it is not the first file
|
||||
@@ -109,32 +103,32 @@ behavior. Some erroneous arguments cause segfaults (negative number of channels,
|
||||
channel id outside valid range). One argument in particular causes an infinite
|
||||
loop printing whitespace.
|
||||
|
||||
#### Techniques:
|
||||
|
||||
##### Obfuscation:
|
||||
### Obfuscation:
|
||||
|
||||
A lot of the obfuscations done came naturally from trying to appease the size
|
||||
tool. To name some:
|
||||
|
||||
* One character names
|
||||
* Merging of related (and not so related) arithmetic operations
|
||||
* Short circuiting for flow control to replace some `if`s
|
||||
* Some `#defines`, sadly
|
||||
* One character names.
|
||||
* Merging of related (and not so related) arithmetic operations.
|
||||
* Short circuiting for flow control to replace some `if`s.
|
||||
* Some `#defines`, sadly.
|
||||
|
||||
On the intersection of size and obfuscation is the data encoding, which was
|
||||
quite fun to design.
|
||||
|
||||
Some additional obfuscation was done to mathematical formulas. Somewhat known
|
||||
expressions was transformed into equivalent but less recognizable counterparts.
|
||||
expressions were transformed into equivalent but less recognizable counterparts.
|
||||
|
||||
I have tried to avoid intentional red herrings in the code, although fishy
|
||||
statements are plentiful.
|
||||
|
||||
|
||||
### Data encoding:
|
||||
|
||||
The large string in the beginning of the source file contains font data, encoded
|
||||
in base64 using characters in the range `' '` to `'_'`. The space was chosen as
|
||||
the zero because the data contains a lot of zeroes, and quite helpfully the size
|
||||
zero because the data contains a lot of zeroes, and quite helpfully the size
|
||||
tool ignores whitespace even in strings. Without this fact the program would
|
||||
have been too large and the decoding feature would have had to go. Fortunately
|
||||
this hole in the size spec was readily available. :)
|
||||
@@ -142,9 +136,10 @@ this hole in the size spec was readily available. :)
|
||||
Characters in the font (5x8 pixels, 40 bits) are packed into 7 base64 digits
|
||||
(which was a pain to decode in minimal code).
|
||||
|
||||
|
||||
### Math:
|
||||
|
||||
Note that even though floats are used for the waveforms, the standard math
|
||||
Note that even though `float`s are used for the waveforms, the standard math
|
||||
library is not used at all! Most arithmetic is done purely on integers. The only
|
||||
major exception is generating a table of sine values which are interpolated to
|
||||
give high resolution waveforms. Can you see when the generation is triggered,
|
||||
@@ -157,13 +152,15 @@ function was used. Although the one used is quite well known, it is not in a
|
||||
form that should be familiar to anyone. What looks like a polynomial and quacks
|
||||
like a polynomial might not actually be a polynomial, at least not deep inside.
|
||||
|
||||
|
||||
### Printing a string:
|
||||
|
||||
The program was written to deal exclusively with file descriptors, so how would
|
||||
one go about printing a char array not from a file descriptor without adding
|
||||
additional logic? Answer: `ungetc` into stdin, one char at a time (to be
|
||||
one go about printing a `char` array not from a file descriptor without adding
|
||||
additional logic? Answer: `ungetc(3)` into `stdin`, one `char` at a time (to be
|
||||
standards compliant). This is used to print the usage instructions.
|
||||
|
||||
|
||||
### Compilation warnings
|
||||
|
||||
Compiling using
|
||||
@@ -179,7 +176,7 @@ clang -Wall -Wextra -pedantic
|
||||
```
|
||||
|
||||
is a bit more pessimistic and gives `-Wempty-body` (I like loops without
|
||||
bodies), `-Wstring-plus-int` (since apparently some people think string+int is a
|
||||
bodies), `-Wstring-plus-int` (since apparently some people think string+`int` is a
|
||||
concatenation) and one of the weirder warnings I have seen from me splitting a
|
||||
negative constant with whitespace. Compiling using
|
||||
|
||||
@@ -190,6 +187,7 @@ clang -Wall -Wextra -pedantic -Weverything
|
||||
produces a few page faults of warnings and makes me feel generally bad about
|
||||
myself. :(
|
||||
|
||||
|
||||
### Misc
|
||||
|
||||
The reported size of the source code using the size tool is very intentionally
|
||||
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate IOCCC winner 2018/algmyr
|
||||
#
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy
|
||||
# way.
|
||||
if [[ -z "$CC" ]]; then
|
||||
CC="cc"
|
||||
fi
|
||||
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear screen after compilation so that only the entry is shown
|
||||
clear
|
||||
|
||||
echo "$ ./prog -h | ./prog -d 1 0" 1>&2
|
||||
./prog -h | ./prog -d 1 0
|
||||
echo 1>&2
|
||||
|
||||
# Who needs cat? Answer: more people than you think.
|
||||
read -r -n 1 -p "Press any key to run: ./prog prog.c | ./prog -d 1 0 (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
./prog prog.c | ./prog -d 1 0 | less -EXF
|
||||
echo 1>&2
|
||||
|
||||
APLAY="$(type -P aplay)"
|
||||
SOX="$(type -P sox)"
|
||||
|
||||
if [[ -z "$SOX" && -z "$APLAY" ]]; then
|
||||
echo "Missing both sox and aplay, cannot do this step."
|
||||
elif [[ -n "$SOX" ]]; then
|
||||
echo "$ echo -n ' MENE MENE TEKEL UPHARSIN ' | ./prog | \
|
||||
sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 \
|
||||
- -n spectrogram -d 10 -X 300" 1>&2
|
||||
echo -n ' MENE MENE TEKEL UPHARSIN ' | ./prog |\
|
||||
sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 - -n spectrogram -d 10 -X 300
|
||||
|
||||
echo "Now open spectrogram.png in an image viewer or editor." 1>&2
|
||||
read -r -n 1 -p "Press any key to continue: "
|
||||
echo 1>&2
|
||||
echo "$ echo "IOCCC 2018" | ./prog | sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 - ioccc.wav"
|
||||
echo "IOCCC 2018" | ./prog | sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 - ioccc.wav
|
||||
echo "Now listen to ioccc.wav." 1>&2
|
||||
|
||||
else
|
||||
echo '<<<<<< /\_/\_/\ _-_-_-_ !!!!! :.:.:.: >>>>>> ****** ~~~~~~~' |
|
||||
./prog | aplay -c1 -fFLOAT_LE -r44100
|
||||
echo '<<<<<< /\_/\_/\ _-_-_-_ !!!!! :.:.:.: >>>>>> ****** ~~~~~~~' |
|
||||
./prog | aplay -c1 -fFLOAT_LE -r44100
|
||||
|
||||
echo "Now open spectrogram.png in an image viewer or editor." 1>&2
|
||||
fi
|
||||
echo 1>&2
|
||||
|
||||
echo "$ echo "IOCCC 2018!" | ./prog | ./prog -d 1 0" 1>&2
|
||||
echo "IOCCC 2018!" | ./prog | ./prog -d 1 0
|
||||
|
||||
|
||||
+19
-14
@@ -4,6 +4,9 @@
|
||||
make
|
||||
```
|
||||
|
||||
There is an alternate version of this entry. See [Alternate
|
||||
code](#alternate-code) below for more details.
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
@@ -15,32 +18,33 @@ make
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
./prog < prog.c
|
||||
./prog < prog.alt.c
|
||||
./prog < README.md
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
## Alternate code:
|
||||
|
||||
An alternate version of this entry, [prog.alt.c](prog.alt.c), is provided.
|
||||
|
||||
Compare [prog.c](prog.c) and [prog.alt.c](prog.alt.c) and find out why we had to
|
||||
modify the entry, and what confused the author (see the author's remarks). No,
|
||||
it was not the shape of the Roman V that we, or the compiler, didn't like.
|
||||
|
||||
To compile this alternate version:
|
||||
|
||||
### Alternate build:
|
||||
|
||||
```sh
|
||||
make alt
|
||||
```
|
||||
|
||||
|
||||
### Alternate use:
|
||||
|
||||
Use `prog.alt` as you would `prog` above.
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
With this entry, you won't need to turn your monitor [upside down](http://en.wikipedia.org/wiki/River_%28typography%29)!
|
||||
With this entry, you won't need to turn your monitor [upside
|
||||
down](http://en.wikipedia.org/wiki/River_%28typography%29)!
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
@@ -52,12 +56,13 @@ cc -Wall -Wextra -Wpedantic -O3 -std=c11 prog.c -o prog
|
||||
```
|
||||
|
||||
Also works with a standard of C99, but C90/C89 will not compile due to
|
||||
for loop initial declarations, along with additional warnings about
|
||||
variable length arrays and lack of a return statement.
|
||||
`for` loop initial declarations, along with additional warnings about
|
||||
variable length arrays and lack of a `return` statement.
|
||||
|
||||
|
||||
### Additional info:
|
||||
|
||||
This small program, when given text on stdin, will produce a pattern of
|
||||
This small program, when given text on `stdin`, will produce a pattern of
|
||||
squiggly lines. This pattern is deterministic, and it shouldn't be too
|
||||
difficult to determine from whence they come. There is even a comment
|
||||
that describes the highlighted phenomena in the source, for those that
|
||||
@@ -74,14 +79,14 @@ such as proper handling of tabs are left as an exercise to the reader.
|
||||
In developing this program, the author found a potentially interesting
|
||||
bug. If the expression `(j=k,j)` (near the middle of the source) is
|
||||
changed to `(j=k,k)`, the program produces different output. The author
|
||||
used compiler gcc 5.4.0, compiled for x86_64-linux-gnu. Enabling or
|
||||
used gcc 5.4.0, compiled for `x86_64-linux-gnu`. Enabling or
|
||||
disabling optimization produces the same results. The author is not
|
||||
sure who is the culprit, but instead shrugged and moved on with life.
|
||||
Of course, YMMV with your own environment.
|
||||
|
||||
The structure of this program, as you may have deduced, is two for
|
||||
loops, one nested in the other. There is also a bunch of direct
|
||||
variable assignment, such as `j=k`. There is some filler fluff, such as
|
||||
The structure of this program, as you may have deduced, is two `for`
|
||||
loops, one nested in the other. There are also a bunch of direct
|
||||
variable assignments, such as `j=k`. There is some filler fluff, such as
|
||||
`0-0+0`, but all that sort should be rather easy to spot. It was mostly
|
||||
added for the purpose of making certain things line up right, and only
|
||||
secondarily to obfuscate.
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate IOCCC winner 2018/anderson
|
||||
#
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy
|
||||
# way.
|
||||
if [[ -z "$CC" ]]; then
|
||||
CC="cc"
|
||||
fi
|
||||
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear screen after compilation so that only the entry is shown
|
||||
clear
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog < prog.c: "
|
||||
echo 1>&2
|
||||
./prog < prog.c
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog < prog.alt.c: "
|
||||
echo 1>&2
|
||||
./prog < prog.alt.c
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog < README.md (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
./prog < README.md | less -EXF
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./prog < Makefile (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
./prog < Makefile | less -EXF
|
||||
+41
-18
@@ -4,6 +4,9 @@
|
||||
make
|
||||
```
|
||||
|
||||
There is an alternate version of this entry. See [Alternate
|
||||
code](#alternate-code) below.
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
@@ -15,8 +18,7 @@ make
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
./prog < prog
|
||||
./prog < prog.c
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -24,15 +26,23 @@ make
|
||||
|
||||
An alternate version of this entry, [prog.alt.c](prog.alt.c), is provided
|
||||
This alternate code was supposed to compile without warnings, however
|
||||
with modern compilers this is no longer the case.
|
||||
with modern compilers this is no longer the case so it will only cleanly compile
|
||||
with `-Wno-` options.
|
||||
|
||||
|
||||
### Alternate build:
|
||||
|
||||
To compile this alternate version:
|
||||
|
||||
```sh
|
||||
make alt
|
||||
```
|
||||
|
||||
|
||||
### Alternate use:
|
||||
|
||||
Use `prog.alt` as you would `prog`.
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
One line, one array, one loop and one statement but it prints many bytes. It won.
|
||||
@@ -40,9 +50,9 @@ One line, one array, one loop and one statement but it prints many bytes. It won
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
Feed this anything on stdin.
|
||||
Feed this anything on `stdin`.
|
||||
|
||||
The [included script](scripthd) may be used as a driver program for this entry.
|
||||
The [included script.sh](scripthd.sh) may be used as a driver program for this entry.
|
||||
It adds several nice-to-have features, and allows salt-to-taste customizability.
|
||||
|
||||
This code has been compiled and tested on:
|
||||
@@ -51,21 +61,24 @@ This code has been compiled and tested on:
|
||||
* X86-Linux, gcc 4.1.2 and 4.8.4, -O0 and -O3
|
||||
* ARM-QEMU, gcc 4.8.4, -O0 and -O3
|
||||
* X86-FreeBSD 10.3, clang 3.4.1, -O0 and -O3
|
||||
* TCC 0.9.26 (x86-64) (used as a proxy for [2001/bellard](http://ioccc.org/years.html#2001_bellard))
|
||||
* TCC 0.9.26 (x86-64) (used as a proxy for [2001/bellard](/years.html#2001_bellard))
|
||||
* UNIX V7 pcc (Johnson's C compiler) on a [simulated PDP-11/45](http://simh.trailing-edge.com/)
|
||||
(see spoiler for further detail)
|
||||
|
||||
<div style="margin-bottom:60em;margin-top:4em"><strong>Spoiler below; scroll down.</strong></div>
|
||||
|
||||
|
||||
### SPOILER:
|
||||
|
||||
This started life as a personal challenge: write the shortest hex dump utility in C.
|
||||
This started life as a personal challenge: write the shortest hex dump utility
|
||||
in C.
|
||||
|
||||
The self-imposed ground rules in the hunt for shortest:
|
||||
|
||||
- the code has to output correctly,
|
||||
- no extraneous newlines, the code must be portable,
|
||||
and without bypassing the solution using execve(2), or functions built upon it (system(3), popen(3), etc).
|
||||
- The code has to output correctly.
|
||||
- No extraneous newlines, the code must be portable,
|
||||
and without bypassing the solution using `execve(2)`, or functions built upon it
|
||||
(`system(3)`, `popen(3)`, etc).
|
||||
|
||||
E.g:
|
||||
|
||||
@@ -155,8 +168,10 @@ $
|
||||
```
|
||||
|
||||
An obfuscated hex dump has been done before:
|
||||
[1986/bright/bright.c](http://ioccc.org/1986/bright/bright.c) is similar in function,
|
||||
but it uses more characters in just setting up its obfuscation than this entire solution!
|
||||
[1986/bright](/1986/bright/README.md) is similar in function,
|
||||
but it uses more characters in just setting up its obfuscation than this entire
|
||||
solution!
|
||||
|
||||
|
||||
### BIGGER SPOILER:
|
||||
|
||||
@@ -165,12 +180,13 @@ replace the cryptic expression `4<(4^l>>5)?l:46` with `32>l|l>126?46:l`.
|
||||
Both take the same number of characters, but the former is a bit more interesting.
|
||||
Bonus question: how does the first expression work?
|
||||
|
||||
|
||||
### BIGGEST SPOILER (and some history):
|
||||
|
||||
Technically, `char o[0];` is illegal (SS 6.7.6.2) according to ISO (N1570). And
|
||||
`char o[];` is a conditionally supported feature (SS 6.7.6.2, 6.10.8.3).
|
||||
However, it works in modern C implementations as an extension, including GCC,
|
||||
Clang and TCC, for X86 and ARM, on multiple operating systems (Linux, OSX,
|
||||
Clang and TCC, for X86 and ARM, on multiple operating systems (Linux, OSX/macOS,
|
||||
FreeBSD), so it is _functionally_ correct. MicroSoft Visual C++ does not allow
|
||||
`char o[]` or `char o[0]`, and implements its close relative `char o[1]` such
|
||||
that writing more than a single char will cause a fault, which is _technically_
|
||||
@@ -185,7 +201,8 @@ bytes following `O`, addressed via `o`, and this code only needs 17. This is
|
||||
_undefined_ behavior, but as shown, it is widely available.
|
||||
|
||||
The [1979 Seventh Edition UNIX][1] (v7) system pre-dates the IOCCC by several years,
|
||||
and the source code to `sh`(1) was a [significant inspiration for this contest][2].
|
||||
and the source code to `sh`(1) was a [significant inspiration for this
|
||||
contest](/all/README.md).
|
||||
There are two C compilers present: `cc` written by Dennis Ritchie, and `pcc` written by Steven Johnson.
|
||||
The nested conditional expressions in 116 and smaller are too complex for `cc` ("Illegal conditional")
|
||||
but `pcc` handles them correctly, and neither compiler accepts `char o[]` or
|
||||
@@ -194,9 +211,9 @@ not yet written for UNIX).
|
||||
|
||||
[1]: http://minnie.tuhs.org/cgi-bin/utree.pl
|
||||
[2]: http://ioccc.org/all/README
|
||||
[3]: https://web.archive.org/web/20180521074522/http://www.computerworld.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/?pp=4
|
||||
[2]: https://web.archive.org/web/20180521074522/http://www.computerworld.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/?pp=4
|
||||
|
||||
More significant is that v7 `printf`(3) does not report the number of characters
|
||||
More significant is that v7 `printf(3)` does not report the number of characters
|
||||
written, and therefore 111 compiles but does not work correctly; 113 is the
|
||||
shortest code that compiles and runs correctly in Ancient UNIX.
|
||||
|
||||
@@ -216,7 +233,7 @@ page 71, remarks:
|
||||
It is fascinating to explore the roots of C through the history of the operating
|
||||
system it was birthed within. C is often criticized as a difficult, inscrutable
|
||||
language, but as this contest demonstrates, this is in parody. _Shell-gol_ is
|
||||
one of those instances where someone [preferred a different language][3], and
|
||||
one of those instances where someone [preferred a different language][2], and
|
||||
(ab)used the preprocessor to re-mold C into something they found comfortable.
|
||||
Most of the rest of the system, especially in the kernel, are models of clarity
|
||||
and efficient expression.
|
||||
@@ -247,6 +264,12 @@ Try:
|
||||
cat prog.c prog.alt.c
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
cmp -b prog.c prog.alt.c
|
||||
```
|
||||
|
||||
to compare the differences (`diff` is not helpful on a one-liner).
|
||||
|
||||
|
||||
|
||||
File renamed without changes.
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate IOCCC winner 2018/burton1
|
||||
#
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy
|
||||
# way.
|
||||
if [[ -z "$CC" ]]; then
|
||||
CC="cc"
|
||||
fi
|
||||
|
||||
make CC="$CC" everything >/dev/null || exit 1
|
||||
|
||||
for i in prog scripthd.sh; do
|
||||
echo "$ ./$i < prog.c" 1>&2
|
||||
./"$i" < prog.c
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./$i < prog (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
./"$i" < prog | less -EXF
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: ./$i < scripthd.sh (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
./"$i" < scripthd.sh | less -EXF
|
||||
echo 1>&2
|
||||
|
||||
|
||||
read -r -n 1 -p "Press any key to run: head $0 | ./$i: "
|
||||
echo 1>&2
|
||||
head "$0" | ./"$i"
|
||||
echo 1>&2
|
||||
|
||||
read -r -n 1 -p "Press any key to run: tail -n 15 Makefile | ./$i: "
|
||||
echo 1>&2
|
||||
tail -n 15 Makefile | ./"$i"
|
||||
done
|
||||
@@ -1,6 +1,7 @@
|
||||
#
|
||||
# sort with: sort -d -u
|
||||
*.dSYM
|
||||
fixed_iocccsize
|
||||
indent
|
||||
indent.c
|
||||
indent.o
|
||||
@@ -8,3 +9,4 @@ keywords
|
||||
manpage
|
||||
prog
|
||||
prog.orig
|
||||
tac
|
||||
@@ -70,7 +70,7 @@
|
||||
"winners_text" : "field-by-field difference between iocccsize and ion"
|
||||
},
|
||||
{
|
||||
"file_path" : "freqcount",
|
||||
"file_path" : "freqcount.sh",
|
||||
"winners_rank" : 100,
|
||||
"created_by" : null,
|
||||
"prog" : null,
|
||||
@@ -190,7 +190,7 @@
|
||||
"winners_text" : "turns ASCII versions of man into real man pages"
|
||||
},
|
||||
{
|
||||
"file_path" : "mkkeywords",
|
||||
"file_path" : "mkkeywords.sh",
|
||||
"winners_rank" : 150,
|
||||
"created_by" : null,
|
||||
"prog" : null,
|
||||
@@ -500,7 +500,7 @@
|
||||
"winners_text" : "results without -k"
|
||||
},
|
||||
{
|
||||
"file_path" : "runtest",
|
||||
"file_path" : "runtest.sh",
|
||||
"winners_rank" : 200,
|
||||
"created_by" : null,
|
||||
"prog" : null,
|
||||
@@ -510,7 +510,7 @@
|
||||
"winners_text" : "test suite"
|
||||
},
|
||||
{
|
||||
"file_path" : "spotcheck",
|
||||
"file_path" : "spotcheck.sh",
|
||||
"winners_rank" : 200,
|
||||
"created_by" : null,
|
||||
"prog" : null,
|
||||
@@ -530,14 +530,14 @@
|
||||
"winners_text" : "reserved words for a given C standard"
|
||||
},
|
||||
{
|
||||
"file_path" : "spotdiff",
|
||||
"file_path" : "spotdiff.sh",
|
||||
"winners_rank" : 250,
|
||||
"created_by" : null,
|
||||
"prog" : null,
|
||||
"filetype" : "shellscript",
|
||||
"winners_show" : true,
|
||||
"display_via" : "github",
|
||||
"winners_text" : "summarize the results of spotcheck"
|
||||
"winners_text" : "summarize the results of spotcheck.sh"
|
||||
},
|
||||
{
|
||||
"file_path" : "2018_burton2.tar.bz2",
|
||||
|
||||
+10
-10
@@ -114,7 +114,7 @@ PROG= prog
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
CSRC= ${PROG}.o
|
||||
DATA= READ_ME.txt manpage java8 kandr kandr2 v7unix
|
||||
DATA= author-README.txt manpage java8 kandr kandr2 v7unix
|
||||
TARGET= ${PROG}
|
||||
#
|
||||
ALT_OBJ=
|
||||
@@ -124,9 +124,9 @@ EXTRA_DATA= ansi c++11 c++14 c++98 c11 c99 discrepancies.md \
|
||||
test01.c test02.c test03.c test04.c test05.c test06.c test07.c \
|
||||
test08.c test09.c test10.c test11.c test12.c test13.c test14.c \
|
||||
iocccbug01.c iocccbug02.c iocccbug03.c iocccbug04.c iocccbug05.c \
|
||||
iocccbug06.c results results.k src.doc.txt patch tac.man author-README.txt \
|
||||
iocccbug06.c results results.k src.doc.txt patch tac.1 author-README.txt \
|
||||
ioc_without_quote
|
||||
UTILITIES= unob.sh tokenfix spotcheck spotdiff freqcount
|
||||
UTILITIES= unob.sh tokenfix.sh spotcheck.sh spotdiff.sh freqcount.sh
|
||||
USAGE="\"prog [-tcksri] < file.c\ntokenize and count stdin\n\t-t\ttokens only\n\t-c\tcompatible counts\n\t-k\tkeep comments\n\t-s\tsuppress output\n\t-r\treserved words count as 1\n\t-i\tioccc count only\n\""
|
||||
|
||||
# this tool requires -trigraphs
|
||||
@@ -164,17 +164,17 @@ data: ${DATA} ${EXTRA_DATA}
|
||||
@${TRUE}
|
||||
|
||||
# keywords: c11
|
||||
keywords: ioccc.kw.freq mkkeywords
|
||||
./mkkeywords $< > keywords
|
||||
keywords: ioccc.kw.freq mkkeywords.sh
|
||||
./mkkeywords.sh $< > keywords
|
||||
|
||||
fixed_iocccsize: fixed_iocccsize.c
|
||||
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
|
||||
|
||||
test: prog tac runtest fixed_iocccsize ${EXTRA_DATA}
|
||||
-./runtest | diff - results
|
||||
-opt=kcrs ./runtest | diff - results.k
|
||||
-opt=rs prog=tac ./runtest | diff - results
|
||||
-opt=rsk prog=tac ./runtest | diff - results.k
|
||||
test: prog tac runtest.sh fixed_iocccsize ${EXTRA_DATA}
|
||||
-./runtest.sh | diff - results
|
||||
-opt=kcrs ./runtest.sh | diff - results.k
|
||||
-opt=rs prog=./tac ./runtest.sh | diff - results
|
||||
-opt=rsk prog=tac ./runtest.sh | diff - results.k
|
||||
./fixed_iocccsize -rs < prog.c
|
||||
./tac -rs prog.c
|
||||
|
||||
|
||||
+128
-122
@@ -15,117 +15,114 @@ make
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
./prog -i < prog.c
|
||||
./prog -s < prog.c
|
||||
./prog -sk < prog.c
|
||||
```
|
||||
|
||||
If you get stuck, try:
|
||||
|
||||
```sh
|
||||
make test
|
||||
./try.sh
|
||||
```
|
||||
|
||||
If you get really stuck, try:
|
||||
|
||||
```sh
|
||||
man ./tac.man
|
||||
man ./tac.1
|
||||
```
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
They say size isn't everything, and in the case of IOCCC [iocccsize.c](https://www.ioccc.org/2018/iocccsize.c)
|
||||
that is saying something! What is this program weighing and how much does it weigh?
|
||||
They say size isn't everything, and in the case of IOCCC
|
||||
[iocccsize.c](https://www.ioccc.org/2018/iocccsize.c) that is saying something!
|
||||
What is this program weighing and how much does it weigh?
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
### tac - tokenize and count C and derivative languages:
|
||||
|
||||
```
|
||||
tac computes C program size
|
||||
(obfuscated / otherwise)
|
||||
by splitting code as tokens small,
|
||||
ignoring space, then counting all.
|
||||
`tac` computes C program size\
|
||||
(obfuscated / otherwise)\
|
||||
by splitting code as tokens small,\
|
||||
ignoring space, then counting all.\
|
||||
|
||||
It tries quite hard to act the same
|
||||
as counting tool of I-OCCC fame.
|
||||
Some bugs were fixed, it's faster too,
|
||||
and does more things, just add some glue!
|
||||
It tries quite hard to act the same\
|
||||
as counting tool of I-OCCC fame.\
|
||||
Some bugs were fixed, it's faster too,\
|
||||
and does more things, just add some glue!\
|
||||
|
||||
It does far more than print the size:
|
||||
the token part's a better prize!
|
||||
With each upon on a single line,
|
||||
how many things can you design?
|
||||
It does far more than print the size:\
|
||||
the token part's a better prize!\
|
||||
With each upon on a single line,\
|
||||
how many things can you design?\
|
||||
|
||||
Included is a keyword sorter,
|
||||
de-obfuscator, freq reporter.
|
||||
With code produced as little parts,
|
||||
just add your own creative arts.
|
||||
Included is a keyword sorter,\
|
||||
de-obfuscator, freq reporter.\
|
||||
With code produced as little parts,\
|
||||
just add your own creative arts.\
|
||||
|
||||
But first you have to figure out
|
||||
the braces part, without a doubt!
|
||||
And then the code - it isn't easy:
|
||||
for as else? That's rather cheesy!
|
||||
But first you have to figure out\
|
||||
the braces part, without a doubt!\
|
||||
And then the code - it isn't easy:\
|
||||
for as else? That's rather cheesy!\
|
||||
|
||||
The rest of it is standard fare:
|
||||
expressions strange, the globals bare,
|
||||
confusing symbols one and oh,
|
||||
and precedence you have to know.
|
||||
The rest of it is standard fare:\
|
||||
expressions strange, the globals bare,\
|
||||
confusing symbols one and oh,\
|
||||
and precedence you have to know.\
|
||||
|
||||
The keyword list was made external,
|
||||
because of standards change eternal.
|
||||
Thus other languages can now,
|
||||
be counted just like C, somehow!
|
||||
The keyword list was made external,\
|
||||
because of standards change eternal.\
|
||||
Thus other languages can now,\
|
||||
be counted just like C, somehow!\
|
||||
|
||||
I hope you find this code obscure\
|
||||
enough to win, and thus procure\
|
||||
a public place for all to see\
|
||||
how badly I can butcher C!\
|
||||
|
||||
I hope you find this code obscure
|
||||
enough to win, and thus procure
|
||||
a public place for all to see
|
||||
how badly I can butcher C!
|
||||
```
|
||||
|
||||
### Said another way....
|
||||
|
||||
`tac` is the inverse of `cat`(1): it un-concatenates its input into C tokens,
|
||||
writing the token stream to `stdout`. There are options to suppress the token ids,
|
||||
summarize the token counts, and several options to allow it to be compatible
|
||||
with `iocccsize`.
|
||||
writing the token stream to `stdout`. There are options to suppress the token
|
||||
ids, summarize the token counts, and several options to allow it to be
|
||||
compatible with `iocccsize`.
|
||||
|
||||
The token-based output is quite useful in analyzing source code (see below),
|
||||
and the counter is more accurate than `iocccsize` (see below); but this can be
|
||||
fixed by using the -c compatibility flag, restoring the following problems as
|
||||
fixed by using the `-c` compatibility flag, restoring the following problems as
|
||||
in the official tool:
|
||||
|
||||
* whitespace **within** a string is **not** counted;
|
||||
this seems wrong, as these chars **are** significant
|
||||
* "`{;}`" is not counted within a double-quoted string
|
||||
* whitespace preceding a comment is char-counted, unless the comment starts a line
|
||||
* `-k` processes the reserved words within `//` comments(!), but not `/*`, changing the counts
|
||||
* Whitespace **within** a string is **not** counted;
|
||||
this seems wrong, as these chars **are** significant.
|
||||
* "`{;}`" is not counted within a double-quoted string.
|
||||
* Whitespace preceding a comment is `char`-counted, unless the comment starts a
|
||||
line.
|
||||
* `-k` processes the reserved words within `//` comments(!), but not `/*`,
|
||||
changing the counts.
|
||||
|
||||
The following bugs are always corrected:
|
||||
|
||||
* treats `/*/` as a complete comment (`/*/int if for/*/` has three keywords)
|
||||
* Treats `/*/` as a complete comment (`/*/int if for/*/` has three keywords)
|
||||
* `-k` enables `//*` or within a line comment `/*` to initiate a comment block until following `*/`
|
||||
* `-k` processes double quote characters in `//` comments - thus a solitary
|
||||
quote consumes everything until the next quote
|
||||
* single quotes are not handled correctly (`'"'` starts a dquote in `iocccsize`)
|
||||
* Single quotes are not handled correctly (`'"'` starts a double quote in `iocccsize`)
|
||||
* `#ifndef` is omitted as a keyword (but `#ifdef` is allowed?)
|
||||
* `I` is not a reserved word.
|
||||
* `tac` correctly penetrates [23rd century cloaking technology][1]. ;-)
|
||||
|
||||
There is one (known) remaining problem with detection:
|
||||
|
||||
* comments between preprocessor hash and keyword are not replaced with whitespace;
|
||||
* Comments between preprocessor hash and keyword are not replaced with whitespace;
|
||||
the following counts #include as two tokens, `#` and `include` (not as a reserved word):
|
||||
|
||||
#/*this will not be counted*/include/*correctly*/<stdio.h>
|
||||
```c
|
||||
#/*this will not be counted*/include/*correctly*/<stdio.h>
|
||||
```
|
||||
|
||||
Fixing this properly hampers backwards compatibility in counting. This requires
|
||||
eliding comments during the translation phases (ISO 5.1.1.2, phase 3), and yet still
|
||||
counting words correctly absent `-k`.
|
||||
|
||||
[1]: http://ioccc.org/2014/birken/hint.html "Best use of port 1701"
|
||||
[1]: /2014/birken/README.md "Best use of port 1701"
|
||||
|
||||
|
||||
### Backwards Compatibility:
|
||||
|
||||
@@ -135,10 +132,11 @@ counting words correctly absent `-k`.
|
||||
find ~/src/obc -type f -name \*.c | wc
|
||||
```
|
||||
|
||||
The discrepancies found are documented and explained in the file "discrepancies".
|
||||
The discrepancies found are documented and explained in the file
|
||||
[discrepancies.md](discrepancies.md).
|
||||
|
||||
```sh
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs ./spotcheck ./prog | ./spotdiff |
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs ./spotcheck.sh ./prog | ./spotdiff.sh |
|
||||
grep -v keep | diff -bw - discrep* | grep "[<>] cl "
|
||||
```
|
||||
|
||||
@@ -159,17 +157,17 @@ designed to allow exhaustive, hand-counted values for comparison with the tool v
|
||||
These test cases were vital in debugging and regression testing, and provided a way to
|
||||
determine which tool was correct when there were differences.
|
||||
|
||||
> A version of this tool in more clearly written C (tac.c)
|
||||
> A version of this tool in more clearly written C ([tac.c](tac.c))
|
||||
> is presented for the Judge's consideration as a more accurate replacement for `iocccsize`.
|
||||
> This obfuscated entry is derived from (and compatible with) that code,
|
||||
> but due to obfuscation, has had some significant, deep changes for the contest.
|
||||
> Nevertheless, the more clearly written code remains a spoiler for this entry.
|
||||
|
||||
NB: `iocccsize` gets a different answer from `tac` on its own
|
||||
([iocccsize.c]([iocccsize.c](https://www.ioccc.org/2018/iocccsize.c)) source code;
|
||||
([iocccsize.c](/2018/iocccsize.c)) source code;
|
||||
`tac` gets the correct answer. This is due to the aforementioned bugs within `iocccsize`,
|
||||
proved by fixing
|
||||
[iocccsize.c](https://www.ioccc.org/2018/iocccsize.c) with the included patch, so `iocccsize` reports
|
||||
[iocccsize.c](/2018/iocccsize.c) with the included patch, so `iocccsize` reports
|
||||
the correct answer for itself.
|
||||
|
||||
### But wait... There's More!
|
||||
@@ -201,25 +199,27 @@ cat $* | ./prog -t | iskeyword | sort -k1nr
|
||||
This script was used to "optimize" the reserved word order so the most frequent IOCCC
|
||||
winning entry keywords are checked first.
|
||||
|
||||
> An interesting aside: as might be expected, obfuscation has changed the frequency of
|
||||
> keyword distribution over time. The top five for the decades:
|
||||
>\
|
||||
> 1980s 1990s 2000s 2010s
|
||||
> ----- ----- ----- -----
|
||||
> 94 if 532 char 375 if 254 int
|
||||
> 69 for 524 if 372 char 217 for
|
||||
> 59 while 417 int 332 int 198 if
|
||||
> 48 char 223 for 184 for 121 return
|
||||
> 43 int 223 void 165 return 104 char
|
||||
An interesting aside: as might be expected, obfuscation has changed the frequency of
|
||||
keyword distribution over time. The top five for the decades:
|
||||
|
||||
```
|
||||
1980s 1990s 2000s 2010s
|
||||
----- ----- ----- -----
|
||||
94 if 532 char 375 if 254 int
|
||||
69 for 524 if 372 char 217 for
|
||||
59 while 417 int 332 int 198 if
|
||||
48 char 223 for 184 for 121 return
|
||||
43 int 223 void 165 return 104 char
|
||||
```
|
||||
|
||||
The keyword list is external to the program, and is easily changed, sorted, checked, verified.
|
||||
This allows such additional programs in concert with the tool's primary operation.
|
||||
|
||||
A poor-man's de-obfuscator can be based upon the output of `tac -t` and a handful of
|
||||
simple rules (and another use of the external keyword file).
|
||||
A more refined version of this is included in the file `unob.sh`,
|
||||
but the simple code below is a serviceable obfuscated C de-obfuscator in a _scripting language_.
|
||||
It really is this easy with `tac`:
|
||||
A poor-man's de-obfuscator can be based upon the output of `tac -t` and a
|
||||
handful of simple rules (and another use of the external keyword file). A more
|
||||
refined version of this is included in the file [unob.sh](unob.sh), but the
|
||||
simple code below is a serviceable obfuscated C de-obfuscator in a _scripting
|
||||
language_. It really is this easy with `tac`:
|
||||
|
||||
|
||||
```sh
|
||||
@@ -277,22 +277,22 @@ sed 's/^# .*$//' | sed 's/^#//' |
|
||||
|
||||
* Keywords follow the 2010s top five, without the `if`, for interesting flow control.
|
||||
* Sometimes a `for` can be an `else` - [inconceivable][3]!
|
||||
* I see the `getopt`. But "[where's the beef?][4]"
|
||||
* No character constants, several int constants, and one string
|
||||
* I see the `getopt(3)`. But "[where's the beef?][4]"
|
||||
* No character constants, several `int` constants, and one string
|
||||
(hint: which does not encode letters) -- how does this code parse code?
|
||||
> Interesting aside: how many is "several int constants"?
|
||||
>
|
||||
> ./prog < prog.c 2>/dev/null | awk '$1~/260/{a[$2]++}END{for(i in a)print i,a[i]}'
|
||||
> ... | wc
|
||||
>
|
||||
> Which numbers are most often used?
|
||||
>
|
||||
> ... | sort -k2nr | sed 5q
|
||||
- Interesting aside: how many is "several `int` constants"?
|
||||
|
||||
./prog < prog.c 2>/dev/null | awk '$1~/260/{a[$2]++}END{for(i in a)print i,a[i]}'
|
||||
... | wc
|
||||
|
||||
Which numbers are most often used?
|
||||
|
||||
... | sort -k2nr | sed 5q
|
||||
|
||||
* The code describes its function by careful arrangement of variables up front...
|
||||
* ...coupled with a description of the typical IOCCC contestant, or at least the author
|
||||
* Why shouldn't trigraph parsing be written in trigraph?
|
||||
* Where [iocccsize.c](https://www.ioccc.org/2018/iocccsize.c) mocks, this code flaunts:
|
||||
* Where [iocccsize.c](/2018/iocccsize.c) mocks, this code flaunts:
|
||||
"_no matter how well you may think you understand this code, you don't, so don't mess with it. :-)_"
|
||||
* `O,0,l,1` are used to confusing effect, local names obscure global names.
|
||||
* Globals are used to pass information between routines: don't reorder "unrelated" statements....
|
||||
@@ -304,6 +304,7 @@ sed 's/^# .*$//' | sed 's/^#//' |
|
||||
[3]: https://www.youtube.com/watch?v=OHVjs4aobqs "Inconceivable"
|
||||
[4]: https://www.youtube.com/watch?v=Ug75diEyiA0 "Where's the beef?"
|
||||
|
||||
|
||||
### Rule 2:
|
||||
|
||||
The keyword list is externalized as an include file. This presents a useful
|
||||
@@ -312,27 +313,28 @@ produced, but the tool can be rebuilt with any set of reserved words, just by
|
||||
using a different list. For instance: removing all the secondary keywords;
|
||||
removing all the C11 keywords; trying just K&R C. Since C++ and Java share the
|
||||
same operators as C, just change the keyword list and `tac` will correctly
|
||||
tokenize both of these; the tokens >>> and :: can be handled with a short
|
||||
tokenize both of these; the tokens `>>>` and `::` can be handled with a short
|
||||
post-filter ([tokenfix.sh](tokenfix.sh), included).
|
||||
|
||||
I believe this entry may also satisfy the request for gratuitous use of all the C11 keywords?
|
||||
Whether this context satisfies "intended C language context" is a matter of interpretation. ;-)
|
||||
And `tac` is ready for the IOCCC++ contest. And the IOJCC trashcan.
|
||||
I believe this entry may also satisfy the request for gratuitous use of all the
|
||||
C11 keywords? Whether this context satisfies "intended C language context" is a
|
||||
matter of interpretation. ;-) And `tac` is ready for the IOCCC++ contest. And
|
||||
the IOJCC trash can.
|
||||
|
||||
The following reserved word files are included:
|
||||
|
||||
|
||||
kandr from my venerable 1978 18th printing "The C Programming Language"
|
||||
v7unix 7th edition Unix source code, extracted from c00.c
|
||||
kandr2 from my 1988 1st printing "The C Programming Language", 2e
|
||||
ansi ANS X3.159-1989
|
||||
c99 ISO/IEC 9899:1999(E)
|
||||
c11 ISO/IEC 9899:201x(E) N1570
|
||||
c++98 http://en.cppreference.com/w/cpp/keyword
|
||||
c++11 ISO/IEC 14882:2011(E) N3337 2012-01-16
|
||||
c++14 ISO/IEC 14882:2014(E) N4296 2014-11-09
|
||||
java8 http://docs.oracle.com/javase/specs/index.html
|
||||
ioccc.kw.freq c11 + additional words, sorted on frequency of occurrence in ioccc winners
|
||||
* [kandr](kandr) from my venerable 1978 18th printing "The C Programming Language"
|
||||
* [v7unix](v7unix) 7th edition Unix source code, extracted from c00.c
|
||||
* [kandr2](kandr2) from my 1988 1st printing "The C Programming Language", 2e
|
||||
* [ansi](ansi) ANSI X3.159-1989
|
||||
* [c99](c99) ISO/IEC 9899:1999(E)
|
||||
* [c11](c11) ISO/IEC 9899:201x(E) N1570
|
||||
* [c++98](c++98) http://en.cppreference.com/w/cpp/keyword
|
||||
* [c++11](c++11) ISO/IEC 14882:2011(E) N3337 2012-01-16
|
||||
* [c++14](c++14) ISO/IEC 14882:2014(E) N4296 2014-11-09
|
||||
* [java8](java8) <http://docs.oracle.com/javase/specs/index.html>
|
||||
* [ioccc.kw.freq](ioccc.kw.freq) c11 + additional words, sorted on frequency of occurrence in IOCCC winners
|
||||
|
||||
|
||||
NB: The keyword file used in this code is derived from the list in [iocccsize.c](https://www.ioccc.org/2018/iocccsize.c),
|
||||
@@ -354,11 +356,12 @@ This also allows the builder to configure the amount of help a utility should pr
|
||||
([you want a manpage? Because that's how you get a manpage.][5]) -- a rather
|
||||
significant point of contention made moot.
|
||||
|
||||
There is definitely abuse of the Rule2 counter, exploiting a "feature" of `iocccsize`:
|
||||
`iocccsize` does not Rule2 count {, } and ; when followed by whitespace -- even within a string!
|
||||
Thus: Freecode, a simple, uncounted, highly obfuscated encoding of a central part
|
||||
of this program. (The reserved word list is not Freecoded, both because it is useful
|
||||
apart from the program, and because Freecode is not entirely free.*)
|
||||
There is definitely abuse of the Rule2 counter, exploiting a "feature" of
|
||||
`iocccsize`: `iocccsize` does not Rule2 count `{`, `}` and `;` when followed by
|
||||
whitespace -- even within a string! Thus: Freecode, a simple, uncounted, highly
|
||||
obfuscated encoding of a central part of this program. (The reserved word list
|
||||
is not Freecoded, both because it is useful apart from the program, and because
|
||||
Freecode is not entirely free.)
|
||||
|
||||
* Some restrictions apply. Not approved for all uses. Some assembly required.
|
||||
|
||||
@@ -370,12 +373,12 @@ The code is ANSI compliant, but it does have a string longer than 509 characters
|
||||
It has been tested on OSX and Linux, Clang and GCC.
|
||||
|
||||
The code uses trigraphs, ironically: it parses trigraphs with trigraph code.
|
||||
Because that's funny. And it remains obscure after, so trigraphs are not used for obfuscation.
|
||||
Thus `-trigraphs -Wno-trigraphs` (which is also humorous).
|
||||
Because that's funny. And it remains obscure after, so trigraphs are not used
|
||||
for obfuscation. Thus `-trigraphs -Wno-trigraphs` (which is also humorous).
|
||||
|
||||
It's obfuscated C. Thus `-Wno-parentheses -Wno-empty-body -Wno-char-subscripts`.
|
||||
|
||||
The code uses unsigned chars, but C strings are signed. Thus `-Wno-pointer-sign`.
|
||||
The code uses `unsigned char`s, but C strings are `signed`. Thus `-Wno-pointer-sign`.
|
||||
NB: This is *not* a portability concern, the one string holds only printable ASCII characters.
|
||||
|
||||
Thus:
|
||||
@@ -387,9 +390,9 @@ cc -ansi -Wall -trigraphs -Wno-trigraphs -Wno-parentheses -Wno-empty-body -Wno-c
|
||||
### Coda:
|
||||
|
||||
[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) was relentless in his pursuit of bugs.
|
||||
Thanks to his reports, the version of `unob.sh` is stronger,
|
||||
`tac` groks digraphs, `tokenfix` corrects for missing digraphs in `prog.c`,
|
||||
and the program `manpage` was added to the corpus.
|
||||
Thanks to his reports, the version of [unob.sh](unob.sh) is stronger,
|
||||
`tac` groks digraphs, [tokenfix.sh](tokenfix.sh) corrects for missing digraphs
|
||||
in [prog.c](prog.c), and the program [manpage.sh](manpage.sh) was added to the corpus.
|
||||
|
||||
[manpage.sh](manpage.sh) is a useful program that turns ASCII versions of man
|
||||
pages (e.g. [tac.man](tac.man)) into real man pages. It works for C and C-like
|
||||
@@ -401,14 +404,17 @@ are not recognised when written as `-rs` in prose).
|
||||
Try:
|
||||
|
||||
```sh
|
||||
./manpage tac
|
||||
./manpage.sh tac
|
||||
|
||||
./manpage -h
|
||||
./manpage -h | ./manpage
|
||||
./manpage -h | ./manpage -R | less
|
||||
./manpage -h | ./manpage -P | lpr
|
||||
./manpage.sh -h
|
||||
./manpage.sh -h | ./manpage.sh
|
||||
./manpage.sh -h | ./manpage.sh -R | less
|
||||
./manpage.sh -h | ./manpage.sh -P | lpr
|
||||
```
|
||||
|
||||
NOTE: in 2023 the `tac.man` was updated to proper man format and renamed
|
||||
[tac.1](tac.1).
|
||||
|
||||
|
||||
## Copyright and CC BY-SA 4.0 License:
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
tac comes with a small suite of support programs to test and validate against.
|
||||
Untar tests and variations in the same dir as the sources,
|
||||
or change runtest and unob.sh to look elsewhere for the keyword and test files.
|
||||
|
||||
keywords is a critical file, created from ioccc.kw.freq by mkkeywords.
|
||||
Only ioccc.kw.freq produces results compatible with iocccsize.c;
|
||||
however, any of the variations can be used instead:
|
||||
|
||||
mkkeywords c11 > keywords
|
||||
|
||||
unob.sh uses the same input file as mkkeywords to control spaces after keywords.
|
||||
The script allows an environment variable, KW, to override this.
|
||||
Use it simply:
|
||||
|
||||
unob.sh prog.c | less
|
||||
unob.sh -p prog.c | less
|
||||
KW=c11 unob.sh prog.c | less
|
||||
|
||||
To handle obscure command line defines, use the environment variable DEF:
|
||||
|
||||
DEF="-D'g(o)'='goto o;'" KW=c11 unob.sh -p prog.c | less
|
||||
|
||||
It does an amazingly good job for such a simple script.
|
||||
|
||||
Manifest
|
||||
|
||||
prog.c the reason for this README
|
||||
keywords the file #included in prog.c, output of mkkeywords
|
||||
mkkeywords reads one of the files from variations, produces string for prog.c
|
||||
ioccc.kw.freq keywords used by iocccsize, sorted by frequency in 201x ioccc winners
|
||||
unob.sh a more robust unobfuscation script; requires variations/c11 in cur dir
|
||||
tokenfix patches up prog -t output for ::, >>>, ...
|
||||
src.doc.txt the answers, or at least significant help
|
||||
tac.c more clearly written code, offered as a replacement of iocccsize.c
|
||||
patch fixes single quotes in iocccsize.c, adds #ifndef, removes "I"
|
||||
fixed_iocccsize.c iocccsize with patch applied, and nop -c argument added
|
||||
|
||||
tests/*
|
||||
runtest script to run the tests; ./runtest | diff results -
|
||||
results results without -k
|
||||
results.k results with -k; opt=kcrs ./runtest | diff results.k -
|
||||
test*.c various test cases looking for compatability
|
||||
iocccbug*.c various test cases demonstrating problems with iocccsize
|
||||
spotcheck script to test a lot of files vs iocccsize
|
||||
spotdiff summarize the results of spotcheck, showing only differences
|
||||
discrepancies text file of the differences found using all the ioccc winning entries
|
||||
|
||||
to test prog:
|
||||
|
||||
runtest | diff - results
|
||||
opt=kcrs runtest | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck prog
|
||||
[ | spotdiff | diff -bw - discrepancies ]
|
||||
|
||||
to test tac:
|
||||
|
||||
prog=tac runtest | diff - results
|
||||
prog=tac opt=krs runtest | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck tac
|
||||
|
||||
variations/* as described in the remarks, and in each file below
|
||||
ansi
|
||||
c++11
|
||||
c++14
|
||||
c++98
|
||||
c11
|
||||
c99
|
||||
java8
|
||||
kandr
|
||||
kandr2
|
||||
v7unix
|
||||
@@ -1,14 +1,14 @@
|
||||
tac comes with a small suite of support programs to test and validate against.
|
||||
Untar tests and variations in the same dir as the sources,
|
||||
or change runtest and unob.sh to look elsewhere for the keyword and test files.
|
||||
or change runtest.sh and unob.sh to look elsewhere for the keyword and test files.
|
||||
|
||||
keywords is a critical file, created from ioccc.kw.freq by mkkeywords.
|
||||
keywords is a critical file, created from ioccc.kw.freq by mkkeywords.sh.
|
||||
Only ioccc.kw.freq produces results compatible with iocccsize.c;
|
||||
however, any of the variations can be used instead:
|
||||
|
||||
mkkeywords c11 > keywords
|
||||
mkkeywords.sh c11 > keywords
|
||||
|
||||
unob.sh uses the same input file as mkkeywords to control spaces after keywords.
|
||||
unob.sh uses the same input file as mkkeywords.sh to control spaces after keywords.
|
||||
The script allows an environment variable, KW, to override this.
|
||||
Use it simply:
|
||||
|
||||
@@ -25,38 +25,38 @@ It does an amazingly good job for such a simple script.
|
||||
Manifest
|
||||
|
||||
prog.c the reason for this README
|
||||
keywords the file #included in prog.c, output of mkkeywords
|
||||
mkkeywords reads one of the files from variations, produces string for prog.c
|
||||
keywords the file #included in prog.c, output of mkkeywords.sh
|
||||
mkkeywords.sh reads one of the files from variations, produces string for prog.c
|
||||
ioccc.kw.freq keywords used by iocccsize, sorted by frequency in 201x ioccc winners
|
||||
unob.sh a more robust unobfuscation script; requires variations/c11 in cur dir
|
||||
tokenfix patches up prog -t output for ::, >>>, ...
|
||||
tokenfix.sh patches up prog -t output for ::, >>>, ...
|
||||
src.doc.txt the answers, or at least significant help
|
||||
tac.c more clearly written code, offered as a replacement of iocccsize.c
|
||||
patch fixes single quotes in iocccsize.c, adds #ifndef, removes "I"
|
||||
fixed_iocccsize.c iocccsize with patch applied, and nop -c argument added
|
||||
|
||||
tests/*
|
||||
runtest script to run the tests; ./runtest | diff results -
|
||||
runtest.sh script to run the tests; ./runtest.sh | diff results -
|
||||
results results without -k
|
||||
results.k results with -k; opt=kcrs ./runtest | diff results.k -
|
||||
test*.c various test cases looking for compatability
|
||||
results.k results with -k; opt=kcrs ./runtest.sh | diff results.k -
|
||||
test*.c various test cases looking for compatibility
|
||||
iocccbug*.c various test cases demonstrating problems with iocccsize
|
||||
spotcheck script to test a lot of files vs iocccsize
|
||||
spotdiff summarize the results of spotcheck, showing only differences
|
||||
discrepancies text file of the differences found using all the ioccc winning entries
|
||||
spotcheck.sh script to test a lot of files vs iocccsize
|
||||
spotdiff.sh summarize the results of spotcheck.sh, showing only differences
|
||||
discrepancies.md markdown file of the differences found using all the ioccc winning entries
|
||||
|
||||
to test prog:
|
||||
|
||||
runtest | diff - results
|
||||
opt=kcrs runtest | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck prog
|
||||
[ | spotdiff | diff -bw - discrepancies ]
|
||||
runtest.sh | diff - results
|
||||
opt=kcrs runtest.sh | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck.sh prog
|
||||
[ | spotdiff.sh | diff -bw - discrepancies ]
|
||||
|
||||
to test tac:
|
||||
|
||||
prog=tac runtest | diff - results
|
||||
prog=tac opt=krs runtest | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck tac
|
||||
prog=tac runtest.sh | diff - results
|
||||
prog=tac opt=krs runtest.sh | diff - results.k
|
||||
find ~/src/obc -type f -a -name "*.c" | xargs spotcheck.sh tac
|
||||
|
||||
variations/* as described in the remarks, and in each file below
|
||||
ansi
|
||||
|
||||
File renamed without changes.
@@ -230,7 +230,7 @@ href="https://ioccc-src.github.io/temp-test-ioccc/2018/burton2/discrepancies.htm
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">frequency count utility</td>
|
||||
<td style="text-align: left;"><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/freqcount">freqcount</a></td>
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/freqcount.sh">freqcount.sh</a></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">tokenize and count man page</td>
|
||||
@@ -299,7 +299,7 @@ href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/manp
|
||||
<td style="text-align: left;">reads a file from variations produces
|
||||
string for prog.c</td>
|
||||
<td style="text-align: left;"><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/mkkeywords">mkkeywords</a></td>
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/mkkeywords.sh">mkkeywords.sh</a></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">results with -k</td>
|
||||
@@ -454,13 +454,13 @@ href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/resu
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">test suite</td>
|
||||
<td style="text-align: left;"><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/runtest">runtest</a></td>
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/runtest.sh">runtest.sh</a></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">script to test a lot of files vs
|
||||
iocccsize</td>
|
||||
<td style="text-align: left;"><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/spotcheck">spotcheck</a></td>
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/spotcheck.sh">spotcheck.sh</a></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">reserved words for a given C standard</td>
|
||||
@@ -468,9 +468,9 @@ href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/spot
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/v7unix">v7unix</a></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">summarize the results of spotcheck</td>
|
||||
<td style="text-align: left;">summarize the results of spotcheck.sh</td>
|
||||
<td style="text-align: left;"><a
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/spotdiff">spotdiff</a></td>
|
||||
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2018/burton2/spotdiff.sh">spotdiff.sh</a></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">download winning source</td>
|
||||
|
||||
File renamed without changes.
Regular → Executable
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,139 @@
|
||||
.TH tac 1 "01 April 2018" "tac" "IOCCC 2018"
|
||||
.SH NAME
|
||||
tac \- tokenize and count C-like program source code
|
||||
.SH SYNOPSIS
|
||||
\fBtac\fP [\-t] [\-c] [\-k] [\-r] [\-s] [\-i] [file]
|
||||
.SH DESCRIPTION
|
||||
\fBtac\fP reads C or C-like source code from \fBstdin\fP or file, breaking it into tokens (lexemes),
|
||||
counting these according to the rules of the IOCCC, and outputting the tokens,
|
||||
counts, or source code as directed by the command line options.
|
||||
The default output is the source code with comments removed on \fBstdout\fP,
|
||||
and the counts on \fBstderr\fP.
|
||||
The count format is a set of integer values in the following order:
|
||||
.RS
|
||||
.TP
|
||||
.B lines
|
||||
number of newlines
|
||||
.TQ
|
||||
.B words
|
||||
number of words
|
||||
.TQ
|
||||
.B chars
|
||||
number of characters
|
||||
.TQ
|
||||
.B ioccc
|
||||
number of IOCCC countable tokens; the IOCCC rule 2 value
|
||||
.TQ
|
||||
.B saved
|
||||
number of characters not counted due to rules and keywords
|
||||
.TQ
|
||||
.B kwcnt
|
||||
number of keywords
|
||||
.TQ
|
||||
.B kwlen
|
||||
number of characters saved by counting keyword length as 1
|
||||
.RE
|
||||
.PP
|
||||
For the following code:
|
||||
.sp
|
||||
.RS 4
|
||||
.nf
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
/* example for loop */
|
||||
for (int ac=1; ac<10; ++ac)
|
||||
printf("%d\n", ac);
|
||||
return 0;
|
||||
}
|
||||
.fi
|
||||
.RE
|
||||
\fBtac\fP prints the code to \fBstdout\fP, and to \fBstderr\fP: '6 15 96 71 25 5 0'
|
||||
which means 6 lines, 15 words, 96 chars, 71 IOCCC counts, 25 chars saved,
|
||||
5 \fBkwcnt\fP, and no characters saved from \fBkwlen\fP. (By default, comments are not
|
||||
counted.)
|
||||
.SH OPTIONS
|
||||
The following options are supported:
|
||||
.TP
|
||||
.B \-t
|
||||
Output just the token stream.
|
||||
.TP
|
||||
.B \-c
|
||||
Correct the accounting bugs in \fBiocccsize(1)\fP, output the token id and the token.
|
||||
.TP
|
||||
.B \-k
|
||||
Keep the comments.
|
||||
.TP
|
||||
.B \-r
|
||||
Reserved words count as size 1.
|
||||
.TP
|
||||
.B \-s
|
||||
Suppress the source code, summarize counts only.
|
||||
.TP
|
||||
.B \-i
|
||||
Report only the official IOCCC rule 2 size: number of octets (implies \fB\-r\fP and \fB\-s\fP).
|
||||
.PP
|
||||
Counts are impacted by the \fB\-k\fP, \fB\-r\fP and \fB\-c\fP options.
|
||||
By default, the counts do not include comments, words are counted as in \fBwc(1)\fP, and reserved words count in full.
|
||||
Using the example code above, the options change the counts as follows:
|
||||
.PP
|
||||
.TP
|
||||
\fB\-r\fP
|
||||
6 15 96 53 25 5 18
|
||||
.TQ
|
||||
\fB\-k\fP
|
||||
7 20 120 89 31 5 0
|
||||
.TQ
|
||||
\fB\-c\fP
|
||||
7 36 98 71 27 5 0
|
||||
.PP
|
||||
The \fB\-c\fP option counts tokens instead of words, and is therefore more accurate for source code.
|
||||
Note the aberration for line count with \fB\-r\fP; it is as\-if the comment never existed.
|
||||
.PP
|
||||
The \fB\-c\fP and \fB\-t\fP options change the output, instead writing a stream of tokens to \fBstdout\fP, one token per line.
|
||||
The \fB\-t\fP option suppresses both the counts and the token ids, writing only the tokens.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Summarize the source code counts:
|
||||
.sp
|
||||
.RS
|
||||
.ft B
|
||||
tac -rs tac.c
|
||||
.ft R
|
||||
.RE
|
||||
.PP
|
||||
Count the 10 most frequently used unique tokens in the source code:
|
||||
.sp
|
||||
.RS
|
||||
.ft B
|
||||
tac -t tac.c 2>/dev/null | sort | uniq -c | sort -k1nr | sed 10q
|
||||
.ft R
|
||||
.RE
|
||||
.PP
|
||||
Count the unique constants in the source:
|
||||
.sp
|
||||
.RS
|
||||
.ft B
|
||||
tac -c tac.c 2>/dev/null | grep ^300 | sort | uniq -c | sort -k1nr | awk '{print $1,$3}'
|
||||
.ft R
|
||||
.RE
|
||||
.SH BUGS
|
||||
\fBtac\fP does not properly count preprocessor tokens with embedded space or comments as reserved words:
|
||||
.sp
|
||||
.RS
|
||||
.ft B
|
||||
echo '#/*comment*/include/*comment*/<stdio.h>' | tac -i
|
||||
.br
|
||||
echo '# include<stdio.h>' | tac -i
|
||||
.br
|
||||
echo '#include<stdio.h>' | tac -i
|
||||
.ft R
|
||||
.RE
|
||||
.sp
|
||||
report no reserved words on the first two inputs, and thus 17 as the IOCCC size, although 10 is the correct answer (as in the final example).
|
||||
.PP
|
||||
The original meaning of the \fB\-c\fP option was "become compatible with \fBiocccsize(1)\fP".
|
||||
Its meaning was flipped so the default behavior is now compatible.
|
||||
.SH SEE ALSO
|
||||
\fBiocccsize(1)\fP, \fBwc(1)\fP
|
||||
.br
|
||||
\<https://ioccc.org/2015/rules.txt\>
|
||||
+1
-1
@@ -37,7 +37,7 @@ awk '/^[^$]/{l=length;m=m>l?m:l;a[l]=a[l]$1}
|
||||
*
|
||||
* DO NOT EDIT the string kw; instead:
|
||||
*
|
||||
* mkkeywords < my.list > my.keywords
|
||||
* mkkeywords.sh < my.list > my.keywords
|
||||
* cc -DW=\"my.keywords\" -o tac tac.c
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
NAME
|
||||
tac - tokenize and count C-like program source code
|
||||
|
||||
SYNOPSIS
|
||||
tac [-t] [-c] [-k] [-r] [-s] [-i] [file]
|
||||
|
||||
DESCRIPTION
|
||||
tac reads C or C-like source code from stdin or file, breaking it into tokens (lexemes),
|
||||
counting these according to the rules of the IOCCC, and outputting the tokens,
|
||||
counts, or source code as directed by the command line options.
|
||||
The default output is the source code with comments removed on stdout,
|
||||
and the counts on stderr.
|
||||
|
||||
The count format is a set of integer values in the following order:
|
||||
|
||||
lines number of newlines
|
||||
words number of words
|
||||
chars number of characters
|
||||
ioccc number of IOCCC countable tokens; the IOCCC rule 2 value
|
||||
saved number of characters not counted due to rules and keywords
|
||||
kwcnt number of keywords
|
||||
kwlen number of characters saved by counting keyword length as 1
|
||||
|
||||
For the following code:
|
||||
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
/* example for loop */
|
||||
for (int ac=1; ac<10; ++ac)
|
||||
printf("%d\n", ac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tac prints the code to stdout, and to stderr:
|
||||
|
||||
6 15 96 71 25 5 0
|
||||
|
||||
which means 6 lines, 15 words, 96 chars, 71 IOCCC counts, 25 chars saved,
|
||||
5 kwcnt, and no characters saved from kwlen. (By default, comments are not
|
||||
counted.)
|
||||
|
||||
The following options are supported:
|
||||
|
||||
-t output just the token stream
|
||||
-c correct the accounting bugs in iocccsize(1), output the token id and the token
|
||||
-k keep the comments
|
||||
-r reserved words count as size 1
|
||||
-s suppress the source code, summarize counts only
|
||||
-i report only the official IOCCC rule 2 size: number of octets (implies -r and -s)
|
||||
|
||||
Counts are impacted by the -k, -r and -c options.
|
||||
By default, the counts do not include comments, words are counted as in wc(1),
|
||||
and reserved words count in full.
|
||||
Using the example code above, the options change the counts as follows:
|
||||
|
||||
-r 6 15 96 53 25 5 18
|
||||
-k 7 20 120 89 31 5 0
|
||||
-c 7 36 98 71 27 5 0
|
||||
|
||||
The -c option counts tokens instead of words, and is therefore more accurate for source code.
|
||||
Note the aberration for line count with -r; it is as-if the comment never existed.
|
||||
|
||||
The -c and -t options change the output, instead writing a stream of tokens to stdout,
|
||||
one token per line.
|
||||
The -t option suppresses both the counts and the token ids, writing only the tokens.
|
||||
|
||||
EXAMPLES
|
||||
Summarize the source code counts:
|
||||
|
||||
tac -rs tac.c
|
||||
|
||||
Count the 10 most frequently used unique tokens in the source code:
|
||||
|
||||
tac -t tac.c 2>/dev/null | sort | uniq -c | sort -k1nr | sed 10q
|
||||
|
||||
Count the unique constants in the source:
|
||||
|
||||
tac -c tac.c 2>/dev/null | grep ^300 | sort | uniq -c | sort -k1nr | awk '{print $1,$3}'
|
||||
|
||||
BUGS
|
||||
tac does not properly count preprocessor tokens with embedded space or
|
||||
comments as reserved words:
|
||||
|
||||
echo '#/*comment*/include/*comment*/<stdio.h>' | tac -i
|
||||
echo '# include<stdio.h>' | tac -i
|
||||
echo '#include<stdio.h>' | tac -i
|
||||
|
||||
reports no reserved words on the first two inputs, and thus 17 as the IOCCC size,
|
||||
although 10 is the correct answer (as in the final example).
|
||||
|
||||
The original meaning of the -c option was "become compatible with iocccsize(1)".
|
||||
Its meaning was flipped so the default behavior is now compatible.
|
||||
|
||||
SEE ALSO
|
||||
iocccsize(1), wc(1)
|
||||
http://ioccc.org/2015/rules.txt
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cat $* | ./prog -t | sort | uniq -c | sort -k1nr
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate IOCCC winner 2018/burton2
|
||||
#
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy
|
||||
# way.
|
||||
if [[ -z "$CC" ]]; then
|
||||
CC="cc"
|
||||
fi
|
||||
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear screen after compilation so that only the entry is shown
|
||||
clear
|
||||
|
||||
|
||||
echo "$ ./prog -i < prog.c" 1>&2
|
||||
./prog -i < prog.c
|
||||
|
||||
echo "$ ./prog -s < prog.c" 1>&2
|
||||
./prog -s < prog.c
|
||||
|
||||
echo "$ ./prog -sk < prog.c" 1>&2
|
||||
./prog -sk < prog.c
|
||||
|
||||
read -r -n 1 -p "Press any key to run: make test (space = next page, q = quit): "
|
||||
echo 1>&2
|
||||
make test | less -EXF
|
||||
@@ -108,4 +108,4 @@ tern && /^:/ { newline(); show($0); --tern; --n; next }
|
||||
{ show($0) }
|
||||
'
|
||||
|
||||
pp $* | $PROG -t | ./tokenfix | awk "$script" # sed 's/""//g'
|
||||
pp $* | $PROG -t | ./tokenfix.sh | awk "$script" # sed 's/""//g'
|
||||
@@ -3151,8 +3151,19 @@ There was no IOCCC in 2017.
|
||||
### Source code: [2018/algmyr/algmyr.c](2018/algmyr/algmyr.c)
|
||||
### Information: [2018/algmyr/README.md](2018/algmyr/README.md)
|
||||
|
||||
This entry is known to crash if a file cannot be opened. This is noted by the
|
||||
author and is easy enough to fix but need not be.
|
||||
The author wrote:
|
||||
|
||||
* There is no error checking done when opening files, so expect segfaults if you
|
||||
provide the wrong path to a file.
|
||||
* This program is bound to misbehave if `int` is less than 32 bits.
|
||||
* Flags will only be interpreted correctly if they are the first argument. Reading
|
||||
a file named `-d` or `-h` is fully possible if it is not the first file
|
||||
provided, even though I am not sure why you would want to do that.
|
||||
* Providing invalid/unexpected arguments to the decode flag will result in odd
|
||||
behavior. Some erroneous arguments cause segfaults (negative number of channels,
|
||||
channel id outside valid range). One argument in particular causes an infinite
|
||||
loop printing whitespace.
|
||||
|
||||
|
||||
|
||||
## 2018 hou
|
||||
@@ -3171,6 +3182,25 @@ Abort trap: 6
|
||||
|
||||
but this is expected and the file `ioccc.html` will be generated properly.
|
||||
|
||||
|
||||
## 2018 mills
|
||||
|
||||
### STATUS: INABIAF - please **DO NOT** fix
|
||||
### Source code: [2018/mills/prog.c](2018/mills/prog.c)
|
||||
### Information: [2018/mills/README.md](2018/mills/README.md)
|
||||
|
||||
The author stated that if you make a typo it can happen that the boot loader can
|
||||
crash and halt. If this is the case type ctrl-e to quit the emulator and try
|
||||
again.
|
||||
|
||||
The author also stated that it is possible to corrupt the virtual disk. If you
|
||||
do this you should type `make clobber all` and try again.
|
||||
|
||||
Cody caused a funny problem where it showed `ERROR` after each command. The
|
||||
solution was to hit ctrl-e and start again. He does not know if this is what was
|
||||
referred to by the author though he doesn't think he made a typo either.
|
||||
|
||||
|
||||
## 2018 vokes
|
||||
|
||||
### STATUS: INABIAF - please **DO NOT** fix
|
||||
|
||||
@@ -3952,6 +3952,17 @@ He also added the [try.sh](/2015/yang/try.sh) script.
|
||||
# <a name="2018"></a>2018
|
||||
|
||||
|
||||
## <a name="2018_anderson"></a>[2018/anderson](/2018/anderson/prog.c) ([README.md](/2018/anderson/README.md))
|
||||
|
||||
[Cody](#cody) added the [try.sh](/2018/anderson/try.sh) script.
|
||||
|
||||
|
||||
## <a name="2018_algmyr"></a>[2018/algmyr](/2018/algmyr/prog.c) ([README.md](/2018/algmyr/README.md))
|
||||
|
||||
|
||||
[Cody](#cody) added the [try.sh](/2018/algmyr/try.sh) script.
|
||||
|
||||
|
||||
## <a name="2018_bellard"></a>[2018/bellard](/2018/bellard/prog.c) ([README.md](/2018/bellard/README.md))
|
||||
|
||||
[Cody](#cody) added explicit linking of libm (`-lm`) for systems that do not do this
|
||||
@@ -3961,6 +3972,40 @@ Cody also added [alt code](/2018/bellard/README.md#alternate-code) that should
|
||||
work for Windows, based on the author's remarks.
|
||||
|
||||
|
||||
## <a name="2018_burton1"></a>[2018/burton1](/2018/burton1/prog.c) ([README.md](/2018/burton1/README.md))
|
||||
|
||||
[Cody](#cody) fixed the `scripthd` script (referred to `prog` not `./prog`) and
|
||||
renamed it to [scripthd.sh](/2018/burton1/scripthd.sh) to help browsers and
|
||||
GitHub as far as downloading/displaying goes.
|
||||
|
||||
Cody also added the [try.sh](/2018/burton1/try.sh) script which also uses
|
||||
`scripthd.sh` to show how it differs from `prog` itself.
|
||||
|
||||
|
||||
## <a name="2018_burton2"></a>[2018/burton2](/2018/burton2/prog.c) ([README.md](/2018/burton2/README.md))
|
||||
|
||||
[Cody](#cody) fixed the `make test` rule: it tried to run `tac(1)` (in systems
|
||||
that have that command) rather than the entry itself which is called `tac` and
|
||||
the `runtest` script (which he renamed to `runtest.sh` for download/browser
|
||||
display purposes) was not executable.
|
||||
|
||||
Cody also renamed `manpage` to `manpage.sh` for download/browser purposes and he
|
||||
did the same with `tokenfix` to `tokenfix.sh` as well as `spotcheck` to
|
||||
`spotcheck.sh`, `spotdiff` to `spotdiff.sh`, `freqcount` to `freqcount.sh` and
|
||||
`mkkeywords` to `mkkeywords.sh`.
|
||||
|
||||
Cody also made the man page properly formatted for `man(1)` and renamed it the
|
||||
file `tac.1`.
|
||||
|
||||
Cody also renamed `discrepancies` to `discrepancies.md` and made it markdown
|
||||
format.
|
||||
|
||||
Cody added the [tokcount.sh](/2018/burton2/tokcount.sh) script which was
|
||||
included in the remarks of the author but not an included file.
|
||||
|
||||
Finally Cody added the [try.sh](/2018/burton2/try.sh) script.
|
||||
|
||||
|
||||
## <a name="2018_ciura"></a>[2018/ciura](/2018/ciura/prog.c) ([README.md](/2018/ciura/README.md))
|
||||
|
||||
[Cody](#cody) added the [try.sh](/2018/ciura/try.sh) script and the PDF file,
|
||||
|
||||
Reference in new issue
Block a user