/*
* This file is part of DGD, http://dgd-osr.sourceforge.net/
* Copyright (C) 1993-2010 Dworkin B.V.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
# ifndef FUNCDEF
# include "kfun.h"
# include "path.h"
# include "comm.h"
# include "call_out.h"
# include "editor.h"
# include "node.h"
# include "control.h"
# include "compile.h"
# endif
# ifdef FUNCDEF
FUNCDEF("0.compile_object", kf_old_compile_object, pt_old_compile_object, 0)
# else
char pt_old_compile_object[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_OBJECT,
T_STRING };
/*
* NAME: kfun->old_compile_object()
* DESCRIPTION: compile an object
*/
int kf_old_compile_object(f)
register frame *f;
{
char file[STRINGSZ];
register object *obj;
if (path_string(file, f->sp->u.string->text,
f->sp->u.string->len) == (char *) NULL) {
return 1;
}
obj = o_find(file, OACC_MODIFY);
if (obj != (object *) NULL) {
if (!(obj->flags & O_MASTER)) {
error("Cannot recompile cloned object");
}
if (O_UPGRADING(obj)) {
error("Object is already being upgraded");
}
if (O_INHERITED(obj)) {
error("Cannot recompile inherited object");
}
}
obj = c_compile(f, file, obj, (string **) NULL, 0,
(OBJR(f->oindex)->flags & O_DRIVER) &&
strcmp(d_get_strconst(f->p_ctrl, f->func->inherit,
f->func->index)->text,
"inherit_program") == 0);
str_del(f->sp->u.string);
PUT_OBJVAL(f->sp, obj);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("compile_object", kf_compile_object, pt_compile_object, 1)
# else
char pt_compile_object[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
T_OBJECT, T_STRING, T_STRING };
/*
* NAME: kfun->compile_object()
* DESCRIPTION: compile an object
*/
int kf_compile_object(f, nargs)
register frame *f;
int nargs;
{
char file[STRINGSZ];
register value *v;
register object *obj;
register string **strs;
register int i;
v = &f->sp[nargs - 1];
if (path_string(file, v->u.string->text, v->u.string->len) == (char *) NULL)
{
return 1;
}
obj = o_find(file, OACC_MODIFY);
if (obj != (object *) NULL) {
if (!(obj->flags & O_MASTER)) {
error("Cannot recompile cloned object");
}
if (O_UPGRADING(obj)) {
error("Object is already being upgraded");
}
if (O_INHERITED(obj)) {
error("Cannot recompile inherited object");
}
}
if (--nargs != 0) {
strs = ALLOCA(string*, nargs);
for (i = nargs, v = f->sp; i > 0; --i) {
*strs++ = (v++)->u.string;
}
if (ec_push((ec_ftn) NULL)) {
AFREE(strs - nargs);
error((char *) NULL);
}
} else {
strs = (string **) NULL;
}
obj = c_compile(f, file, obj, strs, nargs,
(OBJR(f->oindex)->flags & O_DRIVER) &&
strcmp(d_get_strconst(f->p_ctrl, f->func->inherit,
f->func->index)->text,
"inherit_program") == 0);
if (nargs != 0) {
ec_pop();
AFREE(strs - nargs);
i_pop(f, nargs);
}
str_del(f->sp->u.string);
PUT_OBJVAL(f->sp, obj);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("call_other", kf_call_other, pt_call_other, 0)
# else
char pt_call_other[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 2, 1, 0, 9,
T_MIXED, T_MIXED, T_STRING, T_MIXED };
/*
* NAME: kfun->call_other()
* DESCRIPTION: call a function in another object
*/
int kf_call_other(f, nargs)
register frame *f;
int nargs;
{
register value *val;
object *obj;
array *lwobj;
obj = (object *) NULL;
lwobj = (array *) NULL;
val = &f->sp[nargs - 1];
if (val->type == T_STRING) {
*--f->sp = *val;
*val = nil_value; /* erase old copy */
call_driver_object(f, "call_object", 1);
*val = *f->sp++;
}
switch (val->type) {
case T_OBJECT:
obj = OBJR(val->oindex);
break;
case T_LWOBJECT:
lwobj = val->u.array;
break;
default:
/* bad arg 1 */
return 1;
}
if (OBJR(f->oindex)->count == 0) {
/*
* call from destructed object
*/
i_pop(f, nargs);
*--f->sp = nil_value;
return 0;
}
if (i_call(f, obj, lwobj, val[-1].u.string->text, val[-1].u.string->len,
FALSE, nargs - 2)) {
val = f->sp++; /* function exists */
} else {
val = &nil_value; /* function doesn't exist */
}
str_del((f->sp++)->u.string);
i_del_value(f->sp);
*f->sp = *val;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("call_touch", kf_call_touch, pt_call_touch, 0)
# else
char pt_call_touch[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_VOID,
T_OBJECT };
/*
* NAME: kfun->call_touch()
* DESCRIPTION: prepare to call a function when this object is next touched
*/
int kf_call_touch(register frame *f)
{
object *obj;
xfloat flt;
value val, *elts;
if (f->sp->type == T_LWOBJECT) {
elts = d_get_elts(f->sp->u.array);
GET_FLT(&elts[1], flt);
flt.high = TRUE;
PUT_FLTVAL(&val, flt);
d_assign_elt(f->data, f->sp->u.array, &elts[1], &val);
arr_del(f->sp->u.array);
} else {
obj = OBJW(f->sp->oindex);
if (!O_HASDATA(obj)) {
error("call_touch() on uninitialized object");
}
obj->flags &= ~O_TOUCHED;
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("this_object", kf_this_object, pt_this_object, 0)
# else
char pt_this_object[] = { C_STATIC, 0, 0, 0, 6, T_OBJECT };
/*
* NAME: kfun->this_object()
* DESCRIPTION: return the current object
*/
int kf_this_object(f)
register frame *f;
{
register object *obj;
--f->sp;
obj = OBJR(f->oindex);
if (obj->count != 0) {
if (f->lwobj == (array *) NULL) {
PUT_OBJVAL(f->sp, obj);
} else {
PUT_LWOVAL(f->sp, f->lwobj);
}
} else {
*f->sp = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("previous_object", kf_previous_object, pt_previous_object, 0)
# else
char pt_previous_object[] = { C_TYPECHECKED | C_STATIC, 0, 1, 0, 7, T_OBJECT,
T_INT };
/*
* NAME: kfun->previous_object()
* DESCRIPTION: return the previous object in the call_other chain
*/
int kf_previous_object(f, nargs)
register frame *f;
int nargs;
{
register frame *prev;
register object *obj;
if (nargs == 0) {
*--f->sp = nil_value;
} else if (f->sp->u.number < 0) {
return 1;
}
prev = i_prev_object(f, (int) f->sp->u.number);
if (prev != (frame *) NULL) {
obj = OBJR(prev->oindex);
if (obj->count != 0) {
if (prev->lwobj == (array *) NULL) {
PUT_OBJVAL(f->sp, obj);
} else {
PUT_LWOVAL(f->sp, prev->lwobj);
}
return 0;
}
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("previous_program", kf_previous_program, pt_previous_program, 0)
# else
char pt_previous_program[] = { C_TYPECHECKED | C_STATIC, 0, 1, 0, 7, T_STRING,
T_INT };
/*
* NAME: kfun->previous_program()
* DESCRIPTION: return the previous program in the function call chain
*/
int kf_previous_program(f, nargs)
register frame *f;
int nargs;
{
char *prog;
register string *str;
if (nargs == 0) {
*--f->sp = nil_value;
} else if (f->sp->u.number < 0) {
return 1;
}
prog = i_prev_program(f, (int) f->sp->u.number);
if (prog != (char *) NULL) {
PUT_STRVAL(f->sp, str = str_new((char *) NULL, strlen(prog) + 1L));
str->text[0] = '/';
strcpy(str->text + 1, prog);
} else {
*f->sp = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("call_trace", kf_call_trace, pt_call_trace, 0)
# else
char pt_call_trace[] = { C_STATIC, 0, 0, 0, 6, T_MIXED | (2 << REFSHIFT) };
/*
* NAME: kfun->call_trace()
* DESCRIPTION: return the entire call_other chain
*/
int kf_call_trace(f)
register frame *f;
{
PUSH_ARRVAL(f, i_call_trace(f));
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("clone_object", kf_clone_object, pt_clone_object, 0)
# else
char pt_clone_object[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_OBJECT,
T_OBJECT };
/*
* NAME: kfun->clone_object()
* DESCRIPTION: clone a new object
*/
int kf_clone_object(f)
register frame *f;
{
register object *obj;
if (f->sp->type == T_LWOBJECT) {
error("Cloning from a non-persistent object");
}
obj = OBJW(f->sp->oindex);
if (!(obj->flags & O_MASTER)) {
error("Cloning from a clone");
}
obj = o_clone(obj);
PUT_OBJ(f->sp, obj);
if (i_call(f, obj, (array *) NULL, (char *) NULL, 0, TRUE, 0)) {
i_del_value(f->sp++);
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("destruct_object", kf_destruct_object, pt_destruct_object, 0)
# else
char pt_destruct_object[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_VOID,
T_OBJECT };
/*
* NAME: kfun->destruct_object()
* DESCRIPTION: destruct an object
*/
int kf_destruct_object(f)
register frame *f;
{
register object *obj;
if (f->sp->type == T_LWOBJECT) {
error("Destructing a non-persistent object");
}
obj = OBJW(f->sp->oindex);
switch (obj->flags & O_SPECIAL) {
case O_USER:
comm_close(f, obj);
break;
case O_EDITOR:
if (f->level != 0) {
error("Destructing editor object in atomic function");
}
ed_del(obj);
break;
}
o_del(obj, f);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("new_object", kf_new_object, pt_new_object, 0)
# else
char pt_new_object[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_OBJECT,
T_OBJECT };
/*
* NAME: kfun->new_object()
* DESCRIPTION: create a new non-persistent object
*/
int kf_new_object(f)
register frame *f;
{
object *obj;
array *a;
if (f->sp->type == T_OBJECT) {
if (!((obj=OBJW(f->sp->oindex))->flags & O_MASTER)) {
error("Creating new instance from a non-master object");
}
PUT_LWOVAL(f->sp, lwo_new(f->data, obj));
if (i_call(f, (object *) NULL, f->sp->u.array, (char *) NULL, 0, TRUE,
0)) {
i_del_value(f->sp++);
}
} else {
a = lwo_copy(f->data, f->sp->u.array);
arr_del(f->sp->u.array);
PUT_LWOVAL(f->sp, a);
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("object_name", kf_object_name, pt_object_name, 0)
# else
char pt_object_name[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_STRING,
T_OBJECT };
/*
* NAME: kfun->object_name()
* DESCRIPTION: return the name of an object
*/
int kf_object_name(f)
register frame *f;
{
char buffer[STRINGSZ + 12], *name;
register string *str;
uindex n;
if (f->sp->type == T_OBJECT) {
name = o_name(buffer, OBJR(f->sp->oindex));
PUT_STRVAL(f->sp, str = str_new((char *) NULL, strlen(name) + 1L));
str->text[0] = '/';
strcpy(str->text + 1, name);
} else {
n = f->sp->u.array->elts[0].oindex;
arr_del(f->sp->u.array);
name = o_name(buffer, OBJR(n));
PUT_STRVAL(f->sp, str = str_new((char *) NULL, strlen(name) + 4L));
str->text[0] = '/';
strcpy(str->text + 1, name);
strcpy(str->text + str->len - 3, "#-1");
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("find_object", kf_find_object, pt_find_object, 0)
# else
char pt_find_object[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_OBJECT,
T_STRING };
/*
* NAME: kfun->find_object()
* DESCRIPTION: find the loaded object for a given object name
*/
int kf_find_object(f)
register frame *f;
{
char path[STRINGSZ];
object *obj;
if (path_string(path, f->sp->u.string->text,
f->sp->u.string->len) == (char *) NULL) {
str_del(f->sp->u.string);
*f->sp = nil_value;
return 0;
}
i_add_ticks(f, 2);
obj = o_find(path, OACC_READ);
str_del(f->sp->u.string);
if (obj != (object *) NULL) {
PUT_OBJVAL(f->sp, obj);
} else {
*f->sp = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("function_object", kf_function_object, pt_function_object, 0)
# else
char pt_function_object[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING,
T_STRING, T_OBJECT };
/*
* NAME: kfun->function_object()
* DESCRIPTION: return the name of the program a function is in
*/
int kf_function_object(f)
register frame *f;
{
object *obj;
uindex n;
dsymbol *symb;
char *name;
i_add_ticks(f, 2);
if (f->sp->type == T_OBJECT) {
obj = OBJR(f->sp->oindex);
} else {
n = f->sp->u.array->elts[0].oindex;
arr_del(f->sp->u.array);
obj = OBJR(n);
}
f->sp++;
symb = ctrl_symb(o_control(obj), f->sp->u.string->text,
f->sp->u.string->len);
str_del(f->sp->u.string);
if (symb != (dsymbol *) NULL) {
object *o;
o = OBJR(obj->ctrl->inherits[UCHAR(symb->inherit)].oindex);
if (!(d_get_funcdefs(o->ctrl)[UCHAR(symb->index)].class & C_STATIC) ||
obj->index == f->oindex) {
/*
* function exists and is callable
*/
name = o->chain.name;
PUT_STR(f->sp, str_new((char *) NULL, strlen(name) + 1L));
f->sp->u.string->text[0] = '/';
strcpy(f->sp->u.string->text + 1, name);
return 0;
}
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("this_user", kf_this_user, pt_this_user, 0)
# else
char pt_this_user[] = { C_STATIC, 0, 0, 0, 6, T_OBJECT };
/*
* NAME: kfun->this_user()
* DESCRIPTION: return the current user object (if any)
*/
int kf_this_user(f)
register frame *f;
{
object *obj;
obj = comm_user();
if (obj != (object *) NULL) {
PUSH_OBJVAL(f, obj);
} else {
*--f->sp = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("query_ip_number", kf_query_ip_number, pt_query_ip_number, 0)
# else
char pt_query_ip_number[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_STRING,
T_OBJECT };
/*
* NAME: kfun->query_ip_number()
* DESCRIPTION: return the ip number of a user
*/
int kf_query_ip_number(f)
register frame *f;
{
object *obj;
if (f->sp->type == T_OBJECT) {
obj = OBJR(f->sp->oindex);
#ifdef NETWORK_EXTENSIONS
if (comm_is_connection(obj)) {
#else
if ((obj->flags & O_SPECIAL) == O_USER) {
#endif
PUT_STRVAL(f->sp, comm_ip_number(obj));
return 0;
}
} else {
arr_del(f->sp->u.array);
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("query_ip_name", kf_query_ip_name, pt_query_ip_name, 0)
# else
char pt_query_ip_name[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_STRING,
T_OBJECT };
/*
* NAME: kfun->query_ip_name()
* DESCRIPTION: return the ip name of a user
*/
int kf_query_ip_name(f)
register frame *f;
{
object *obj;
if (f->sp->type == T_OBJECT) {
obj = OBJR(f->sp->oindex);
#ifdef NETWORK_EXTENSIONS
if (comm_is_connection(obj)) {
#else
if ((obj->flags & O_SPECIAL) == O_USER) {
#endif
PUT_STRVAL(f->sp, comm_ip_name(obj));
return 0;
}
} else {
arr_del(f->sp->u.array);
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("users", kf_users, pt_users, 0)
# else
char pt_users[] = { C_STATIC, 0, 0, 0, 6, T_OBJECT | (1 << REFSHIFT) };
/*
* NAME: kfun->users()
* DESCRIPTION: return the array of users
*/
int kf_users(f)
register frame *f;
{
#ifdef NETWORK_EXTENSIONS
PUSH_ARRVAL(f, comm_users(f->data, FALSE));
#else
PUSH_ARRVAL(f, comm_users(f->data));
#endif
i_add_ticks(f, f->sp->u.array->size);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("strlen", kf_strlen, pt_strlen, 0)
# else
char pt_strlen[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT, T_STRING };
/*
* NAME: kfun->strlen()
* DESCRIPTION: return the length of a string
*/
int kf_strlen(f)
register frame *f;
{
ssizet len;
len = f->sp->u.string->len;
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, len);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("allocate", kf_allocate, pt_allocate, 0)
# else
char pt_allocate[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7,
T_MIXED | (1 << REFSHIFT), T_INT };
/*
* NAME: kfun->allocate()
* DESCRIPTION: allocate an array
*/
int kf_allocate(f)
register frame *f;
{
register int i;
register value *v;
if (f->sp->u.number < 0) {
return 1;
}
i_add_ticks(f, f->sp->u.number);
PUT_ARRVAL(f->sp, arr_new(f->data, (long) f->sp->u.number));
for (i = f->sp->u.array->size, v = f->sp->u.array->elts; i > 0; --i, v++) {
*v = nil_value;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("allocate_int", kf_allocate_int, pt_allocate_int, 0)
# else
char pt_allocate_int[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7,
T_INT | (1 << REFSHIFT), T_INT };
/*
* NAME: kfun->allocate_int()
* DESCRIPTION: allocate an array of integers
*/
int kf_allocate_int(f)
register frame *f;
{
register int i;
register value *v;
if (f->sp->u.number < 0) {
return 1;
}
i_add_ticks(f, f->sp->u.number);
PUT_ARRVAL(f->sp, arr_new(f->data, (long) f->sp->u.number));
for (i = f->sp->u.array->size, v = f->sp->u.array->elts; i > 0; --i, v++) {
*v = zero_int;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("allocate_float", kf_allocate_float, pt_allocate_float, 0)
# else
char pt_allocate_float[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7,
T_FLOAT | (1 << REFSHIFT), T_INT };
/*
* NAME: kfun->allocate_float()
* DESCRIPTION: allocate an array
*/
int kf_allocate_float(f)
register frame *f;
{
register int i;
register value *v;
if (f->sp->u.number < 0) {
return 1;
}
i_add_ticks(f, f->sp->u.number);
PUT_ARRVAL(f->sp, arr_new(f->data, (long) f->sp->u.number));
for (i = f->sp->u.array->size, v = f->sp->u.array->elts; i > 0; --i, v++) {
*v = zero_float;
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("sizeof", kf_sizeof, pt_sizeof, 0)
# else
char pt_sizeof[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT,
T_MIXED | (1 << REFSHIFT) };
/*
* NAME: kfun->sizeof()
* DESCRIPTION: return the size of an array
*/
int kf_sizeof(f)
register frame *f;
{
unsigned short size;
size = f->sp->u.array->size;
arr_del(f->sp->u.array);
PUT_INTVAL(f->sp, size);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("map_indices", kf_map_indices, pt_map_indices, 0)
# else
char pt_map_indices[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7,
T_MIXED | (1 << REFSHIFT), T_MAPPING };
/*
* NAME: kfun->map_indices()
* DESCRIPTION: return the array of mapping indices
*/
int kf_map_indices(f)
register frame *f;
{
array *a;
a = map_indices(f->data, f->sp->u.array);
i_add_ticks(f, f->sp->u.array->size);
arr_del(f->sp->u.array);
PUT_ARRVAL(f->sp, a);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("map_values", kf_map_values, pt_map_values, 0)
# else
char pt_map_values[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7,
T_MIXED | (1 << REFSHIFT), T_MAPPING };
/*
* NAME: kfun->map_values()
* DESCRIPTION: return the array of mapping values
*/
int kf_map_values(f)
register frame *f;
{
array *a;
a = map_values(f->data, f->sp->u.array);
i_add_ticks(f, f->sp->u.array->size);
arr_del(f->sp->u.array);
PUT_ARRVAL(f->sp, a);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("map_sizeof", kf_map_sizeof, pt_map_sizeof, 0)
# else
char pt_map_sizeof[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT,
T_MAPPING };
/*
* NAME: kfun->map_sizeof()
* DESCRIPTION: return the number of index/value pairs in a mapping
*/
int kf_map_sizeof(f)
register frame *f;
{
unsigned short size;
i_add_ticks(f, f->sp->u.array->size);
size = map_size(f->data, f->sp->u.array);
arr_del(f->sp->u.array);
PUT_INTVAL(f->sp, size);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("typeof", kf_typeof, pt_typeof, 0)
# else
char pt_typeof[] = { C_STATIC, 1, 0, 0, 7, T_INT, T_MIXED };
/*
* NAME: kfun->typeof()
* DESCRIPTION: return the type of a value
*/
int kf_typeof(f)
register frame *f;
{
i_del_value(f->sp);
PUT_INTVAL(f->sp, (f->sp->type == T_LWOBJECT) ? T_OBJECT : f->sp->type);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("error", kf_error, pt_error, 0)
# else
char pt_error[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_VOID, T_STRING };
/*
* NAME: kfun->error()
* DESCRIPTION: cause an error
*/
int kf_error(f)
frame *f;
{
serror(f->sp->u.string);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("send_message", kf_send_message, pt_send_message, 0)
# else
char pt_send_message[] = { C_STATIC, 1, 0, 0, 7, T_INT, T_MIXED };
/*
* NAME: kfun->send_message()
* DESCRIPTION: send a message to a user
*/
int kf_send_message(f)
register frame *f;
{
register object *obj;
int num;
if (f->sp->type != T_STRING && f->sp->type != T_INT) {
return 1;
}
num = 0;
if (f->lwobj == (array *) NULL) {
obj = OBJR(f->oindex);
if (obj->count != 0) {
if ((obj->flags & O_SPECIAL) == O_USER) {
if (f->sp->type == T_INT) {
num = comm_echo(obj, f->sp->u.number != 0);
} else {
num = comm_send(OBJW(obj->index), f->sp->u.string);
}
} else if ((obj->flags & O_DRIVER) && f->sp->type == T_STRING) {
P_message(f->sp->u.string->text);
num = f->sp->u.string->len;
}
}
}
if (f->sp->type == T_STRING) {
str_del(f->sp->u.string);
}
PUT_INTVAL(f->sp, num);
return 0;
}
# endif
#ifndef NETWORK_EXTENSIONS
# ifdef FUNCDEF
FUNCDEF("send_datagram", kf_send_datagram, pt_send_datagram, 0)
# else
char pt_send_datagram[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT,
T_STRING };
/*
* NAME: kfun->send_datagram()
* DESCRIPTION: send a datagram to a user (non networkpackage function)
*/
int kf_send_datagram(f)
register frame *f;
{
object *obj;
int num;
num = 0;
if (f->lwobj == (array *) NULL) {
obj = OBJW(f->oindex);
if ((obj->flags & O_SPECIAL) == O_USER && obj->count != 0) {
num = comm_udpsend(obj, f->sp->u.string);
}
}
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, num);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("datagram_challenge", kf_datagram_challenge, pt_datagram_challenge, 0)
# else
char pt_datagram_challenge[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_VOID,
T_STRING };
/*
* NAME: kfun->datagram_challenge()
* DESCRIPTION: set the challenge for a datagram connection to attach
*/
int kf_datagram_challenge(f)
register frame *f;
{
object *obj;
if (f->lwobj == (array *) NULL) {
obj = OBJW(f->oindex);
if ((obj->flags & O_SPECIAL) == O_USER && obj->count != 0) {
comm_challenge(obj, f->sp->u.string);
}
}
str_del(f->sp->u.string);
*f->sp = nil_value;
return 0;
}
# endif
# endif
# ifdef FUNCDEF
FUNCDEF("block_input", kf_block_input, pt_block_input, 0)
# else
char pt_block_input[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_VOID, T_INT };
/*
* NAME: kfun->block_input()
* DESCRIPTION: block input for the current object
*/
int kf_block_input(f)
register frame *f;
{
object *obj;
if (f->lwobj == (array *) NULL) {
obj = OBJR(f->oindex);
if ((obj->flags & O_SPECIAL) == O_USER && obj->count != 0) {
comm_block(obj, f->sp->u.number != 0);
}
}
*f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("time", kf_time, pt_time, 0)
# else
char pt_time[] = { C_STATIC, 0, 0, 0, 6, T_INT };
/*
* NAME: kfun->time()
* DESCRIPTION: return the current time
*/
int kf_time(f)
frame *f;
{
PUSH_INTVAL(f, P_time());
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("millitime", kf_millitime, pt_millitime, 0)
# else
char pt_millitime[] = { C_STATIC, 0, 0, 0, 6, T_MIXED | (1 << REFSHIFT) };
/*
* NAME: kfun->millitime()
* DESCRIPTION: return the current time in milliseconds
*/
int kf_millitime(f)
frame *f;
{
array *a;
unsigned short milli;
xfloat flt;
i_add_ticks(f, 2);
a = arr_new(f->data, 2L);
PUT_INTVAL(&a->elts[0], P_mtime(&milli));
flt_itof((Int) milli, &flt);
flt_mult(&flt, &thousandth);
PUT_FLTVAL(&a->elts[1], flt);
PUSH_ARRVAL(f, a);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("call_out", kf_call_out, pt_call_out, 0)
# else
char pt_call_out[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 2, 1, 0, 9, T_INT,
T_STRING, T_MIXED, T_MIXED };
/*
* NAME: kfun->call_out()
* DESCRIPTION: start a call_out
*/
int kf_call_out(f, nargs)
register frame *f;
int nargs;
{
Int delay;
unsigned short mdelay;
xfloat flt1, flt2;
uindex handle;
if (f->sp[nargs - 2].type == T_INT) {
delay = f->sp[nargs - 2].u.number;
if (delay < 0) {
/* delay less than 0 */
return 2;
}
mdelay = 0xffff;
} else if (f->sp[nargs - 2].type == T_FLOAT) {
GET_FLT(&f->sp[nargs - 2], flt1);
if (FLT_ISNEG(flt1.high, flt1.low) || flt_cmp(&flt1, &max_int) > 0) {
/* delay < 0.0 or delay > MAX_INT */
return 2;
}
flt_modf(&flt1, &flt2);
delay = flt_ftoi(&flt2);
flt_mult(&flt1, &thousand);
mdelay = flt_ftoi(&flt1);
} else {
return 2;
}
if (f->lwobj != (array *) NULL) {
error("call_out() in non-persistent object");
}
i_add_ticks(f, nargs);
if (OBJR(f->oindex)->count != 0 &&
(handle=d_new_call_out(f->data, f->sp[nargs - 1].u.string, delay,
mdelay, f, nargs - 2)) != 0) {
/* pop duration */
f->sp++;
} else {
/* no call_out was started: pop all arguments */
i_pop(f, nargs - 1);
handle = 0;
}
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, handle);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("remove_call_out", kf_remove_call_out, pt_remove_call_out, 0)
# else
char pt_remove_call_out[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_MIXED,
T_INT };
/*
* NAME: kfun->remove_call_out()
* DESCRIPTION: remove a call_out
*/
int kf_remove_call_out(f)
register frame *f;
{
Int delay;
unsigned short mdelay;
xfloat flt1, flt2;
if (f->lwobj != (array *) NULL) {
error("remove_call_out() in non-persistent object");
}
i_add_ticks(f, 10);
delay = d_del_call_out(f->data, (Uint) f->sp->u.number, &mdelay);
if (mdelay != 0xffff) {
flt_itof(delay, &flt1);
flt_itof(mdelay, &flt2);
flt_mult(&flt2, &thousandth);
flt_add(&flt1, &flt2);
PUT_FLTVAL(f->sp, flt1);
} else {
PUT_INT(f->sp, delay);
}
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("swapout", kf_swapout, pt_swapout, 0)
# else
char pt_swapout[] = { C_STATIC, 0, 0, 0, 6, T_VOID };
/*
* NAME: kfun->swapout()
* DESCRIPTION: swap out all objects
*/
int kf_swapout(f)
frame *f;
{
swapout();
*--f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("0.dump_state", kf_old_dump_state, pt_old_dump_state, 0)
# else
char pt_old_dump_state[] = { C_STATIC, 0, 0, 0, 6, T_VOID };
/*
* NAME: kfun->old_dump_state()
* DESCRIPTION: dump state
*/
int kf_old_dump_state(f)
frame *f;
{
dump_state();
*--f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("dump_state", kf_dump_state, pt_dump_state, 1)
# else
char pt_dump_state[] = { C_TYPECHECKED | C_STATIC, 0, 1, 0, 7, T_VOID, T_INT };
/*
* NAME: kfun->dump_state()
* DESCRIPTION: dump state
*/
int kf_dump_state(f, nargs)
frame *f;
int nargs;
{
if (nargs != 0) {
f->sp++;
}
dump_state();
*--f->sp = nil_value;
return 0;
}
# endif
#ifdef NETWORK_EXTENSIONS
# ifdef FUNCDEF
FUNCDEF("open_port", kf_open_port, pt_open_port, 0)
#else
char pt_open_port[] = { C_TYPECHECKED | C_STATIC ,1 ,1 ,0 ,8,
T_VOID, T_STRING, T_INT};
/*
* NAME: kfun->open_port
* DESCRIPTION: open a listening port
*/
int kf_open_port(f, nargs)
register frame *f;
int nargs;
{
unsigned short port;
unsigned char protocol;
char *protoname;
object *obj;
if (f->lwobj != (array *) NULL) {
error("open_port() in non-persistent object");
}
obj = OBJW(f->oindex);
if (obj->count == 0) {
error("open_port() in destructed object");
}
if (obj->flags & O_SPECIAL) {
error("open_port() in special purpose object");
}
if (f->level != 0) {
error("open_port() within atomic function");
}
port=0;
if (nargs==2)
{
port=f->sp->u.number;
if ((port < 1)) /* || (port > 65535)) */ {
error("Port number not in allowed range");
}
f->sp++;
}
protoname=f->sp->u.string->text;
if (!strcmp(protoname,"tcp")) {
protocol=P_TCP;
} else if (!strcmp(protoname, "udp")) {
protocol=P_UDP;
} else if (!strcmp(protoname, "telnet")){
protocol=P_TELNET;
} else {
error("Unkown protocol");
}
str_del(f->sp->u.string);
comm_openport(f, obj, protocol, port);
*f->sp=nil_value;
return 0;
}
#endif
# ifdef FUNCDEF
FUNCDEF("connect", kf_connect, pt_connect, 0)
#else
char pt_connect[] = { C_TYPECHECKED | C_STATIC , 2, 1, 0, 9,
T_VOID, T_STRING, T_INT, T_STRING };
/*
* NAME: kfun->connect
* DESCRIPTION: connect to a server
*/
int kf_connect(f, nargs)
register frame *f;
int nargs;
{
char * addr, proto, *protoname;
unsigned short port;
object *obj;
if (f->lwobj != (array *) NULL) {
error("connect() in non-persistent object");
}
obj = OBJW(f->oindex);
if (obj->count == 0) {
error("connect() in destructed object");
}
if (obj->flags & O_SPECIAL) {
error("connect() in special purpose object");
}
if (f->level != 0) {
error("connect() within atomic function");
}
if (nargs==3) {
protoname=f->sp->u.string->text;
if (!strcmp(protoname, "tcp")) {
proto=P_TCP;
} else if (!strcmp(protoname, "telnet")) {
proto=P_TELNET;
}
else
return 3;
str_del((f->sp++)->u.string);
}
port=(f->sp++)->u.number;
if (port < 1) /* || port > 65535) */ {
error("Port number out of range");
}
addr=f->sp->u.string->text;
comm_connect(f, obj, addr, proto, port);
*f->sp=nil_value;
return 0;
}
#endif
# ifdef FUNCDEF
FUNCDEF("ports", kf_ports, pt_ports, 0)
# else
char pt_ports[] = { C_STATIC, 0,0,0,6,T_OBJECT | (1 << REFSHIFT)};
/*
* NAME: kfun->ports()
* DESCRIPTION: return the array of port objects
*/
int kf_ports(f)
register frame *f;
{
PUSH_ARRVAL(f, comm_users(f->data, TRUE));
i_add_ticks(f, f->sp->u.array->size);
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("close_user", kf_close_user, pt_close_user, 0)
# else
char pt_close_user[] = { C_STATIC,0,0,0,6, T_VOID};
/*
* NAME: kfun->close_user()
* DESCRIPTION: return the array of port objects
*/
int kf_close_user(f)
register frame *f;
{
register object *obj;
if (f->lwobj != (array *) NULL) {
error("close_user() in non-persistent object");
}
obj = OBJW(f->oindex);
if (!((obj->flags & O_SPECIAL) == O_USER)) {
error("close_user() for non user-object");
}
if (f->level != 0) {
error("close_user() in atomic function");
}
comm_close(f, obj);
*--f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("send_datagram", kf_send_datagram, pt_send_datagram, 0)
# else
char pt_send_datagram[] = { C_TYPECHECKED | C_STATIC, 3,0,0,9,T_INT,
T_STRING, T_STRING, T_INT};
/*
* NAME: kfun->send_datagram()
* DESCRIPTION: send a udp datagram (Network Package Function)
*/
int kf_send_datagram(f)
register frame *f;
{
register object *obj;
int num;
string *str,*ip;
int port;
num=0;
obj=OBJW(f->oindex);
port=(f->sp++)->u.number;
ip=(f->sp++)->u.string;
str=f->sp->u.string;
if (f->lwobj == (array *) NULL) {
if ((obj->flags & O_SPECIAL) == O_USER && obj->count != 0) {
num = comm_senddatagram(obj, str, ip, port);
}
}
str_del(ip);
str_del(f->sp->u.string);
PUT_INTVAL(f->sp, num);
return 0;
}
# endif
#endif
# ifdef FUNCDEF
FUNCDEF("shutdown", kf_shutdown, pt_shutdown, 0)
# else
char pt_shutdown[] = { C_STATIC, 0, 0, 0, 6, T_VOID };
/*
* NAME: kfun->shutdown()
* DESCRIPTION: shut down the mud
*/
int kf_shutdown(f)
frame *f;
{
finish();
*--f->sp = nil_value;
return 0;
}
# endif
# ifdef FUNCDEF
FUNCDEF("status", kf_status, pt_status, 0)
# else
char pt_status[] = { C_TYPECHECKED | C_STATIC, 0, 1, 0, 7,
T_MIXED | (1 << REFSHIFT), T_OBJECT };
/*
* NAME: kfun->status()
* DESCRIPTION: return an array with status information about the gamedriver
* or an object
*/
int kf_status(f, nargs)
register frame *f;
int nargs;
{
array *a;
uindex n;
i_add_ticks(f, 100);
if (nargs == 0) {
a = conf_status(f);
--f->sp;
} else {
if (f->sp->type == T_OBJECT) {
n = f->sp->oindex;
} else {
n = f->sp->u.array->elts[0].oindex;
arr_del(f->sp->u.array);
}
a = conf_object(f->data, OBJR(n));
}
PUT_ARRVAL(f->sp, a);
return 0;
}
# endif