Author:
- Name: Etienne Duble
Location: FR - French Republic (France)
To build:
make
There is an alternate version of this entry, discussed in the author’s remarks. See Alternate code below.
Bugs and (Mis)features:
The current status of this entry is:
STATUS: INABIAF - please DO NOT fix
For more detailed information see 2015/duble in bugs.html.
To use:
echo Some text | ./prog
Try:
./try.sh
As the script says if you want to move to the next command at any point (lorem-ipsum.txt takes a while to print in particular) you may do so by hitting ctrl-c/sending intr.
Alternate code:
This alternate code, provided by the author, is discussed in more detail by the author in the ‘prog.c vs prog.alt.c’ section of their remarks.
Alternate build:
make alt
Alternate use:
Use prog.alt
as you would prog
above.
Judges’ remarks:
Beautiful penmanship! However, your fonts may vary.
How does this entry compress the font it uses? What’s the purpose of
lrand48(3)
? Why does the program dump core, when it does :) ?
Author’s remarks:
Introduction
This program prints text in your terminal with an interesting hand-writing effect.
It uses the Braille patterns range of the unicode standard: this allows to consider each terminal character as a tiny 2x4 bitmap.
Turning the Braille code into something visual might be considered blasphemous. When I was fighting to make this program work, I started wondering if it was not the reason for its very erratic behaviour.
prog.c vs prog.alt.c
The file prog.alt.c is the one I submitted.
Gil Dogon noted a few unsafe statements (statements whose behaviour is undefined in the C standard and, as such, could cause issues with other compilers or optimization levels). These have been fixed in prog.c.
After this fix, in order to remain rule-2-compliant, a variable name has also been shortened in this file.
How to build
If you have clang
:
CC=clang make -e
Otherwise (gcc):
make
(You will get a few warnings in this case.)
How to use it
You need a terminal configured to handle a UTF-8 encoding and a font including Braille patterns.
This is the default on most modern GNU/Linux operating systems.
The default terminal application (gnome-terminal) or even a simple xterm should render things properly.
I tested this on several Debian and Ubuntu systems, 32 and 64bits and no configuration was needed.
I also tested it on FreeBSD 9.3 32bits (font and encoding configuration was needed in this case).
Basic mode:
$ echo 'I am testing this thing.' | ./prog
[... rendering ...]
$ ./prog < lorem-ipsum.txt
[... rendering ...]
Interactive mode:
$ ./prog
> hello world!!!
[... rendering ...]
>
Obfuscation:
This entry is obfuscated in various ways:
- The structure is hidden by avoiding loops,
if
statements, ternary conditionals, and jump-related instructions. Instead, recursion is heavily used. - Merging all functions into one added even more recursion. ;)
- The provided code does not contain the same number of opening and closing parenthesis.
- Preprocessing the code inflates it and adds lots of indents. Removing some of the tricks involved without breaking the program will be challenging.
- The program ‘plays’ with standard input & output streams, which causes unusual side effects.
- Some variables are re-used for unrelated processes.
- Crucial data may be hidden in unexpected places (e.g. as the size of a temporary buffer).
- Some parts of the code may have no effect (but may have an effect in a specific context, who knows?), and classical libc functions may not act as usual.
- And of course variable names are hard to read (or distracting).
On the other hand, the following may help:
- The code layout should help to identify which part of the code is obfuscated. ;)
- File codes.txt shows how each character is drawn. This data is
encoded in macro
O_o
at the top of the source file.
Limitations:
Charset
In order to comply with the size rule, I encoded only a part of the visible ASCII chars:
a-z, A-Z, '.' ':' ',' ';' '!' and '?'.
Uppercase and lowercase chars are rendered the same. The program also
understands space and linefeed (\n
). Other chars are simply ignored (most of
the time ;)
Stack size
This limitation is due to the heavy use of recursion. After having processed a large number of characters, the process may exceed the stack size and crash. (However I did not experience this myself. The top-level recursion might be removed by the compiler as part of its optimizations.)
Line rendering
The program does its best to avoid cutting words at the end of lines, but it could still happen in case of long words.
Subtleties and extra features
Handling more than text docs?
Given the limited set of characters handled, the program is mostly limited to simple text documents.
Thus, if you try for example:
$ ./prog < prog.c
You will not get something that looks like C code. (but you can still try, if you are curious. :)
A ‘draft’ mode
Defining an environment variable called DRAFT
will enable the ‘draft-mode’.
Try for example:
$ echo 'testing the draft mode' | DRAFT=1 ./prog
The program will run much faster but the rendering will be less precise.
The subtle interactive mode
I saved the best for last: usually, programs that handle an “interactive mode”
have to check whether their standard input is a terminal or not (by using
isatty()
). Did you notice that this program does not perform any such
detection, but still behaves (or seems to behave) appropriately?
Inventory for 2015/duble
Primary files
- prog.c - entry source code
- Makefile - entry Makefile
- prog.alt.c - alternate source code
- prog.orig.c - original source code
- codes.txt - shows how each character is drawn
- lorem-ipsum.txt - sample input
- try.sh - script to try entry
Secondary files
- 2015_duble.tar.bz2 - download entry tarball
- README.md - markdown source for this web page
- .entry.json - entry summary and manifest in JSON
- .gitignore - list of files that should not be committed under git
- .path - directory path from top level directory
- index.html - this web page