2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
gbx_subr_misc.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-02-12 02:53:46 +01:00
|
|
|
(c) 2000-2017 Benoît Minisini <g4mba5@gmail.com>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
This program 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.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
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 General Public License for more details.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2011-06-03 02:51:09 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
2011-12-31 03:39:20 +01:00
|
|
|
MA 02110-1301, USA.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "gb_common.h"
|
|
|
|
#include "gbx_subr.h"
|
|
|
|
#include "gbx_class.h"
|
|
|
|
#include "gambas.h"
|
|
|
|
#include "gbx_eval.h"
|
|
|
|
#include "gbx_date.h"
|
|
|
|
#include "gbx_archive.h"
|
|
|
|
|
|
|
|
#include "gbx_api.h"
|
|
|
|
#include "gbx_c_collection.h"
|
|
|
|
#include "gbx_c_process.h"
|
|
|
|
#include "gbx_debug.h"
|
|
|
|
#include "gbx_watch.h"
|
|
|
|
#include "gbx_math.h"
|
|
|
|
|
|
|
|
|
|
|
|
static EVAL_INTERFACE EVAL;
|
|
|
|
static CCOLLECTION *eval_env;
|
|
|
|
|
|
|
|
static void init_eval()
|
|
|
|
{
|
|
|
|
static bool init = FALSE;
|
|
|
|
|
|
|
|
if (init)
|
|
|
|
return;
|
|
|
|
|
|
|
|
COMPONENT_load(COMPONENT_create("gb.eval"));
|
|
|
|
LIBRARY_get_interface_by_name("gb.eval", EVAL_INTERFACE_VERSION, &EVAL);
|
|
|
|
init = TRUE;
|
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
void SUBR_error(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-21 11:28:34 +02:00
|
|
|
SP->type = T_BOOLEAN;
|
|
|
|
SP->_boolean.value = EXEC_got_error ? -1 : 0;
|
|
|
|
SP++;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
void SUBR_wait(ushort code)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-21 11:28:34 +02:00
|
|
|
SUBR_ENTER();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2014-12-16 23:15:59 +01:00
|
|
|
EXEC_set_native_error(FALSE);
|
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
if (NPARAM == 0)
|
2012-08-25 00:29:53 +02:00
|
|
|
GB_Wait(0);
|
2008-10-21 11:28:34 +02:00
|
|
|
else
|
2012-08-25 00:29:53 +02:00
|
|
|
GB_Wait((int)(SUBR_get_float(PARAM) * 1000 + 0.5));
|
2014-12-16 23:15:59 +01:00
|
|
|
|
|
|
|
if (EXEC_has_native_error())
|
|
|
|
{
|
|
|
|
EXEC_set_native_error(FALSE);
|
|
|
|
PROPAGATE();
|
|
|
|
}
|
2012-08-25 00:29:53 +02:00
|
|
|
|
|
|
|
SUBR_LEAVE_VOID();
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-12 23:25:37 +01:00
|
|
|
void SUBR_sleep(ushort code)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
SUBR_ENTER_PARAM(1);
|
|
|
|
|
2014-11-28 00:31:51 +01:00
|
|
|
switch(code & 0x3F)
|
2014-11-12 23:25:37 +01:00
|
|
|
{
|
2014-11-28 00:31:51 +01:00
|
|
|
case 0: // Sleep
|
|
|
|
{
|
|
|
|
double wait;
|
|
|
|
struct timespec rem;
|
|
|
|
|
|
|
|
wait = SUBR_get_float(PARAM);
|
|
|
|
|
|
|
|
rem.tv_sec = (time_t)(int)wait;
|
|
|
|
rem.tv_nsec = (int)(frac(wait) * 1E9);
|
|
|
|
|
|
|
|
while (nanosleep(&rem, &rem) < 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: // Use
|
|
|
|
{
|
|
|
|
char *name = SUBR_get_string(PARAM);
|
|
|
|
COMPONENT *comp = COMPONENT_find(name);
|
|
|
|
if (!comp)
|
|
|
|
comp = COMPONENT_create(name);
|
|
|
|
|
|
|
|
COMPONENT_load(comp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2: // CheckExec
|
|
|
|
{
|
|
|
|
CPROCESS_check(PARAM->_object.object);
|
|
|
|
break;
|
|
|
|
}
|
2014-11-12 23:25:37 +01:00
|
|
|
}
|
2014-11-28 00:31:51 +01:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
SUBR_LEAVE();
|
|
|
|
}
|
|
|
|
|
2017-09-28 02:05:43 +02:00
|
|
|
static void error_subr_exec(CPROCESS *process)
|
2012-04-15 01:35:33 +02:00
|
|
|
{
|
2017-09-28 02:05:43 +02:00
|
|
|
OBJECT_UNREF(process);
|
2012-04-15 01:35:33 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
void SUBR_exec(ushort code)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-21 11:28:34 +02:00
|
|
|
void *cmd;
|
|
|
|
bool wait;
|
|
|
|
int mode;
|
|
|
|
CPROCESS *process;
|
|
|
|
bool ret;
|
|
|
|
bool shell;
|
|
|
|
char *name;
|
2009-05-22 16:52:36 +02:00
|
|
|
CARRAY *env;
|
2008-10-21 11:28:34 +02:00
|
|
|
|
|
|
|
SUBR_ENTER_PARAM(4);
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
shell = (code & 0x1F) != 0;
|
2008-10-21 11:28:34 +02:00
|
|
|
|
|
|
|
if (shell)
|
|
|
|
cmd = (void *)SUBR_get_string(PARAM);
|
|
|
|
else
|
|
|
|
{
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_object(PARAM, (TYPE)CLASS_StringArray);
|
2008-10-21 11:28:34 +02:00
|
|
|
cmd = (void *)(PARAM->_object.object);
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (!cmd)
|
|
|
|
THROW(E_ARG);
|
|
|
|
|
2009-05-22 16:52:36 +02:00
|
|
|
if (VALUE_is_null(&PARAM[1]))
|
|
|
|
env = NULL;
|
|
|
|
else
|
|
|
|
{
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_object(&PARAM[1], (TYPE)CLASS_StringArray);
|
2009-05-22 16:52:36 +02:00
|
|
|
env = (PARAM[1]._object.object);
|
|
|
|
}
|
|
|
|
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_integer(&PARAM[2]);
|
2008-10-21 11:28:34 +02:00
|
|
|
mode = PARAM[2]._integer.value;
|
2009-05-22 16:52:36 +02:00
|
|
|
wait = mode & PM_WAIT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
name = SUBR_get_string(&PARAM[3]);
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
ret = TRUE; // !PCODE_is_void(code);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
if (shell)
|
|
|
|
mode |= PM_SHELL;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
//STRING_ref(name); ## This should not be needed
|
2009-05-22 16:52:36 +02:00
|
|
|
process = CPROCESS_create(mode, cmd, name, env);
|
2008-10-21 11:28:34 +02:00
|
|
|
//STRING_unref(&name);
|
|
|
|
|
|
|
|
if (wait)
|
|
|
|
{
|
2013-03-30 14:51:10 +01:00
|
|
|
OBJECT_REF(process);
|
2008-10-21 11:28:34 +02:00
|
|
|
|
2017-09-28 02:05:43 +02:00
|
|
|
ON_ERROR_1(error_subr_exec, process)
|
2012-04-15 01:35:33 +02:00
|
|
|
{
|
2012-08-31 00:49:21 +02:00
|
|
|
CPROCESS_wait_for(process, 0);
|
2012-04-15 01:35:33 +02:00
|
|
|
}
|
|
|
|
END_ERROR
|
2008-10-21 11:28:34 +02:00
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
{
|
2013-03-30 14:51:10 +01:00
|
|
|
OBJECT_UNREF(process);
|
2008-10-21 11:28:34 +02:00
|
|
|
}
|
|
|
|
else if (!process->to_string)
|
|
|
|
{
|
2013-03-30 14:51:10 +01:00
|
|
|
OBJECT_UNREF_KEEP(process);
|
2008-10-21 11:28:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (process->to_string)
|
|
|
|
{
|
2012-02-27 00:07:14 +01:00
|
|
|
char *result = process->result;
|
2008-10-21 11:28:34 +02:00
|
|
|
process->result = NULL;
|
2012-02-27 00:07:14 +01:00
|
|
|
|
|
|
|
RELEASE_MANY(SP, NPARAM);
|
|
|
|
|
|
|
|
SP->type = T_STRING;
|
|
|
|
SP->_string.addr = result;
|
|
|
|
SP->_string.start = 0;
|
|
|
|
SP->_string.len = STRING_length(result);
|
|
|
|
SP++;
|
|
|
|
|
2013-03-30 14:51:10 +01:00
|
|
|
OBJECT_UNREF(process);
|
2008-10-21 11:28:34 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RETURN->_object.class = CLASS_Process;
|
|
|
|
RETURN->_object.object = process;
|
2012-02-27 00:07:14 +01:00
|
|
|
SUBR_LEAVE();
|
2008-10-21 11:28:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SUBR_LEAVE_VOID();
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool get_value(const char *sym, int len, GB_VARIANT *value)
|
|
|
|
{
|
2008-10-21 11:28:34 +02:00
|
|
|
if (eval_env)
|
|
|
|
if (!GB_CollectionGet(eval_env, sym, len, value))
|
|
|
|
return FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
value->type = GB_T_NULL;
|
|
|
|
return TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
void EVAL_string(char *expr)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int len;
|
2008-10-21 11:28:34 +02:00
|
|
|
EXPRESSION *eval;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
init_eval();
|
|
|
|
len = strlen(expr);
|
|
|
|
eval_env = NULL;
|
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
EVAL.New((void **)(void *)&eval, expr, len);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-05-27 00:34:39 +02:00
|
|
|
if (EVAL.Compile(eval, FALSE))
|
2010-09-04 15:21:11 +02:00
|
|
|
{
|
|
|
|
GB_Error(eval->error);
|
2008-10-21 11:28:34 +02:00
|
|
|
goto _ERROR;
|
2010-09-04 15:21:11 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
if (!EVAL.Run(eval, get_value))
|
|
|
|
goto _ERROR;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
goto _FREE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_ERROR:
|
2008-10-21 11:28:34 +02:00
|
|
|
EVAL.Free((void **)(void *)&eval);
|
|
|
|
PROPAGATE();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_FREE:
|
2008-10-21 11:28:34 +02:00
|
|
|
EVAL.Free((void **)(void *)&eval);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
VALUE_to_string(RETURN, &expr, &len);
|
2008-08-14 21:42:27 +02:00
|
|
|
STREAM_write(CSTREAM_stream(CFILE_out), expr, len);
|
|
|
|
STREAM_write_eol(CSTREAM_stream(CFILE_out));
|
|
|
|
STREAM_flush(CSTREAM_stream(CFILE_out));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
void SUBR_eval(ushort code)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2008-10-21 11:28:34 +02:00
|
|
|
char *expr;
|
|
|
|
int len;
|
|
|
|
EXPRESSION *eval;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
SUBR_ENTER();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
init_eval();
|
2008-10-21 11:28:34 +02:00
|
|
|
SUBR_get_string_len(PARAM, &expr, &len);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
if (NPARAM == 2)
|
|
|
|
{
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_object(&PARAM[1], (TYPE)CLASS_Collection);
|
2008-10-21 11:28:34 +02:00
|
|
|
eval_env = (CCOLLECTION *)(PARAM[1]._object.object);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
eval_env = NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
EVAL.New((void **)(void *)&eval, expr, len);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-07-14 18:33:29 +02:00
|
|
|
if (EVAL.Compile(eval, FALSE))
|
2010-09-04 15:21:11 +02:00
|
|
|
{
|
|
|
|
GB_Error(eval->error);
|
2008-10-21 11:28:34 +02:00
|
|
|
goto _ERROR;
|
2010-09-04 15:21:11 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
if (!EVAL.Run(eval, get_value))
|
|
|
|
goto _ERROR;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
goto _FREE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_ERROR:
|
2016-05-04 03:38:46 +02:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
EVAL.Free((void **)(void *)&eval);
|
|
|
|
PROPAGATE();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_FREE:
|
|
|
|
|
2016-05-04 03:38:46 +02:00
|
|
|
EVAL.Free((void **)(void *)&eval);
|
2008-10-21 11:28:34 +02:00
|
|
|
SUBR_LEAVE();
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
void SUBR_array(ushort code)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2014-01-28 00:46:37 +01:00
|
|
|
static bool reuse = FALSE;
|
|
|
|
|
2009-09-17 22:58:27 +02:00
|
|
|
TYPE type;
|
2014-01-28 00:46:37 +01:00
|
|
|
int i, j;
|
|
|
|
CARRAY *array;
|
|
|
|
bool next_reuse;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-10-21 11:28:34 +02:00
|
|
|
SUBR_ENTER();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2014-01-28 17:17:40 +01:00
|
|
|
next_reuse = code & CODE_CALL_VARIANT;
|
2014-01-28 00:46:37 +01:00
|
|
|
|
|
|
|
if (reuse)
|
|
|
|
{
|
|
|
|
array = (CARRAY *)(PARAM[-1]._object.object);
|
|
|
|
type = array->type;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
type = SUBR_check_good_type(PARAM, NPARAM);
|
|
|
|
|
|
|
|
if (type == T_NULL)
|
|
|
|
type = T_OBJECT;
|
|
|
|
}
|
|
|
|
|
2011-07-17 12:57:55 +02:00
|
|
|
for (i = 0; i < NPARAM; i++)
|
|
|
|
VALUE_conv(&PARAM[i], type);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
if (reuse)
|
|
|
|
{
|
|
|
|
j = array->count;
|
|
|
|
CARRAY_resize(array, j + NPARAM);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
j = 0;
|
|
|
|
GB_ArrayNew(POINTER(&array), type, NPARAM);
|
|
|
|
OBJECT_REF(array);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < NPARAM; i++, j++)
|
2008-10-21 11:28:34 +02:00
|
|
|
{
|
2014-01-28 00:46:37 +01:00
|
|
|
GB_Store(type, (GB_VALUE *)&PARAM[i], GB_ArrayGet(array, j));
|
2010-06-13 14:03:29 +02:00
|
|
|
RELEASE(&PARAM[i]);
|
2008-10-21 11:28:34 +02:00
|
|
|
}
|
2014-01-28 00:46:37 +01:00
|
|
|
|
|
|
|
if (reuse)
|
|
|
|
{
|
|
|
|
SP = PARAM;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PARAM->_object.class = OBJECT_class(array); //CLASS_Array;
|
|
|
|
PARAM->_object.object = array;
|
|
|
|
SP = PARAM + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
reuse = next_reuse;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
void SUBR_collection(ushort code)
|
2008-11-11 18:22:38 +01:00
|
|
|
{
|
2014-01-28 00:46:37 +01:00
|
|
|
static bool reuse = FALSE;
|
|
|
|
|
2008-11-11 18:22:38 +01:00
|
|
|
int i;
|
|
|
|
GB_COLLECTION col;
|
|
|
|
char *key;
|
|
|
|
int len;
|
|
|
|
VALUE *vkey, *vval;
|
2014-01-28 00:46:37 +01:00
|
|
|
bool next_reuse;
|
2008-11-11 18:22:38 +01:00
|
|
|
|
|
|
|
SUBR_ENTER();
|
|
|
|
|
2014-01-28 17:17:40 +01:00
|
|
|
next_reuse = code & CODE_CALL_VARIANT;
|
2014-01-28 00:46:37 +01:00
|
|
|
|
|
|
|
if (reuse)
|
|
|
|
col = (GB_COLLECTION)(PARAM[-1]._object.object);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GB_CollectionNew(&col, GB_COMP_BINARY);
|
|
|
|
OBJECT_REF(col);
|
|
|
|
}
|
2008-11-11 18:22:38 +01:00
|
|
|
|
|
|
|
for (i = 0; i < NPARAM; i += 2)
|
|
|
|
{
|
|
|
|
vkey = &PARAM[i];
|
|
|
|
vval = vkey + 1;
|
|
|
|
SUBR_get_string_len(vkey, &key, &len);
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_variant(vval);
|
2009-09-17 22:58:27 +02:00
|
|
|
if (GB_CollectionSet(col, key, len, (GB_VARIANT *)vval))
|
|
|
|
{
|
2013-03-30 14:51:10 +01:00
|
|
|
OBJECT_UNREF(col);
|
2009-09-17 22:58:27 +02:00
|
|
|
THROW(E_VKEY);
|
|
|
|
}
|
2010-06-13 14:03:29 +02:00
|
|
|
RELEASE_STRING(&PARAM[i]);
|
|
|
|
RELEASE(&PARAM[i + 1]);
|
2008-11-11 18:22:38 +01:00
|
|
|
}
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
if (reuse)
|
|
|
|
{
|
|
|
|
SP = PARAM;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PARAM->_object.class = OBJECT_class(col); //CLASS_Array;
|
|
|
|
PARAM->_object.object = col;
|
|
|
|
SP = PARAM + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
reuse = next_reuse;
|
2008-11-11 18:22:38 +01:00
|
|
|
}
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|