/* This file is part of cqual.
   Copyright (C) 2002 The Regents of the University of California.

   cqual is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   cqual is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with cqual; see the file COPYING.  If not, write to
   the Free Software Foundation, 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA. */

#include <stdio.h>
#include <assert.h>

#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/memory.h>
#include <caml/alloc.h>

#include "cil-ast.h"
#include "cqual.h"

region parse_region;
declaration the_program;
extern char **copy_argv;

void init_types() {}

cil_typ dummy_ptr_type;
cil_typ dummy_number_type;


void init_parse()
{
  static value *gdt = NULL;
  value v;
  struct typepair { cil_typ ptr, num; } *p;

  char *cil_argv[] = {"cilcqual", NULL};
  caml_startup(cil_argv);  
  //caml_startup(copy_argv); 

  if (gdt == NULL)
    gdt = caml_named_value("get_dummy_types");
  assert(gdt);
  v = callback(*gdt, Val_unit);
  assert(Tag_val(v) == 0 && Wosize_val(v) == 2);
  p = (struct typepair *) v;

  dummy_ptr_type = p->ptr;
  dummy_number_type = p->num;
  register_global_root((value*) &dummy_ptr_type);
  register_global_root((value*) &dummy_number_type);
}


int parse(const char *fname) 
{
  CAMLparam0();
  static value *parse_fn = NULL;
  static bool init = FALSE;

  if ( !init ) {
    init_parse();
    init = TRUE;
  }
  if (parse_fn == NULL) 
    parse_fn = caml_named_value("cil_parse");

  /* For ocaml gc: Registration of a global variable v is achieved by
     calling register_global_root(&v) just before a valid value is stored
     in v for the first time.  */ 
  /* eventually call remove_global_root(&the_program) to unregister */
  register_global_root((value*) &the_program); 

  the_program = (declaration)callback(*parse_fn, copy_string(fname ? fname : "stdin"));

  CAMLreturn(0);
}

/* !!for now we'll ignore to and dump to stdout */
void unparse(FILE *to, value cil_ast)
{
  CAMLparam1(cil_ast);
  static value *unparse_fn = NULL;
  caml__dummy_cil_ast = caml__dummy_cil_ast; /* supresses the warning */

  if (unparse_fn == NULL) 
    unparse_fn = caml_named_value("cil_unparse");

  callback(*unparse_fn, cil_ast);
  CAMLreturn0;
}

/******** the following added to make it link ******/

void cval_init() {}

//the one in errors.c prints the error with filename and line number (using globals)
//fix later
void verror(const char *format, va_list args)
{
  vfprintf(stderr, format, args);
  putc('\n', stderr);
}

/* from errors.c/h (gcc) */
int errorcount;

/* Report a fatal error at the current line number.  */
void vfatal(const char *format, va_list args)
{
  verror(format, args);
  exit(-1); //exit(FATAL_EXIT_CODE);
}

void fatal(const char *format, ...)
{
  va_list args;
  
  va_start(args, format);
  vfatal(format, args);
  va_end(args);
}

