// File: rfotino[P]consolite-assembler/src/parser.cpp
// Function: Parser::secondPass()
bool Parser::secondPass() {
  // Reset the tokenizer to the start of the input
  // file so that we can do a second pass through it
  _tokenizer->reset();
  if (_tokenizer->hasError()) {
    std::cerr << "Error resetting input stream to start of file for 2nd pass."
              << std::endl;
    return false;
  }

  // Opens up the output file and checks that it succeeded
  _output.open(_outfileName);
  if (!_output.good()) {
    std::cerr << "Error opening file " << _outfileName
              << " for output." << std::endl;
    return false;
  }

  // Read tokens again line by line and output machine code
  std::vector<Token> tokens;
  while (true) {
    // Get the next line of tokens
    _tokenizer->getLineOfTokens(tokens);
    // If there is an error or the tokenizer is
    // empty, break out of the loop
    if (_tokenizer->isEmpty() || _tokenizer->hasError()) {
      break;
    }
    // Skip empty lines with no tokens
    if (0 == tokens.size()) {
      continue;
    }
    // For the second pass we only care about lines starting
    // with an opcode or data.
    if (OPCODE == tokens[0].getType()) {
      const std::string opcode = tokens[0].getData();
      // Output the 4 bytes for this instruction
      size_t bytes_output = 0;
      for (auto token = tokens.begin(); token != tokens.end(); token++) {
        switch (token->getType()) {
        case OPCODE:
          bytes_output += 1;
          _output << opcodes.at(token->getData());
          break;
        case REGISTER:
          bytes_output += 1;
          _output << registers.at(token->getData());
          break;
        case DATA:
          // The RET instruction has only 1 byte of data following
          // it. All other instructions with data have 2 bytes,
          // and must be padded if they are only using one.
          if ("RET" == opcode) {
            bytes_output += 1;
          } else {
            bytes_output += 2;
            if (1 == token->getSize()) {
              _output << '\0';
            }
          }
          _output << token->getData();
          break;
        case LABELREF:
          bytes_output += 2;
          {
            unsigned address = _labels[token->getData()];
            std::string addr_str;
            addr_str.push_back((address >> 8) & 0xff);
            addr_str.push_back(address & 0xff);
            _output << addr_str;
          }
          break;
        case LABELDECL:
        case UNKNOWN:
          break;
        }
      }
      // Output any padding bytes necessary
      while (bytes_output < 4) {
        _output << '\0';
        bytes_output++;
      }
    } else if (DATA == tokens[0].getType()) {
      // Directly output all data, in big endian order
      size_t data_size = 0;
      for (auto token = tokens.begin(); token != tokens.end(); token++) {
        const std::string data = token->getData();
        data_size += token->getSize();
        _output << data;
      }
      // Make sure to pad the data to a multiple of 4 bytes,
      // so that any instructions that follow are aligned properly.
      while (0 != data_size % 4) {
        data_size++;
        _output << '\0';
      }
    }
  }

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x168(%rbp)
movq (%rax), %rdi
callq 0x6180
movq -0x168(%rbp), %rax
movq (%rax), %rdi
callq 0x6a40
testb $0x1, %al
jne 0xbd47
jmp 0xbd72
movq 0xa2a2(%rip), %rdi      # 0x15ff0
leaq 0x36c5(%rip), %rsi      # 0xf41a
callq 0x21e0
movq %rax, %rdi
movq 0xa25c(%rip), %rsi      # 0x15fc0
callq 0x2240
movb $0x0, -0x1(%rbp)
jmp 0xc47e
movq -0x168(%rbp), %rsi
movq %rsi, %rdi
addq $0x70, %rdi
addq $0x50, %rsi
movl $0x10, %edx
callq 0x20f0
movq -0x168(%rbp), %rax
movq %rax, %rdi
addq $0x70, %rdi
movq 0x70(%rax), %rax
addq -0x18(%rax), %rdi
callq 0x2370
testb $0x1, %al
jne 0xbdfa
movq 0xa23c(%rip), %rdi      # 0x15ff0
leaq 0x369b(%rip), %rsi      # 0xf456
callq 0x21e0
movq -0x168(%rbp), %rsi
movq %rax, %rdi
addq $0x50, %rsi
callq 0x21c0
movq %rax, %rdi
leaq 0x368d(%rip), %rsi      # 0xf46a
callq 0x21e0
movq %rax, %rdi
movq 0xa1d4(%rip), %rsi      # 0x15fc0
callq 0x2240
movb $0x0, -0x1(%rbp)
jmp 0xc47e
leaq -0x28(%rbp), %rdi
callq 0xc5c0
jmp 0xbe05
movq -0x168(%rbp), %rax
movq (%rax), %rdi
leaq -0x28(%rbp), %rsi
callq 0x5f60
jmp 0xbe1a
movq -0x168(%rbp), %rax
movq (%rax), %rdi
callq 0xc5e0
movb %al, -0x169(%rbp)
jmp 0xbe31
movb -0x169(%rbp), %al
testb $0x1, %al
jne 0xbe60
jmp 0xbe3d
movq -0x168(%rbp), %rax
movq (%rax), %rdi
callq 0x6a40
movb %al, -0x16a(%rbp)
jmp 0xbe54
movb -0x16a(%rbp), %al
testb $0x1, %al
jne 0xbe60
jmp 0xbe76
jmp 0xc464
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xc473
leaq -0x28(%rbp), %rdi
callq 0x9620
movq %rax, %rcx
xorl %eax, %eax
cmpq %rcx, %rax
jne 0xbe8e
jmp 0xbe03
xorl %eax, %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0xc6d0
movq %rax, %rdi
callq 0xc520
movl %eax, -0x170(%rbp)
jmp 0xbeab
movl -0x170(%rbp), %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0xc2fe
xorl %eax, %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0xc6d0
movq %rax, %rsi
leaq -0x58(%rbp), %rdi
callq 0xc4c0
jmp 0xbed6
movq $0x0, -0x60(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x9470
movq %rax, -0x68(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x92a0
movq %rax, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0xc630
testb $0x1, %al
jne 0xbf0e
jmp 0xc2b7
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rdi
callq 0xc520
movl %eax, -0x174(%rbp)
jmp 0xbf27
movl -0x174(%rbp), %eax
movl %eax, %ecx
movq %rcx, -0x180(%rbp)
subl $0x5, %eax
ja 0xc29e
movq -0x180(%rbp), %rax
leaq 0x324f(%rip), %rcx      # 0xf19c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xc2f0
movq -0x168(%rbp), %rax
movq -0x60(%rbp), %rcx
incq %rcx
movq %rcx, -0x60(%rbp)
addq $0x70, %rax
movq %rax, -0x188(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rsi
leaq -0x90(%rbp), %rdi
callq 0xc4c0
jmp 0xbf9e
leaq 0xa2f3(%rip), %rdi      # 0x16298
leaq -0x90(%rbp), %rsi
callq 0xc9c0
movq %rax, -0x190(%rbp)
jmp 0xbfba
movq -0x188(%rbp), %rdi
movq -0x190(%rbp), %rax
movsbl (%rax), %esi
callq 0x22a0
jmp 0xbfd2
leaq -0x90(%rbp), %rdi
callq 0x2120
jmp 0xc29e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2120
jmp 0xc2f0
movq -0x168(%rbp), %rax
movq -0x60(%rbp), %rcx
incq %rcx
movq %rcx, -0x60(%rbp)
addq $0x70, %rax
movq %rax, -0x198(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0xc4c0
jmp 0xc037
leaq 0xa28a(%rip), %rdi      # 0x162c8
leaq -0xb0(%rbp), %rsi
callq 0xca60
movq %rax, -0x1a0(%rbp)
jmp 0xc053
movq -0x198(%rbp), %rdi
movq -0x1a0(%rbp), %rax
movzbl (%rax), %esi
callq 0x2320
jmp 0xc06b
leaq -0xb0(%rbp), %rdi
callq 0x2120
jmp 0xc29e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x2120
jmp 0xc2f0
leaq 0x2faf(%rip), %rdi      # 0xf04f
leaq -0x58(%rbp), %rsi
callq 0xc4f0
movb %al, -0x1a1(%rbp)
jmp 0xc0b1
movb -0x1a1(%rbp), %al
testb $0x1, %al
jne 0xc0bd
jmp 0xc0cb
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x60(%rbp)
jmp 0xc11a
movq -0x60(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x60(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rdi
callq 0xc530
movq %rax, -0x1b0(%rbp)
jmp 0xc0f1
movq -0x1b0(%rbp), %rcx
movl $0x1, %eax
cmpq %rcx, %rax
jne 0xc118
movq -0x168(%rbp), %rdi
addq $0x70, %rdi
xorl %esi, %esi
callq 0x22a0
jmp 0xc116
jmp 0xc118
jmp 0xc11a
movq -0x168(%rbp), %rax
addq $0x70, %rax
movq %rax, -0x1b8(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rsi
leaq -0xd0(%rbp), %rdi
callq 0xc4c0
jmp 0xc146
movq -0x1b8(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x21c0
jmp 0xc15b
leaq -0xd0(%rbp), %rdi
callq 0x2120
jmp 0xc29e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x2120
jmp 0xc2f0
movq -0x168(%rbp), %rax
movq -0x60(%rbp), %rcx
addq $0x2, %rcx
movq %rcx, -0x60(%rbp)
addq $0x8, %rax
movq %rax, -0x1c0(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xc670
movq %rax, %rsi
leaq -0xf8(%rbp), %rdi
callq 0xc4c0
jmp 0xc1c1
movq -0x1c0(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0xcb00
movq %rax, -0x1c8(%rbp)
jmp 0xc1dd
movq -0x1c8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x1d4(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x2120
movl -0x1d4(%rbp), %eax
movl %eax, -0xd4(%rbp)
leaq -0x118(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x22e0
movq -0x1d0(%rbp), %rdi
movsbl -0xd3(%rbp), %esi
callq 0x21a0
jmp 0xc22c
movsbl -0xd4(%rbp), %esi
leaq -0x118(%rbp), %rdi
callq 0x21a0
jmp 0xc241
movq -0x168(%rbp), %rdi
addq $0x70, %rdi
leaq -0x118(%rbp), %rsi
callq 0x21c0
jmp 0xc25a
leaq -0x118(%rbp), %rdi
callq 0x2120
jmp 0xc29e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x2120
jmp 0xc2f0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x2120
jmp 0xc2f0
jmp 0xc29e
jmp 0xc2a0
leaq -0x68(%rbp), %rdi
xorl %esi, %esi
callq 0xc690
movq %rax, -0x120(%rbp)
jmp 0xbeeb
jmp 0xc2b9
cmpq $0x4, -0x60(%rbp)
jae 0xc2e2
movq -0x168(%rbp), %rdi
addq $0x70, %rdi
xorl %esi, %esi
callq 0x22a0
jmp 0xc2d4
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x60(%rbp)
jmp 0xc2b9
leaq -0x58(%rbp), %rdi
callq 0x2120
jmp 0xc45f
leaq -0x58(%rbp), %rdi
callq 0x2120
jmp 0xc473
xorl %eax, %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0xc6d0
movq %rax, %rdi
callq 0xc520
movl %eax, -0x1d8(%rbp)
jmp 0xc31b
movl -0x1d8(%rbp), %ecx
movl $0x2, %eax
cmpl %ecx, %eax
jne 0xc45d
movq $0x0, -0x128(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x9470
movq %rax, -0x130(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x92a0
movq %rax, -0x138(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0xc630
testb $0x1, %al
jne 0xc375
jmp 0xc420
leaq -0x130(%rbp), %rdi
callq 0xc670
movq %rax, %rsi
leaq -0x158(%rbp), %rdi
callq 0xc4c0
jmp 0xc392
leaq -0x130(%rbp), %rdi
callq 0xc670
movq %rax, %rdi
callq 0xc530
movq %rax, -0x1e0(%rbp)
jmp 0xc3af
movq -0x168(%rbp), %rdi
movq -0x1e0(%rbp), %rcx
movq -0x128(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x128(%rbp)
addq $0x70, %rdi
leaq -0x158(%rbp), %rsi
callq 0x21c0
jmp 0xc3e0
leaq -0x158(%rbp), %rdi
callq 0x2120
leaq -0x130(%rbp), %rdi
xorl %esi, %esi
callq 0xc690
movq %rax, -0x160(%rbp)
jmp 0xc349
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x2120
jmp 0xc473
jmp 0xc422
movq -0x128(%rbp), %rcx
andq $0x3, %rcx
xorl %eax, %eax
cmpq %rcx, %rax
je 0xc45b
movq -0x168(%rbp), %rdi
movq -0x128(%rbp), %rax
incq %rax
movq %rax, -0x128(%rbp)
addq $0x70, %rdi
xorl %esi, %esi
callq 0x22a0
jmp 0xc459
jmp 0xc422
jmp 0xc45d
jmp 0xc45f
jmp 0xbe03
movb $0x1, -0x1(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xc960
jmp 0xc47e
leaq -0x28(%rbp), %rdi
callq 0xc960
jmp 0xc48c
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
movq -0x30(%rbp), %rdi
callq 0x23a0
nopw %cs:(%rax,%rax)
nop