9da7f4 | 2001-06-05 | Martin Stjernholm | | /* -*- c -*-
|
2aca9f | 2001-06-19 | Henrik Grubbström (Grubba) | | * $Id: builtin.cmod,v 1.38 2001/06/19 21:34:28 grubba Exp $
|
9da7f4 | 2001-06-05 | Martin Stjernholm | | */
|
c3da7f | 2000-07-04 | Martin Stjernholm | |
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | #include "global.h"
#include "interpret.h"
#include "svalue.h"
#include "opcodes.h"
#include "pike_macros.h"
#include "object.h"
#include "program.h"
#include "array.h"
|
bb8a78 | 2000-12-01 | Fredrik Hübinette (Hubbe) | | #include "pike_error.h"
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | #include "constants.h"
#include "mapping.h"
#include "stralloc.h"
#include "multiset.h"
#include "pike_types.h"
#include "pike_memory.h"
#include "threads.h"
#include <math.h>
#include <ctype.h>
#include "module_support.h"
#include "cyclic.h"
#include "bignum.h"
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | #include "main.h"
|
b8c5b2 | 2000-05-25 | Fredrik Hübinette (Hubbe) | | #include "operators.h"
|
9da7f4 | 2001-06-05 | Martin Stjernholm | | #include "builtin_functions.h"
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | |
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl array column(array data, mixed index)
*!
*! Extract a column from a two-dimensional array.
*!
*! This function is exactly equivalent to:
*! @code{map(@[data], lambda(mixed x,mixed y) { return x[y]; }, @[index])@}
*!
*! Except of course it is a lot shorter and faster.
*! That is, it indices every index in the array data on the value of
*! the argument index and returns an array with the results.
*!
*! @seealso
*! @[rows()]
*/
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | PIKEFUN array column(array data, mixed index)
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | efun;
optflags OPT_TRY_OPTIMIZE;
{
INT32 e;
struct array *a;
DECLARE_CYCLIC();
/* Optimization */
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | if(data->refs == 1)
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | {
/* An array with one ref cannot possibly be cyclic */
struct svalue sval;
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | data->type_field = BIT_MIXED | BIT_UNFINISHED;
for(e=0;e<data->size;e++)
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | {
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | index_no_free(&sval, ITEM(data)+e, index);
free_svalue(ITEM(data)+e);
ITEM(data)[e]=sval;
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | }
pop_stack();
return;
}
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | if((a=(struct array *)BEGIN_CYCLIC(data,0)))
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | {
add_ref(a);
}else{
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | push_array(a=allocate_array(data->size));
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | SET_CYCLIC_RET(a);
for(e=0;e<a->size;e++)
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | index_no_free(ITEM(a)+e, ITEM(data)+e, index);
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | |
sp--;
}
END_CYCLIC();
RETURN a;
}
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl multiset mkmultiset(array a)
*!
*! This function creates a multiset from an array.
*!
*! @seealso
*! @[aggregate_multiset()]
*!
*/
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | PIKEFUN multiset(1) mkmultiset(array(1=mixed) a)
efun;
|
8f998d | 2000-08-31 | Henrik Grubbström (Grubba) | | optflags OPT_TRY_OPTIMIZE|OPT_EXTERNAL_DEPEND;
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | {
RETURN mkmultiset(a);
}
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl int trace(int t)
*!
*! This function changes the debug trace level.
*!
*! The old level is returned.
*!
*! Trace level 1 or higher means that calls to Pike functions are
*! printed to stderr, level 2 or higher means calls to builtin functions
*! are printed, 3 means every opcode interpreted is printed, 4 means
*! arguments to these opcodes are printed as well.
*!
*! See the @tt{-t@} command-line option for more information.
*/
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | PIKEFUN int trace(int t)
efun;
optflags OPT_SIDE_EFFECT;
{
pop_n_elems(args);
push_int(t_flag);
t_flag=t;
}
|
d6fd96 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl string ctime(int timestamp)
*!
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | *! Convert the output from a previous call to @[time()] into a readable
*! string containing the current year, month, day and time.
*!
*! @seealso
*! @[time()], @[localtime()], @[mktime()], @[gmtime()]
*/
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | PIKEFUN string ctime(int timestamp)
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | efun;
optflags OPT_TRY_OPTIMIZE;
{
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | time_t i=(time_t)timestamp;
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | RETURN make_shared_string(ctime(&i));
}
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl mapping mkmapping(array ind, array val)
*!
*! Make a mapping from two arrays.
*!
*! Makes a mapping @[ind[x]]:@[val[x]], @tt{0 <= x < sizeof(ind)@}.
*!
*! @[ind] and @[val] must have the same size.
*!
*! This is the inverse operation of @[indices()] and @[values()].
*!
*! @seealso
*! @[indices()], @[values()]
*/
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | PIKEFUN mapping(1:2) mkmapping(array(1=mixed) ind, array(2=mixed) val)
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | efun;
|
8f998d | 2000-08-31 | Henrik Grubbström (Grubba) | | optflags OPT_TRY_OPTIMIZE|OPT_EXTERNAL_DEPEND;
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | {
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | if(ind->size != val->size)
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | bad_arg_error("mkmapping", sp-args, args, 2, "array", sp+1-args,
"mkmapping called on arrays of different sizes (%d != %d)\n",
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | ind->size, val->size);
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | |
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | RETURN mkmapping(ind, val);
|
098c80 | 2000-05-24 | Fredrik Hübinette (Hubbe) | | }
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | |
|
269ef0 | 2001-04-18 | Martin Stjernholm | | /*! @decl int String.count(string haystack, string needle)
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | *!
*! Count the number of non-overlapping times the string @[needle] occurrs
*! in the string @[haystack].
*!
*! @seealso
*! @[search()], @[`/()]
*/
|
661305 | 2000-08-10 | Henrik Grubbström (Grubba) | | PIKEFUN int string_count(string haystack, string needle)
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | errname String.count;
optflags OPT_TRY_OPTIMIZE;
{
|
89fc4c | 2000-08-10 | Henrik Grubbström (Grubba) | | ptrdiff_t c = 0;
ptrdiff_t i, j;
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | |
switch (needle->len)
{
case 0:
switch (haystack->len)
{
case 0: c=1; break; /* "" appears one time in "" */
case 1: c=0; break; /* "" doesn't appear in "x" */
default: c=haystack->len-1; /* one time between each character */
}
break;
case 1:
/* maybe optimize? */
default:
for (i=0; i<haystack->len; i++)
{
j=string_search(haystack,needle,i);
if (j==-1) break;
i=j+needle->len-1;
c++;
}
break;
}
|
661305 | 2000-08-10 | Henrik Grubbström (Grubba) | | RETURN DO_NOT_WARN((INT_TYPE)c);
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | }
|
269ef0 | 2001-04-18 | Martin Stjernholm | | /*! @decl string String.trim_whites (string s)
|
5117f1 | 2001-04-16 | Martin Stjernholm | | *!
*! Trim leading and trailing spaces and tabs from the string @[s].
*/
PIKEFUN string string_trim_whites (string s)
errname String.trim_whites;
optflags OPT_TRY_OPTIMIZE;
{
ptrdiff_t start = 0, end = s->len;
int chr;
switch (s->size_shift) {
#define DO_IT(TYPE) \
{ \
for (; start < s->len; start++) { \
chr = ((TYPE *) s->str)[start]; \
if (chr != ' ' && chr != '\t') break; \
} \
while (--end > start) { \
chr = ((TYPE *) s->str)[end]; \
if (chr != ' ' && chr != '\t') break; \
} \
}
case 0: DO_IT (p_wchar0); break;
case 1: DO_IT (p_wchar1); break;
case 2: DO_IT (p_wchar2); break;
#undef DO_IT
}
RETURN string_slice (s, start, end + 1 - start);
}
|
269ef0 | 2001-04-18 | Martin Stjernholm | | /*! @decl string String.trim_all_whites (string s)
|
5117f1 | 2001-04-16 | Martin Stjernholm | | *!
*! Trim leading and trailing white spaces characters (space, tab,
*! newline and carriage return) from the string @[s].
*/
PIKEFUN string string_trim_all_whites (string s)
errname String.trim_all_whites;
optflags OPT_TRY_OPTIMIZE;
{
ptrdiff_t start = 0, end = s->len;
int chr;
switch (s->size_shift) {
#define DO_IT(TYPE) \
{ \
for (; start < s->len; start++) { \
chr = ((TYPE *) s->str)[start]; \
if (chr != ' ' && chr != '\t' && chr != '\n' && chr != '\r') \
break; \
} \
while (--end > start) { \
chr = ((TYPE *) s->str)[end]; \
if (chr != ' ' && chr != '\t' && chr != '\n' && chr != '\r') \
break; \
} \
}
case 0: DO_IT (p_wchar0); break;
case 1: DO_IT (p_wchar1); break;
case 2: DO_IT (p_wchar2); break;
#undef DO_IT
}
RETURN string_slice (s, start, end + 1 - start);
}
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl int program_implements(program prog, program api)
*!
*! Returns 1 if @[prog] implements @[api].
*/
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | PIKEFUN int program_implements(program prog, program api)
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | errname Program.implements;
optflags OPT_TRY_OPTIMIZE;
{
|
b0f835 | 2001-01-07 | Henrik Grubbström (Grubba) | | RETURN implements(prog, api);
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | }
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl int program_inherits(program child, program parent)
*!
*! Returns 1 if @[child] has inherited @[parent].
*/
|
f3c715 | 2001-04-14 | Fredrik Hübinette (Hubbe) | | PIKEFUN int program_inherits(program parent, program child)
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | errname Program.inherits;
optflags OPT_TRY_OPTIMIZE;
{
|
f3c715 | 2001-04-14 | Fredrik Hübinette (Hubbe) | | RETURN low_get_storage(parent, child) != -1;
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | }
|
85081b | 2001-02-27 | Martin Stjernholm | | /*! @decl string program_defined(program p)
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | *!
*! Returns a string with filename and linenumber describing where
*! the program @[p] was defined.
*!
*! The returned string is of the format @tt{"@i{filename@}:@i{linenumber@}"@}.
*!
*! If it cannot be determined where the program was defined, @tt{0@} (zero)
*! will be returned.
*/
|
b8c5b2 | 2000-05-25 | Fredrik Hübinette (Hubbe) | | PIKEFUN string program_defined(program p)
errname Program.defined;
optflags OPT_TRY_OPTIMIZE;
{
if(p && p->num_linenumbers)
{
char *tmp;
INT32 line;
if((tmp=get_line(p->program, p, &line)))
{
struct pike_string *tmp2;
tmp2=make_shared_string(tmp);
pop_n_elems(args);
push_string(tmp2);
if(line > 1)
{
push_constant_text(":");
push_int(line);
f_add(3);
}
return;
}
}
pop_n_elems(args);
push_int(0);
}
|
269ef0 | 2001-04-18 | Martin Stjernholm | | /*! @decl int(8..8)|int(16..16)|int(32..32) String.width(string s)
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | *!
*! Returns the width of a string.
*!
*! Three return values are possible:
*! @int
*! @value 8
*! The string @[s] only contains characters <= 255.
*! @value 16
*! The string @[s] only contains characters <= 65535.
*! @value 32
*! The string @[s] contains characters >= 65536.
*! @endint
*/
|
d6fd96 | 2001-02-10 | Henrik Grubbström (Grubba) | | PIKEFUN int(8 .. 8)|int(16 .. 16)|int(32 .. 32) string_width(string s)
|
991fdf | 2000-05-25 | Fredrik Hübinette (Hubbe) | | errname String.width;
optflags OPT_TRY_OPTIMIZE;
{
RETURN 8 * (1 << s->size_shift);
}
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | /*! @decl mixed m_delete(object|mapping map, mixed index)
*!
*! If @[map] is an object that implements @[lfun::_m_delete()],
*! that function will be called with @[index] as the signle argument.
*!
*! Other wise if @[map] is a mapping the entry with index @[index]
*! will be removed from @[map] destructively.
*!
*! If the mapping does not have an entry with index @[index], nothing is done.
*!
*! @returns
*! The value that was removed will be returned.
*!
*! @note
*! Note that @[m_delete()] changes @[map] destructively.
*!
*! @seealso
*! @[mappingp()]
*/
|
a3453e | 2001-02-05 | Per Hedbor | | PIKEFUN mixed m_delete(object|mapping map, mixed index)
|
7f80d4 | 2000-06-19 | Fredrik Hübinette (Hubbe) | | efun;
optflags OPT_SIDE_EFFECT;
{
|
a3453e | 2001-02-05 | Per Hedbor | | /*FIXME: Should be
* type function(mapping(1=mixed:2=mixed),1:2)|
* function(object,mixed:mixed);
*
* or similar
*/
if( map->type == T_MAPPING )
{
struct svalue s;
map_delete_no_free(map->u.mapping, index, &s);
pop_n_elems(args);
*sp=s;
sp++;
}
|
e9af83 | 2001-02-10 | Martin Stjernholm | | else if (map->type == T_OBJECT && map->u.object->prog)
|
a3453e | 2001-02-05 | Per Hedbor | | {
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | int id = FIND_LFUN(map->u.object->prog, LFUN__M_DELETE);
|
ea5601 | 2001-02-09 | Per Hedbor | |
if( id == -1 )
SIMPLE_BAD_ARG_ERROR("m_delete", 1, "object with _m_delete");
apply_low( map->u.object, id, 1 );
|
a3453e | 2001-02-05 | Per Hedbor | | stack_swap();
pop_stack();
|
79f698 | 2001-02-05 | Henrik Grubbström (Grubba) | | } else {
SIMPLE_BAD_ARG_ERROR("m_delete", 1, "object|mapping");
|
a3453e | 2001-02-05 | Per Hedbor | | }
|
7f80d4 | 2000-06-19 | Fredrik Hübinette (Hubbe) | | }
|
9da7f4 | 2001-06-05 | Martin Stjernholm | | /*! @decl int get_weak_flag(array|mapping|multiset m)
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | *!
|
9da7f4 | 2001-06-05 | Martin Stjernholm | | *! Returns the weak flag settings for @[m]. It's a combination of
*! @[Pike.WEAK_INDICES] and @[Pike.WEAK_VALUES].
|
049833 | 2001-02-10 | Henrik Grubbström (Grubba) | | */
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | PIKEFUN int get_weak_flag(array m)
|
ee9fa9 | 2000-07-06 | Martin Stjernholm | | efun;
|
8f998d | 2000-08-31 | Henrik Grubbström (Grubba) | | optflags OPT_EXTERNAL_DEPEND;
|
ee9fa9 | 2000-07-06 | Martin Stjernholm | | {
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | RETURN (m->flags & ARRAY_WEAK_FLAG) ? PIKE_WEAK_VALUES : 0;
}
PIKEFUN int get_weak_flag(mapping m)
{
RETURN mapping_get_flags(m) & MAPPING_WEAK;
}
PIKEFUN int get_weak_flag(multiset m)
{
RETURN (m->ind->flags & (ARRAY_WEAK_FLAG|ARRAY_WEAK_SHRINK)) ?
|
9da7f4 | 2001-06-05 | Martin Stjernholm | | PIKE_WEAK_INDICES : 0;
|
ee9fa9 | 2000-07-06 | Martin Stjernholm | | }
|
aa68b1 | 2001-03-19 | Fredrik Hübinette (Hubbe) | | PIKEFUN program __empty_program()
efun;
optflags OPT_EXTERNAL_DEPEND;
{
RETURN low_allocate_program();
}
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | | /*! @decl string function_name(function f)
*!
*! Return the name of the function @[f].
*!
*! If @[f] is a global function defined in the runtime @tt{0@} (zero)
*! will be returned.
*!
*! @seealso
*! @[function_object()]
*/
PIKEFUN string function_name(program|function func)
efun;
optflags OPT_TRY_OPTIMIZE;
{
struct pike_string *s;
switch(func->type)
{
default:
if(!func->u.object->prog)
bad_arg_error("function_name", Pike_sp-args, args, 1,
"function|program", Pike_sp-args,
"Bad argument.\n");
return; /* NOTREACHED */
case PIKE_T_PROGRAM:
{
struct program *p=func->u.program;
if(p->parent)
{
int e;
p=p->parent;
/* search constants in parent for this
* program...
*/
for(e = p->num_identifier_references; e--; )
{
struct identifier *id;
if (p->identifier_references[e].id_flags & ID_HIDDEN)
continue;
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_CONSTANT(id->identifier_flags) &&
is_eq( & PROG_FROM_INT(p, e)->constants[id->func.offset].sval,
func))
REF_RETURN id->name;
}
}
break;
}
case PIKE_T_FUNCTION:
if(func->subtype == FUNCTION_BUILTIN) break;
if(!func->u.object->prog)
bad_arg_error("function_name", Pike_sp-args, args, 1,
"function", Pike_sp-args,
"Destructed object.\n");
|
5a6d7d | 2001-04-10 | Fredrik Hübinette (Hubbe) | | if(func->u.object->prog == pike_trampoline_program)
{
struct pike_trampoline *t;
t=((struct pike_trampoline *)func->u.object->storage);
if(t->frame->current_object->prog)
REF_RETURN ID_FROM_INT(t->frame->current_object->prog,
t->func)->name;
}
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | |
REF_RETURN ID_FROM_INT(func->u.object->prog, func->subtype)->name;
}
pop_n_elems(args);
push_int(0);
}
/*! @decl object function_object(function|program f)
*!
*! Return the object the function @[f] is in.
*!
*! If @[f] is a global function defined in the runtime @tt{0@} (zero)
*! will be returned.
*!
*! @seealso
*! @[function_name()]
*/
|
5a6d7d | 2001-04-10 | Fredrik Hübinette (Hubbe) | | PIKEFUN object|program function_object(object|program|function func)
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | | efun;
optflags OPT_TRY_OPTIMIZE;
|
5a6d7d | 2001-04-10 | Fredrik Hübinette (Hubbe) | | type function(function|object:object)|function(program:program);
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | | {
switch(func->type)
{
case PIKE_T_PROGRAM:
{
struct program *p;
if(!(p=func->u.program->parent)) break;
add_ref(p);
free_program(func->u.program);
func->u.program=p;
return;
}
case PIKE_T_FUNCTION:
if(func->subtype == FUNCTION_BUILTIN) break;
|
5a6d7d | 2001-04-10 | Fredrik Hübinette (Hubbe) | | if(func->u.object->prog == pike_trampoline_program)
{
struct object *o;
o=((struct pike_trampoline *)func->u.object->storage)->frame->current_object;
add_ref(o);
pop_n_elems(args);
push_object(o);
return;
}
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | | func->type=T_OBJECT;
return;
|
5a6d7d | 2001-04-10 | Fredrik Hübinette (Hubbe) | |
default:
SIMPLE_BAD_ARG_ERROR("function_object",1,"function");
|
1c1c5e | 2001-04-08 | Fredrik Hübinette (Hubbe) | | }
pop_n_elems(args);
push_int(0);
}
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | | /*! @decl int random(int max)
*!
*! This function returns a random number in the range 0 - @[max]-1.
*!
*! @seealso
*! @[random_seed()]
*/
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | |
PIKEFUN mixed random(object o)
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | | efun;
optflags OPT_TRY_OPTIMIZE|OPT_EXTERNAL_DEPEND;
{
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | apply(o,"_random",0);
stack_swap();
pop_stack();
}
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | PIKEFUN int random(int i)
{
if(i <= 0) RETURN 0;
RETURN my_rand() % i;
}
PIKEFUN float random(float f)
{
if(f<=0.0) RETURN 0.0;
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | | #define N 1048576
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | RETURN f * (my_rand()%N/((float)N)) +
f * (my_rand()%N/( ((float)N) * ((float)N) ));
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | }
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | PIKEFUN mixed random(array a)
{
if(!a->size)
SIMPLE_BAD_ARG_ERROR("random", 1, "array with elements in it");
push_svalue(a->item + (my_rand() % a->size));
stack_swap();
pop_stack();
}
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | PIKEFUN mixed random(multiset m)
{
if(!m->ind->size)
SIMPLE_BAD_ARG_ERROR("random", 1, "multiset with elements in it");
push_svalue(m->ind->item + (my_rand() % m->ind->size));
stack_swap();
pop_stack();
}
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | | PIKEFUN mapping random(mapping m)
{
struct mapping_data *md=m->data;
size_t bucket, count;
struct keypair *k;
if(!m_sizeof(m))
SIMPLE_BAD_ARG_ERROR("random", 1, "mapping with elements in it");
/* Find a random, nonempty bucket */
bucket=my_rand() % md->hashsize;
while(! md->hash[bucket] )
if(++bucket > (size_t)md->hashsize)
bucket=0;
/* Count entries in bucket */
count=0;
for(k=md->hash[bucket];k;k=k->next) count++;
/* Select a random entry in this bucket */
count = my_rand() % count;
k=md->hash[bucket];
while(count-- > 0) k=k->next;
/* Push result and return */
push_svalue(&k->ind);
push_svalue(&k->val);
f_aggregate(2);
stack_swap();
pop_stack();
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | | }
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | /*
* Backtrace handling.
*/
/*! @class BacktraceFrame
*/
PIKECLASS backtrace_frame
{
|
2aca9f | 2001-06-19 | Henrik Grubbström (Grubba) | | PIKEVAR function fun;
PIKEVAR array args;
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | CVAR struct program *prog;
CVAR unsigned char *pc;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | CVAR struct pike_string *filename;
|
2aca9f | 2001-06-19 | Henrik Grubbström (Grubba) | | CVAR INT_TYPE lineno;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | |
INIT
{
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | THIS->fun.type = T_INT;
THIS->prog = NULL;
THIS->pc = 0;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | THIS->lineno = 0;
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | THIS->args = NULL;
THIS->filename = NULL;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
EXIT
{
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->prog) {
free_program(THIS->prog);
THIS->prog = NULL;
}
if (THIS->args) {
free_array(THIS->args);
THIS->args = NULL;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
if (THIS->filename) {
free_string(THIS->filename);
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | THIS->filename = NULL;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | THIS->pc = 0;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | THIS->lineno = 0;
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | free_svalue(&THIS->fun);
THIS->fun.type = T_INT;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | PIKEFUN int(0..1) _is_type(string t)
{
INT_TYPE res = (t == findstring("array"));
pop_n_elems(args);
push_int(res);
}
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | PIKEFUN string _sprintf(int c, mapping|void opts)
{
pop_n_elems(args);
push_text("backtrace_frame(");
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->pc) {
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | if (!THIS->filename) {
THIS->filename =
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | make_shared_string(get_line(THIS->pc, THIS->prog, &THIS->lineno));
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
ref_push_string(THIS->filename);
push_text(":");
push_int(THIS->lineno);
push_text(", ");
f_add(4);
} else {
push_text("Unknown file, ");
}
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->fun.type == PIKE_T_FUNCTION) {
if (THIS->fun.u.object->prog) {
push_svalue(&THIS->fun);
f_function_name(1);
push_text("(), ");
f_add(2);
} else {
free_svalue(&THIS->fun);
THIS->fun.type = PIKE_T_INT;
THIS->fun.u.integer = 0;
THIS->fun.subtype = NUMBER_DESTRUCTED;
push_text("destructed_function(), ");
}
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | } else {
push_text("destructed_function(), ");
}
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->args) {
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | push_text("Args: ");
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | push_int(THIS->args->size);
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | f_add(2);
} else {
push_text("No args");
}
push_text(")");
f_add(5);
}
PIKEFUN int _sizeof()
{
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->args) {
push_int(THIS->args->size + 3);
} else {
push_int(3);
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
}
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | PIKEFUN mixed `[](int index, int|void end_or_none)
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | {
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | INT_TYPE end = index;
INT32 numargs = 0;
INT32 i;
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->args) {
numargs = THIS->args->size;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | |
numargs += 3;
if (!end_or_none) {
if (index < 0) {
index_error("pike_frame->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
"Indexing with negative index (%"PRINTPIKEINT"d)\n", index);
} else if (index >= numargs) {
index_error("pike_frame->`[]", Pike_sp-args, args, NULL, Pike_sp-args,
"Indexing with too large index (%"PRINTPIKEINT"d)\n", index);
}
} else {
if (end_or_none->type != PIKE_T_INT) {
SIMPLE_BAD_ARG_ERROR("`[]",2,"int|void");
}
end = end_or_none->u.integer;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
pop_n_elems(args);
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | if (end_or_none) {
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if ((end < 0) || (end < index) || (index >= numargs)) {
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | f_aggregate(0);
return;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | |
if (end >= numargs) {
end = numargs-1;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | }
for (i = index; i <= end; i++) {
switch(i) {
case 0: /* Filename */
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->pc) {
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | if (!THIS->filename) {
THIS->filename =
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | make_shared_string(get_line(THIS->pc, THIS->prog,
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | &THIS->lineno));
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | ref_push_string(THIS->filename);
} else {
push_int(0);
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | break;
case 1: /* Linenumber */
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if (THIS->pc) {
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | if (!THIS->filename) {
THIS->filename =
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | make_shared_string(get_line(THIS->pc, THIS->prog,
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | &THIS->lineno));
}
push_int(THIS->lineno);
} else {
push_int(0);
}
break;
case 2: /* Function */
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | push_svalue(&THIS->fun);
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | break;
default: /* Arguments */
{
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | if ((i > 2) && (THIS->args) && (i-3 < THIS->args->size)) {
push_svalue(THIS->args->item + (i - 3));
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | break;
}
bad_arg_error("backtrace_frame->`[]", Pike_sp-args, args, 1,
"int(0..)", Pike_sp-args,
"Bad argument 1 to backtrace_frame->`[](): "
"Expected int(0..%d)\n",
numargs + 2);
}
/* NOT_REACHED */
break;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | | }
if (end_or_none) {
f_aggregate(1 + end - index);
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | }
}
|
d2cd4e | 2001-06-18 | Henrik Grubbström (Grubba) | |
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | };
/*! @endclass
*/
|
91d397 | 2001-06-19 | Henrik Grubbström (Grubba) | | /*! @decl array(array) backtrace()
*!
*! Get a description of the current call stack.
*!
*! The description is returned as an array with one entry for each call
*! frame on the stack.
*!
*! Each entry has this format:
*! @array
*! @elem string file
*! A string with the filename if known, else zero.
*! @elem int line
*! An integer containing the linenumber if known, else zero.
*! @elem function fun
*! The function that was called at this level.
*! @elem mixed|void ... args
*! The arguments that the function was called with.
*! @endarray
*!
*! The current call frame will be last in the array.
*!
*! @note
*! Please note that the frame order may be reversed in a later version
*! (than 7.1) of Pike to accomodate for deferred backtraces.
*!
*! Note that the arguments reported in the backtrace are the current
*! values of the variables, and not the ones that were at call-time.
*! This can be used to hide sensitive information from backtraces
*! (eg passwords).
*!
*! @seealso
*! @[catch()], @[throw()]
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | */
|
91d397 | 2001-06-19 | Henrik Grubbström (Grubba) | | PMOD_EXPORT
PIKEFUN array(mixed) backtrace()
efun;
optflags OPT_EXTERNAL_DEPEND;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | {
struct pike_frame *f;
int size = 0;
|
a3b6b0 | 2001-06-19 | Henrik Grubbström (Grubba) | | for (f = Pike_fp; f; f = f->next) {
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | struct object *o = low_clone(backtrace_frame_program);
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | | struct backtrace_frame_struct *bf;
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | call_c_initializers(o);
|
0f47db | 2001-06-19 | Henrik Grubbström (Grubba) | |
bf = OBJ2_BACKTRACE_FRAME(o);
if ((bf->prog = f->context.prog)) {
add_ref(bf->prog);
bf->pc = f->pc;
}
if ((bf->fun.u.object = f->current_object) &&
(bf->fun.u.object->prog)) {
add_ref(bf->fun.u.object);
bf->fun.subtype = f->fun;
bf->fun.type = PIKE_T_FUNCTION;
} else {
bf->fun.u.integer = 0;
bf->fun.subtype = NUMBER_DESTRUCTED;
bf->fun.type = PIKE_T_INT;
}
if (f->locals) {
INT32 numargs = DO_NOT_WARN((INT32) MINIMUM(f->num_args,
Pike_sp - f->locals));
numargs = MAXIMUM(numargs, 0);
if (numargs) {
bf->args = allocate_array_no_init(numargs, 0);
assign_svalues_no_free(bf->args->item, f->locals, numargs, BIT_MIXED);
}
}
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | push_object(o);
size++;
}
|
d95fa8 | 2001-06-05 | Fredrik Hübinette (Hubbe) | |
|
d27df5 | 2001-06-18 | Henrik Grubbström (Grubba) | | f_aggregate(size);
f_reverse(1);
}
|
e1b419 | 2001-06-06 | Fredrik Hübinette (Hubbe) | |
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | void init_builtin(void)
{
|
ab8282 | 2000-05-25 | Fredrik Hübinette (Hubbe) | | INIT
|
3a5b1d | 2000-05-24 | Fredrik Hübinette (Hubbe) | | }
|