/*
** Raw Data -> Object
*/

//$ //

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

#include "tinker_old/tinker_coff.h"

#include "mr4th_pe.objfromraw.h"

#include "mr4th_base.c"
#include "mr4th_stdio.c"
#include "mr4th_cmdln.c"
#include "tinker_old/tinker_coff.c"

int main(int argc, char **argv){
  os_main_init(argc, argv);
  
  Arena *arena = arena_alloc();
  
  // parse command line inputs
  String8List args = os_command_line_arguments();
  CMDLN *cmdln = cmdln_from_args(arena, &args);
  
#if 0
  {
    String8List dump = {0};
    cmdln_dump(arena, &dump, cmdln, 0);
    m4_print_str8list(&dump);
  }
#endif
  
  // symbol list from cmdln
  ORAW_Symbol *first_symbol = 0;
  ORAW_Symbol *last_symbol = 0;
  U64 symbol_count = 0;
  
  {
    B32 add_null_terminator = 0;
    
    for (CMDLN_Node *node = cmdln->first;
         node != 0;
         node = node->next){
      
      // save an input as a symbol
      if (node->params == 0){
        String8 input = node->string;
        String8 data = os_file_read(arena, input);
        
        if (data.size == 0){
          m4_printf("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 *symbol = push_array(arena, ORAW_Symbol, 1);
          SLLQueuePush(first_symbol, last_symbol, symbol);
          symbol_count += 1;
          symbol->name = name;
          symbol->data = final_data;
        }
      }
      
      if (node->params != 0){
        if ((node->string.size == 1 &&
             node->string.str[0] == 'N') ||
            str8_match(node->string, str8_lit("nullterm"), 0)){
          add_null_terminator = 1;
        }
      }
    }
  }
  
  // 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;
    }
  }
  // TODO(allen): check: can we open this file for output?
  
  /// object file generator ///
  TNK_Coff* obj = tnk_coff_alloc();
  
  // section data
  for (ORAW_Symbol *oraw_symbol = first_symbol;
       oraw_symbol != 0;
       oraw_symbol = oraw_symbol->next){
    TNK_ID section = tnk_coff_section_new(obj);
    
    {
      TNK_CoffSectionFields *fields = tnk_coff_section_fields(obj, section);
      Assert(fields != 0);
      
      MemoryCopy(fields->name, ".rdata$s", 8);
      fields->data = oraw_symbol->data;
      fields->flags = (PE_SectionFlag_CNT_INITIALIZED_DATA |
                       PE_SectionFlag_MEM_READ);
    }
    
    TNK_ID symbol = tnk_coff_symbol_new(obj);
    {
      TNK_CoffSymbolFields *fields = tnk_coff_symbol_fields(obj, symbol);
      fields->name = oraw_symbol->name;
      fields->kind = TNK_CoffSymbolKind_Global;
      fields->section = section;
      fields->offset = 0;
      fields->is_external = 1;
    }
    
  }
  
  // render file
  {
    String8 gen_data = tnk_coff_generate(arena, obj);
    os_file_write(output_file_name, gen_data);
  }
  
  return(0);
}
