IOCCC (1985)
in C on IOCCC
lycklama.c
#define o define
#o ___o write
#o ooo (unsigned)
#o o_o_ 1
#o _o_ char
#o _oo goto
#o _oo_ read
#o o_o for
#o o_ main
#o o__ if
#o oo_ 0
#o _o(_,__,___)(void)___o(_,__,ooo(___))
#o __o (o_o_<<((o_o_<<(o_o_<<o_o_))+(o_o_<<o_o_)))+(o_o_<<(o_o_<<(o_o_<<o_o_)))
o_(){_o_ _=oo_,__,___,____[__o];_oo ______;_____:___=__o-o_o_; _______:
_o(o_o_,____,__=(_-o_o_<___?_-o_o_:___));o_o(;__;_o(o_o_,"\b",o_o_),__--);
_o(o_o_," ",o_o_);o__(--___)_oo _______;_o(o_o_,"\n",o_o_);______:o__(_=_oo_(
oo_,____,__o))_oo _____;}
This is the code.
Analysing the code, and removing some obfuscation
Let’s analyse some of the #define
s made.
#o __o (o_o_<<((o_o_<<(o_o_<<o_o_))+(o_o_<<o_o_)))+(o_o_<<(o_o_<<(o_o_<<o_o_)))
Let’s simplfiy this a bit more. Becuase of the#define
,o_o_
is just1
and the<<
operator is the left shift operator. So this basically becomes:
#define __o (1<<((1<<(1<<1))+(1<<1)))+(1<<(1<<(1<<1)))
Now, because all the right shifts are just multiplying by two here, we can further simplify it as:
#define __o (1<<((1<<2)+2))+(1<<(1<<2))
, which is the same as #define __o (1<<(4+2))+(1<<4)
.
Now, this simplifies to #define __o (1<<6)+8
, which becomes #define __o 20
We can remove all the crazy defines and make it look a bit simpler, after which it looks like this:
#define _o(_,__,___)(void)write(_,__,(unsigned)(___))
main()
{
char _=0,__,___,____[20];
goto ______;
_____:___=20-1;
_______:_o(1,____,__=(_-1<___?_-1:___));
for(;__;_o(1,"\b",1),__--);
_o(1," ",1);
if(--___)goto _______;
_o(1,"\n",1);
______:
if(_=read(0,____,20))
_oo _____;}
If you have a keen eye, you will notice that there are three characters here, one array, and one goto
.
Now, time for me to rename some values. I’ll just call them char1
, char2
, char3
, and arr
. I’ll call the goto
label label
. Becuase I have zero creatvity, like whatever I had done until now.
Decoding the mess
This uses write
and read
, both UNIX system commands, to print out a hello world. At least, that’s what it’s supposed to do.
The “fixed” (read: changed some names) code:
#include <sys/syscall.h>
#include <unistd.h>
#define _o(_,__,___)(void)write(_,__,(unsigned)(___))
int main()
{
char char1=0,char2,char3,arr[20];
goto label;
label2:char3=19;
label3:_o(1,arr,char2=(char1--<char3?char1--:char3));
for(;char2;_o(1,"\b",1),char2--);
_o(1," ",1);
if(--char3)goto label3;
_o(1,"\n",1);
label:
if(char1=read(0,arr,20))
goto label2;
}
Apparently, you have to give it very long lines as arguments. But based on what I can see, it will basically write the whole line again, but will be very inefficient in doing so.
The copyright
Copyright (c) 1984, Landon Curt Noll. All Rights Reserved. Permission for personal, educational or non-profit use is granted provided this this copyright and notice are included in its entirety and remains unaltered. All other uses must receive prior permission in writing from both Landon Curt Noll and Larry Bassel.