// File: occivink[P]pyct/pyct.cpp
// Function: main
int main(int argc, char** argv) {
    try {
        const auto args = parse_args(argc, argv);
        if (args.help) {
            print_help();
            return 0;
        }
        auto get_hash = [&args](bool confirm) {
            if (args.hash)
                return *args.hash;
            string password;
            if (args.password)
                password =  *args.password;
            else if (args.interactive)
                password = ask_pass(confirm);
            else
                throw invalid_argument{"Either hash or password must be provided in non-interactive mode"};
            const auto salt = args.salt.value_or("86627104");
            return hash_password(password, salt,
                args.iterations.value_or((u64)10),
                args.work_area_size.value_or((u64)1024*1024*128));
        };

        if (args.operation == Args::Operation::Encrypt) {
            const auto hash = get_hash(args.confirm);
            auto input = read_from_fd<vector<u8>>(args.input_data_fd);
            const auto encrypted = encrypt(move(input), args.padded_length, hash);
            if (args.base64) {
                cout << to_base_64(encrypted) << endl;
            } else {
                copy_n(reinterpret_cast<const u8*>(encrypted.data()), encrypted.size(), ostreambuf_iterator<char>(cout));
            }
        } else if (args.operation == Args::Operation::Decrypt) {
            const auto hash = get_hash(false);
            vector<u8> input = args.base64 ?
                from_base_64(read_from_fd<string>(args.input_data_fd)) :
                read_from_fd<vector<u8>>(args.input_data_fd);
            const auto decrypted = decrypt(move(input), hash);
            copy_n(reinterpret_cast<const u8*>(decrypted.data()), decrypted.size(), ostreambuf_iterator<char>(cout));
        } else if (args.operation == Args::Operation::Hash) {
            cout << to_base_64(get_hash(args.confirm)) << endl;
        }
    } catch (const exception& e) {
        cerr << e.what() << endl;
        return 1;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl -0x8(%rbp), %esi
movq -0x10(%rbp), %rdx
leaq -0xc8(%rbp), %rdi
callq 0x14fb0
jmp 0x1636e
testb $0x1, -0xc4(%rbp)
je 0x163c2
callq 0x16170
jmp 0x1637e
movl $0x0, -0x4(%rbp)
movl $0x1, -0xd8(%rbp)
jmp 0x16881
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x168af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x168a3
leaq -0xc8(%rbp), %rax
movq %rax, -0xe0(%rbp)
cmpl $0x0, -0xc8(%rbp)
jne 0x165da
movzbl -0xc1(%rbp), %edx
andl $0x1, %edx
leaq -0x100(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x16970
jmp 0x163fc
movl -0xc0(%rbp), %esi
leaq -0x118(%rbp), %rdi
callq 0x17dc0
jmp 0x16410
leaq -0x148(%rbp), %rdi
movq %rdi, -0x288(%rbp)
leaq -0x118(%rbp), %rsi
callq 0x175e0
movq -0x288(%rbp), %rsi
leaq -0x20(%rbp), %rdx
leaq -0x130(%rbp), %rdi
leaq -0x100(%rbp), %rcx
callq 0x149f0
jmp 0x1644a
leaq -0x148(%rbp), %rdi
callq 0x17210
testb $0x1, -0xc3(%rbp)
je 0x16517
leaq -0x168(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0x17f60
jmp 0x16478
movq 0xdb29(%rip), %rdi      # 0x23fa8
leaq -0x168(%rbp), %rsi
callq 0x3280
movq %rax, -0x290(%rbp)
jmp 0x16494
movq -0x290(%rbp), %rdi
movq 0xdaee(%rip), %rsi      # 0x23f90
callq 0x3310
jmp 0x164a9
leaq -0x168(%rbp), %rdi
callq 0x31b0
jmp 0x165a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x17210
jmp 0x165c9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
jmp 0x165bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x168(%rbp), %rdi
callq 0x31b0
jmp 0x165bd
leaq -0x130(%rbp), %rdi
movq %rdi, -0x2b8(%rbp)
callq 0x183b0
movq -0x2b8(%rbp), %rdi
movq %rax, -0x2b0(%rbp)
callq 0x17400
movq %rax, -0x2a8(%rbp)
movq 0xda5d(%rip), %rsi      # 0x23fa8
leaq -0x178(%rbp), %rdi
callq 0x183d0
movq -0x2b0(%rbp), %rdi
movq -0x2a8(%rbp), %rsi
movq -0x178(%rbp), %rdx
movl -0x170(%rbp), %ecx
callq 0x18310
movb %dl, -0x299(%rbp)
movq %rax, -0x298(%rbp)
jmp 0x16586
movb -0x299(%rbp), %al
movq -0x298(%rbp), %rcx
movq %rcx, -0x188(%rbp)
movb %al, -0x180(%rbp)
leaq -0x130(%rbp), %rdi
callq 0x17210
leaq -0x118(%rbp), %rdi
callq 0x17210
jmp 0x16877
leaq -0x130(%rbp), %rdi
callq 0x17210
leaq -0x118(%rbp), %rdi
callq 0x17210
jmp 0x168a3
cmpl $0x1, -0xc8(%rbp)
jne 0x167d3
leaq -0x1a8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
xorl %edx, %edx
callq 0x16970
jmp 0x165fe
movb -0xc3(%rbp), %al
movb $0x0, -0x1e1(%rbp)
testb $0x1, %al
je 0x16641
movl -0xc0(%rbp), %esi
leaq -0x1e0(%rbp), %rdi
callq 0x17880
jmp 0x16623
movb $0x1, -0x1e1(%rbp)
leaq -0x1c0(%rbp), %rdi
leaq -0x1e0(%rbp), %rsi
callq 0x13820
jmp 0x1663f
jmp 0x16657
movl -0xc0(%rbp), %esi
leaq -0x1c0(%rbp), %rdi
callq 0x17dc0
jmp 0x16655
jmp 0x16657
testb $0x1, -0x1e1(%rbp)
jne 0x16662
jmp 0x1666e
leaq -0x1e0(%rbp), %rdi
callq 0x31b0
leaq -0x218(%rbp), %rdi
movq %rdi, -0x2c0(%rbp)
leaq -0x1c0(%rbp), %rsi
callq 0x175e0
movq -0x2c0(%rbp), %rsi
leaq -0x200(%rbp), %rdi
leaq -0x1a8(%rbp), %rdx
callq 0x14da0
jmp 0x166a4
leaq -0x218(%rbp), %rdi
callq 0x17210
leaq -0x200(%rbp), %rdi
movq %rdi, -0x2e8(%rbp)
callq 0x183b0
movq -0x2e8(%rbp), %rdi
movq %rax, -0x2e0(%rbp)
callq 0x17400
movq %rax, -0x2d8(%rbp)
movq 0xd8c4(%rip), %rsi      # 0x23fa8
leaq -0x228(%rbp), %rdi
callq 0x183d0
movq -0x2e0(%rbp), %rdi
movq -0x2d8(%rbp), %rsi
movq -0x228(%rbp), %rdx
movl -0x220(%rbp), %ecx
callq 0x18310
movb %dl, -0x2c9(%rbp)
movq %rax, -0x2c8(%rbp)
jmp 0x1671f
movb -0x2c9(%rbp), %al
movq -0x2c8(%rbp), %rcx
movq %rcx, -0x238(%rbp)
movb %al, -0x230(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x17210
leaq -0x1c0(%rbp), %rdi
callq 0x17210
jmp 0x16875
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
testb $0x1, -0x1e1(%rbp)
jne 0x16773
jmp 0x1677f
leaq -0x1e0(%rbp), %rdi
callq 0x31b0
jmp 0x168a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x17210
jmp 0x167c2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x17210
leaq -0x1c0(%rbp), %rdi
callq 0x17210
jmp 0x168a3
cmpl $0x2, -0xc8(%rbp)
jne 0x16873
movzbl -0xc1(%rbp), %edx
andl $0x1, %edx
leaq -0x278(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x16970
jmp 0x167ff
leaq -0x258(%rbp), %rdi
leaq -0x278(%rbp), %rsi
callq 0x18440
jmp 0x16814
movq 0xd78d(%rip), %rdi      # 0x23fa8
leaq -0x258(%rbp), %rsi
callq 0x3280
movq %rax, -0x2f0(%rbp)
jmp 0x16830
movq -0x2f0(%rbp), %rdi
movq 0xd752(%rip), %rsi      # 0x23f90
callq 0x3310
jmp 0x16845
leaq -0x258(%rbp), %rdi
callq 0x31b0
jmp 0x16873
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x31b0
jmp 0x168a3
jmp 0x16875
jmp 0x16877
movl $0x0, -0xd8(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x17d80
movl -0xd8(%rbp), %eax
testl %eax, %eax
je 0x1689e
jmp 0x16899
jmp 0x16945
jmp 0x16945
leaq -0xc8(%rbp), %rdi
callq 0x17d80
movl -0xd4(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x16951
movq -0xd0(%rbp), %rdi
callq 0x30d0
movq %rax, -0x280(%rbp)
movq -0x280(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, %rsi
movq 0xd6f9(%rip), %rdi      # 0x23fe8
callq 0x32c0
movq %rax, -0x2f8(%rbp)
jmp 0x168fd
movq -0x2f8(%rbp), %rdi
movq 0xd685(%rip), %rsi      # 0x23f90
callq 0x3310
jmp 0x16912
movl $0x1, -0x4(%rbp)
movl $0x1, -0xd8(%rbp)
callq 0x3490
jmp 0x16945
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd0(%rbp)
movl %eax, -0xd4(%rbp)
callq 0x3490
jmp 0x16943
jmp 0x16951
movl -0x4(%rbp), %eax
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
movq -0xd0(%rbp), %rdi
callq 0x34f0
movq %rax, %rdi
callq 0x17a60
nopw %cs:(%rax,%rax)