Fixes to 2018/burton1
Add links to script in entry when referred to in README.md. Fix scripthd to refer to not prog but ./prog. Fix dead link in README.html. Formatting and possible typo fixes.
This commit is contained in:
1 parent
1b225f6b73
commit
51939ecc17
2 files changed
+63
-55
No files matched your search
+62
-54
@@ -24,8 +24,8 @@ make
|
|||||||
|
|
||||||
### Alternate code:
|
### Alternate code:
|
||||||
|
|
||||||
An alternate version of this entry, `prog.alt.c`, is provided
|
An alternate version of this entry, [prog.alt.c](prog.alt.c), is provided
|
||||||
This alternate code was supposed compile without warnings, however
|
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.
|
||||||
|
|
||||||
To compile this alternate version:
|
To compile this alternate version:
|
||||||
@@ -42,7 +42,7 @@ One line, one array, one loop and one statement but it prints many bytes. It won
|
|||||||
|
|
||||||
Feed this anything on stdin.
|
Feed this anything on stdin.
|
||||||
|
|
||||||
The included script may be used as a driver program for this entry.
|
The [included script](scripthd) may be used as a driver program for this entry.
|
||||||
It adds several nice-to-have features, and allows salt-to-taste customizability.
|
It adds several nice-to-have features, and allows salt-to-taste customizability.
|
||||||
|
|
||||||
This code has been compiled and tested on:
|
This code has been compiled and tested on:
|
||||||
@@ -57,21 +57,25 @@ This code has been compiled and tested on:
|
|||||||
|
|
||||||
<div style="margin-bottom:60em;margin-top:4em"><strong>Spoiler below; scroll down.</strong></div>
|
<div style="margin-bottom:60em;margin-top:4em"><strong>Spoiler below; scroll down.</strong></div>
|
||||||
|
|
||||||
### SPOILER
|
### 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 self-imposed ground rules in the hunt for shortest:
|
||||||
the code has to output correctly,
|
|
||||||
no extraneous newlines, the code must be portable,
|
- the code has to output correctly,
|
||||||
and without bypassing the solution using execve(2),
|
- no extraneous newlines, the code must be portable,
|
||||||
or functions built upon it (system(3), popen(3), etc). E.g:
|
and without bypassing the solution using execve(2), or functions built upon it (system(3), popen(3), etc).
|
||||||
|
|
||||||
|
E.g:
|
||||||
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
main(){system("hd");} // it's turtles all the way down!
|
main(){system("hd");} // it's turtles all the way down!
|
||||||
```
|
```
|
||||||
|
|
||||||
is not acceptable.
|
is not acceptable.
|
||||||
|
|
||||||
And, "output correctly" is the output format of this entry. QED.
|
And, "output correctly" is the output format of this entry. QED.
|
||||||
|
|
||||||
Early attempts ended up at a reasonably short 157 characters.
|
Early attempts ended up at a reasonably short 157 characters.
|
||||||
@@ -79,6 +83,7 @@ This was too long for a one-liner, so it had to be formatted as something more i
|
|||||||
This solution is pleasing, but a true one-liner was the hoped-for goal.
|
This solution is pleasing, but a true one-liner was the hoped-for goal.
|
||||||
Here is the 157 character version in it's entirety:
|
Here is the 157 character version in it's entirety:
|
||||||
|
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char O,o[ 20];L(O){
|
char O,o[ 20];L(O){
|
||||||
putchar ( O+ 48+39 *(9<
|
putchar ( O+ 48+39 *(9<
|
||||||
@@ -153,67 +158,70 @@ An obfuscated hex dump has been done before:
|
|||||||
[1986/bright/bright.c](http://ioccc.org/1986/bright/bright.c) is similar in function,
|
[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!
|
but it uses more characters in just setting up its obfuscation than this entire solution!
|
||||||
|
|
||||||
### BIGGER SPOILER
|
### BIGGER SPOILER:
|
||||||
|
|
||||||
If you are unhappy with the way DEL (character 127) is handled,
|
If you are unhappy with the way DEL (character 127) is handled,
|
||||||
replace the cryptic expression `4<(4^l>>5)?l:46` with `32>l|l>126?46:l`.
|
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.
|
Both take the same number of characters, but the former is a bit more interesting.
|
||||||
Bonus question: how does the first expression work?
|
Bonus question: how does the first expression work?
|
||||||
|
|
||||||
### BIGGEST SPOILER (and some history)
|
### BIGGEST SPOILER (and some history):
|
||||||
|
|
||||||
Technically, `char o[0];` is illegal (SS 6.7.6.2) according to ISO (N1570).
|
Technically, `char o[0];` is illegal (SS 6.7.6.2) according to ISO (N1570). And
|
||||||
And `char o[];` is a conditionally supported feature (SS 6.7.6.2, 6.10.8.3).
|
`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,
|
However, it works in modern C implementations as an extension, including GCC,
|
||||||
including GCC, Clang and TCC, for X86 and ARM,
|
Clang and TCC, for X86 and ARM, on multiple operating systems (Linux, OSX,
|
||||||
on multiple operating systems (Linux, OSX, FreeBSD), so it is _functionally_ correct.
|
FreeBSD), so it is _functionally_ correct. MicroSoft Visual C++ does not allow
|
||||||
MicroSoft Visual C++ does not allow `char o[]` or `char o[0]`,
|
`char o[]` or `char o[0]`, and implements its close relative `char o[1]` such
|
||||||
and implements its close relative `char o[1]`
|
that writing more than a single char will cause a fault, which is _technically_
|
||||||
such that writing more than a single char will cause a fault, which is _technically_ correct.
|
correct.
|
||||||
|
|
||||||
But how does this work at all, even as an extension?
|
But how does this work at all, even as an extension? `o[]` allocates one(!)
|
||||||
`o[]` allocates one(!) byte in a zero-filled data area (formerly BSS).
|
byte in a zero-filled data area (formerly
|
||||||
The UNIX-derived systems this code was run upon all place the
|
[BSS](https://en.wikipedia.org/wiki/.bss)). The UNIX-derived systems this code
|
||||||
storage of `O` and `o` into a zero-filled VM page with nothing following:
|
was run upon all place the storage of `O` and `o` into a zero-filled VM page
|
||||||
thus, there are plenty of available and unused zero bytes following `O`, addressed via `o`,
|
with nothing following: thus, there are plenty of available and unused zero
|
||||||
and this code only needs 17.
|
bytes following `O`, addressed via `o`, and this code only needs 17. This is
|
||||||
This is _undefined_ behavior, but as shown, it is widely available.
|
_undefined_ behavior, but as shown, it is widely available.
|
||||||
|
|
||||||
The [1979 Seventh Edition UNIX][1] (v7) system pre-dates the IOCCC by several years,
|
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][2].
|
||||||
There are two C compilers present: `cc` written by Dennis Ritchie, and `pcc` written by Steven Johnson.
|
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")
|
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 `char o[0]` nor puts the bytes in
|
but `pcc` handles them correctly, and neither compiler accepts `char o[]` or
|
||||||
a zero-filled page (as a paged VM was not yet written for UNIX).
|
`char o[0]` and neither put the bytes in a zero-filled page (as a paged VM was
|
||||||
|
not yet written for UNIX).
|
||||||
|
|
||||||
[1]: http://minnie.tuhs.org/cgi-bin/utree.pl
|
[1]: http://minnie.tuhs.org/cgi-bin/utree.pl
|
||||||
[2]: http://ioccc.org/all/README
|
[2]: http://ioccc.org/all/README
|
||||||
[3]: http://www.computerworld.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/?pp=4
|
[3]: 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 written,
|
More significant is that v7 `printf`(3) does not report the number of characters
|
||||||
and therefore 111 compiles but does not work correctly;
|
written, and therefore 111 compiles but does not work correctly; 113 is the
|
||||||
113 is the shortest code that compiles and runs correctly in Ancient UNIX.
|
shortest code that compiles and runs correctly in Ancient UNIX.
|
||||||
|
|
||||||
> Interesting digression: v7 `printf` (`_doprnt`) was written in PDP-11 assembler.
|
Interesting digression: v7 `printf` (`_doprnt`) was written in PDP-11 assembly.
|
||||||
> It pre-dates `varargs.h`, and assembly was the only way to gain access to the variable argument types.
|
It pre-dates `varargs.h`, and assembly was the only way to gain access to the
|
||||||
> The first edition _The C Programming Language_, 1978, page 71, remarks:
|
variable argument types. The first edition _The C Programming Language_, 1978,
|
||||||
|
page 71, remarks:
|
||||||
|
|
||||||
>> By the way, there is no entirely satisfactory way to write a portable function
|
> By the way, there is no entirely satisfactory way to write a portable function
|
||||||
>> that accepts a variable number of arguments, because there is no portable way
|
> that accepts a variable number of arguments, because there is no portable way
|
||||||
>> for the called function to determine how many arguments where actually passed to it in a given call.
|
> for the called function to determine how many arguments where actually passed
|
||||||
>> ...
|
> to it in a given call.
|
||||||
>> `printf`, the most common C function with a variable number of arguments,
|
> ...
|
||||||
>> ... is also non-portable and must be modified for different environments.
|
> `printf`, the most common C function with a variable number of arguments,
|
||||||
|
> ... is also non-portable and must be modified for different environments.
|
||||||
|
|
||||||
> It is fascinating to explore the roots of C through the history of the operating system
|
It is fascinating to explore the roots of C through the history of the operating
|
||||||
> it was birthed within. C is often criticized as a difficult, inscrutable language,
|
system it was birthed within. C is often criticized as a difficult, inscrutable
|
||||||
> but as this contest demonstrates, this is in parody.
|
language, but as this contest demonstrates, this is in parody. _Shell-gol_ is
|
||||||
> _Shell-gol_ is one of those instances where someone [preferred a different language][3],
|
one of those instances where someone [preferred a different language][3], and
|
||||||
> and (ab)used the preprocessor to re-mold C into something they found comfortable.
|
(ab)used the preprocessor to re-mold C into something they found comfortable.
|
||||||
> Most of the rest of the system, especially in the kernel,
|
Most of the rest of the system, especially in the kernel, are models of clarity
|
||||||
> are models of clarity and efficient expression.
|
and efficient expression.
|
||||||
|
|
||||||
### TL;DR
|
### TL;DR:
|
||||||
|
|
||||||
So which version is the shortest, portable hex dump?
|
So which version is the shortest, portable hex dump?
|
||||||
|
|
||||||
@@ -222,16 +230,16 @@ So which version is the shortest, portable hex dump?
|
|||||||
* 113 works on Ancient UNIX and the portable C compiler.
|
* 113 works on Ancient UNIX and the portable C compiler.
|
||||||
* 119 works on all platforms, including the original Ritchie PDP-11 C compiler.
|
* 119 works on all platforms, including the original Ritchie PDP-11 C compiler.
|
||||||
|
|
||||||
### Coda
|
### Coda:
|
||||||
|
|
||||||
Clearly, the smallest possible program violates modern best practice.
|
Clearly, the smallest possible program violates modern best practice.
|
||||||
It is not even possible to compile cleanly, but it will compile correctly.
|
It is not even possible to compile cleanly, but it will compile correctly.
|
||||||
|
|
||||||
Included is `prog.alt.c`, a modern C implementation that is -- perhaps -- the smallest,
|
Included is [prog.alt.c](prog.alt.c), a modern C implementation that is --
|
||||||
clean-compiling version using `clang` or `gcc` with `-Wall -pedantic`.
|
perhaps -- the smallest, clean-compiling version using `clang` or `gcc` with
|
||||||
Note that while this is larger than all but the original attempt,
|
`-Wall -pedantic`. Note that while this is larger than all but the original
|
||||||
it will *not* work with the original Ritchie PDP-11 C compiler,
|
attempt, it will *not* work with the original Ritchie PDP-11 C compiler, since
|
||||||
since the expression within the ternary remains too complex.
|
the expression within the ternary remains too complex.
|
||||||
|
|
||||||
Try:
|
Try:
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
hd=${HD:=prog}
|
hd=${HD:=./prog}
|
||||||
|
|
||||||
cat $* |
|
cat $* |
|
||||||
$hd |
|
$hd |
|
||||||
|
|||||||
Reference in new issue
Block a user