315 lines
7.9 KiB
C
315 lines
7.9 KiB
C
/*
|
|
*
|
|
* e x t e n d . c -- All the stuff dealing with
|
|
* extended types
|
|
*
|
|
* Copyright © 1993-1998 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
|
|
*
|
|
*
|
|
* Permission to use, copy, and/or distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
* that both the above copyright notice and this permission notice appear in
|
|
* all copies and derived works. Fees for distribution or use of this
|
|
* software or derived works may only be charged with express written
|
|
* permission of the copyright holder.
|
|
* This software is provided ``as is'' without express or implied warranty.
|
|
*
|
|
* This software is a derivative work of other copyrighted softwares; the
|
|
* copyright notices of these softwares are placed in the file COPYRIGHTS
|
|
*
|
|
*
|
|
* Author: Erick Gallesio [eg@kaolin.unice.fr]
|
|
* Creation date: 15-Mar-1995 11:31
|
|
* Last file update: 16-Jan-1998 22:09
|
|
*/
|
|
|
|
#include "stk.h"
|
|
#include "stklos.h"
|
|
#include "extend.h"
|
|
|
|
#define EXT_TYPE_DESCR(x) (xtypes[TYPE(x)- tc_start_extd])
|
|
|
|
static int extended_type_stamp = tc_start_extd;
|
|
static STk_extended_scheme_type *xtypes[tc_stop_extd-tc_start_extd+1];
|
|
|
|
#ifdef USE_STKLOS
|
|
static SCM xclasses[tc_stop_extd-tc_start_extd+1];
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Extended Types
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***
|
|
***
|
|
*** Default functions
|
|
***
|
|
***/
|
|
|
|
static void internal_display(SCM obj, SCM port, int mode)
|
|
{
|
|
sprintf(STk_tkbuffer, "#<%s %lx>", (EXT_TYPE_DESCR(obj))->type_name,
|
|
(unsigned long) obj);
|
|
Puts(STk_tkbuffer, PORT_FILE(port));
|
|
}
|
|
|
|
static SCM internal_apply(SCM obj, SCM args, SCM env)
|
|
{
|
|
Err("apply: bad procedure", obj);
|
|
return UNDEFINED; /* to make the compiler happy */
|
|
}
|
|
|
|
static SCM internal_compare(SCM x, SCM y, int equalp)
|
|
{
|
|
return Ntruth;
|
|
}
|
|
|
|
/***
|
|
***
|
|
*** Utilities
|
|
***
|
|
***/
|
|
void STk_extended_mark(SCM x)
|
|
{
|
|
STk_extended_scheme_type *p= EXT_TYPE_DESCR(x);
|
|
if (p->gc_mark_fct) (*(p->gc_mark_fct))(x);
|
|
}
|
|
|
|
void STk_extended_sweep(SCM x)
|
|
{
|
|
STk_extended_scheme_type *p = EXT_TYPE_DESCR(x);
|
|
if (p->gc_sweep_fct) (*(p->gc_sweep_fct))(x);
|
|
}
|
|
|
|
SCM STk_extended_apply(SCM x, SCM args, SCM env)
|
|
{
|
|
return (*(EXT_TYPE_DESCR(x)->apply_fct))(x, args, env);
|
|
}
|
|
|
|
void STk_extended_display(SCM x, SCM port, int mode)
|
|
{
|
|
(*(EXT_TYPE_DESCR(x)->display_fct))(x, port, mode);
|
|
}
|
|
|
|
int STk_extended_procedurep(SCM x)
|
|
{
|
|
return (EXT_TYPE_DESCR(x)->flags && EXT_ISPROC);
|
|
}
|
|
|
|
int STk_extended_eval_parameters(SCM x)
|
|
{
|
|
return (EXT_TYPE_DESCR(x)->flags && EXT_EVALPARAM);
|
|
}
|
|
|
|
SCM STk_extended_compare(SCM x, SCM y, int equalp)
|
|
{
|
|
/* One of x or y (at least) is extended. */
|
|
return EXTENDEDP(x) ? (*(EXT_TYPE_DESCR(x)->compare_fct))(x, y, equalp)
|
|
: (*(EXT_TYPE_DESCR(y)->compare_fct))(x, y, equalp);
|
|
}
|
|
|
|
char *STk_get_extended_name(int i)
|
|
{
|
|
return ((i>=tc_start_extd) && (i<extended_type_stamp)) ?
|
|
(xtypes[i - tc_start_extd])->type_name :
|
|
NULL;
|
|
}
|
|
|
|
#ifdef USE_STKLOS
|
|
void STk_register_extended_class(SCM c, int type_index)
|
|
{
|
|
if (NNULLP(c)) {
|
|
int i = type_index - tc_start_extd;
|
|
xclasses[i] = c;
|
|
STk_gc_protect(xclasses+i);
|
|
}
|
|
}
|
|
|
|
SCM STk_extended_class_of(SCM obj) /* Warning: obj MUST be an extd type */
|
|
{
|
|
return xclasses[TYPE(obj)-tc_start_extd];
|
|
}
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
*
|
|
* C-pointer
|
|
*
|
|
******************************************************************************/
|
|
|
|
typedef void (*STk_disp_function)(SCM x, SCM port, int mode);
|
|
|
|
static int Cpointer_id = ANONYMOUS_DYN_PTR_ID + 1;
|
|
static int size = 0;
|
|
static STk_disp_function *display_array = NULL;
|
|
|
|
|
|
static void Cpointer_default_display(SCM obj, SCM port, int mode)
|
|
{
|
|
sprintf(STk_tkbuffer, "#<C-pointer %d %lx>", EXTID(obj), EXTDATA(obj));
|
|
Puts(STk_tkbuffer, PORT_FILE(port));
|
|
}
|
|
|
|
|
|
void STk_Cpointer_display(SCM obj, SCM port, int mode)
|
|
{
|
|
int id = EXTID(obj);
|
|
|
|
if (id <= ANONYMOUS_DYN_PTR_ID)
|
|
Cpointer_default_display(obj, port, mode);
|
|
else
|
|
(*(display_array[id]))(obj, port, mode);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* C variable
|
|
*
|
|
******************************************************************************/
|
|
|
|
static Tcl_HashTable Cvars;
|
|
static C_hash_table_initialized = 0;
|
|
|
|
struct get_n_set_box {
|
|
SCM (*getter)();
|
|
void (*setter)();
|
|
};
|
|
|
|
|
|
SCM STk_apply_getter_C_variable(char *var)
|
|
{
|
|
Tcl_HashEntry *entry;
|
|
|
|
if (entry = Tcl_FindHashEntry(&Cvars, var)) {
|
|
struct get_n_set_box *p = (struct get_n_set_box *) Tcl_GetHashValue(entry);
|
|
|
|
return (*(p->getter))(var);
|
|
}
|
|
else {
|
|
fprintf(STk_stderr, "internal error: %s variable has no getter!!\n", var);
|
|
return UNDEFINED;
|
|
}
|
|
}
|
|
|
|
void STk_apply_setter_C_variable(char *var, SCM value)
|
|
{
|
|
Tcl_HashEntry *entry;
|
|
|
|
if (entry = Tcl_FindHashEntry(&Cvars, var)) {
|
|
struct get_n_set_box *p = (struct get_n_set_box *) Tcl_GetHashValue(entry);
|
|
|
|
(*(p->setter))(var, value);
|
|
}
|
|
else
|
|
fprintf(STk_stderr, "internal error: %s variable has no setter!!\n", var);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Extended types and C-pointer User interface
|
|
*
|
|
******************************************************************************/
|
|
|
|
int STk_add_new_type(STk_extended_scheme_type *p)
|
|
{
|
|
if (!p) Err("bad new type description", NIL);
|
|
|
|
/* Set the apply procedure if not defined */
|
|
if (!p->apply_fct) p->apply_fct = internal_apply;
|
|
|
|
/* Replace NULL display function by a default function */
|
|
if (!p->display_fct) p->display_fct = internal_display;
|
|
|
|
/* Replace NULL compare function by a default function */
|
|
if (!p->compare_fct) p->compare_fct = internal_compare;
|
|
|
|
/* Store the new type descriptor in the xtypes array */
|
|
xtypes[extended_type_stamp - tc_start_extd] = p;
|
|
|
|
#ifdef USE_STKLOS
|
|
/* Create a new class for this type and register it */
|
|
STk_register_extended_class(STk_make_extended_class(p->type_name),
|
|
extended_type_stamp);
|
|
#endif
|
|
return extended_type_stamp++;
|
|
}
|
|
|
|
void STk_add_new_primitive(char *fct_name, int fct_type, struct obj * (*fct_ptr)())
|
|
{
|
|
SCM z;
|
|
|
|
NEWCELL(z, fct_type);
|
|
z->storage_as.subr0.name = fct_name;
|
|
z->storage_as.subr0.f = fct_ptr;
|
|
STk_define_public_var(STk_selected_module, Intern(fct_name), z);
|
|
}
|
|
|
|
SCM STk_eval_C_string(char *s, SCM env)
|
|
{
|
|
SCM tmp = STk_internal_eval_string(s, ERR_OK, env);
|
|
return tmp == EVAL_ERROR ? NULL: tmp;
|
|
}
|
|
|
|
/*************************/
|
|
|
|
int STk_new_Cpointer_id(void (*display_func)(SCM x, SCM port, int mode))
|
|
{
|
|
if (++Cpointer_id >= size) {
|
|
if (display_array == NULL) {
|
|
display_array = must_malloc(10*sizeof (STk_disp_function));
|
|
size = 10;
|
|
}
|
|
else {
|
|
size += size / 2;
|
|
display_array = must_realloc(display_array,
|
|
size * sizeof (STk_disp_function));
|
|
}
|
|
}
|
|
/* store function in array */
|
|
display_array[Cpointer_id]= display_func? display_func : Cpointer_default_display;
|
|
return Cpointer_id;
|
|
}
|
|
|
|
SCM STk_make_Cpointer(int Cpointer_id, void *ptr, int staticp)
|
|
{
|
|
register SCM z;
|
|
|
|
NEWCELL(z, tc_Cpointer);
|
|
EXTDATA(z) = ptr;
|
|
EXTID(z) = Cpointer_id;
|
|
EXTSTATICP(z) = staticp;
|
|
return z;
|
|
}
|
|
|
|
/*************************/
|
|
|
|
void STk_define_C_variable(char *var, SCM (*getter)(), void (*setter)())
|
|
{
|
|
Tcl_HashEntry *entry;
|
|
int new;
|
|
struct get_n_set_box *p;
|
|
|
|
if (!C_hash_table_initialized) {
|
|
/* First C-var. Create Hash table */
|
|
Tcl_InitHashTable(&Cvars, TCL_STRING_KEYS);
|
|
C_hash_table_initialized = 1;
|
|
}
|
|
|
|
p = must_malloc(sizeof(struct get_n_set_box));
|
|
p->getter = getter;
|
|
p->setter = setter;
|
|
entry = Tcl_CreateHashEntry(&Cvars, var, &new);
|
|
if (!new) {
|
|
fprintf(STk_stderr, "Attempt to multi-define C variable `%s' !!\n", var);
|
|
return;
|
|
}
|
|
Tcl_SetHashValue(entry, p);
|
|
|
|
/* Now enter variable in obarray and set its info field to C variable */
|
|
Intern(var)->cell_info = CELL_INFO_C_VAR;
|
|
}
|