// File: cjxgm[P]libgpp/src/memory-pp.cpp
// Function: main
int main() try
{
    {
        std::cout << "Start preprocessing...\n";
        std::cout.flush();

        auto result = libgpp::preprocess(
            "#define BLOCK(X)    X\n"
            "#define EXPAND      BLOCK(#defeval DO_EXPAND #1#2#3#4#5#6#7#8#9\n"
            "DO_EXPAND)\n"
            "\n"
            "#define ANSWER_EVERYTHING    42\n"
            "#define ANSWER_TO(WHAT)      EXPAND(ANSWER_,WHAT)\n"
            "ANSWER_TO(EVERYTHING)        // Should give result: 42\n"
            "\n"
            "#define DOUBLE(X)            #eval (X)*2\n"
            "EXPAND(DOU,BLE,(21))         // Should give result: 42\n"
            "\n"
        );

        std::cout
            << "Preprocessed. Result:\n"
            << result
            << "\n"
        ;
        std::cout.flush();
    }

    {
        std::cout << "Start preprocessing...\n";
        std::cout.flush();

        output_buffer.clear();
        libgpp::preprocess_to_buffer(
            "#define BLOCK(X)    X\n"
            "#define EXPAND      BLOCK(#defeval DO_EXPAND #1#2#3#4#5#6#7#8#9\n"
            "DO_EXPAND)\n"
            "\n"
            "#define ANSWER_EVERYTHING    42\n"
            "#define ANSWER_TO(WHAT)      EXPAND(ANSWER_,WHAT)\n"
            "ANSWER_TO(EVERYTHING)        // Should give result: 42\n"
            "\n"
            "#define #DOUBLE(X)           #eval (X)*2\n"
            , output_buffer
        );

        std::cout
            << "SHOULD NOT REACH HERE:\n"
            << output_buffer
            << "\n"
        ;
        std::cout.flush();
    }
}
catch (std::exception const& e) {
    std::cerr << "\e[1;31m ERROR \e[0m " << e.what() << "\n";
    std::cerr << "Partial result:\n" << output_buffer << "\n";
}
catch (...) {
    std::cerr << "\e[1;31m UNKNOWN ERROR \e[0m\n";
    std::cerr << "Partial result:\n" << output_buffer << "\n";
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movl $0x0, -0x4(%rbp)
movq 0xcb67(%rip), %rdi      # 0xefc0
leaq 0x8ba4(%rip), %rsi      # 0xb004
callq 0x2150
jmp 0x2467
movq 0xcb52(%rip), %rdi      # 0xefc0
callq 0x20d0
jmp 0x2475
leaq -0x59(%rbp), %rdi
movq %rdi, -0x98(%rbp)
callq 0x2290
movq -0x98(%rbp), %rdx
leaq 0x8b89(%rip), %rsi      # 0xb01c
leaq -0x58(%rbp), %rdi
callq 0x21b0
jmp 0x249e
leaq -0x38(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x2fe0
jmp 0x24ad
leaq -0x58(%rbp), %rdi
callq 0x22d8
leaq -0x59(%rbp), %rdi
callq 0x2160
movq 0xcafa(%rip), %rdi      # 0xefc0
leaq 0x8c9d(%rip), %rsi      # 0xb16a
callq 0x2150
movq %rax, -0xa0(%rbp)
jmp 0x24db
movq -0xa0(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x2120
movq %rax, -0xa8(%rbp)
jmp 0x24f4
movq -0xa8(%rbp), %rdi
leaq 0x8c66(%rip), %rsi      # 0xb168
callq 0x2150
jmp 0x2509
movq 0xcab0(%rip), %rdi      # 0xefc0
callq 0x20d0
jmp 0x2517
leaq -0x38(%rbp), %rdi
callq 0x22d8
movq 0xca99(%rip), %rdi      # 0xefc0
leaq 0x8ad6(%rip), %rsi      # 0xb004
callq 0x2150
jmp 0x2535
movq 0xca84(%rip), %rdi      # 0xefc0
callq 0x20d0
jmp 0x2543
leaq 0xcc56(%rip), %rdi      # 0xf1a0
callq 0x2190
leaq -0x81(%rbp), %rdi
movq %rdi, -0xb0(%rbp)
callq 0x2290
movq -0xb0(%rbp), %rdx
leaq 0x8c11(%rip), %rsi      # 0xb181
leaq -0x80(%rbp), %rdi
callq 0x21b0
jmp 0x257b
leaq 0xcc1e(%rip), %rsi      # 0xf1a0
leaq -0x80(%rbp), %rdi
callq 0x2e10
jmp 0x258d
leaq -0x80(%rbp), %rdi
callq 0x22d8
leaq -0x81(%rbp), %rdi
callq 0x2160
movq 0xca17(%rip), %rdi      # 0xefc0
leaq 0x8ce7(%rip), %rsi      # 0xb297
callq 0x2150
movq %rax, -0xb8(%rbp)
jmp 0x25be
movq -0xb8(%rbp), %rdi
leaq 0xcbd4(%rip), %rsi      # 0xf1a0
callq 0x2120
movq %rax, -0xc0(%rbp)
jmp 0x25da
movq -0xc0(%rbp), %rdi
leaq 0x8b80(%rip), %rsi      # 0xb168
callq 0x2150
jmp 0x25ef
movq 0xc9ca(%rip), %rdi      # 0xefc0
callq 0x20d0
jmp 0x25fd
jmp 0x274f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
jmp 0x2684
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
jmp 0x2633
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x22d8
leaq -0x59(%rbp), %rdi
callq 0x2160
jmp 0x2684
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x22d8
jmp 0x2684
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
jmp 0x2678
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x22d8
leaq -0x81(%rbp), %rdi
callq 0x2160
movl -0x14(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x275b
movq -0x10(%rbp), %rdi
callq 0x2060
movq %rax, -0x90(%rbp)
movq 0xc93d(%rip), %rdi      # 0xefe8
leaq 0x8c2a(%rip), %rsi      # 0xb2dc
callq 0x2150
movq %rax, -0xc8(%rbp)
jmp 0x26c0
movq -0x90(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0xc8(%rbp), %rdi
movq %rax, %rsi
callq 0x2150
movq %rax, -0xd0(%rbp)
jmp 0x26e8
movq -0xd0(%rbp), %rdi
leaq 0x8a72(%rip), %rsi      # 0xb168
callq 0x2150
jmp 0x26fd
movq 0xc8e4(%rip), %rdi      # 0xefe8
leaq 0x8bc0(%rip), %rsi      # 0xb2cb
callq 0x2150
movq %rax, -0xd8(%rbp)
jmp 0x2719
movq -0xd8(%rbp), %rdi
leaq 0xca79(%rip), %rsi      # 0xf1a0
callq 0x2120
movq %rax, -0xe0(%rbp)
jmp 0x2735
movq -0xe0(%rbp), %rdi
leaq 0x8a25(%rip), %rsi      # 0xb168
callq 0x2150
jmp 0x274a
callq 0x2250
movl -0x4(%rbp), %eax
addq $0xf0, %rsp
popq %rbp
retq
movq -0x10(%rbp), %rdi
callq 0x2060
movq 0xc87d(%rip), %rdi      # 0xefe8
leaq 0x8b3d(%rip), %rsi      # 0xb2af
callq 0x2150
jmp 0x2779
movq 0xc868(%rip), %rdi      # 0xefe8
leaq 0x8b44(%rip), %rsi      # 0xb2cb
callq 0x2150
movq %rax, -0xe8(%rbp)
jmp 0x2795
movq -0xe8(%rbp), %rdi
leaq 0xc9fd(%rip), %rsi      # 0xf1a0
callq 0x2120
movq %rax, -0xf0(%rbp)
jmp 0x27b1
movq -0xf0(%rbp), %rdi
leaq 0x89a9(%rip), %rsi      # 0xb168
callq 0x2150
jmp 0x27c6
callq 0x2250
jmp 0x274f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
callq 0x2250
jmp 0x27e0
jmp 0x27f7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
callq 0x2250
jmp 0x27f5
jmp 0x27f7
movq -0x10(%rbp), %rdi
callq 0x2280
movq %rax, %rdi
callq 0x2810
nopl (%rax,%rax)