Fixes in 2015/burton
Format fixes (maybe typos?) in README.md. Added calc.1 which is essentially what was calc.man but so one can actually get expected formatting when using man ./calc.1. If I fixed any typos they are not fixed in calc.man. I kept the commands the same so one would have to change calc to ./prog. Formatting and maybe typos in road.to.obscurity.
This commit is contained in:
1 parent
dbc6a3b812
commit
fa31f80b39
3 files changed
+339
-175
No files matched your search
+76
-61
@@ -46,13 +46,14 @@ grep '[0-9]' prog.c
|
||||
|
||||
./prog < test.in
|
||||
|
||||
man ./calc.man
|
||||
man ./calc.1
|
||||
```
|
||||
|
||||
## Alternate code
|
||||
|
||||
An alternate version of this entry, `prog.alt.c`, is provided.
|
||||
This alternate code is discussed in the "prog.c vs prog.alt.c" section of the author's comments below.
|
||||
This alternate code is discussed in the "prog.c vs prog.alt.c" section of the
|
||||
author's comments below.
|
||||
|
||||
To compile this alternate version:
|
||||
|
||||
@@ -66,10 +67,11 @@ Use `prog.alt` as you would `prog` above.
|
||||
|
||||
"Look, Ma, no ~~hands~~ digits!"
|
||||
|
||||
The place where some arithmetic operations are done, for example,
|
||||
division or modulo, are easy to find. Where are addition and subtraction?
|
||||
The place where some arithmetic operations are done, for example, division or
|
||||
modulo, are easy to find. Where are addition and subtraction?
|
||||
|
||||
We were impressed with the level of detail the author "blogged" the obfuscation process.
|
||||
We were impressed with the level of detail the author "blogged" the obfuscation
|
||||
process.
|
||||
|
||||
## Author's comments:
|
||||
|
||||
@@ -80,10 +82,10 @@ See the included man page. ;-)
|
||||
|
||||
### Notes
|
||||
|
||||
This program is named calc. Onomatopoeia of sorts, in the visual realm.
|
||||
The formatting was easier: Form Follows Function (although [Hou][1] did this better).
|
||||
It was tempting to call it iCalc, with i for integer (and it was written on an iDevice),
|
||||
but sanity prevailed.
|
||||
This program is named calc. Onomatopoeia of sorts, in the visual realm. The
|
||||
formatting was easier: Form Follows Function (although [Hou][1] did this
|
||||
better). It was tempting to call it iCalc, with i for integer (and it was
|
||||
written on an iDevice), but sanity prevailed.
|
||||
|
||||
Printed in 8 pt Courier, it makes aesthetically pleasing 8.5 x 11 wall art.
|
||||
|
||||
@@ -91,12 +93,13 @@ Printed in 8 pt Courier, it makes aesthetically pleasing 8.5 x 11 wall art.
|
||||
|
||||
### prog.c vs prog.alt.c
|
||||
|
||||
Dominik Muth observed a syntax error on `1+1`, `1-1`, `1|1`, and `1^1` when using an
|
||||
ARM based computer, although `1*1` and others worked correctly.
|
||||
This occurs because some platforms by default treat `char` as `unsigned char`.
|
||||
The original code has this weakness, which can be corrected by adding `-fsigned-char`
|
||||
to the compile line.
|
||||
The modified code is agnostic to `char` signed-ness.
|
||||
Dominik Muth observed a syntax error on `1+1`, `1-1`, `1|1`, and `1^1` when
|
||||
using an ARM based computer, although `1*1` and others worked correctly. This
|
||||
occurs because some platforms by default treat `char` as `unsigned char`. The
|
||||
original code has this weakness, which can be corrected by adding
|
||||
`-fsigned-char` to the compile line.
|
||||
|
||||
The modified code is agnostic to `char` signedness.
|
||||
|
||||
### Why is this entry obfuscated/interesting?
|
||||
|
||||
@@ -105,21 +108,24 @@ Yes, this is another calculator program.
|
||||
However, unlike any other calculator source code the author is aware of,
|
||||
this one contains no digits. At all. Anywhere. As in
|
||||
|
||||
grep '[0-9]' prog.c || echo no digits!
|
||||
```sh
|
||||
grep '[0-9]' prog.c || echo no digits!
|
||||
```
|
||||
|
||||
Nor are the digits simply obfuscated. There are no character constants.
|
||||
There is only one single, short string, and it does not contain any obfuscated digits.
|
||||
And yet the output is in decimal and hexadecimal, and it accepts octal, decimal, and hex input.
|
||||
Nor are the digits simply obfuscated. There are no character constants. There
|
||||
is only one single, short string, and it does not contain any obfuscated digits.
|
||||
And yet the output is in decimal and hexadecimal, and it accepts octal, decimal,
|
||||
and hex input.
|
||||
|
||||
Flow control is by `for` and `return`. It is If-less. Switch-less. While-less. Hope-less.
|
||||
Literally, if not figuratively. ;-)
|
||||
Flow control is by `for` and `return`. It is if-less, switch-less,
|
||||
while-less, and hopeless. Literally, if not figuratively. ;-)
|
||||
|
||||
The code size is intentionally 2015, as stated by iocccsize -i,
|
||||
and can be reformatted without changes (as in rule2.c) to exactly 4096 octets.
|
||||
The code size is intentionally 2015, as stated by iocccsize -i, and can be
|
||||
reformatted without changes (as in rule2.c) to exactly 4096 octets.
|
||||
|
||||
Finally, calc is interesting, if for no other reason than it is practically useful:
|
||||
Hex/decimal conversion, arithmetic, byte-swapping, bit-shifting, and logical operations with memory,
|
||||
on the command line, or interactively.
|
||||
Finally, calc is interesting, if for no other reason than it is practically
|
||||
useful: Hex/decimal conversion, arithmetic, byte-swapping, bit-shifting, and
|
||||
logical operations with memory, on the command line, or interactively.
|
||||
|
||||
### But the question is why is the entry obfuscated?
|
||||
|
||||
@@ -130,52 +136,57 @@ The code follows many industry best-practices:
|
||||
- Numbers and digits have often been used for obfuscation,
|
||||
so in a bid for better clarity, this code has no digits at all.
|
||||
|
||||
- In the spirit of clarity, most of the variables are declared before use, so they
|
||||
are readily visible, with single letter names that don't clutter the screen,
|
||||
in a tautological arrangement.
|
||||
- In the spirit of clarity, most of the variables are declared before use, so
|
||||
they are readily visible, with single letter names that don't clutter the
|
||||
screen, in a tautological arrangement.
|
||||
|
||||
- More helpful is the use of `typedef`s instead of `#define`, so the types remain useful
|
||||
even in the debugger, and source code beautifiers will not undo careful presentation.
|
||||
- More helpful is the use of `typedef`s instead of `#define`, so the types
|
||||
remain useful even in the debugger, and source code beautifiers will not undo
|
||||
careful presentation.
|
||||
|
||||
- `#defines` are used here in the best spirit of the preprocessor: to shorten
|
||||
repetitive constructs, not for obscurity.
|
||||
repetitive constructs, not for obscurity.
|
||||
|
||||
- All functions are short (and therefore easy to understand?) and do only one thing, well, ....
|
||||
- All functions are short (and therefore easy to understand?) and do only one
|
||||
thing, well, ....
|
||||
|
||||
- Curly braces invite endless holy wars over readability. This code only uses them
|
||||
for function definitions, thereby greatly improving readability, and reducing arguments
|
||||
about said readability.
|
||||
- Curly braces invite endless holy wars over readability. This code only uses
|
||||
them for function definitions, thereby greatly improving readability, and
|
||||
reducing arguments about said readability.
|
||||
|
||||
- One of C's many blessings (until recently) is a modicum of keywords,
|
||||
of which only 8 are used:
|
||||
`for`, `return`, `typedef`, `void`, `char`, `short`, `unsigned` and `long`;
|
||||
10 if `#include` and `#define` are counted.
|
||||
- One of C's many blessings (until recently) is a modicum of keywords, of which
|
||||
only 8 are used: `for`, `return`, `typedef`, `void`, `char`, `short`, `unsigned`
|
||||
and `long`; 10 if `#include` and `#define` are counted.
|
||||
|
||||
- The code helpfully declares "syntax_error!" right up front, filling the reader with confidence.
|
||||
- The code helpfully declares `"syntax_error!"` right up front, filling the
|
||||
reader with confidence.
|
||||
|
||||
- In spite of its inherent clarity, the code was presented to both *indent*(1) and
|
||||
*clang-format*(1), after running it through the preprocessor, sustaining its better qualities.
|
||||
- In spite of its inherent clarity, the code was presented to both *indent*(1)
|
||||
and *clang-format*(1), after running it through the preprocessor, sustaining its
|
||||
better qualities.
|
||||
|
||||
- That the code is obfuscated is spelled out two different ways in the source; it helps
|
||||
to reformat the code to see the second spelling.
|
||||
- That the code is obfuscated is spelled out two different ways in the source;
|
||||
it helps to reformat the code to see the second spelling.
|
||||
|
||||
- The author is overly fond of the code that handles input.
|
||||
There is no memory allocation, nor pre-allocation of arrays, so where does the
|
||||
memory come from? The multi-base strtol() code is pretty trick.
|
||||
No special attempt was made to replace operations with obscure mathematical relations,
|
||||
as the (lack of) beauty is in the parsing -- ask not where is the modulus operation,
|
||||
but how does it know when to mod -- okay, but where is add and subtract?
|
||||
And really, who doesn't enjoy a setjmp() in the argument list?
|
||||
- The author is overly fond of the code that handles input. There is no memory
|
||||
allocation, nor pre-allocation of arrays, so where does the memory come from?
|
||||
The multi-base strtol() code is pretty tricky. No special attempt was made to
|
||||
replace operations with obscure mathematical relations, as the (lack of) beauty
|
||||
is in the parsing -- ask not where is the modulus operation, but how does it
|
||||
know when to mod -- okay, but where is add and subtract? And really, who
|
||||
doesn't enjoy a setjmp() in the argument list?
|
||||
|
||||
- Finally, documentation of the source code structure is helpfully provided in rot13 format.
|
||||
But isn't it unsportsmanlike to rely upon it? However, even with this helpful guide,
|
||||
things like reading input lines remain as tricky to read as they are to write.
|
||||
- Finally, documentation of the source code structure is helpfully provided in
|
||||
rot13 format. But isn't it unsportsmanlike to rely upon it? However, even with
|
||||
this helpful guide, things like reading input lines remain as tricky to read as
|
||||
they are to write.
|
||||
|
||||
### Compiler warnings
|
||||
|
||||
Calc is C99 compliant, and is ANSI/C90 compliant except for wanting 64-bit `long long`.
|
||||
Changing the two `long long` typedefs to `long`, and compiling with `gcc -m32`
|
||||
yields a program that operates on 32-bit values, with wrap-around of shifts mod 32:
|
||||
Calc is C99 compliant, and is ANSI/C90 compliant except for wanting 64-bit `long
|
||||
long`. Changing the two `long long` typedefs to `long`, and compiling with `gcc
|
||||
-m32` yields a program that operates on 32-bit values, with wrap-around of
|
||||
shifts mod 32:
|
||||
|
||||
1<<48
|
||||
65536 0x00010000
|
||||
@@ -185,8 +196,10 @@ This is my workaday compiler. gcc is also clean with -ansi, and -std=c99.
|
||||
|
||||
clang 3.6.0 lives up to its namesake, resounding on non-problems.
|
||||
To stifle these complaints:
|
||||
|
||||
-Wno-return-type -Wno-parentheses -Wno-empty-body
|
||||
|
||||
|
||||
When invoked with -ansi -pedantic, there are two warnings, which can be ignored:
|
||||
|
||||
* `ISO C90 does not support 'long long'`
|
||||
@@ -202,12 +215,14 @@ With -Wall -std=c99, both are quite noisy, and all can be ignored:
|
||||
If the program name begins with an "e", it echoes stdin to stdout.
|
||||
This allows for a convenient test suite:
|
||||
|
||||
ln -s prog eprog
|
||||
PATH=. eprog < test.in | diff - test.out
|
||||
```sh
|
||||
ln -s prog eprog
|
||||
PATH=. eprog < test.in | diff - test.out
|
||||
```
|
||||
|
||||
### Spoilers
|
||||
|
||||
If you do not want to puzzle out how it works, see spoilers.markdown.
|
||||
If you do not want to puzzle out how it works, see `spoilers.markdown`.
|
||||
|
||||
## Copyright:
|
||||
|
||||
|
||||
Reference in new issue
Block a user