Merge pull request #230 from xexyl/2015-burton
This commit is contained in:
3 files changed
+46
-12
No files matched your search
@@ -9,7 +9,7 @@
|
||||
make
|
||||
```
|
||||
|
||||
### To run:
|
||||
## To run:
|
||||
|
||||
```sh
|
||||
./prog "expression"
|
||||
@@ -23,7 +23,7 @@ or:
|
||||
|
||||
Type in expressions on standard input.
|
||||
|
||||
### Try:
|
||||
## Try:
|
||||
|
||||
```sh
|
||||
./prog '?0x3343<<2'
|
||||
@@ -49,7 +49,7 @@ grep '[0-9]' prog.c
|
||||
man ./calc.1
|
||||
```
|
||||
|
||||
## Alternate code
|
||||
## 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
|
||||
@@ -210,7 +210,7 @@ With -Wall -std=c99, both are quite noisy, and all can be ignored:
|
||||
* `value computed is not used [-Wunused-value]`
|
||||
* `operation on 'j' may be undefined [-Wsequence-point]`
|
||||
|
||||
### Test Suite
|
||||
### Test Suite:
|
||||
|
||||
If the program name begins with an "e", it echoes stdin to stdout.
|
||||
This allows for a convenient test suite:
|
||||
@@ -220,9 +220,9 @@ ln -s prog eprog
|
||||
PATH=. eprog < test.in | diff - test.out
|
||||
```
|
||||
|
||||
### Spoilers
|
||||
### 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.md](spoilers.md).
|
||||
|
||||
## Copyright and CC BY-SA 4.0 License:
|
||||
|
||||
|
||||
+6
-6
@@ -14,8 +14,8 @@ I H char O;
|
||||
I H short Y;
|
||||
I H long long Z;
|
||||
|
||||
O S[]="syntax_error!"
|
||||
"M@K~|JOEF\\^~_NHI]"; L*N,*K,*
|
||||
O S[]="syntax_error="
|
||||
"M@K~|JOEF\\^~_NHIA"; L*N,*K,*
|
||||
B,*E,*T,*A,*x,D; Q(*k)(),v; V z(P),j,_,*
|
||||
o,b,f,u,s,c,a,t,e,d; J l; Q _k(P){ R*K?*K++:
|
||||
~-d; } V r(L a){ R a&&putchar(a); } L n(){ R*T=j=
|
||||
@@ -90,21 +90,21 @@ I H long long Z;
|
||||
,L**K){ V*A; q(K); W(w())**
|
||||
K-c*c-b||p(B),_i(!setjmp(l)?T=B
|
||||
,M(((A=(*o=m()==c-~s&&(j=a|T[-b])&&
|
||||
s-m()==~s)?&o[j-a*u]:(T=B,&_)),*A=F())
|
||||
c-m()==-c)?&o[j-a*u]:(T=B,&_)),*A=F())
|
||||
),B:(L*)S); } V z(P){ V
|
||||
s; W(m() &&v<=f*c
|
||||
s; W(m() &&v< f*c
|
||||
)R v<t ?(v-f)*
|
||||
z():( v-=u<<
|
||||
f)<f ?v?--v
|
||||
?G() : i(z(
|
||||
)):~ z( ):
|
||||
(v-= f) <u
|
||||
(v-= f) <f
|
||||
?v?s = F()
|
||||
,m() ==a>>
|
||||
b?s :G ():
|
||||
_:! (v-=
|
||||
t)? --T,_f
|
||||
(): v-f?o[
|
||||
(): v==b?o[
|
||||
(T[ -b]|a)-
|
||||
a*u]: !z();
|
||||
G(); }
|
||||
@@ -0,0 +1,34 @@
|
||||
### Spoilers
|
||||
|
||||
|
||||
Calc is a recursive-descent parser. It allocates from the stack deep enough
|
||||
that all expressions are exhausted before the recursion stack depth reaches the
|
||||
allocations. The memory map and source is documented in src.doc.rot13. Tokens
|
||||
are encoded using values 0-20, where 0 is an invalid token, 1 is minus, 2 is
|
||||
space, 3 is plus, etc. The necessary constants are derived at the start of the program,
|
||||
using the guarantee that globals are initialized to zero; so a correct null pointer
|
||||
is obtained from an uninitialized global pointer variable, and the integers from
|
||||
uninitialized global int variables. If x is a global int, then !x is 1, and the
|
||||
derivation proceeds from there, using some identities that are confusingly similar
|
||||
and interestingly combined (increasing obfuscation):
|
||||
|
||||
obc clr
|
||||
--- ---
|
||||
-~x x+1
|
||||
~-x x-1
|
||||
y-~x y+x+1
|
||||
|
||||
The derived constants are a compromise between simple expressions, maximum utility,
|
||||
and minimum number of variables used.
|
||||
|
||||
Command line arguments are copied into the upper half of the input buffer,
|
||||
separated by a space. This allows the code to have a single input parser by using
|
||||
a pointer-to-func to either getchar() if live, or a getchar() simulator.
|
||||
|
||||
A small amount of obfuscation comes from void functions declared int, but missing return.
|
||||
This is necessary to allow these functions in ternary ?: expressions and paired with && and ||;
|
||||
but the requisite returns would add symbol count at no benefit to obscurity or functionality.
|
||||
Function decomposition was mostly chosen to avoid curly braces:
|
||||
if a for-loop required multiple statements, the body became a new function.
|
||||
Last, but not least: sharing state via global variables is an ancient and honored
|
||||
form of obfuscation, and remarkably effective.
|
||||
Reference in new issue
Block a user