Whitespace and Perl, 992 975 characters
Good Evening Ladies and Gentlemen.
To start with, here is my submission encoded in base64, which I feel is the best way to communicate a large Whitespace program. (You really don't want to use an encoding that leaves any whitespace as-is, so there's no point in selecting something more "readable".)
c2F5PDwgeDI7c2F5PDwwLDAgIApzYXk8PCB4MjtzYXk8PDAsMCAgCgoJCQogICAJCSAgCSAgCSAJ
CSAgCSAgCQkgCSAJIAkJCQkJICAJCSAJCQkgCQkJCQkgCSAJIAkJIAkgCSAgIAkJCQkJICAgCQkg
IAkgCQkgCSAJCSAJICAgIAkJCQkgCSAgCSAJCSAJICAgIAkgCQkgICAJICAgICAgCQkJIAkJCQkJ
IAkJCSAJCQkJICAgICAJCQkgCSAgICAgIAkJCQkJICAgICAgCQkgICAJCSAgICAJCQkJCQkJCSAg
CSAJIAkgICAJCQkgICAJCQkJCSAgCQkJCSAJICAgIAkgCQkJCQkgCSAgICAgCSAgCSAJICAgICAg
CSAgICAJICAgICAJCSAgIAkJCSAJIAkJCQkJCSAJCSAJIAkgICAgICAgCQkgIAkgICAgICAgICAg
IAkJICAgCSAJCQkgCSAgICAgCQkJCQkJIAkgICAgCQkJCSAJCQkJICAJCQkgICAJCQkgCSAgCSAg
IAkJCQkgIAkJIAkJCSAgIAkJCSAJCQkgCQkJICAJCSAJICAJIAkJCSAJIAkgCQkgICAgIAkgCSAJ
ICAJICAJIAkJICAgICAJIAkgICAgCQkJCSAgCSAJCSAJIAkJIAkgIAkgCSAJCSAJCSAJCSAJCQkg
CQkJICAgIAkJCSAgCSAgCQogICAJICAgICAJCQkJCSAJCSAJIAkgCSAJICAJCQkgICAJICAgCSAg
ICAJCSAJICAgICAgICAgCSAgIAkJCQkgCQkgICAgCQkgCSAJICAJCQkgCQkJCSAJCQkgICAJICAg
IAkgCSAJCQkgIAkJCQkgCSAJCSAJIAkgCQkJCSAJICAJIAkJIAkgICAJCiAKICAKICAgIAogCSAg
CQoKICAJCiAKICAgIAkJCQkgCSAKCSAJCQkKICAgICAJCQkJIAkgCgkgCSAgCiAgIAkJCgkgIAoK
CQkJCiAKCgoJIAkKICAgCSAgIAkgIAoKIAkKIAkgIAkKCiAJIAogICAJIAoKIAkKCiAJIAoKIAkK
CQogCSAgIAkgCgogCQoKCgoKICAgCiAgIAogCiAKIAkKCiAJCgogICAgCiAKIAoJIAogCiAgICAJ
IAoJIAkJIAoJICAgCSAKCSAJIAogCSAgCgogIAogCiAgICAJCQoJIAkJICAJCSAJCQkKCSAgCiAg
CQkJICAgCgkgCQkgICAJICAgICAKCSAgIAkKICAgICAJCQoJIAkgIAogICAJCQoJICAKCgkJCiAK
CgoJCjAK
Here's an excerpt that highlights all of the visible parts of the source. ⇥
is used to indicate a tab and ↲
to indicate a newline.
say<< x2;say<<0,0 ↲
say<< x2;say<<0,0 ↲
↲
⇥⇥↲
⇥⇥ ⇥ [... etcetera ... skipping rest of a really long line ...]↲
⇥⇥⇥ ⇥⇥[... etcetera ... shorter but still quite a long line ...]↲
↲
↲
↲
⇥ ⇥↲
[... etcetera ... whole lotta whitespace in here ...]
⇥⇥↲
↲
↲
↲
⇥↲
0↲
Perl was the natural choice for the second language in this challenge, being one of the best general-purpose languages for writing compact quines. My shortest Perl quine is 19 bytes:
say<< x2
say<< x2
– and you can see how it was the seed for the Perl half of the double quine. My best Whitespace quine, in comparison, is 541 bytes long. (Though shorter ones do exist – 445 bytes is the best I've seen.)
From the Perl interpreter's point of view, the first line of the double quine's source file contains the two statements that make up the entire program proper, as the remaining contents are two quoted strings. The first string is the repeated line of Perl, and is delimited by the blank third line. The second string is all whitespace, and runs from the fourth line of the source all the way to the 0
delimiter at the bottom of the file.
When taken as a Whitespace program, the first four lines contain three instructions that are largely useless. (Their effect is to push two zero values onto the stack, and then discard the second one.) They're included just to get safely past the newlines that the Perl program requires – the real program starts after that. Rather than quote the unreadable source any further, here's a paraphrasing of the instructions that make up the Whitespace program, in an assembly-like format:
# Representation of "say<< ;say<<0,0 \n" in base 122 as ASCII chars.
PERLCODE = 44892457841068708924520433691075560592081
# Represention of the whitespace program, following the "push PERLCODE"
# instruction, in base 3 (see comments on wsout).
WSCODE = 9823454421986355730445143846606456399449033186160554878002671428613111806443504867738858766142050504887335990409088441824104338753030405625930185
# Set up the stack and the heap. The first three instructions are not
# particularly useful; they're just there to skip past the newlines in
# the Perl code. (Though the initial zero on the stack does get used
# at the very end.)
push 0
push 0
jneg wsout
push WSCODE
push PERLCODE
dup
dup
push 0
copy 1
# Output the first four lines of the file.
perl: dup
mod 122
putchar
div 122
dup
jnzero perl
pop
jzero perl
push 68 # represents "jneg wsout"
call wsout
# Output the rest of the file.
copy 1
call pushout
push 2
call wsout
call pushout
call wsout
putnum
push 2
call wsout
exit
# pushout: Output a Whitespace push instruction, using the number on
# the top of the stack as the instruction's argument. (Recursion is
# used to output the bits MSB-first.)
pushout:
push 0
dup
call wsout
call wsout
bits: dup
jzero bitend
dup
mod 2
swap
div 2
call bits
bitend: call wsout
ret
# wsout: Output a sequence of whitespace characters as represented by
# the number on the top of the stack. The number is read in base 3,
# LSB-first, with 0 = SPC, 1 = TAB, 2 = NL. Calling wsout with a value
# of zero will output a single space.
wsout:
dup
mod 3
mul -23 # some ugly math that transforms
mod -24 # (0, 1, 2) into (32, 9, 10)
add 32
putchar
div 3
dup
jnzero wsout
pop
ret
The giant numbers at the top are what we Whitespace users have to use in lieu of actual strings. Don't bother trying to run this on a Whitespace interpreter that doesn't have proper bignum support.
Finally, here's the program again, but this time with C-style escapes, since it was specifically requested:
say<< x2;say<<0,0 \nsay<< x2;say<<0,0 \n\n\t\t\n \t\t \t \t \t\t \t \t\t \t \t \t\t\t\t\t \t\t \t\t\t \t\t\t\t\t \t \t \t\t \t \t \t\t\t\t\t \t\t \t \t\t \t \t\t \t \t\t\t\t \t \t \t\t \t \t \t\t \t \t\t\t \t\t\t\t\t \t\t\t \t\t\t\t \t\t\t \t \t\t\t\t\t \t\t \t\t \t\t\t\t\t\t\t\t \t \t \t \t\t\t \t\t\t\t\t \t\t\t\t \t \t \t\t\t\t\t \t \t \t \t \t \t \t\t \t\t\t \t \t\t\t\t\t\t \t\t \t \t \t\t \t \t\t \t \t\t\t \t \t\t\t\t\t\t \t \t\t\t\t \t\t\t\t \t\t\t \t\t\t \t \t \t\t\t\t \t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t \t \t \t\t\t \t \t \t\t \t \t \t \t \t \t\t \t \t \t\t\t\t \t \t\t \t \t\t \t \t \t \t\t \t\t \t\t \t\t\t \t\t\t \t\t\t \t \t\n \t \t\t\t\t\t \t\t \t \t \t \t \t\t\t \t \t \t\t \t \t \t\t\t\t \t\t \t\t \t \t \t\t\t \t\t\t\t \t\t\t \t \t \t \t\t\t \t\t\t\t \t \t\t \t \t \t\t\t\t \t \t \t\t \t \t\n \n \n \n \t \t\n\n \t\n \n \t\t\t\t \t \n\t \t\t\t\n \t\t\t\t \t \n\t \t \n \t\t\n\t \n\n\t\t\t\n \n\n\n\t \t\n \t \t \n\n \t\n \t \t\n\n \t \n \t \n\n \t\n\n \t \n\n \t\n\t\n \t \t \n\n \t\n\n\n\n\n \n \n \n \n \t\n\n \t\n\n \n \n \n\t \n \n \t \n\t \t\t \n\t \t \n\t \t \n \t \n\n \n \n \t\t\n\t \t\t \t\t \t\t\t\n\t \n \t\t\t \n\t \t\t \t \n\t \t\n \t\t\n\t \t \n \t\t\n\t \n\n\t\t\n \n\n\n\t\n0\n
1
Would an xxd hex dump do?
– Ilmari Karonen – 2013-08-02T12:26:45.840Yes. I'll accept it. – lochok – 2013-08-02T12:57:49.083