diff --git a/2018/vokes/README.md b/2018/vokes/README.md index 7817de857..fd304dd3e 100644 --- a/2018/vokes/README.md +++ b/2018/vokes/README.md @@ -5,26 +5,37 @@ make ``` +### Bugs and (Mis)features: + +The current status of this entry is: + +``` +STATUS: INABIAF - please **DO NOT** fix +``` + +For more detailed information see [2018 vokes in bugs.md](/bugs.md#2018-vokes). + + + ## To use: ```sh -./prog < example-1.txt +./prog < file.txt ``` ### Try: ```sh -./prog < example-2.txt -./prog < example-tab.txt -./prog < ioccc.txt +./try.sh ``` ## Judges' remarks: What this program does is not witchcraft and there are no spectres, but you -might have a meltdown trying to work it all out. +might have a meltdown trying to work it all out (look at the source code to +understand this better). This entry is designed to mislead in many ways. However, if you find yourself wanting to know the possibilities for navigating a graph, you will get the @@ -33,6 +44,7 @@ answer you seek with no hocus pocus. ## Author's remarks: + ### Introduction: This program reads a directed graph (as lines with integer node IDs), @@ -41,7 +53,7 @@ grouped into strongly connected components. Given a set of nodes representing targets and edges representing dependencies between them, it produces a build order with any dependency cycles gathered. -For example, the following input (provided as `example-1.txt`): +For example, the following input (provided as [example-1.txt](example-1.txt)): ``` 0 4 8 @@ -80,12 +92,14 @@ sorted order: 4: 7 ``` -It uses Tarjan's strongly connected components algorithm for the -grouping and reverse-topological sorting, along with a bonus hidden +It uses [Tarjan's strongly connected components +algorithm](https://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm) +for the grouping and reverse-topological sorting, along with a bonus hidden implementation of counting sort, which sorts each group. -For other details about the input format, see "Issues and -Limitations". +For other details about the input format, see [Issues and +Limitations](#issues-and-limitations). + ### Building: @@ -104,7 +118,8 @@ Note: The program can also be built with `-std=c99` or `-std=c89`. If building with `-Weverything`, then `-Wno-strict-prototypes` may also be necessary -- the function pointer declarations for `_` and `B` may get warnings otherwise, for reasons described -under "Obfuscations". +next in [Obfuscations](#obfuscations). + ### Obfuscations: @@ -117,11 +132,11 @@ under "Obfuscations". of parameters, the argument count and types are unconstrained. `_` is set to different functions in several places, but it is always called with appropriate argument(s) for its possible current functions. This - is allowed by the standard -- The section on F,I,N,D,M,Y,C,L,U,E has - further details. + is allowed by the standard -- The section on + `F`,`I`,`N`,`D`,`M`,`Y`,`C`,`L`,`U`,`E` has further details. -- It uses `_` in three different scopes: as a goto label (function - scope), as an enum name, and a `_` function pointer (which is required +- It uses `_` in three different scopes: as a `goto` label (function + scope), as an `enum` name, and a `_` function pointer (which is required to have file scope, since it starts with `_`). There are also other `_`s: it appears in a string, obscured by a hexadecimal escape sequence (`\x5f`), and the cauldron is supported by a giant underscore. @@ -133,48 +148,48 @@ under "Obfuscations". functions have their names reused for different things in other functions. -- There is an enum early on that defines several single-letter - identifiers: F,I,N,D,M,Y,C,L,U,E. These are used for array offsets, - both individually and in combination. The first several values are - also a clue: ISO/IEC 9899:1999 chapter 6.7.5.3 verse 14 describes how - function declarators with an empty parameter list behave. (As does - 3.5.4.3 for ANSI C, which explains the 0x3543 that appears soon - after.) +- There is an enum early on that defines several single-letter identifiers: + `F`,`I`,`N`,`D`,`M`,`Y`,`C`,`L`,`U`,`E`. These are used for array offsets, + both individually and in combination. The first several values are also a + clue: ISO/IEC 9899:1999 chapter 6.7.5.3 verse 14 describes how function + declarators with an empty parameter list behave. (As does 3.5.4.3 for ANSI C, + which explains the `0x3543` that appears soon after.) - Several parts of the program's state are stashed in otherwise unused offsets of the node arrays. These locations are accessed in multiple - ways, such as using `I[p]` (where I == 7) as well as `p[F+L]` (6+1), - or `b[M-N]` (14-5) and `U[b]` (where U == 9). + ways, such as using `I[p]` (where `I == 7`) as well as `p[F+L]` (6+1), + or `b[M-N]` (14-5) and `U[b]` (where `U == 9`). - The other identifiers are misleading, punny, or both. `spectre` does not exploit CVE-2017-5753 or CVE-2017-5715, for example -- it just fits the witch theme. `cast` doesn't cast, `hex` has nothing to do with hexadecimal, `bubble` is not bubble sort, there is no undefined - behavior in `nasal_demons`, and `main` has absolutely nothing to do + behavior in `nasal_demons`, and `main()` has absolutely nothing to do with a hand. - For well-formed input, how the program determines when to exit is a - bit obscure. `main` ends with a `goto` leading back to an earlier `_` + bit obscure. `main()` ends with a `goto` leading back to an earlier `_` label, so it just loops forever, and `exit` only appears in code paths related to error-handling. It looks like `cast` calls `meltdown` with its second argument set to 0, which would call `exit`, but running in - gdb with a breakpoint on `cast` reveals that it isn't being called... + `gdb(1)` with a breakpoint on `cast` reveals that it isn't being called... -- Instead of using `isdigit()`, the program checks the numeric value of - each `char`, and literals that would suggest comparing against e.g. '0' +- Instead of using `isdigit(3)`, the program checks the numeric value of + each `char`, and literals that would suggest comparing against e.g. `'0'` are specified in octal in one place, and produced by arithmetic using - the enum elsewhere. + the `enum` elsewhere. - Common conventions are subverted: `i` is not a loop index, `argv` and `argc`'s names are swapped. - `NULL` does not appear in the program. Instead, `argc[argv]` (which is - required to be a null pointer) is saved and passed to where its value + required to be a NULL pointer) is saved and passed to where its value is needed. - Oh, and the program is squashed into the shape of a bubbling cauldron, on top of a giant underscore, so there's that. + ### Issues and Limitations: - Despite appearances, it does not handle numbers in hex, or provide @@ -217,9 +232,9 @@ under "Obfuscations". nodes are visited. Addressing this would put the program over the size limit. -- The implementation depends on the characters '0', '1', ... '9' having - the values 48 through 57, rather than using `isdigit()`. As noted - above, this program has nothing to do with a hand. +- The implementation depends on the characters `'0'`, `'1'`, ... `'9'` having + the values `48` through `57`, rather than using `isdigit(3)`. As noted above, + this program has nothing to do with a hand. ## Copyright and CC BY-SA 4.0 License: diff --git a/2018/vokes/try.sh b/2018/vokes/try.sh new file mode 100755 index 000000000..a0ea4684b --- /dev/null +++ b/2018/vokes/try.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# try.sh - demonstrate IOCCC winner 2018/vokes +# + +# 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 < example-1.txt: " +echo 1>&2 +./prog < example-1.txt + +read -r -n 1 -p "Press any key to run: ./prog < example-2.txt: " +echo 1>&2 +./prog < example-2.txt + +read -r -n 1 -p "Press any key to run: ./prog < example-tab.txt: " +echo 1>&2 +./prog < example-tab.txt + +read -r -n 1 -p "Press any key to run: ./prog < ioccc.txt: " +echo 1>&2 +./prog < ioccc.txt diff --git a/bugs.md b/bugs.md index 0cd52b439..3c11c3e49 100644 --- a/bugs.md +++ b/bugs.md @@ -3171,6 +3171,58 @@ Abort trap: 6 but this is expected and the file `ioccc.html` will be generated properly. +## 2018 vokes + +### STATUS: INABIAF - please **DO NOT** fix +### Source code: [2018/vokes/vokes.c](2018/vokes/vokes.c) +### Information: [2018/vokes/README.md](2018/vokes/README.md) + +The author wrote the following: + +- Despite appearances, it does not handle numbers in hex, or provide + a `curses(3)`-based interface. + +- The expected input format is zero or more lines of space-separated + integers. If other characters appear in the input, it will either + reject the input entirely and exit with a non-zero status, or skip + number(s) adjacent to the non-digit characters, depending on where the + characters appear. Tabs and multiple consecutive spaces are handled + correctly, however. + +- Individual lines of input longer than `0x3543 - 1` bytes will be + split and processed as if they were multiple lines of input, which can + produce incorrect results. This magic number's significance is + described earlier. + +- The algorithm expects its input to represent a fully connected graph. + While the output is otherwise topologically sorted, if there are nodes + completely unconnected to the rest of the graph (with or without + self-cycles), they will be output as soon as they are processed -- + this means that, when there are disconnected nodes, reordering the + input lines can produce different output. Addressing this by adding + another pass is would put the program over the size limit. + +- While the node IDs don't need to be consecutive or start at 0, the + implementation doesn't have special handling for sparse graphs. If you + give it a graph with nodes numbered 0 and 2147483647, it will attempt + to allocate sufficient memory (potentially around 32 GB) for the + entire range of graph nodes, even if those are the only ones. If + memory allocation returns NULL, it will gracefully exit, otherwise it + will succeed, eventually, perhaps after a great deal of swapping. + +- Node IDs >= 2147483648 will cause the program to print an error + message and exit with a non-zero status. This shrinks the code that + detects overflowing the array size by a bit. + +- A very large group of nodes in a cycle can cause a stack overflow. + This typically takes over 100,000 nodes, and depends on the order the + nodes are visited. Addressing this would put the program over the size + limit. + +- The implementation depends on the characters `'0'`, `'1'`, ... `'9'` having + the values `48` through `57`, rather than using `isdigit(3)`. As noted above, + this program has nothing to do with a hand. + # 2019 diff --git a/thanks-for-help.md b/thanks-for-help.md index 3fa1b9353..a3b85ceb0 100644 --- a/thanks-for-help.md +++ b/thanks-for-help.md @@ -3967,6 +3967,12 @@ that's probably true: let's just say that for the IOCCC I'm (Cody) a weasel! :-) (Linux doesn't seem to but macOS does). +## [2018/vokes](/2018/vokes/prog.c) ([README.md](/2018/vokes/README.md)) + +[Cody](#cody) added the [try.sh](/2018/vokes/try.sh) script. + + + # 2019