/* -*-mode:C++-*- */
/*
 * ksi_int.h
 * Internal structs
 *
 * Copyright (C) 1997-2010, ivan demakov
 *
 * The software is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * The software 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 Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the software; see the file COPYING.LESSER.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 *
 * Author:        Ivan Demakov <ksion@users.sourceforge.net>
 * Creation date: Thu Jul 31 19:19:17 1997
 * Last Update:   Fri Jan 22 16:51:07 2010
 *
 */

#ifndef KSI_INT_H
#define KSI_INT_H

#include "ksi_type.h"
#include "ksi_port.h"
#include "ksi_jump.h"
#include "ksi_evt.h"
#include "ksi_proc.h"
#include "ksi_comp.h"

#ifdef WIN32
#  include <windows.h>
#endif


enum ksi_errlog_priority_t
{
  ERRLOG_EMERG = 0,             /* system is unusable */
  ERRLOG_ALERT,                 /* action must be taken immediately */
  ERRLOG_ERROR,                 /* error conditions */
  ERRLOG_WARNING,               /* warning conditions */
  ERRLOG_NOTICE,                /* normal but significant condition */
  ERRLOG_INFO,                  /* informational */
  ERRLOG_DEBUG,                 /* debug-level messages */
  ERRLOG_ALL = ERRLOG_DEBUG
};

typedef void (*ksi_errlog_proc_t) (int pri, const char *msg);

struct Ksi_Interp
{
    volatile int have_event;
    ksi_event_mgr event_mgr;
    ksi_event waiting_events, pending_events, active_events;

    ksi_stack stack;
    ksi_wind wind;
    ksi_wind exit_catch;
    ksi_obj user_quit_exn;
    ksi_obj jump_val;
    ksi_obj exit_handlers;
    ksi_obj error_handlers;

    int errlog_priority;
    ksi_obj module_priority;

    ksi_port input_port;
    ksi_port output_port;
    ksi_port error_port;
    ksi_port errlog_port;

    ksi_errlog_proc_t errlog_proc;

//  ksi_port		std_input_port;
//  ksi_port		std_output_port;
//  ksi_port		std_error_port;

    struct Ksi_Dynl_Lib *dynl_libs;
};


struct Ksi_Dynl_Lib
{
  struct Ksi_Dynl_Lib *next;
  char *name;
  void *handle;
  unsigned count;
};


#define KSI_CHECK_EVENTS do { if (ksi_int_data && ksi_int_data->have_event) ksi_do_events(); } while (0)


#define KSI_EXN_P(x)            (KSI_OBJ_IS ((x), KSI_TAG_EXN))
#define KSI_EXN_TYPE(x)         KSI_VEC_REF ((x), 0)
#define KSI_EXN_MSG(x)          KSI_VEC_REF ((x), 1)
#define KSI_EXN_VAL(x)          KSI_VEC_REF ((x), 2)
#define KSI_EXN_SRC(x)          KSI_VEC_REF ((x), 3)


#define KSI_ASSERT(t)         ((void)((t)||ksi_exn_error(0, 0, "assert failed: %s [%s %d]", #t, __FILE__, __LINE__)))
#define KSI_CHECK(a,c,s)      ((void)((c)||ksi_exn_error(0, (a), (s))))
#define KSI_WNA(c,p,s)        ((void)((c)||ksi_exn_error(0, (p), ksi_wna_s, (s))))
#define KSI_SYNTAX(a,c,s)     ((void)((c)||ksi_exn_error(ksi_syntax_s, (a), (s))))



#ifdef __cplusplus
extern "C" {
#endif


/* Initialization & termination. */

SI_API
struct Ksi_Interp*
ksi_init (void *top_stack_addr);

SI_API
void
ksi_init_std_ports (int in_fd, int out_fd, int err_fd);

SI_API
void
ksi_term (void);

SI_API
void
ksi_load_boot_file (const char* fn, ksi_env env);

SI_API
void
ksi_load_library_file (const char *filename);

SI_API
const char*
ksi_mk_filename (ksi_obj x, char* name);


/* error handling */

SI_API
ksi_obj
ksi_open_errlog (ksi_obj port_or_fname);

SI_API
ksi_obj
ksi_errlog_priority (ksi_obj priority, ksi_obj module);

SI_API
ksi_obj
ksi_exn_p (ksi_obj x);

SI_API
ksi_obj
ksi_exn_type (ksi_obj x);

SI_API
ksi_obj
ksi_exn_message (ksi_obj x);

SI_API
ksi_obj
ksi_exn_value (ksi_obj x);

SI_API
ksi_obj
ksi_exn_source (ksi_obj x);

SI_API
void
ksi_errlog_msg (int pri, const char *msg);

SI_API
ksi_obj
ksi_errlog (ksi_obj module, int priority, const char *fmt, ...);

SI_API
ksi_obj
ksi_make_exn (const char *type, ksi_obj errobj, const char *msg, const char *src);

SI_API
int
ksi_exn_error (const char *type, ksi_obj errobj, const char *fmt, ...);

SI_API
int
ksi_src_error (const char *src, const char *fmt, ...);

SI_API
int
ksi_debug (const char *fmt, ...);

SI_API
int
ksi_warn (const char *fmt, ...);

SI_API
int
ksi_handle_error (ksi_obj tag, ksi_obj exn);

SI_API
ksi_obj
ksi_add_exit_handler (ksi_obj proc);

SI_API
ksi_obj
ksi_add_error_handler (ksi_obj proc);

SI_API
ksi_obj
ksi_remove_error_handler (ksi_obj proc);


/* dump & undump ksi objects */

SI_API
void*
ksi_dump (ksi_obj x, int* size);

SI_API
ksi_obj
ksi_undump (void* data, int size);

SI_API
ksi_obj
ksi_obj2dump (ksi_obj x);

SI_API
ksi_obj
ksi_dump2obj (ksi_obj x);

SI_API
ksi_obj
ksi_read_dump (ksi_obj port);

SI_API
ksi_obj
ksi_write_dump (ksi_obj x, ksi_obj port);


/* Dynamic loading */

SI_API
ksi_obj
ksi_dynamic_link (ksi_obj mod, ksi_obj sym);

SI_API
ksi_obj
ksi_dynamic_call (ksi_obj func, ksi_obj arg_list);

SI_API
ksi_obj
ksi_dynamic_unlink (ksi_obj func);



/* internal and not public declarations */

SI_DATA
struct Ksi_Interp *ksi_int_data;

SI_DATA
const char *ksi_char_names[];

SI_DATA
const char *ksi_wna_s;

SI_DATA
const char *ksi_syntax_s;

SI_DATA
const char *ksi_assertion_s;


void
ksi_init_klos (void);

void
ksi_init_events (void);

void
ksi_term_events (void);

void
ksi_init_signals (void);

void
ksi_term_signals (void);

void
ksi_init_dynl (void);

const char*
ksi_dynload_file (char* fname);

void
ksi_term_dynl (void);


#ifdef __cplusplus
}
#endif

#endif

/* End of code */
