|
Packit |
bd2e5d |
/***********************************************************************/
|
|
Packit |
bd2e5d |
/* */
|
|
Packit |
bd2e5d |
/* MLTk, Tcl/Tk interface of OCaml */
|
|
Packit |
bd2e5d |
/* */
|
|
Packit |
bd2e5d |
/* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis */
|
|
Packit |
bd2e5d |
/* projet Cristal, INRIA Rocquencourt */
|
|
Packit |
bd2e5d |
/* Jacques Garrigue, Kyoto University RIMS */
|
|
Packit |
bd2e5d |
/* */
|
|
Packit |
bd2e5d |
/* Copyright 2002 Institut National de Recherche en Informatique et */
|
|
Packit |
bd2e5d |
/* en Automatique and Kyoto University. All rights reserved. */
|
|
Packit |
bd2e5d |
/* This file is distributed under the terms of the GNU Library */
|
|
Packit |
bd2e5d |
/* General Public License, with the special exception on linking */
|
|
Packit |
bd2e5d |
/* described in file LICENSE found in the OCaml source tree. */
|
|
Packit |
bd2e5d |
/* */
|
|
Packit |
bd2e5d |
/***********************************************************************/
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* $Id$ */
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
#include <tcl.h>
|
|
Packit |
bd2e5d |
#include <tk.h>
|
|
Packit |
bd2e5d |
#include <mlvalues.h>
|
|
Packit |
bd2e5d |
#include <alloc.h>
|
|
Packit |
bd2e5d |
#include <callback.h>
|
|
Packit |
bd2e5d |
#include <fail.h>
|
|
Packit |
bd2e5d |
#include "camltk.h"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
value * tkerror_exn = NULL;
|
|
Packit |
bd2e5d |
value * handler_code = NULL;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* The Tcl command for evaluating callback in OCaml */
|
|
Packit |
bd2e5d |
int CamlCBCmd(ClientData clientdata, Tcl_Interp *interp,
|
|
Packit |
bd2e5d |
int argc, CONST84 char **argv)
|
|
Packit |
bd2e5d |
{
|
|
Packit |
bd2e5d |
CheckInit();
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* Assumes no result */
|
|
Packit |
bd2e5d |
Tcl_SetResult(interp, NULL, NULL);
|
|
Packit |
bd2e5d |
if (argc >= 2) {
|
|
Packit |
bd2e5d |
int id;
|
|
Packit |
bd2e5d |
if (Tcl_GetInt(interp, argv[1], &id) != TCL_OK)
|
|
Packit |
bd2e5d |
return TCL_ERROR;
|
|
Packit |
bd2e5d |
caml_callback2(*handler_code,Val_int(id),
|
|
Packit |
bd2e5d |
copy_string_list(argc - 2,(char **)&argv[2]));
|
|
Packit |
bd2e5d |
/* Never fails (OCaml would have raised an exception) */
|
|
Packit |
bd2e5d |
/* but result may have been set by callback */
|
|
Packit |
bd2e5d |
return TCL_OK;
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
return TCL_ERROR;
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* Callbacks are always of type _ -> unit, to simplify storage
|
|
Packit |
bd2e5d |
* But a callback can nevertheless return something (to Tcl) by
|
|
Packit |
bd2e5d |
* using the following. TCL_VOLATILE ensures that Tcl will make
|
|
Packit |
bd2e5d |
* a copy of the string
|
|
Packit |
bd2e5d |
*/
|
|
Packit |
bd2e5d |
CAMLprim value camltk_return (value v)
|
|
Packit |
bd2e5d |
{
|
|
Packit |
bd2e5d |
CheckInit();
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
Tcl_SetResult(cltclinterp, String_val(v), TCL_VOLATILE);
|
|
Packit |
bd2e5d |
return Val_unit;
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* Note: caml_raise_with_string WILL copy the error message */
|
|
Packit |
bd2e5d |
CAMLprim void tk_error(const char *errmsg)
|
|
Packit |
bd2e5d |
{
|
|
Packit |
bd2e5d |
caml_raise_with_string(*tkerror_exn, errmsg);
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
/* The initialisation of the C global variables pointing to OCaml values
|
|
Packit |
bd2e5d |
must be made accessible from OCaml, so that we are sure that it *always*
|
|
Packit |
bd2e5d |
takes place during loading of the protocol module
|
|
Packit |
bd2e5d |
*/
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
CAMLprim value camltk_init(value v)
|
|
Packit |
bd2e5d |
{
|
|
Packit |
bd2e5d |
/* Initialize the OCaml pointers */
|
|
Packit |
bd2e5d |
if (tkerror_exn == NULL)
|
|
Packit |
bd2e5d |
tkerror_exn = caml_named_value("tkerror");
|
|
Packit |
bd2e5d |
if (handler_code == NULL)
|
|
Packit |
bd2e5d |
handler_code = caml_named_value("camlcb");
|
|
Packit |
bd2e5d |
return Val_unit;
|
|
Packit |
bd2e5d |
}
|