#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#ifdef USE_NLLIBC
#include <nllibc.h>
#endif

#include "llllib.h"
#include "argument.h"
#include "lll.h"

static void signal_init(void);

static void sigint_handler(int arg)
{
  lll_finish();
#ifdef WIN32
  signal_init();
#endif
  return;
}

#ifdef WIN32
#define USE_OLD_SIGNAL
#endif

static void signal_init(void)
{
#ifndef USE_OLD_SIGNAL
  struct sigaction sa;

  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = sigint_handler;

  sigaction(SIGINT, &sa, NULL);
#else
  signal(SIGINT, sigint_handler);
#endif
}

static void signal_reset(void)
{
#ifndef USE_OLD_SIGNAL
  struct sigaction sa;

  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_DFL;

  sigaction(SIGINT, &sa, NULL);
#else
  signal(SIGINT, SIG_DFL);
#endif
}

static void init(void)
{
  int r;

  signal_init();

  if ((r = lll_init()) < 0)
    LLL_ERREXIT(r, "(INIT)", 0);
}

static void done(void)
{
  int r;

  if ((r = lll_done()) < 0)
    LLL_ERREXIT(r, "(DONE)", 0);

  signal_reset();
}

static void help(void)
{
  printf("lll [-help|-h] [-version|-v] [-o <filename>|-] [<filename>|-]...\n");
  printf("\t-help,-h\tOutput help message.\n");
  printf("\t-version,-v\tOutput version.\n");
  printf("\t-o <filename>\tOutput file.\n");
  printf("\t-\t\tThe file for stdin/stdout.\n");
  printf("Examples:\n");
  printf("\t$ nltl -o sample.s sample.tl\n");
  printf("\t$ cc -o sample sample.s\n");
  exit(0);
}

static void outver(void)
{
#ifdef NLTL_VERSION
  printf("%s\n", NLTL_VERSION);
#endif
  exit(0);
}

static char *outfile = NULL;

static argument_t args[] = {
  { "-help"      , ARGUMENT_TYPE_FUNCTION, help     },
  { "-h"         , ARGUMENT_TYPE_FUNCTION, help     },
  { "-version"   , ARGUMENT_TYPE_FUNCTION, outver   },
  { "-v"         , ARGUMENT_TYPE_FUNCTION, outver   },
  { "-o"         , ARGUMENT_TYPE_STRING  , &outfile },
  { NULL, ARGUMENT_TYPE_NONE, NULL }
};

int main(int argc, char *argv[])
{
  FILE *out;
  int r;

  argc--;
  argv++;

  argument_read(&argc, argv, args, ARGUMENT_NOTFOUND_BREAK);

  init();

  out = stdout;

  if (outfile) {
    if (strcmp(outfile, "-")) {
      out = fopen(outfile, "w");
      if (!out) {
	LLL_ERREXIT(LLL_ERRCODE_FILE_NOT_FOUND, outfile, 0);
      }
    }
  }

  r = lll_main(argc, argv, out);

  if (out != stdout)
    fclose(out);

  done();

  return r;
}
