// File: exrok[P]evdoublebind/./src/make_config.cc
// Function: generate_xkb_file(xkb_keymap*, Config&, Settings&)
void generate_xkb_file(xkb_keymap *keymap, Config &config, Settings &settings) {
    FILE * xkbfile;
    if (settings.xkb_conf_output == NULL) {
        char buf[1024];
        if (system("mkdir -p $HOME/.xkb/symbols/") != 0) {
            fprintf(stderr,"Failed creating $HOME/.xkb/symbols/");
            exit(1);
        }
        int len = snprintf(buf,1024, "%s/.xkb/rules/evdev-doublebind", getenv("HOME"));
        if (len >= 1023) {
            fprintf(stderr,"WOW, your home path is really long, CRITICAL ERROR");
            fprintf(stderr,"You should specify the xkb conf output manually");
            exit(1);
        }
        if (access(buf, F_OK) == -1) {
            fprintf(stderr, "Warning: ~/.xkb/rules/evdev-doublebind is missing. To use the XKB\n");
            fprintf(stderr, "        option 'evdoublebind:mapping' a custom rule set is needed.\n");
            fprintf(stderr, "        Running `evdoublebind-make-config  -g` will generate one.\n\n");
        }
        snprintf(buf,1024, "%s/.xkb/symbols/evdoublebind", getenv("HOME"));
        fprintf(stderr,"Outputing XKB option[evdoublebind:mapping] to:\n    %s\n", buf);
        xkbfile = fopen(buf, "w");
    } else {
        fprintf(stderr,"Outputing XKB option[evdoublebind:mapping] to:\n    %s\n",
                settings.xkb_conf_output);
        xkbfile = fopen(settings.xkb_conf_output, "w");
    }
    if (xkbfile == NULL) {
        perror("Failed Creating xkb config file: ");
        exit(1);
    }

    auto unused = config.unused_keys.begin();

     fprintf(xkbfile,"partial modifier_keys\n");
     fprintf(xkbfile,"xkb_symbols \"mapping\" {\n");
     for (auto & mapping: config.mappings) {
         const char * keyname = xkb_keymap_key_get_name(keymap, mapping.keycode);
         if (mapping.hold_map[0] != NULL) {
             fprintf(xkbfile,"   replace key <%s> { [ ",  keyname);
             print_keysyms(xkbfile,mapping.hold_map);
             fprintf(xkbfile," ] };\n");
         }
         if (mapping.tap_map[0] != NULL) {
             if (unused == config.unused_keys.end()) {
                 fprintf(stderr,"ERROR: not enough unused keys specified for config\n");
                 exit(1);
             }
             const char * tapkeyname = xkb_keymap_key_get_name(keymap, *unused);
             fprintf(xkbfile,"   replace key <%s> { [ ",  tapkeyname);
             print_keysyms(xkbfile,mapping.tap_map);
             fprintf(xkbfile," ] };\n");
             unused++;
         }
         generate_modifier_mapping(xkbfile, keyname, mapping.hold_map);
         fprintf(xkbfile,"\n");
     }
     fprintf(xkbfile,"};\n");
     fclose(xkbfile);
}

// Assembly:
subq $0x488, %rsp            # imm = 0x488
movq %rdi, 0x480(%rsp)
movq %rsi, 0x478(%rsp)
movq %rdx, 0x470(%rsp)
movq 0x470(%rsp), %rax
cmpq $0x0, 0x38(%rax)
jne 0x3e60
leaq 0x328d(%rip), %rdi      # 0x6f86
callq 0x3080
cmpl $0x0, %eax
je 0x3d25
movq 0x62ee(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x328f(%rip), %rsi      # 0x6fa3
movb $0x0, %al
callq 0x3130
movl $0x1, %edi
callq 0x3220
leaq 0x60(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0x282a(%rip), %rdi      # 0x6560
callq 0x3030
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl $0x400, %esi            # imm = 0x400
leaq 0x3278(%rip), %rdx      # 0x6fc7
movb $0x0, %al
callq 0x30a0
movl %eax, 0x5c(%rsp)
cmpl $0x3ff, 0x5c(%rsp)      # imm = 0x3FF
jl 0x3d9e
movq 0x628d(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x3271(%rip), %rsi      # 0x6fe6
movb $0x0, %al
callq 0x3130
movq 0x6275(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x328c(%rip), %rsi      # 0x7019
movb $0x0, %al
callq 0x3130
movl $0x1, %edi
callq 0x3220
leaq 0x60(%rsp), %rdi
xorl %esi, %esi
callq 0x31c0
cmpl $-0x1, %eax
jne 0x3df7
movq 0x6242(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x3289(%rip), %rsi      # 0x7049
movb $0x0, %al
callq 0x3130
movq 0x622a(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x32b4(%rip), %rsi      # 0x708c
movb $0x0, %al
callq 0x3130
movq 0x6212(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x32e0(%rip), %rsi      # 0x70d0
movb $0x0, %al
callq 0x3130
leaq 0x60(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x2758(%rip), %rdi      # 0x6560
callq 0x3030
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl $0x400, %esi            # imm = 0x400
leaq 0x32f3(%rip), %rdx      # 0x7114
movb $0x0, %al
callq 0x30a0
movq 0x61c9(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x60(%rsp), %rdx
leaq 0x32f3(%rip), %rsi      # 0x7131
movb $0x0, %al
callq 0x3130
leaq 0x60(%rsp), %rdi
leaq 0x3317(%rip), %rsi      # 0x7168
callq 0x31d0
movq %rax, 0x468(%rsp)
jmp 0x3ea4
movq 0x6191(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
movq 0x470(%rsp), %rax
movq 0x38(%rax), %rdx
leaq 0x32b4(%rip), %rsi      # 0x7131
movb $0x0, %al
callq 0x3130
movq 0x470(%rsp), %rax
movq 0x38(%rax), %rdi
leaq 0x32d1(%rip), %rsi      # 0x7168
callq 0x31d0
movq %rax, 0x468(%rsp)
cmpq $0x0, 0x468(%rsp)
jne 0x3ec5
leaq 0x32b4(%rip), %rdi      # 0x716a
callq 0x31e0
movl $0x1, %edi
callq 0x3220
movq 0x478(%rsp), %rdi
addq $0x20, %rdi
callq 0x4b80
movq %rax, 0x50(%rsp)
movq 0x468(%rsp), %rdi
leaq 0x32a2(%rip), %rsi      # 0x718c
movb $0x0, %al
callq 0x3130
movq 0x468(%rsp), %rdi
leaq 0x32a3(%rip), %rsi      # 0x71a3
movb $0x0, %al
callq 0x3130
movq 0x478(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
callq 0x4b90
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rdi
callq 0x4ba0
movq %rax, 0x38(%rsp)
movq 0x40(%rsp), %rax
cmpq 0x38(%rsp), %rax
je 0x40c4
movq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x480(%rsp), %rdi
movq 0x30(%rsp), %rax
movl (%rax), %esi
callq 0x31a0
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
cmpq $0x0, 0x8(%rax)
je 0x3fb8
movq 0x468(%rsp), %rdi
movq 0x28(%rsp), %rdx
leaq 0x3237(%rip), %rsi      # 0x71bc
movb $0x0, %al
callq 0x3130
movq 0x468(%rsp), %rdi
movq 0x30(%rsp), %rsi
addq $0x8, %rsi
callq 0x3a90
movq 0x468(%rsp), %rdi
leaq 0x3224(%rip), %rsi      # 0x71d5
movb $0x0, %al
callq 0x3130
movq 0x30(%rsp), %rax
cmpq $0x0, 0x28(%rax)
je 0x4080
movq 0x50(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x478(%rsp), %rdi
addq $0x20, %rdi
callq 0x4bc0
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jne 0x4012
movq 0x6001(%rip), %rax      # 0x9ff8
movq (%rax), %rdi
leaq 0x31db(%rip), %rsi      # 0x71dc
movb $0x0, %al
callq 0x3130
movl $0x1, %edi
callq 0x3220
movq 0x480(%rsp), %rdi
movq 0x50(%rsp), %rax
movl (%rax), %esi
callq 0x31a0
movq %rax, 0x20(%rsp)
movq 0x468(%rsp), %rdi
movq 0x20(%rsp), %rdx
leaq 0x317d(%rip), %rsi      # 0x71bc
movb $0x0, %al
callq 0x3130
movq 0x468(%rsp), %rdi
movq 0x30(%rsp), %rsi
addq $0x28, %rsi
callq 0x3a90
movq 0x468(%rsp), %rdi
leaq 0x316a(%rip), %rsi      # 0x71d5
movb $0x0, %al
callq 0x3130
movq 0x50(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x50(%rsp)
movq 0x468(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
addq $0x8, %rdx
callq 0x39a0
movq 0x468(%rsp), %rdi
leaq 0x3068(%rip), %rsi      # 0x7112
movb $0x0, %al
callq 0x3130
movq 0x40(%rsp), %rax
addq $0x50, %rax
movq %rax, 0x40(%rsp)
jmp 0x3f32
movq 0x468(%rsp), %rdi
leaq 0x2cef(%rip), %rsi      # 0x6dc2
movb $0x0, %al
callq 0x3130
movq 0x468(%rsp), %rdi
callq 0x3070
addq $0x488, %rsp            # imm = 0x488
retq
nop