/*
** Raw Data -> Object
*/

#include "mr4th_base.h"
#include "mr4th_stdio.h"
#include "mr4th_cmdln.h"
#include "mr4th_tinker.h"

#include "mr4th_objfromraw.h"

#include "mr4th_base.c"
#include "mr4th_stdio.c"
#include "mr4th_cmdln.c"
#include "mr4th_tinker.c"

////////////////////////////////
// Main

int main(int argc, char **argv){
  os_main_init(argc, argv);
  
  Arena *arena = arena_alloc();
  
  // parse command line
  String8List args = os_command_line_arguments();
  CMDLN *cmdln = cmdln_from_args(arena, &args);
  
  B32 add_null_terminator = cmdln_has_flag(cmdln, str8_lit("nullterm"), 'N');
  
  // symbol list from cmdln
  U64 input_count = cmdln_input_count(cmdln);
  U64 oraw_symbol_count = 0;
  ORAW_Symbol *oraw_symbols = push_array(arena, ORAW_Symbol, input_count);
  
  for (U32 i = 0; i < input_count; i += 1){
    String8 input = cmdln_input_from_idx(cmdln, i);
    String8 data = os_file_read(arena, input);
    
    if (data.size == 0){
      m4_fprintf(stderr, "could not load input file '%S'\n", &input);
    }
    
    if (data.size > 0){
      String8 final_data = data;
      if (add_null_terminator){
        final_data.size += 1;
      }
      
      String8 file_name = str8_file_name_from_path(input);
      String8 name_og = str8_base_name_from_file_name(file_name);
      String8 name = str8_push_copy(arena, name_og);
      
      ORAW_Symbol *oraw_symbol = &oraw_symbols[oraw_symbol_count];
      oraw_symbol_count += 1;
      
      oraw_symbol->name = name;
      oraw_symbol->data = final_data;
    }
  }
  
  // determine output file name
  String8 output_file_name = str8_lit("raw.obj");
  {
    String8 output_file_name_user = cmdln_get_str8(cmdln, str8_lit("out"), 0);
    if (output_file_name_user.size > 0){
      output_file_name = output_file_name_user;
    }
  }
  
  // determine output format
  TNK_Format output_format = 0;
  {
#if OS_WINDOWS
    output_format = TNK_Format_COFF;
#elif OS_LINUX
    output_format = TNK_Format_ELF;
#else
# error no default output format for this OS
#endif
  }
  {
    String8 output_format_user = cmdln_get_str8(cmdln, str8_lit("format"), 0);
    if (str8_match(output_format_user, str8_lit("COFF"), 0)){
      output_format = TNK_Format_COFF;
    }
    else if (str8_match(output_format_user, str8_lit("ELF"), 0)){
      output_format = TNK_Format_ELF;
    }
  }
  
  // begin tinker
  TNK_Object *object = tnk_object_new();
  for (U32 i = 0; i < oraw_symbol_count; i += 1){
    ORAW_Symbol *oraw_symbol = &oraw_symbols[i];
    
    TNK_ID section = tnk_node_new(object, TNK_NodeKind_Section);
    tnk_node_set_name(object, section, str8_lit(".rdata"));
    tnk_node_set_flags(object, section, TNK_SectionFlag_R);
    tnk_node_data_edit(object, section, 0, 0, oraw_symbol->data);
    
    TNK_ID symbol = tnk_node_new(object, TNK_NodeKind_Symbol);
    tnk_node_set_name(object, symbol, oraw_symbol->name);
    tnk_node_set_flags(object, symbol, TNK_SymbolFlag_External);
    tnk_node_set_position(object, symbol, section, 0);
  }
  
  // generate file
  {
    String8 generated_data = tnk_generate(arena, object, output_format);
    os_file_write(output_file_name, generated_data);
  }
  
  // cleanup
  tnk_object_release(object);
  
  return(0);
}
