Files
42_EXT_01_dr_quine/notes.md
2025-01-04 11:30:57 +01:00

9.5 KiB


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 ;)