-
-
Save alexd2580/dea8bdbaa91fe59c4592e0961336e124 to your computer and use it in GitHub Desktop.
Selfchained polyglot in 12 languages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef X//[<?php echo"\rExecuted with PHP\n";system("a68g ".$argv[0].";rm .Random.seed");system("ruby ".$argv[0]);__halt_compiler();]#COMMENT | |
#++++++++++[->+>+++>+++++++>+++++++>++++++++>++++++++++>++++++++++++<<<<<<<]> | |
#>>-.>>>>.<+.--.>---.-.<++.-.<<<<++.>>>>>+++.<+++++.>---.<-.<<<<.>---.>>++.<<-.>+++.>----.<---.>+++++++.<<++.>+++++.<<<.<[ | |
q="";""":";q=+1;q=%^;#=;q@ | |
echo "Executed with BASH";cp "$0" "$0.lhs";runghc --ghc-arg=-cpp --ghc-arg=-pgmP --ghc-arg="python $0" "$0.lhs";rm "$0.lhs";exit 0 | |
@;print"Executed with PERL\n";system("cp $0 $0.f90;gfortran -cpp $0.f90 -o f90 2>-;./f90;rm f90 $0.f90");q@""" | |
import sys,os;s=sys.argv | |
if len(s)<2:print("Executed with PYTHON",flush=True);os.system('cp {a} {a}.c;g++ -trigraphs {a}.c -o cpp 2>-;./cpp;rm cpp {a}.c'.format(a=s[0]));sys.exit(0) | |
with open(next(b for(a,b)in zip(s,s[1:])if a[0]!='-'and b[0]!='-'))as i,open(next(b for(a,b)in zip(s,s[1:])if a=='-o'),"a")as o: | |
[o.write(l)for l in i if l[0]!='#'] | |
""" | |
#else | |
#define F!??/ | |
program H!??/ | |
character(len=:),allocatable::a!??/ | |
print"(A)","Executed with FORTRAN"!??/ | |
CALL system("python "//__FILE__)!??/ | |
end program H!??/ | |
#if 0 | |
#define P(X) printf("Executed with C%s\n",X);fflush(stdout); | |
#include<stdio.h> | |
#include<stdlib.h> | |
main(int i,char*v[]){char a[99],c,c2; | |
#ifdef __cplusplus | |
P("++");snprintf(a,99,"gcc %s -o c -trigraphs 2>-;./c;rm c",__FILE__);system(a); | |
#else | |
if(i<2){P("");snprintf(a,99,"%s %s",v[0],__FILE__);system(a);}else{FILE*f=fopen(v[1],"r");int m[99]={0},p=0,s=0;for(c=fgetc(f);c!=-1;c=fgetc(f)){m[p+=(c==62)-(c==60)]+=(c==43)-(c==45);if(c==46)putchar(m[p]);if(c==91&&m[p]==0||c==93&&m[p]!=0){s=(c==91)-(c==93);do{fseek(f,-2*(c==93),1);c2=fgetc(f);s+=(c2==91)-(c2==93);}while(s!=0||c2==c||(c2!=91&&c2!=93));}}fclose(f);} | |
#endif | |
return 0;} | |
#endif//??/ | |
#endif | |
#if 0 | |
> import System.Process | |
> import System.Environment | |
> main=putStrLn"Executed with HASKELL">>getProgName>>=system.("php "++) | |
console.log "Executed with COFFEESCRIPT" | |
require('child_process').exec "perl "+process.argv[1],(f,o,e)->process.stdout.write o | |
""" | |
#endif//@;#^;puts"Executed with RUBY";a=__FILE__;b="#{a}.litcoffee";system("cp #{a} #{b};coffee #{b};rm #{b}")#]COMMENT print(("Executed with ALGOL68",newline)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to run
Requirements
The brainfuck interpreter is contained within the C code, you can test the validity of the BFC code here: https://minond.xyz/brainfuck/
Tricks used
Algol68
This language has lots of different comment styles. Block comments can be wrapped in
#
or literallyCOMMENT
. This is great since the first line starts with a # mark anyway. Unfortunately i did not spend enough time figuring out how to run syscalls from algol, so its execution is not actually chained, but instead sequenced from PHP.Python
Treats
#
as comment line and"""
as string expression."""
can be made into valid bash and ruby (?) by extending it to""":"
.Except for the first code line after the header, all foreign code is "string-ed" out, and the preprocessor instructions are comments.
Fortran
Doesn't know trigraphs,
!
is a comment.Can use the C preprocessor to enter the same
#ifdef
scope. All foreign code is either not inside an enabledifdef
, or behind a#define
.C/C++
C++ has the
_cplusplus
macro. Both use the preprocessor,#define
s and trigraphs to hide fortran code inside an enabled#ifdef
block that is not visible togcc
andg++
, but is only visible togfortran
.Bash
Bash doesn't require the entire file to be valid bash if we can early exit using
exit
.#
are comments. Most languages come after bash, soexit
skips them.Brainfuck
BF ignores most letters and symbols. The only relevant ones are
[ ] + - < > , .
. We put the BF code as early as possible to prevent pollution of the BF tape with unintended use of these symbols. We leave the BF code in a state where the register index points to an empty (0) tape cell. Then, by putting the rest of the code between[
and]
we can do a jump to the end of the code. In between, all square brackets must come in pairs, the rest is irrelevant, because we don't execute it.Literate Haskell
LHS ignores everything that is not marked with
>
at the start of the line. Unfortunately, it also uses a variant of the C preprocessor, though it is possible to run a custom preprocessor instead (which simply removes all preprocessor instructions) and only leaves LHS code. The replacement preprocessor is contained in the python code.Coffeescript
Same here, literate CS only sees blocks that are indented. The rest is implicit comments.
Perl
q-strings -
q=
starts a string that ends at the next=
sign. Luckily this looks exactly like an assignment in bash/ruby/python.Numbers can be added to strings with no issue.
#
are comments unless they are in a string, duh. Most code is put inside aq@
-string, while the bash/python/ruby glue code usesq=
strings.Ruby
%-strings - same as in perl, just with
%
as the string marker.q=%^;...
looks like an assignment of%^
toq
in bash, dunno what it does, but to ruby it looks like an assignment of a long%
-string to q. This string wraps most foreign code.#
are comments, thus skipping the preprocessor header.PHP
Doesn't care about anything other than the PHP markers. To remove unwanted output we put the PHP at the start of the code, and print a carriage return
\r
, also terminating the PHPcompiler
early.