pike.git
/
src
/
builtin.cmod
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/builtin.cmod:23:
#include "cyclic.h" #include "bignum.h" #include "main.h" #include "operators.h" #include "builtin_functions.h" #include "fsort.h" #include "port.h" #include "gc.h" #include "block_alloc.h" #include "pikecode.h"
+
#include "opcodes.h"
#include <ctype.h> #include <errno.h> #include <math.h> DECLARATIONS /*! @decl array(array(int|string|type)) describe_program(program p) *! @belongs Debug *!
pike.git/src/builtin.cmod:598:
}, { \ SET_SVAL(get, T_FLOAT, 0, float_number, \ DO_NOT_WARN ((FLOAT_TYPE) VAR)); \ }); HANDLE_PARAM ("enabled", { if (TYPEOF(*set) != T_INT || set->u.integer < -1 || set->u.integer > 1) SIMPLE_BAD_ARG_ERROR ("Pike.gc_parameters", 1, "integer in the range -1..1 for 'enabled'"); if (gc_enabled != set->u.integer) {
-
if (gc_enabled > 0)
-
gc_
enabled
=
set
->u.integer;
-
else
{
-
gc_
enabled
=
1;
-
if (
alloc_threshold =
=
GC
_
MAX_ALLOC_THRESHOLD)
-
alloc_threshold = GC_
MIN
_ALLOC_THRESHOLD;
+
if (gc_enabled > 0)
{
+
/* Disabling automatic
gc
- save the old alloc
_
threshold
and
set
it to
+
*
the
maximum
value
to
avoid
getting
gc_
evaluator_callback
added.
*/
+
saved_
alloc_threshold =
alloc
_
threshold;
+
alloc_threshold = GC_
MAX
_ALLOC_THRESHOLD;
}
-
+
else if (set->u.integer > 0) {
+
/* Enabling automatic gc - restore the old alloc_threshold. If the
+
* gc interval has gotten longer than it should be then the
+
* multiplier calculation in do_gc should compensate. */
+
alloc_threshold = saved_alloc_threshold;
}
-
+
gc_enabled = set->u.integer;
+
}
}, { SET_SVAL(get, T_INT, NUMBER_NUMBER, integer, gc_enabled); }); HANDLE_FLOAT_FACTOR ("garbage_ratio_low", gc_garbage_ratio_low); HANDLE_FLOAT_FACTOR ("time_ratio", gc_time_ratio); HANDLE_FLOAT_FACTOR ("garbage_ratio_high", gc_garbage_ratio_high); HANDLE_FLOAT_FACTOR ("min_gc_time_ratio", gc_min_time_ratio); HANDLE_FLOAT_FACTOR ("average_slowness", gc_average_slowness); #undef HANDLE_PARAM
pike.git/src/builtin.cmod:1674:
* assume no other entities are naughty enough to modify it). */ mapping_string_insert_string (env_allocs, env_alloc_var, putenv_str); else { struct svalue key; SET_SVAL(key, T_STRING, 0, string, env_alloc_var); map_delete (env_allocs, &key); } #endif /* !USE_SETENV */ }
+
#if defined(PIKE_DEBUG) && defined(PIKE_PORTABLE_BYTECODE)
+
+
/*! @decl void disassemble(function fun)
+
*! @belongs Debug
+
*!
+
*! Disassemble a Pike function to @[Stdio.stderr].
+
*!
+
*! @note
+
*! This function is only available if the Pike runtime
+
*! has been compiled with debug enabled.
+
*/
+
PIKEFUN void _disassemble(function fun)
+
{
+
if ((TYPEOF(*fun) != T_FUNCTION) ||
+
(SUBTYPEOF(*fun) == FUNCTION_BUILTIN)) {
+
fprintf(stderr,
+
"Disassembly only supported for functions implemented in Pike.\n");
+
} else if (!fun->u.object->prog) {
+
fprintf(stderr, "Function in destructed object.\n");
+
} else {
+
int f = SUBTYPEOF(*fun);
+
struct reference *ptr = PTR_FROM_INT(fun->u.object->prog, f);
+
struct program *p = PROG_FROM_PTR(fun->u.object->prog, ptr);
+
struct identifier *id = p->identifiers + ptr->identifier_offset;
+
if (id->func.offset >= 0) {
+
struct pike_string *tripples =
+
p->strings[read_program_data(p->program + id->func.offset, -1)];
+
switch(tripples->size_shift) {
+
#define CASE(SHIFT) \
+
case SHIFT: \
+
{ \
+
PIKE_CONCAT(p_wchar, SHIFT) *str = \
+
PIKE_CONCAT(STR, SHIFT)(tripples); \
+
int i=0; \
+
while(i < tripples->len) { \
+
fprintf(stderr, "@@@ %d: %s, %d, %d\n", \
+
i/3, \
+
instrs[*str - F_OFFSET]. \
+
name, \
+
str[1], str[2]); \
+
str += 3; \
+
i += 3; \
+
} \
+
} \
+
break
+
CASE(0);
+
CASE(1);
+
CASE(2);
+
#undef CASE
+
}
+
} else {
+
fprintf(stderr, "Prototype.\n");
+
}
+
}
+
pop_n_elems(args);
+
push_int(0);
+
}
+
+
#endif /* PIKE_DEBUG && PIKE_PORTABLE_BYTECODE */
+
/* * Backtrace handling. */ /*! @module Pike */ /*! @class BacktraceFrame */
pike.git/src/builtin.cmod:4364:
} /*! @decl mixed tail() *! *! Get the element at the tail of the list. *! *! @throws *! Throws an error if the list is empty. *! *! @seealso
-
*! @[is_empty()], @[head()], @[pop()]
+
*! @[is_empty()], @[head()], @[pop
_back
()]
*/ PIKEFUN mixed tail() {
-
if (THIS->
tail
->
prev
) {
-
push_svalue(&
THIS
->
tail
->val);
+
struct pike_list_node * node = TAIL_SENTINEL(THIS);
+
if (THIS->
head
->
next
) {
+
push_svalue(&
node
->
prev
->val);
} else { Pike_error("Empty list.\n"); } }
-
+
static inline void pop_node(struct pike_list_node * node) {
+
push_svalue(&node->val);
+
if (node->refs == 2) {
+
unlink_list_node(node);
+
} else {
+
detach_list_node(node);
+
}
+
THIS->num_elems--;
+
}
+
/*! @decl mixed pop() *! *! Pop the element at the head of the list from the list. *! *! @throws *! Throws an error if the list is empty. *! *! @seealso
-
*! @[is_empty()], @[head()], @[tail()]
+
*! @[is_empty()], @[head()], @[tail()]
, @[pop_back()]
*/ PIKEFUN mixed pop() { if (THIS->head->next) {
-
push
_
svalue(&THIS->head->val);
-
if (THIS->head->refs == 2) {
-
unlink_list_
node(THIS->head);
+
pop
_node(THIS->head);
} else {
-
detach
_
list_node
(
THIS->head
);
+
Pike_error("Empty
list
.\n"
);
}
-
THIS->
num
_
elems
-
-
;
+
}
+
+
/*!
@decl
mixed pop_back()
+
*!
+
*! Pop the element at the tail of the list from the list.
+
*!
+
*! @throws
+
*! Throws an error if the list is empty.
+
*!
+
*! @seealso
+
*! @[is_empty()], @[head()], @[tail()], @[pop()]
+
*/
+
PIKEFUN mixed pop_back()
+
{
+
const struct pike_list_node * node = TAIL_SENTINEL(
THIS
);
+
if (THIS
->
head->next) {
+
pop
_
node(node
-
>prev)
;
} else { Pike_error("Empty list.\n"); } }
-
+
/*! @decl array _values()
+
*!
+
*! Returns an array of elements in the list.
+
*/
+
PIKEFUN array _values()
+
flags ID_PROTECTED;
+
{
+
struct array * a;
+
push_int(THIS->num_elems);
+
f_allocate(1);
+
+
a = Pike_sp[-1].u.array;
+
if (THIS->num_elems) {
+
struct pike_list_node *node = THIS->head;
+
int i;
+
for (i = 0; i < THIS->num_elems; i++) {
+
assign_svalue_no_free(ITEM(a) + i, &node->val);
+
node = node->next;
+
}
+
}
+
}
+
+
/*! @decl mixed cast(string type)
+
*!
+
*! Cast the lists. @expr{array@} and @expr{object@} are the only
+
*! supported types.
+
*/
+
PIKEFUN mixed cast(string type)
+
flags ID_PROTECTED;
+
{
+
if (type == MK_STRING("array")) {
+
pop_n_elems(args);
+
apply_current(f_List_cq__values_fun_num, 0);
+
} else if (type == MK_STRING("object")) {
+
pop_n_elems(args);
+
ref_push_object(Pike_fp->current_object);
+
} else {
+
Pike_error("Cannot cast to %o.\n", Pike_sp-1);
+
}
+
}
+
+
+
/*! @decl mixed `[](mixed key) */
+
PIKEFUN mixed `[](mixed key)
+
flags ID_PROTECTED;
+
{
+
struct pike_list_node *node;
+
INT_TYPE n;
+
if (TYPEOF(*key) != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("`[]", 1, "int");
+
+
n = key->u.integer;
+
if (n < 0) n = -(n+1);
+
+
if (n >= THIS->num_elems) Pike_error("out of bounds");
+
+
if (n >= THIS->num_elems >> 1) { /* use shorter direction */
+
n = THIS->num_elems - n - 1;
+
key->u.integer = - key->u.integer - 1;
+
}
+
+
if (key->u.integer < 0) {
+
node = TAIL_SENTINEL(THIS)->prev;
+
while (n--) node = node->prev;
+
} else {
+
node = THIS->head;
+
while (n--) node = node->next;
+
}
+
+
pop_n_elems(args);
+
push_svalue(&node->val);
+
}
+
/*! @decl void append(mixed ... values) *! *! Append @[values] to the end of the list. *! *! @seealso *! @[insert()] */ PIKEFUN void append(mixed ... values) { struct pike_list_node *node = TAIL_SENTINEL(THIS);
pike.git/src/builtin.cmod:4440:
while (args--) { struct pike_list_node *new_node = alloc_pike_list_node(); new_node->val = *(--Pike_sp); prepend_list_node(node, new_node); free_list_node(node = new_node); THIS->num_elems++; } push_int(0); }
+
/*! @decl void flush()
+
*!
+
*! Empties the List.
+
*/
+
PIKEFUN void flush() {
+
if (THIS->num_elems) {
+
while (THIS->head->next) {
+
if (THIS->head->refs == 2)
+
unlink_list_node(THIS->head);
+
else
+
detach_list_node(THIS->head);
+
}
+
THIS->num_elems = 0;
+
}
+
}
+
/*! @decl protected void create(mixed ... values) *! *! Create a new @[List], and initialize it with @[values].
-
*!
-
*! @fixme
-
*! Ought to reset the @[List] if called multiple times.
+
*/ PIKEFUN void create(mixed ... values) flags ID_PROTECTED; {
-
/*
FIXME:
Reset
the
list?
*/
+
if
(THIS->num_elems)
+
apply_current(f_List_flush_fun_num, 0);
apply_current(f_List_append_fun_num, args); } /*! @class _get_iterator *! *! @[Iterator] that loops over the @[List]. */ PIKECLASS _get_iterator program_flags PROGRAM_USES_PARENT; flags ID_PROTECTED;
pike.git/src/builtin.cmod:4475:
/* NOTE: cur may never refer to an unlinked node. * cur may however refer to a detached node, or to sentinels. */ static struct List_struct *List__get_iterator_find_parent() { struct external_variable_context loc; loc.o = Pike_fp->current_object; loc.parent_identifier = Pike_fp->fun;
-
loc.inherit =
INHERIT
_
FROM_INT(loc.o
->
prog, loc.parent_identifier)
;
+
loc.inherit =
Pike
_
fp
->
context
;
find_external_context(&loc, 1); return (struct List_struct *)(loc.o->storage + loc.inherit->storage_offset); } INIT { add_ref(THIS->cur = List__get_iterator_find_parent()->head); THIS->ind = 0; }