9.5 KiB
- interactions between MACRO and comments
- preprocessor strip comments before exapnding macros
- create an include with a macro OR NOT
make rules :
- make in root will make all projects
- make in each project will compile this project
- make diff : compile if necessary, and run the program then compare the output
- make concat : create the concatenated version, finale version, of the quine
folder structure
Each programs will have to be coded in C and in Assembly, and respectivly in a folder named C and ASM, each folders containing its own Makefile with the usual rules.
dr_quine/
| C/
| | Colleen.c
| | Grace.c
| | Sully.c
| | Makefile
| | ...
| ASM/
| | Colleen.asm
| | Grace.asm
| | Sully.asm
| | Makefile
| | ...
Grace
1 : a string containing itself, almost
#define xstr(s) str(s)
#define str(s) char *quine = #s ; printf(quine);
xstr(str())
expansions :
-> xstr ( char *quine = "" ; printf(quine); )
-> char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine);
problem : \"\" instead of #s :
-> char *quine = "char *quine = #s ; printf(quine);" ; printf(quine);
1.2 : the output, first try
#include <stdio.h>
#define MAIN(s) int main(){ s return 0; }
#define xstr(s) str(s)
#define str(s) char *quine = #s ; printf(quine);
MAIN(xstr(str()))
expansions :
-> MAIN( xstr( char *quine = "" ; printf(quine); ))
-> MAIN( char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine); )
-> int main(){ char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine); return 0; }
exploded view :
int main(){
char *quine = "char *quine = \"\" ; printf(quine);" ;
printf(quine);
return 0;
}
output :
char *quine = "" ; printf(quine);
problem 1 : missing the main function around the content problem 2 : quine does not contain itself, but an empty string
1.3 : the output, second try
#include <stdio.h>
#define MAIN(s) int main(){ s return 0; }
#define xstr(s) str(s)
#define str(s) char *quine = #s ; printf(quine);
MAIN(xstr(MAIN(xstr(str()))))
expansions :
-> MAIN( xstr( MAIN( xstr( char *quine = "" ; printf(quine); ))))
-> MAIN( xstr( MAIN( char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine); )))
-> MAIN( xstr( int main(){ char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine); return 0; } ))
-> MAIN( char *quine = "int main(){ char *quine = \"char *quine = \\\"\\\" ; printf(quine);\" ; printf(quine); return 0; }" ; printf(quine); )
-> int main(){ char *quine = "int main(){ char *quine = \"char *quine = \\\"\\\" ; printf(quine);\" ; printf(quine); return 0; }" ; printf(quine); return 0; }
exploded view :
int main()
{
char *quine =
"
int main()
{
char *quine = \"char *quine = \\\"\\\" ; printf(quine);\" ;
printf(quine);
return 0;
}
";
printf(quine);
return 0;
}
output :
int main(){ char *quine = "char *quine = \"\" ; printf(quine);" ; printf(quine); return 0; }%
exploded view :
int main()
{
char *quine = "char *quine = \"\" ; printf(quine);";
printf(quine);
return 0;
}
problem : this new program will only print :
char *quine = "" ; printf(quine);
1.3 : the output, third try
#include <stdio.h>
#define MAIN(s) int main(){ s return 0; }
#define xstr(s) str(s)
#define str(s) char *quine = #s ; printf(quine);
MAIN(xstr(MAIN(xstr(MAIN(xstr())))))
output :
int main(){ char *quine = "int main(){ char *quine = \"\" ; printf(quine); return 0; }" ; printf(quine); return 0; }
exploded view :
int main()
{
char *quine =
"
int main()
{
char *quine = \"\";
printf(quine);
return 0;
}
";
printf(quine);
return 0;
}
problem : we cannot gon on like this, there will always be one level missing
idea : changing the inner char* quine = content to '%s' and printing printf(quine, quine)
2 : second approach
a quine could be this structure basically :
int main()
{
char *quine = THE_WHOLE_PROGRAM;
printf(quine);
return 0;
}
with macros :
#include <stdio.h>
#define MAIN() int main() { char *quine = "BEFORE" "THIS_MACRO_ITSELF" "AFTER"; printf(quine); return 0; }
MAIN()
2.1 : let's try it
#include <stdio.h>
#define MAIN(s) \
int main() \
{ \
char *quine = "#include <stdio.h>\n#define MAIN(s) " \
s \
"\n\nMAIN(s)\n"; \
printf(quine); \
return 0; \
}
MAIN(s)
expands to :
int main()
{
char *quine = "#include <stdio.h>\n#define MAIN(s) "
s
"\n\nMAIN(s)\n";
printf(quine);
return 0;
}
problem : the char *quine string should contain a copy of the whole code in place of "s"
2.2 : second try, macro calling itself : MAIN(MAIN)
#include <stdio.h>
#define MAIN(s) \
int main() \
{ \
char *quine = "#include <stdio.h>\n#define MAIN(s) " \
s \
"\n\nMAIN(MAIN(s))\n"; \
printf(quine); \
return 0; \
}
MAIN(MAIN(s))
expands to :
int main()
{
char *quine = "#include <stdio.h>\n#define MAIN(s) " int main()
{
char *quine = "#include <stdio.h>\n#define MAIN(s) "
s
"\n\nMAIN(MAIN(s))\n";
printf(quine);
return 0;
}
"\n\nMAIN(MAIN(s))\n";
printf(quine);
return 0;
}
problem : almost there, but the content of the string quine should be a litteral string instead of code
2.3 : lets stringify the content of the inner MAIN
the previous can be written with an extra step :
#define str(s) s
#define MAIN(s) content s content
MAIN(str(MAIN(s)))
/* EQUIVALENT TO : */
#define MAIN(s) content s content
MAIN((MAIN(s)))
we can use this extra step to stringify the content with #s :
#define str(s) #s
#define MAIN(s) content s content
MAIN(str(MAIN(s)))
example :
#include <stdio.h>
#define str(s) #s
#define MAIN(s) \
int main() \
{ \
char *quine = "#include <stdio.h>\n#define str(s) #s\n#define MAIN(s) " \
s \
"\n\nMAIN(str(MAIN(s)))\n"; \
printf(quine); \
return 0; \
}
MAIN(str(MAIN(s)))
expands to :
int main()
{
char *quine = "#include <stdio.h>\n#define str(s) #s\n#define MAIN(s) "
"MAIN(s)"
"\n\nMAIN(str(MAIN(s)))\n";
printf(quine);
return 0;
}
problem : oops, it stringified the parameter name, not it's expanded version, see https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
2.4 : working stringification
#include <stdio.h>
#define str(s) #s
#define xstr(s) str(s)
#define MAIN(s) \
int main() \
{ \
char *quine = "#include <stdio.h>\n#define str(s) #s\n#define xstr(s) str(s)\n#define MAIN(s) " \
s \
"\n\nMAIN(xstr(MAIN(s)))\n"; \
printf(quine); \
return 0; \
}
MAIN(xstr(MAIN(s)))
expands to :
int main()
{
char *quine = "#include <stdio.h>\n#define str(s) #s\n#define xstr(s) str(s)\n#define MAIN(s) "
"int main() { char *quine = \"#include <stdio.h>\\n#define str(s) #s\\n#define xstr(s) str(s)\\n#define MAIN(s) \" s \"\\n\\nMAIN(xstr(MAIN(s)))\\n\"; printf(quine); return 0; }"
"\n\nMAIN(xstr(MAIN(s)))\n";
printf(quine);
return 0;
}
output :
#include <stdio.h>
#define str(s) #s
#define xstr(s) str(s)
#define MAIN(s) int main() { char *quine = "#include <stdio.h>\n#define str(s) #s\n#define xstr(s) str(s)\n#define MAIN(s) "s"\n\nMAIN(xstr(MAIN(s)))\n"; printf(quine); return 0; }
MAIN(xstr(MAIN(s)))
victory ;)