#include <stdio.h>
#include "main.h"
#include "cmdline.h"
#include "parse.h"
#include "emit.h"

static CMD_LINE_OPT_ENV wrap_env[1];

int main(int argc, char *argv[])
{
  OBJECT *scene, *hsr_scene;
  int ret;
  FILE *out_file;
  SYMBOL_TABLE *sym_tab;

  // create the outer symbol table
  sym_tab = new_scope(NULL); 

  // make first pass through options to process those that are position-independent
  // save the rest in the wrap environment for later processing
  process_global_options(wrap_env, argc, argv, sym_tab);

  if (wrap_env->out_file_name) {
    out_file = fopen(wrap_env->out_file_name, "w");
    if (!out_file)
      err(no_line, "can't open '%s' for output", wrap_env->out_file_name);
  }
  else {
    out_file = stdout;
  }

  // die if there were errors parsing options
  if (trouble_p())
    report_errors();

  // set up the global environment for the parser
  init_global_env(global_env);

  // process first set of tag defs and set up first input file
  ret = yywrap();

  // quits if there were file opening errors in wrap
  if (ret == 0) {
    if (trouble_p())
      report_errors();
  }
  else {
    if (wrap_env->skip_stdin_p)
      return 0;
    set_lexer_file("<stdin>", stdin);
  }

	if (parse(sym_tab) != 0 && !trouble_p())
    // emit an error to ensure report_errors halts 
    err(line, "parse error");

  // quits if there is trouble
  report_errors();

  // flatten the object hierarchy into a scene
  scene = flat_scene(parsed_objects(), global_env);

  // painter's algorithm for HSR / HLR
  if (wrap_env->bsp_only_p) {
    hsr_scene = hsr_scene_with_bsp(scene);
  }
  else {
    hsr_scene = hsr_scene_with_depth_sort(scene);
  }

  // emit PStricks or TikZ
	emit(out_file, hsr_scene, global_env, wrap_env->doc_template_file_name);

	return 0;
}

int yywrap(void)
{
  char *file_name = advance_to_next_file_name(wrap_env);
  if (file_name) {
    FILE *f = fopen(file_name, "r");
    if (f) {
      set_lexer_file(file_name, f);
      return 0;
    }
    else {
      err(no_line, "can't open file '%s' for input", file_name);
    }
  }
  return 1;
}
