#include <climits>
#include <string>
#include <iostream>
#include <stdexcept>
#include <vector>
#include "merl.h"

int main(int argc, char** argv) {
  try {
    // Read relocation address from command line and compute offset
    int64_t relocAddress;
    if(argc > 1) { 
      relocAddress = std::stoull(argv[1], nullptr, 0);
      if(relocAddress > UINT_MAX) {
        throw std::out_of_range("");
      }
    } else {
      throw std::runtime_error("Relocation address must be provided as command line argument.");
    }
    int relocOffset = relocAddress - HEADER_SIZE;
    // Read the MERL file
    MERL merl(std::cin);
    // Perform relocation
    for( Entry &entry : merl.table ) {
      int relocIndex = (entry.location - HEADER_SIZE) / WORD_SIZE;
      if(entry.formatCode == REL) {
        merl.code[relocIndex] += relocOffset;
      }
    }
    // Print just the MIPS code segment, in human-readable hex
    for(int i = 0; i < merl.code.size(); ++i) {
      writeWord(merl.code[i], std::cout, true);
    }
  } catch(std::runtime_error &e) {
    std::cerr << "ERROR: " << e.what() << '\n';
    return 1;
  } catch(std::out_of_range &e) {
    std::cerr << "ERROR: Invalid relocation address (out of 32-bit range)" << '\n';
    return 1;
  } catch(std::invalid_argument &e) {
    std::cerr << "ERROR: Invalid relocation address (failed to parse number)" << '\n';
    return 1;
  }
  return 0; 
}
