|
|
|
|
|
|
#include "global.h" |
RCSID("$Id: builtin_functions.c,v 1.345 2001/02/23 14:29:01 grubba Exp $"); |
#include "interpret.h" |
#include "svalue.h" |
#include "pike_macros.h" |
#include "object.h" |
#include "program.h" |
#include "array.h" |
#include "pike_error.h" |
#include "constants.h" |
#include "mapping.h" |
#include "stralloc.h" |
#include "multiset.h" |
#include "pike_types.h" |
#include "rusage.h" |
#include "operators.h" |
#include "fsort.h" |
#include "callback.h" |
#include "gc.h" |
#include "backend.h" |
#include "main.h" |
#include "pike_memory.h" |
#include "threads.h" |
#include "time_stuff.h" |
#include "version.h" |
#include "encode.h" |
#include <math.h> |
#include <ctype.h> |
#include "module_support.h" |
#include "module.h" |
#include "opcodes.h" |
#include "cyclic.h" |
#include "signal_handler.h" |
#include "security.h" |
#include "builtin_functions.h" |
#include "bignum.h" |
|
#ifdef HAVE_POLL |
#ifdef HAVE_POLL_H |
#include <poll.h> |
#endif /* HAVE_POLL_H */ |
|
#ifdef HAVE_SYS_POLL_H |
#include <sys/poll.h> |
#endif /* HAVE_SYS_POLL_H */ |
#endif /* HAVE_POLL */ |
|
#ifdef HAVE_CRYPT_H |
#include <crypt.h> |
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_equal(INT32 args) |
{ |
int i; |
if(args != 2) |
PIKE_ERROR("equal", "Bad number of arguments.\n", Pike_sp, args); |
|
i=is_equal(Pike_sp-2,Pike_sp-1); |
pop_n_elems(args); |
push_int(i); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void debug_f_aggregate(INT32 args) |
{ |
struct array *a; |
#ifdef PIKE_DEBUG |
if(args < 0) fatal("Negative args to f_aggregate() (%d)\n",args); |
#endif |
|
a=aggregate_array(args); |
push_array(a); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_compat_hash( INT32 args ) |
{ |
struct pike_string *s = Pike_sp[-args].u.string; |
unsigned int i; |
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash",1); |
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("hash", 1, "string"); |
|
if( s->size_shift ) |
{ |
f_hash( args ); |
return; |
} |
|
i = hashstr( (unsigned char *)s->str, MINIMUM(100,s->len)); |
if(args > 1) |
{ |
if(Pike_sp[1-args].type != T_INT) |
SIMPLE_BAD_ARG_ERROR("hash",2,"int"); |
|
if(!Pike_sp[1-args].u.integer) |
PIKE_ERROR("hash", "Modulo by zero.\n", Pike_sp, args); |
|
i%=(unsigned INT32)Pike_sp[1-args].u.integer; |
} |
pop_n_elems(args); |
push_int( i ); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_hash(INT32 args) |
{ |
size_t i = 0; |
struct pike_string *s = Pike_sp[-args].u.string; |
|
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash",1); |
|
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("hash", 1, "string"); |
|
i = simple_hashmem((unsigned char *)s->str, s->len<<s->size_shift, |
100<<s->size_shift); |
|
if(args > 1) |
{ |
if(Pike_sp[1-args].type != T_INT) |
SIMPLE_BAD_ARG_ERROR("hash",2,"int"); |
|
if(!Pike_sp[1-args].u.integer) |
PIKE_ERROR("hash", "Modulo by zero.\n", Pike_sp, args); |
|
i%=(unsigned INT32)Pike_sp[1-args].u.integer; |
} |
pop_n_elems(args); |
push_int64(i); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_copy_value(INT32 args) |
{ |
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("copy_value",1); |
|
pop_n_elems(args-1); |
copy_svalues_recursively_no_free(Pike_sp,Pike_sp-1,1,0); |
free_svalue(Pike_sp-1); |
Pike_sp[-1]=Pike_sp[0]; |
dmalloc_touch_svalue(Pike_sp-1); |
} |
|
struct case_info { |
int low; |
int mode; |
int data; |
}; |
|
#define CIM_NONE 0 /* Case-less */ |
#define CIM_UPPERDELTA 1 /* Upper-case, delta to lower-case in data */ |
#define CIM_LOWERDELTA 2 /* Lower-case, -delta to upper-case in data */ |
#define CIM_CASEBIT 3 /* Some case, case mask in data */ |
#define CIM_CASEBITOFF 4 /* Same as above, but also offset by data */ |
|
static const struct case_info case_info[] = { |
#ifdef IN_TPIKE |
#include "dummy_ci.h" |
#else /* !IN_TPIKE */ |
#include "case_info.h" |
#endif /* IN_TPIKE */ |
{ 0x10000, CIM_NONE, 0x0000, }, |
}; |
|
static struct case_info *find_ci(int c) |
{ |
static struct case_info *cache = NULL; |
struct case_info *ci = cache; |
int lo = 0; |
int hi = NELEM(case_info); |
|
if ((c < 0) || (c > 0xffff)) |
return NULL; |
|
if ((ci) && (ci[0].low <= c) && (ci[1].low > c)) { |
return ci; |
} |
|
while (lo != hi-1) { |
int mid = (lo + hi)/2; |
if (case_info[mid].low < c) { |
lo = mid; |
} else if (case_info[mid].low == c) { |
lo = mid; |
break; |
} else { |
hi = mid; |
} |
} |
return(cache = (struct case_info *)case_info + lo); |
} |
|
static struct case_info *find_ci_shift0(int c) |
{ |
static struct case_info *cache = NULL; |
struct case_info *ci = cache; |
int lo = 0; |
int hi = CASE_INFO_SHIFT0_HIGH; |
|
if ((c < 0) || (c > 0xffff)) |
return NULL; |
|
if ((ci) && (ci[0].low <= c) && (ci[1].low > c)) { |
return ci; |
} |
|
while (lo != hi-1) { |
int mid = (lo + hi)>>1; |
if (case_info[mid].low < c) { |
lo = mid; |
} else if (case_info[mid].low == c) { |
lo = mid; |
break; |
} else { |
hi = mid; |
} |
} |
return(cache = (struct case_info *)case_info + lo); |
} |
|
#define DO_LOWER_CASE(C) do {\ |
int c = C; \ |
struct case_info *ci = find_ci(c); \ |
if (ci) { \ |
switch(ci->mode) { \ |
case CIM_NONE: case CIM_LOWERDELTA: break; \ |
case CIM_UPPERDELTA: C = c + ci->data; break; \ |
case CIM_CASEBIT: C = c | ci->data; break; \ |
case CIM_CASEBITOFF: C = ((c - ci->data) | ci->data) + ci->data; break; \ |
default: fatal("lower_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_LOWER_CASE_SHIFT0(C) do {\ |
int c = C; \ |
struct case_info *ci = find_ci_shift0(c); \ |
if (ci) { \ |
switch(ci->mode) { \ |
case CIM_NONE: case CIM_LOWERDELTA: break; \ |
case CIM_UPPERDELTA: C = c + ci->data; break; \ |
case CIM_CASEBIT: C = c | ci->data; break; \ |
case CIM_CASEBITOFF: C = ((c - ci->data) | ci->data) + ci->data; break; \ |
default: fatal("lower_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_UPPER_CASE(C) do {\ |
int c = C; \ |
struct case_info *ci = find_ci(c); \ |
if (ci) { \ |
switch(ci->mode) { \ |
case CIM_NONE: case CIM_UPPERDELTA: break; \ |
case CIM_LOWERDELTA: C = c - ci->data; break; \ |
case CIM_CASEBIT: C = c & ~ci->data; break; \ |
case CIM_CASEBITOFF: C = ((c - ci->data)& ~ci->data) + ci->data; break; \ |
default: fatal("upper_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_UPPER_CASE_SHIFT0(C) do {\ |
int c = C; \ |
struct case_info *ci = find_ci_shift0(c); \ |
if (ci) { \ |
switch(ci->mode) { \ |
case CIM_NONE: case CIM_UPPERDELTA: break; \ |
case CIM_LOWERDELTA: C = c - ci->data; break; \ |
case CIM_CASEBIT: C = c & ~ci->data; break; \ |
case CIM_CASEBITOFF: C = ((c - ci->data)& ~ci->data) + ci->data; break; \ |
default: fatal("lower_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_lower_case(INT32 args) |
{ |
ptrdiff_t i; |
struct pike_string *orig; |
struct pike_string *ret; |
get_all_args("lower_case", args, "%W", &orig); |
|
ret = begin_wide_shared_string(orig->len, orig->size_shift); |
|
MEMCPY(ret->str, orig->str, orig->len << orig->size_shift); |
|
i = orig->len; |
|
if (!orig->size_shift) { |
p_wchar0 *str = STR0(ret); |
|
while(i--) { |
DO_LOWER_CASE_SHIFT0(str[i]); |
} |
} else if (orig->size_shift == 1) { |
p_wchar1 *str = STR1(ret); |
|
while(i--) { |
DO_LOWER_CASE(str[i]); |
} |
} else if (orig->size_shift == 2) { |
p_wchar2 *str = STR2(ret); |
|
while(i--) { |
DO_LOWER_CASE(str[i]); |
} |
} else { |
fatal("lower_case(): Bad string shift:%d\n", orig->size_shift); |
} |
|
pop_n_elems(args); |
push_string(end_shared_string(ret)); |
} |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_upper_case(INT32 args) |
{ |
ptrdiff_t i; |
struct pike_string *orig; |
struct pike_string *ret; |
int widen = 0; |
get_all_args("upper_case",args,"%W",&orig); |
|
ret=begin_wide_shared_string(orig->len,orig->size_shift); |
MEMCPY(ret->str, orig->str, orig->len << orig->size_shift); |
|
i = orig->len; |
|
if (!orig->size_shift) { |
p_wchar0 *str = STR0(ret); |
|
while(i--) { |
if(str[i]!=0xff && str[i]!=0xb5) { |
DO_UPPER_CASE_SHIFT0(str[i]); |
} else { |
widen = 1; |
} |
} |
} else if (orig->size_shift == 1) { |
p_wchar1 *str = STR1(ret); |
|
while(i--) { |
DO_UPPER_CASE(str[i]); |
} |
} else if (orig->size_shift == 2) { |
p_wchar2 *str = STR2(ret); |
|
while(i--) { |
DO_UPPER_CASE(str[i]); |
} |
} else { |
fatal("lower_case(): Bad string shift:%d\n", orig->size_shift); |
} |
|
pop_n_elems(args); |
push_string(end_shared_string(ret)); |
|
if (widen) { |
|
orig = Pike_sp[-1].u.string; |
ret = begin_wide_shared_string(orig->len, 1); |
|
i = orig->len; |
|
while(i--) { |
switch(STR1(ret)[i] = STR0(orig)[i]) { |
case 0xff: STR1(ret)[i] = 0x178; break; |
case 0xb5: STR1(ret)[i] = 0x39c; break; |
} |
} |
free_string(Pike_sp[-1].u.string); |
Pike_sp[-1].u.string = end_shared_string(ret); |
} |
} |
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_random(INT32 args) |
{ |
INT_TYPE i; |
|
if(args && (Pike_sp[-args].type == T_OBJECT)) |
{ |
pop_n_elems(args-1); |
apply(Pike_sp[-1].u.object,"_random",0); |
stack_swap(); |
pop_stack(); |
return; |
} |
|
get_all_args("random",args,"%i",&i); |
|
if(i <= 0) |
{ |
i = 0; |
}else{ |
i = my_rand() % i; |
} |
pop_n_elems(args); |
push_int(i); |
} |
|
|
|
|
|
PMOD_EXPORT void f_random_string(INT32 args) |
{ |
struct pike_string *ret; |
INT_TYPE len, e; |
get_all_args("random_string",args,"%i",&len); |
ret = begin_shared_string(len); |
for(e=0;e<len;e++) ret->str[e]=my_rand(); |
pop_n_elems(args); |
push_string(end_shared_string(ret)); |
} |
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_random_seed(INT32 args) |
{ |
INT_TYPE i; |
#ifdef AUTO_BIGNUM |
check_all_args("random_seed",args,BIT_INT | BIT_OBJECT, 0); |
if(Pike_sp[-args].type == T_INT) |
{ |
i=Pike_sp[-args].u.integer; |
}else{ |
i=hash_svalue(Pike_sp-args); |
} |
#else |
get_all_args("random_seed",args,"%i",&i); |
#endif |
my_srand(i); |
pop_n_elems(args); |
} |
|
|
|
|
|
|
|
|
|
|
|
void f_query_num_arg(INT32 args) |
{ |
pop_n_elems(args); |
push_int(Pike_fp ? Pike_fp->args : 0); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_search(INT32 args) |
{ |
ptrdiff_t start; |
|
if(args < 2) |
SIMPLE_TOO_FEW_ARGS_ERROR("search", 2); |
|
switch(Pike_sp[-args].type) |
{ |
case T_STRING: |
{ |
char *ptr; |
if(Pike_sp[1-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("search", 2, "string"); |
|
start=0; |
if(args > 2) |
{ |
if(Pike_sp[2-args].type!=T_INT) |
SIMPLE_BAD_ARG_ERROR("search", 3, "int"); |
|
start=Pike_sp[2-args].u.integer; |
if(start<0) { |
bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp+2-args, |
"Start must be greater or equal to zero.\n"); |
} |
} |
|
if(Pike_sp[-args].u.string->len < start) |
bad_arg_error("search", Pike_sp-args, args, 1, "int(0..)", Pike_sp-args, |
"Start must not be greater than the " |
"length of the string.\n"); |
|
start=string_search(Pike_sp[-args].u.string, |
Pike_sp[1-args].u.string, |
start); |
|
pop_n_elems(args); |
push_int64(start); |
break; |
} |
|
case T_ARRAY: |
start=0; |
if(args > 2) |
{ |
if(Pike_sp[2-args].type!=T_INT) |
SIMPLE_BAD_ARG_ERROR("search", 3, "int"); |
|
start=Pike_sp[2-args].u.integer; |
if(start<0) { |
bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp+2-args, |
"Start must be greater or equal to zero.\n"); |
} |
} |
start=array_search(Pike_sp[-args].u.array,Pike_sp+1-args,start); |
pop_n_elems(args); |
push_int64(start); |
break; |
|
case T_MAPPING: |
if(args > 2) { |
mapping_search_no_free(Pike_sp,Pike_sp[-args].u.mapping,Pike_sp+1-args,Pike_sp+2-args); |
} else { |
mapping_search_no_free(Pike_sp,Pike_sp[-args].u.mapping,Pike_sp+1-args,0); |
} |
free_svalue(Pike_sp-args); |
Pike_sp[-args]=*Pike_sp; |
dmalloc_touch_svalue(Pike_sp); |
pop_n_elems(args-1); |
return; |
|
default: |
SIMPLE_BAD_ARG_ERROR("search", 1, "string|array|mapping"); |
} |
} |
|
|
|
|
|
|
PMOD_EXPORT void f_has_prefix(INT32 args) |
{ |
struct pike_string *a, *b; |
|
get_all_args("has_prefix", args, "%W%W", &a, &b); |
|
|
if ((b->len > a->len) || (b->size_shift > a->size_shift)) { |
pop_n_elems(args); |
push_int(0); |
return; |
} |
|
|
if ((a == b)||(!b->len)) { |
pop_n_elems(args); |
push_int(1); |
return; |
} |
|
if (a->size_shift == b->size_shift) { |
int res = !MEMCMP(a->str, b->str, b->len << b->size_shift); |
pop_n_elems(args); |
push_int(res); |
return; |
} |
|
|
#define TWO_SHIFTS(S1, S2) ((S1)|((S2)<<2)) |
switch(TWO_SHIFTS(a->size_shift, b->size_shift)) { |
#define CASE_SHIFT(S1, S2) \ |
case TWO_SHIFTS(S1, S2): \ |
{ \ |
PIKE_CONCAT(p_wchar,S1) *s1 = PIKE_CONCAT(STR,S1)(a); \ |
PIKE_CONCAT(p_wchar,S2) *s2 = PIKE_CONCAT(STR,S2)(b); \ |
ptrdiff_t len = b->len; \ |
while(len-- && (s1[len] == s2[len])) \ |
; \ |
pop_n_elems(args); \ |
push_int(len == -1); \ |
return; \ |
} \ |
break |
|
CASE_SHIFT(1,0); |
CASE_SHIFT(2,0); |
CASE_SHIFT(2,1); |
default: |
Pike_error("has_prefix(): Unexpected string shift combination: a:%d, b:%d!\n", |
a->size_shift, b->size_shift); |
break; |
} |
#undef CASE_SHIFT |
#undef TWO_SHIFTS |
} |
|
|
|
|
|
|
PMOD_EXPORT void f_has_suffix(INT32 args) |
{ |
struct pike_string *a, *b; |
|
get_all_args("has_suffix", args, "%W%W", &a, &b); |
|
|
if ((b->len > a->len) || (b->size_shift > a->size_shift)) { |
pop_n_elems(args); |
push_int(0); |
return; |
} |
|
|
if ((a == b)||(!b->len)) { |
pop_n_elems(args); |
push_int(1); |
return; |
} |
|
if (a->size_shift == b->size_shift) { |
int res = !MEMCMP(a->str + ((a->len - b->len)<<b->size_shift), b->str, |
b->len << b->size_shift); |
pop_n_elems(args); |
push_int(res); |
return; |
} |
|
|
#define TWO_SHIFTS(S1, S2) ((S1)|((S2)<<2)) |
switch(TWO_SHIFTS(a->size_shift, b->size_shift)) { |
#define CASE_SHIFT(S1, S2) \ |
case TWO_SHIFTS(S1, S2): \ |
{ \ |
PIKE_CONCAT(p_wchar,S1) *s1 = PIKE_CONCAT(STR,S1)(a) + a->len - b->len; \ |
PIKE_CONCAT(p_wchar,S2) *s2 = PIKE_CONCAT(STR,S2)(b); \ |
ptrdiff_t len = b->len; \ |
while(len-- && (s1[len] == s2[len])) \ |
; \ |
pop_n_elems(args); \ |
push_int(len == -1); \ |
return; \ |
} \ |
break |
|
CASE_SHIFT(1,0); |
CASE_SHIFT(2,0); |
CASE_SHIFT(2,1); |
default: |
Pike_error("has_prefix(): Unexpected string shift combination: a:%d, b:%d!\n", |
a->size_shift, b->size_shift); |
break; |
} |
#undef CASE_SHIFT |
#undef TWO_SHIFTS |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_has_index(INT32 args) |
{ |
int t = 0; |
|
if(args != 2) |
PIKE_ERROR("has_index", "Bad number of arguments.\n", Pike_sp, args); |
|
switch(Pike_sp[-2].type) |
{ |
case T_STRING: |
if(Pike_sp[-1].type == T_INT) |
t = (0 <= Pike_sp[-1].u.integer && Pike_sp[-1].u.integer < Pike_sp[-2].u.string->len); |
|
pop_n_elems(args); |
push_int(t); |
break; |
|
case T_ARRAY: |
if(Pike_sp[-1].type == T_INT) |
t = (0 <= Pike_sp[-1].u.integer && Pike_sp[-1].u.integer < Pike_sp[-2].u.array->size); |
|
pop_n_elems(args); |
push_int(t); |
break; |
|
case T_MULTISET: |
case T_MAPPING: |
f_index(2); |
f_zero_type(1); |
|
if(Pike_sp[-1].type == T_INT) |
Pike_sp[-1].u.integer = !Pike_sp[-1].u.integer; |
else |
PIKE_ERROR("has_index", |
"Function `zero_type' gave incorrect result.\n", Pike_sp, args); |
break; |
|
case T_OBJECT: |
|
|
|
|
|
|
|
|
|
|
|
default: |
stack_swap(); |
f_indices(1); |
stack_swap(); |
f_search(2); |
|
if(Pike_sp[-1].type == T_INT) |
Pike_sp[-1].u.integer = (Pike_sp[-1].u.integer != -1); |
else |
PIKE_ERROR("has_index", |
"Function `search' gave incorrect result.\n", Pike_sp, args); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_has_value(INT32 args) |
{ |
if(args != 2) |
PIKE_ERROR("has_value", "Bad number of arguments.\n", Pike_sp, args); |
|
switch(Pike_sp[-2].type) |
{ |
case T_MAPPING: |
f_search(2); |
f_zero_type(1); |
|
if(Pike_sp[-1].type == T_INT) |
Pike_sp[-1].u.integer = !Pike_sp[-1].u.integer; |
else |
PIKE_ERROR("has_value", |
"Function `zero_type' gave incorrect result.\n", Pike_sp, args); |
break; |
|
case T_OBJECT: |
|
|
|
|
|
|
|
|
|
|
|
|
default: |
stack_swap(); |
f_values(1); |
stack_swap(); |
|
case T_STRING: |
case T_ARRAY: |
f_search(2); |
|
if(Pike_sp[-1].type == T_INT) |
Pike_sp[-1].u.integer = (Pike_sp[-1].u.integer != -1); |
else |
PIKE_ERROR("has_value", "Search gave incorrect result.\n", Pike_sp, args); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_backtrace(INT32 args) |
{ |
INT32 frames; |
struct pike_frame *f,*of; |
struct array *a,*i; |
|
frames=0; |
if(args) pop_n_elems(args); |
for(f=Pike_fp;f;f=f->next) frames++; |
|
Pike_sp->type=T_ARRAY; |
Pike_sp->u.array=a=allocate_array_no_init(frames,0); |
Pike_sp++; |
|
|
of=0; |
for(f=Pike_fp;f;f=(of=f)->next) |
{ |
char *program_name; |
|
debug_malloc_touch(f); |
frames--; |
|
if(f->current_object && f->context.prog) |
{ |
INT32 args; |
if(!f->locals) |
{ |
args=0; |
}else{ |
args=f->num_args; |
args = DO_NOT_WARN((INT32) MINIMUM(f->num_args, Pike_sp - f->locals)); |
if(of) |
args = DO_NOT_WARN((INT32)MINIMUM(f->num_args,of->locals - f->locals)); |
args=MAXIMUM(args,0); |
} |
|
ITEM(a)[frames].u.array=i=allocate_array_no_init(3+args,0); |
ITEM(a)[frames].type=T_ARRAY; |
if(f->locals) |
assign_svalues_no_free(ITEM(i)+3, f->locals, args, BIT_MIXED); |
if(f->current_object->prog) |
{ |
ITEM(i)[2].type=T_FUNCTION; |
ITEM(i)[2].subtype=f->fun; |
ITEM(i)[2].u.object=f->current_object; |
add_ref(f->current_object); |
}else{ |
ITEM(i)[2].type=T_INT; |
ITEM(i)[2].subtype=NUMBER_DESTRUCTED; |
ITEM(i)[2].u.integer=0; |
} |
|
if(f->pc) |
{ |
program_name=get_line(f->pc, f->context.prog, & ITEM(i)[1].u.integer); |
ITEM(i)[1].subtype=NUMBER_NUMBER; |
ITEM(i)[1].type=T_INT; |
|
ITEM(i)[0].u.string=make_shared_string(program_name); |
#ifdef __CHECKER__ |
ITEM(i)[0].subtype=0; |
#endif |
ITEM(i)[0].type=T_STRING; |
}else{ |
ITEM(i)[1].u.integer=0; |
ITEM(i)[1].subtype=NUMBER_NUMBER; |
ITEM(i)[1].type=T_INT; |
|
ITEM(i)[0].u.integer=0; |
ITEM(i)[0].subtype=NUMBER_NUMBER; |
ITEM(i)[0].type=T_INT; |
} |
}else{ |
ITEM(a)[frames].type=T_INT; |
ITEM(a)[frames].u.integer=0; |
} |
} |
a->type_field = BIT_ARRAY | BIT_INT; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_add_constant(INT32 args) |
{ |
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, ("add_constant: permission denied.\n")); |
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("add_constant", 1); |
|
if(Pike_sp[-args].type!=T_STRING) |
SIMPLE_BAD_ARG_ERROR("add_constant", 1, "string"); |
|
if(args>1) |
{ |
dmalloc_touch_svalue(Pike_sp-args+1); |
low_add_efun(Pike_sp[-args].u.string, Pike_sp-args+1); |
}else{ |
low_add_efun(Pike_sp[-args].u.string, 0); |
} |
pop_n_elems(args); |
} |
|
#ifndef __NT__ |
#define IS_SEP(X) ( (X)=='/' ) |
#define IS_ABS(X) (IS_SEP((X)[0])?1:0) |
#else |
|
#define IS_SEP(X) ( (X) == '/' || (X) == '\\' ) |
|
static int find_absolute(char *s) |
{ |
if(isalpha(s[0]) && s[1]==':' && IS_SEP(s[2])) |
return 3; |
|
if(IS_SEP(s[0]) && IS_SEP(s[1])) |
{ |
int l; |
for(l=2;isalpha(s[l]);l++); |
return l; |
} |
|
return 0; |
} |
#define IS_ABS(X) find_absolute((X)) |
|
#define IS_ROOT(X) (IS_SEP((X)[0])?1:0) |
#endif |
|
static void free_nonull(char **ptr) |
{ |
if(*ptr) free(*ptr); |
} |
|
static char *combine_path(char *cwd,char *file) |
{ |
|
char *ret; |
register char *from,*to; |
char *my_cwd; |
char *cwdbuf = 0; |
int tmp; |
ONERROR err; |
|
SET_ONERROR(err, free_nonull, &cwdbuf); |
|
if((tmp=IS_ABS(file))) |
{ |
cwdbuf = (char *)xalloc(tmp+1); |
MEMCPY(cwdbuf,file,tmp); |
cwdbuf[tmp]=0; |
cwd=cwdbuf; |
file+=tmp; |
} |
|
#ifdef IS_ROOT |
else if(IS_ROOT(file)) |
{ |
if(tmp=IS_ABS(cwd)) |
{ |
cwdbuf = (char *)xalloc(tmp+1); |
MEMCPY(cwdbuf,cwd,tmp); |
cwdbuf[tmp]=0; |
cwd=cwdbuf; |
file+=IS_ROOT(file); |
}else{ |
tmp = IS_ROOT(file); |
cwdbuf = (char *)xalloc(tmp+1); |
MEMCPY(cwdbuf,file,tmp); |
cwdbuf[IS_ROOT(file)]=0; |
cwd=cwdbuf; |
file+=IS_ROOT(file); |
} |
} |
#endif |
|
#ifdef PIKE_DEBUG |
if(!cwd) |
fatal("No cwd in combine_path!\n"); |
#endif |
|
if(!*cwd || IS_SEP(cwd[strlen(cwd)-1])) |
{ |
ret=(char *)xalloc(strlen(cwd)+strlen(file)+1); |
strcpy(ret,cwd); |
strcat(ret,file); |
}else{ |
ret=(char *)xalloc(strlen(cwd)+strlen(file)+2); |
strcpy(ret,cwd); |
strcat(ret,"/"); |
strcat(ret,file); |
} |
|
from=to=ret; |
|
|
#ifdef __NT__ |
if(IS_SEP(from[0]) && IS_SEP(from[1])) |
*(to++)=*(from++); |
else |
#endif |
|
|
while(from[0]=='.' && IS_SEP(from[1])) from+=2; |
|
while(( *to = *from )) |
{ |
if(IS_SEP(*from)) |
{ |
while(to>ret && to[-1]=='/') to--; |
if(from[1] == '.') |
{ |
switch(from[2]) |
{ |
case '.': |
if(IS_SEP(from[3]) || !from[3]) |
{ |
char *tmp=to; |
while(--tmp>=ret) |
if(IS_SEP(*tmp)) |
break; |
tmp++; |
|
if(tmp[0]=='.' && tmp[1]=='.' && (IS_SEP(tmp[2]) || !tmp[2])) |
break; |
|
from+=3; |
to=tmp; |
continue; |
} |
break; |
|
case 0: |
case '/': |
#ifdef __NT__ |
case '\\': |
#endif |
from+=2; |
continue; |
} |
} |
} |
from++; |
to++; |
} |
|
if(*ret && !IS_SEP(from[-1]) && IS_SEP(to[-1])) |
*--to=0; |
|
if(!*ret) |
{ |
if(IS_SEP(*cwd)) |
{ |
ret[0]='/'; |
ret[1]=0; |
}else{ |
ret[0]='.'; |
ret[1]=0; |
} |
} |
|
CALL_AND_UNSET_ONERROR(err); |
|
return ret; |
} |
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_combine_path(INT32 args) |
{ |
char *path=0; |
int e,dofree=0; |
struct pike_string *ret; |
|
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("combine_path", 1); |
|
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("combine_path", 1, "string"); |
|
path=Pike_sp[-args].u.string->str; |
|
for(e=1;e<args;e++) |
{ |
char *newpath; |
if(Pike_sp[e-args].type != T_STRING) |
{ |
if(dofree) free(path); |
SIMPLE_BAD_ARG_ERROR("combine_path", e+1, "string"); |
} |
|
newpath=combine_path(path,Pike_sp[e-args].u.string->str); |
if(dofree) free(path); |
path=newpath; |
dofree=1; |
} |
|
ret=make_shared_string(path); |
if(dofree) free(path); |
pop_n_elems(args); |
push_string(ret); |
} |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_function_object(INT32 args) |
{ |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("function_object",1); |
if(Pike_sp[-args].type != T_FUNCTION) |
SIMPLE_BAD_ARG_ERROR("function_object",1,"function"); |
|
if(Pike_sp[-args].subtype == FUNCTION_BUILTIN) |
{ |
pop_n_elems(args); |
push_int(0); |
}else{ |
pop_n_elems(args-1); |
Pike_sp[-1].type=T_OBJECT; |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_function_name(INT32 args) |
{ |
struct pike_string *s; |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("function_name", 1); |
if(Pike_sp[-args].type != T_FUNCTION) |
SIMPLE_BAD_ARG_ERROR("function_name", 1, "function"); |
|
if(Pike_sp[-args].subtype == FUNCTION_BUILTIN) |
{ |
pop_n_elems(args); |
push_int(0); |
}else{ |
if(!Pike_sp[-args].u.object->prog) |
bad_arg_error("function_name", Pike_sp-args, args, 1, "function", Pike_sp-args, |
"Destructed object.\n"); |
|
copy_shared_string(s,ID_FROM_INT(Pike_sp[-args].u.object->prog, |
Pike_sp[-args].subtype)->name); |
pop_n_elems(args); |
|
Pike_sp->type=T_STRING; |
Pike_sp->u.string=s; |
Pike_sp++; |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_zero_type(INT32 args) |
{ |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("zero_type",1); |
|
if(Pike_sp[-args].type != T_INT) |
{ |
pop_n_elems(args); |
push_int(0); |
} |
else if((Pike_sp[-args].type==T_OBJECT || Pike_sp[-args].type==T_FUNCTION) |
&& !Pike_sp[-args].u.object->prog) |
{ |
pop_n_elems(args); |
push_int(NUMBER_DESTRUCTED); |
} |
{ |
pop_n_elems(args-1); |
Pike_sp[-1].u.integer=Pike_sp[-1].subtype; |
Pike_sp[-1].subtype=NUMBER_NUMBER; |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_string_to_unicode(INT32 args) |
{ |
struct pike_string *in; |
struct pike_string *out = NULL; |
ptrdiff_t len; |
ptrdiff_t i; |
|
get_all_args("string_to_unicode", args, "%W", &in); |
|
switch(in->size_shift) { |
case 0: |
|
len = in->len * 2; |
out = begin_shared_string(len); |
if (len) { |
MEMSET(out->str, 0, len); |
#ifdef PIKE_DEBUG |
if (d_flag) { |
for(i = len; i--;) { |
if (out->str[i]) { |
fatal("MEMSET didn't clear byte %ld of %ld\n", |
PTRDIFF_T_TO_LONG(i+1), |
PTRDIFF_T_TO_LONG(len)); |
} |
} |
} |
#endif /* PIKE_DEBUG */ |
for(i = in->len; i--;) { |
out->str[i * 2 + 1] = in->str[i]; |
} |
} |
out = end_shared_string(out); |
break; |
case 1: |
|
|
len = in->len * 2; |
out = begin_shared_string(len); |
#if (PIKE_BYTEORDER == 4321) |
|
* |
* FIXME: Future optimization: Check if refcount is == 1, |
* and perform sufficient magic to be able to convert in place. |
*/ |
MEMCPY(out->str, in->str, len); |
#else |
|
{ |
p_wchar1 *str1 = STR1(in); |
for(i = in->len; i--;) { |
unsigned INT32 c = str1[i]; |
out->str[i * 2 + 1] = c & 0xff; |
out->str[i * 2] = c >> 8; |
} |
} |
#endif |
out = end_shared_string(out); |
break; |
case 2: |
|
{ |
p_wchar2 *str2 = STR2(in); |
ptrdiff_t j; |
len = in->len * 2; |
|
for(i = in->len; i--;) { |
if (str2[i] > 0xfffd) { |
if (str2[i] < 0x10000) { |
|
|
|
Pike_error("string_to_unicode(): Illegal character 0x%04x (index %ld) " |
"is not a Unicode character.", |
str2[i], PTRDIFF_T_TO_LONG(i)); |
} |
if (str2[i] > 0x10ffff) { |
Pike_error("string_to_unicode(): Character 0x%08x (index %ld) " |
"is out of range (0x00000000 - 0x0010ffff).", |
str2[i], PTRDIFF_T_TO_LONG(i)); |
} |
|
|
|
len += 2; |
} |
} |
out = begin_shared_string(len); |
j = len; |
for(i = in->len; i--;) { |
unsigned INT32 c = str2[i]; |
|
j -= 2; |
|
if (c > 0xffff) { |
|
c -= 0x10000; |
|
out->str[j + 1] = c & 0xff; |
out->str[j] = 0xdc | ((c >> 8) & 0x03); |
j -= 2; |
c >>= 10; |
c |= 0xd800; |
} |
out->str[j + 1] = c & 0xff; |
out->str[j] = c >> 8; |
} |
#ifdef PIKE_DEBUG |
if (j) { |
fatal("string_to_unicode(): Indexing error: len:%ld, j:%ld.\n", |
PTRDIFF_T_TO_LONG(len), PTRDIFF_T_TO_LONG(j)); |
} |
#endif /* PIKE_DEBUG */ |
out = end_shared_string(out); |
} |
break; |
default: |
Pike_error("string_to_unicode(): Bad string shift: %d!\n", in->size_shift); |
break; |
} |
pop_n_elems(args); |
push_string(out); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_unicode_to_string(INT32 args) |
{ |
struct pike_string *in; |
struct pike_string *out = NULL; |
ptrdiff_t len; |
|
get_all_args("unicode_to_string", args, "%S", &in); |
|
if (in->len & 1) { |
bad_arg_error("unicode_to_string", Pike_sp-args, args, 1, "string", Pike_sp-args, |
"String length is odd.\n"); |
} |
|
|
|
len = in->len / 2; |
|
out = begin_wide_shared_string(len, 1); |
#if (PIKE_BYTEORDER == 4321) |
|
* |
* FIXME: Future optimization: Perform sufficient magic |
* to do the conversion in place if the ref-count is == 1. |
*/ |
MEMCPY(out->str, in->str, in->len); |
#else |
|
{ |
ptrdiff_t i; |
p_wchar1 *str1 = STR1(out); |
|
for (i = len; i--;) { |
str1[i] = (((unsigned char *)in->str)[i*2]<<8) + |
((unsigned char *)in->str)[i*2 + 1]; |
} |
} |
#endif /* PIKE_BYTEORDER == 4321 */ |
out = end_shared_string(out); |
pop_n_elems(args); |
push_string(out); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_string_to_utf8(INT32 args) |
{ |
ptrdiff_t len; |
struct pike_string *in; |
struct pike_string *out; |
ptrdiff_t i,j; |
int extended = 0; |
|
get_all_args("string_to_utf8", args, "%W", &in); |
|
if (args > 1) { |
if (Pike_sp[1-args].type != T_INT) { |
SIMPLE_BAD_ARG_ERROR("string_to_utf8", 2, "int|void"); |
} |
extended = Pike_sp[1-args].u.integer; |
} |
|
len = in->len; |
|
for(i=0; i < in->len; i++) { |
unsigned INT32 c = index_shared_string(in, i); |
if (c & ~0x7f) { |
|
len++; |
if (c & ~0x7ff) { |
|
len++; |
if (c & ~0xffff) { |
|
len++; |
if (c & ~0x1fffff) { |
|
len++; |
if (c & ~0x3ffffff) { |
|
len++; |
if (c & ~0x7fffffff) { |
|
if (!extended) { |
Pike_error("string_to_utf8(): " |
"Value 0x%08x (index %ld) is larger than 31 bits.\n", |
c, PTRDIFF_T_TO_LONG(i)); |
} |
len++; |
|
} |
} |
} |
} |
} |
} |
} |
if (len == in->len) { |
|
pop_n_elems(args - 1); |
return; |
} |
out = begin_shared_string(len); |
|
for(i=j=0; i < in->len; i++) { |
unsigned INT32 c = index_shared_string(in, i); |
if (!(c & ~0x7f)) { |
|
out->str[j++] = c; |
} else if (!(c & ~0x7ff)) { |
|
out->str[j++] = 0xc0 | (c >> 6); |
out->str[j++] = 0x80 | (c & 0x3f); |
} else if (!(c & ~0xffff)) { |
|
out->str[j++] = 0xe0 | (c >> 12); |
out->str[j++] = 0x80 | ((c >> 6) & 0x3f); |
out->str[j++] = 0x80 | (c & 0x3f); |
} else if (!(c & ~0x1fffff)) { |
|
out->str[j++] = 0xf0 | (c >> 18); |
out->str[j++] = 0x80 | ((c >> 12) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 6) & 0x3f); |
out->str[j++] = 0x80 | (c & 0x3f); |
} else if (!(c & ~0x3ffffff)) { |
|
out->str[j++] = 0xf8 | (c >> 24); |
out->str[j++] = 0x80 | ((c >> 18) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 12) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 6) & 0x3f); |
out->str[j++] = 0x80 | (c & 0x3f); |
} else if (!(c & ~0x7fffffff)) { |
|
out->str[j++] = 0xfc | (c >> 30); |
out->str[j++] = 0x80 | ((c >> 24) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 18) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 12) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 6) & 0x3f); |
out->str[j++] = 0x80 | (c & 0x3f); |
} else { |
|
|
out->str[j++] = 0xfe; |
out->str[j++] = 0x80 | ((c >> 30) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 24) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 18) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 12) & 0x3f); |
out->str[j++] = 0x80 | ((c >> 6) & 0x3f); |
out->str[j++] = 0x80 | (c & 0x3f); |
} |
} |
#ifdef PIKE_DEBUG |
if (len != j) { |
fatal("string_to_utf8(): Calculated and actual lengths differ: " |
"%ld != %ld\n", |
PTRDIFF_T_TO_LONG(len), PTRDIFF_T_TO_LONG(j)); |
} |
#endif /* PIKE_DEBUG */ |
out = end_shared_string(out); |
pop_n_elems(args); |
push_string(out); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_utf8_to_string(INT32 args) |
{ |
struct pike_string *in; |
struct pike_string *out; |
int len = 0; |
int shift = 0; |
int i,j; |
int extended = 0; |
|
get_all_args("utf8_to_string", args, "%S", &in); |
|
if (args > 1) { |
if (Pike_sp[1-args].type != T_INT) { |
SIMPLE_BAD_ARG_ERROR("utf8_to_string()", 2, "int|void"); |
} |
extended = Pike_sp[1-args].u.integer; |
} |
|
for(i=0; i < in->len; i++) { |
unsigned int c = ((unsigned char *)in->str)[i]; |
len++; |
if (c & 0x80) { |
int cont = 0; |
if ((c & 0xc0) == 0x80) { |
Pike_error("utf8_to_string(): " |
"Unexpected continuation block 0x%02x at index %d.\n", |
c, i); |
} |
if ((c & 0xe0) == 0xc0) { |
|
cont = 1; |
if (c & 0x1c) { |
if (shift < 1) { |
shift = 1; |
} |
} |
} else if ((c & 0xf0) == 0xe0) { |
|
cont = 2; |
if (shift < 1) { |
shift = 1; |
} |
} else { |
shift = 2; |
if ((c & 0xf8) == 0xf0) { |
|
cont = 3; |
} else if ((c & 0xfc) == 0xf8) { |
|
cont = 4; |
} else if ((c & 0xfe) == 0xfc) { |
|
cont = 5; |
} else if (c == 0xfe) { |
|
if (!extended) { |
Pike_error("utf8_to_string(): " |
"Character 0xfe at index %d when not in extended mode.\n", |
i); |
} |
cont = 6; |
} else { |
Pike_error("utf8_to_string(): " |
"Unexpected character 0xff at index %d.\n", |
i); |
} |
} |
while(cont--) { |
i++; |
if (i >= in->len) { |
Pike_error("utf8_to_string(): Truncated UTF8 sequence.\n"); |
} |
c = ((unsigned char *)(in->str))[i]; |
if ((c & 0xc0) != 0x80) { |
Pike_error("utf8_to_string(): " |
"Expected continuation character at index %d (got 0x%02x).\n", |
i, c); |
} |
} |
} |
} |
if (len == in->len) { |
|
pop_n_elems(args-1); |
return; |
} |
|
out = begin_wide_shared_string(len, shift); |
|
for(j=i=0; i < in->len; i++) { |
unsigned int c = ((unsigned char *)in->str)[i]; |
|
if (c & 0x80) { |
int cont = 0; |
|
|
|
|
if ((c & 0xe0) == 0xc0) { |
|
cont = 1; |
c &= 0x1f; |
} else if ((c & 0xf0) == 0xe0) { |
|
cont = 2; |
c &= 0x0f; |
} else if ((c & 0xf8) == 0xf0) { |
|
cont = 3; |
c &= 0x07; |
} else if ((c & 0xfc) == 0xf8) { |
|
cont = 4; |
c &= 0x03; |
} else if ((c & 0xfe) == 0xfc) { |
|
cont = 5; |
c &= 0x01; |
} else { |
|
cont = 6; |
c = 0; |
} |
while(cont--) { |
unsigned INT32 c2 = ((unsigned char *)(in->str))[++i] & 0x3f; |
c = (c << 6) | c2; |
} |
} |
low_set_index(out, j++, c); |
} |
#ifdef PIKE_DEBUG |
if (j != len) { |
fatal("utf8_to_string(): Calculated and actual lengths differ: %d != %d\n", |
len, j); |
} |
#endif /* PIKE_DEBUG */ |
out = end_shared_string(out); |
pop_n_elems(args); |
push_string(out); |
} |
|
|
|
static void f_parse_pike_type( INT32 args ) |
{ |
struct pike_type *t; |
struct pike_string *res; |
if( !args || Pike_sp[-1].type != T_STRING || |
Pike_sp[-1].u.string->size_shift ) |
Pike_error( "__parse_pike_type requires a 8bit string as its first argument\n" ); |
t = parse_type( (char *)STR0(Pike_sp[-1].u.string) ); |
pop_stack(); |
|
|
|
|
push_string( res = t ); |
} |
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_all_constants(INT32 args) |
{ |
pop_n_elems(args); |
ref_push_mapping(get_builtin_constants()); |
} |
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_allocate(INT32 args) |
{ |
INT32 size; |
struct array *a; |
|
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("allocate",1); |
|
if(Pike_sp[-args].type!=T_INT) |
SIMPLE_BAD_ARG_ERROR("allocate",1,"int"); |
|
size=Pike_sp[-args].u.integer; |
if(size < 0) |
PIKE_ERROR("allocate", "Can't allocate array of negative size.\n", Pike_sp, args); |
a=allocate_array(size); |
if(args>1) |
{ |
INT32 e; |
for(e=0;e<a->size;e++) |
copy_svalues_recursively_no_free(a->item+e, Pike_sp-args+1, 1, 0); |
} |
pop_n_elems(args); |
push_array(a); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_rusage(INT32 args) |
{ |
INT32 *rus,e; |
struct array *v; |
pop_n_elems(args); |
rus=low_rusage(); |
if(!rus) |
PIKE_ERROR("rusage", "System rusage information not available.\n", Pike_sp, args); |
v=allocate_array_no_init(29,0); |
|
for(e=0;e<29;e++) |
{ |
ITEM(v)[e].type=T_INT; |
ITEM(v)[e].subtype=NUMBER_NUMBER; |
ITEM(v)[e].u.integer=rus[e]; |
} |
|
Pike_sp->u.array=v; |
Pike_sp->type=T_ARRAY; |
Pike_sp++; |
} |
|
|
|
|
|
void f_this_object(INT32 args) |
{ |
pop_n_elems(args); |
if(Pike_fp) |
{ |
ref_push_object(Pike_fp->current_object); |
}else{ |
push_int(0); |
} |
} |
|
node *fix_this_object_type(node *n) |
{ |
free_type(n->type); |
type_stack_mark(); |
|
|
|
|
push_object_type(0, Pike_compiler->new_program->id); |
n->type = pop_unfinished_type(); |
if (n->parent) { |
n->parent->node_info |= OPT_TYPE_NOT_FIXED; |
} |
return NULL; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_throw(INT32 args) |
{ |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("throw", 1); |
assign_svalue(&throw_value,Pike_sp-args); |
pop_n_elems(args); |
throw_severity=0; |
pike_throw(); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_exit(INT32 args) |
{ |
static int in_exit=0; |
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, ("exit: permission denied.\n")); |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("exit", 1); |
|
if(Pike_sp[-args].type != T_INT) |
SIMPLE_BAD_ARG_ERROR("exit", 1, "int"); |
|
if(in_exit) Pike_error("exit already called!\n"); |
in_exit=1; |
|
assign_svalue(&throw_value, Pike_sp-args); |
throw_severity=THROW_EXIT; |
pike_throw(); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
void f__exit(INT32 args) |
{ |
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, ("_exit: permission denied.\n")); |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("_exit", 1); |
|
if(Pike_sp[-args].type != T_INT) |
SIMPLE_BAD_ARG_ERROR("_exit", 1, "int"); |
|
exit(Pike_sp[-args].u.integer); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_time(INT32 args) |
{ |
if(!args) |
{ |
GETTIMEOFDAY(¤t_time); |
}else{ |
if(Pike_sp[-args].type == T_INT && Pike_sp[-args].u.integer > 1) |
{ |
struct timeval tmp; |
GETTIMEOFDAY(¤t_time); |
tmp.tv_sec=Pike_sp[-args].u.integer; |
tmp.tv_usec=0; |
my_subtract_timeval(&tmp,¤t_time); |
pop_n_elems(args); |
push_float( - (FLOAT_TYPE)tmp.tv_sec-((FLOAT_TYPE)tmp.tv_usec)/1000000 ); |
return; |
} |
} |
pop_n_elems(args); |
push_int(current_time.tv_sec); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_crypt(INT32 args) |
{ |
char salt[2]; |
char *ret, *saltp; |
char *choise = |
"cbhisjKlm4k65p7qrJfLMNQOPxwzyAaBDFgnoWXYCZ0123tvdHueEGISRTUV89./"; |
|
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("crypt", 1); |
|
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("crypt", 1, "string"); |
|
|
if(args>1) |
{ |
if(Pike_sp[1-args].type != T_STRING || |
Pike_sp[1-args].u.string->len < 2) |
{ |
pop_n_elems(args); |
push_int(0); |
return; |
} |
|
saltp=Pike_sp[1-args].u.string->str; |
} else { |
unsigned int foo; |
foo=my_rand(); |
salt[0] = choise[foo % (size_t) strlen(choise)]; |
foo=my_rand(); |
salt[1] = choise[foo % (size_t) strlen(choise)]; |
saltp=salt; |
} |
#ifdef HAVE_CRYPT |
ret = (char *)crypt(Pike_sp[-args].u.string->str, saltp); |
#else |
#ifdef HAVE__CRYPT |
ret = (char *)_crypt(Pike_sp[-args].u.string->str, saltp); |
#else |
ret = Pike_sp[-args].u.string->str; |
#endif |
#endif |
if(args < 2) |
{ |
pop_n_elems(args); |
push_string(make_shared_string(ret)); |
}else{ |
int i; |
i=!strcmp(ret,Pike_sp[1-args].u.string->str); |
pop_n_elems(args); |
push_int(i); |
} |
} |
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_destruct(INT32 args) |
{ |
struct object *o; |
if(args) |
{ |
if(Pike_sp[-args].type != T_OBJECT) |
SIMPLE_BAD_ARG_ERROR("destruct", 1, "object"); |
|
o=Pike_sp[-args].u.object; |
}else{ |
if(!Pike_fp) |
PIKE_ERROR("destruct", "Destruct called without argument from callback function.\n", Pike_sp, args); |
|
o=Pike_fp->current_object; |
} |
if (o->prog && o->prog->flags & PROGRAM_NO_EXPLICIT_DESTRUCT) |
PIKE_ERROR("destruct", "Object can't be destructed explicitly.\n", Pike_sp, args); |
#ifdef PIKE_SECURITY |
if(!CHECK_DATA_SECURITY(o, SECURITY_BIT_DESTRUCT)) |
Pike_error("Destruct permission denied.\n"); |
#endif |
destruct(o); |
pop_n_elems(args); |
destruct_objects_to_destruct(); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_indices(INT32 args) |
{ |
ptrdiff_t size; |
struct array *a = NULL; |
|
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("indices", 1); |
|
switch(Pike_sp[-args].type) |
{ |
case T_STRING: |
size=Pike_sp[-args].u.string->len; |
goto qjump; |
|
case T_ARRAY: |
size=Pike_sp[-args].u.array->size; |
|
qjump: |
a=allocate_array_no_init(size,0); |
while(--size>=0) |
{ |
ITEM(a)[size].type=T_INT; |
ITEM(a)[size].subtype=NUMBER_NUMBER; |
ITEM(a)[size].u.integer = DO_NOT_WARN((INT_TYPE)size); |
} |
break; |
|
case T_MAPPING: |
a=mapping_indices(Pike_sp[-args].u.mapping); |
break; |
|
case T_MULTISET: |
a=copy_array(Pike_sp[-args].u.multiset->ind); |
break; |
|
case T_OBJECT: |
a=object_indices(Pike_sp[-args].u.object); |
break; |
|
case T_PROGRAM: |
a = program_indices(Pike_sp[-args].u.program); |
break; |
|
case T_FUNCTION: |
{ |
struct program *p = program_from_svalue(Pike_sp-args); |
if (p) { |
a = program_indices(p); |
break; |
} |
} |
|
|
default: |
SIMPLE_BAD_ARG_ERROR("indices", 1, |
"string|array|mapping|" |
"multiset|object|program|function"); |
return; |
} |
pop_n_elems(args); |
push_array(a); |
} |
|
|
#define FIX_OVERLOADED_TYPE(n, lf, X) fix_overloaded_type(n,lf,X,CONSTANT_STRLEN(X)) |
|
* and should probably be in pike_types.h instead. |
*/ |
static node *fix_overloaded_type(node *n, int lfun, const char *deftype, int deftypelen) |
{ |
node **first_arg; |
struct pike_type *t, *t2; |
first_arg=my_get_arg(&_CDR(n), 0); |
if(!first_arg) return 0; |
t=first_arg[0]->type; |
if(!t || match_types(t, object_type_string)) |
{ |
if(t && (t->str[0] == T_OBJECT)) |
{ |
struct program *p = id_to_program(extract_type_int(t->str+2)); |
if(p) |
{ |
int fun=FIND_LFUN(p, lfun); |
|
|
|
|
if(fun!=-1 && |
(t2 = check_call(function_type_string, ID_FROM_INT(p, fun)->type, |
0))) |
{ |
free_type(n->type); |
n->type = t2; |
return 0; |
} |
} |
} |
|
|
|
|
#if 1 |
if(deftype) |
{ |
t2 = make_shared_binary_string(deftype, deftypelen); |
t = n->type; |
n->type = or_pike_types(t,t2,0); |
free_type(t); |
free_type(t2); |
} |
#endif |
} |
|
return 0; |
} |
|
static node *fix_indices_type(node *n) |
{ |
return FIX_OVERLOADED_TYPE(n, LFUN__INDICES, tArray); |
} |
|
static node *fix_values_type(node *n) |
{ |
return FIX_OVERLOADED_TYPE(n, LFUN__VALUES, tArray); |
} |
|
static node *fix_aggregate_mapping_type(node *n) |
{ |
struct pike_type *types[2] = { NULL, NULL }; |
node *args = CDR(n); |
struct pike_type *new_type = NULL; |
|
#ifdef PIKE_DEBUG |
if (l_flag > 2) { |
fprintf(stderr, "Fixing type for aggregate_mapping():\n"); |
print_tree(n); |
|
fprintf(stderr, "Original type:"); |
simple_describe_type(n->type); |
} |
#endif /* PIKE_DEBUG */ |
|
if (args) { |
node *arg = args; |
int argno = 0; |
|
|
args->parent = 0; |
|
while(arg) { |
#ifdef PIKE_DEBUG |
if (l_flag > 4) { |
fprintf(stderr, "Searching for arg #%d...\n", argno); |
} |
#endif /* PIKE_DEBUG */ |
if (arg->token == F_ARG_LIST) { |
if (CAR(arg)) { |
CAR(arg)->parent = arg; |
arg = CAR(arg); |
continue; |
} |
if (CDR(arg)) { |
CDR(arg)->parent = arg; |
arg = CDR(arg); |
continue; |
} |
|
retrace: |
#ifdef PIKE_DEBUG |
if (l_flag > 4) { |
fprintf(stderr, "Retracing in search for arg %d...\n", argno); |
} |
#endif /* PIKE_DEBUG */ |
while (arg->parent && |
(!CDR(arg->parent) || (CDR(arg->parent) == arg))) { |
arg = arg->parent; |
} |
if (!arg->parent) { |
|
break; |
} |
arg = arg->parent; |
CDR(arg)->parent = arg; |
arg = CDR(arg); |
continue; |
} |
if (arg->token == F_PUSH_ARRAY) { |
|
|
|
MAKE_CONSTANT_SHARED_STRING(new_type, tMap(tMixed, tMixed)); |
goto set_type; |
} |
#ifdef PIKE_DEBUG |
if (l_flag > 4) { |
fprintf(stderr, "Found arg #%d:\n", argno); |
print_tree(arg); |
simple_describe_type(arg->type); |
} |
#endif /* PIKE_DEBUG */ |
do { |
if (types[argno]) { |
struct pike_type *t = or_pike_types(types[argno], arg->type, 0); |
free_type(types[argno]); |
types[argno] = t; |
#ifdef PIKE_DEBUG |
if (l_flag > 4) { |
fprintf(stderr, "Resulting type for arg #%d:\n", argno); |
simple_describe_type(types[argno]); |
} |
#endif /* PIKE_DEBUG */ |
} else { |
copy_type(types[argno], arg->type); |
} |
argno = !argno; |
|
|
|
} while (argno && arg->parent && CAR(arg->parent) == CDR(arg->parent)); |
goto retrace; |
} |
|
if (argno) { |
yyerror("Odd number of arguments to aggregate_mapping()."); |
goto done; |
} |
|
if (!types[0]) { |
|
MAKE_CONSTANT_SHARED_STRING(new_type, tMap(tZero, tZero)); |
goto set_type; |
} |
|
type_stack_mark(); |
push_finished_type(types[1]); |
push_finished_type(types[0]); |
push_type(T_MAPPING); |
new_type = pop_unfinished_type(); |
} else { |
|
MAKE_CONSTANT_SHARED_STRING(new_type, tMap(tZero, tZero)); |
goto set_type; |
} |
if (new_type) { |
set_type: |
free_type(n->type); |
n->type = new_type; |
|
#ifdef PIKE_DEBUG |
if (l_flag > 2) { |
fprintf(stderr, "Result type: "); |
simple_describe_type(new_type); |
} |
#endif /* PIKE_DEBUG */ |
|
if (n->parent) { |
n->parent->node_info |= OPT_TYPE_NOT_FIXED; |
} |
} |
done: |
if (args) { |
|
args->parent = n; |
} |
if (types[1]) { |
free_type(types[1]); |
} |
if (types[0]) { |
free_type(types[0]); |
} |
return NULL; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_values(INT32 args) |
{ |
ptrdiff_t size; |
struct array *a = NULL; |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("values", 1); |
|
switch(Pike_sp[-args].type) |
{ |
case T_STRING: |
size = Pike_sp[-args].u.string->len; |
a = allocate_array_no_init(size,0); |
while(--size >= 0) |
{ |
ITEM(a)[size].type = T_INT; |
ITEM(a)[size].subtype = NUMBER_NUMBER; |
ITEM(a)[size].u.integer = index_shared_string(Pike_sp[-args].u.string, size); |
} |
break; |
|
case T_ARRAY: |
a=copy_array(Pike_sp[-args].u.array); |
break; |
|
case T_MAPPING: |
a=mapping_values(Pike_sp[-args].u.mapping); |
break; |
|
case T_MULTISET: |
size=Pike_sp[-args].u.multiset->ind->size; |
a=allocate_array_no_init(size,0); |
while(--size>=0) |
{ |
ITEM(a)[size].type=T_INT; |
ITEM(a)[size].subtype=NUMBER_NUMBER; |
ITEM(a)[size].u.integer=1; |
} |
break; |
|
case T_OBJECT: |
a=object_values(Pike_sp[-args].u.object); |
break; |
|
case T_PROGRAM: |
a = program_values(Pike_sp[-args].u.program); |
break; |
|
case T_FUNCTION: |
{ |
struct program *p = program_from_svalue(Pike_sp - args); |
if (p) { |
a = program_values(p); |
break; |
} |
} |
|
|
default: |
SIMPLE_BAD_ARG_ERROR("values", 1, |
"string|array|mapping|multiset|" |
"object|program|function"); |
return; |
} |
pop_n_elems(args); |
push_array(a); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_next_object(INT32 args) |
{ |
struct object *o; |
if(args < 1) |
{ |
o = first_object; |
}else{ |
if(Pike_sp[-args].type != T_OBJECT) |
SIMPLE_BAD_ARG_ERROR("next_object", 1, "object"); |
o = Pike_sp[-args].u.object->next; |
} |
while(o && !o->prog) o=o->next; |
pop_n_elems(args); |
if(!o) |
{ |
push_int(0); |
}else{ |
ref_push_object(o); |
} |
} |
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_object_program(INT32 args) |
{ |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("object_program", 1); |
|
if(Pike_sp[-args].type == T_OBJECT) |
{ |
struct object *o=Pike_sp[-args].u.object; |
struct program *p; |
if((p=o->prog)) |
{ |
if(o->parent && o->parent->prog) |
{ |
INT32 id=o->parent_identifier; |
o=o->parent; |
add_ref(o); |
pop_n_elems(args); |
push_object(o); |
Pike_sp[-1].subtype=id; |
Pike_sp[-1].type=T_FUNCTION; |
return; |
}else{ |
add_ref(p); |
pop_n_elems(args); |
push_program(p); |
return; |
} |
} |
} |
|
pop_n_elems(args); |
push_int(0); |
} |
|
node *fix_object_program_type(node *n) |
{ |
|
|
|
|
node *nn; |
struct pike_type *new_type = NULL; |
|
if (!n->type) { |
copy_type(n->type, program_type_string); |
} |
if (!(nn = CDR(n))) return NULL; |
if ((nn->token == F_ARG_LIST) && (!(nn = CAR(nn)))) return NULL; |
if (!nn->type) return NULL; |
|
|
new_type = object_type_to_program_type(nn->type); |
if (new_type) { |
free_type(n->type); |
n->type = new_type; |
} |
return NULL; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_reverse(INT32 args) |
{ |
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("reverse", 1); |
|
switch(Pike_sp[-args].type) |
{ |
case T_STRING: |
{ |
INT32 e; |
struct pike_string *s; |
s=begin_wide_shared_string(Pike_sp[-args].u.string->len, |
Pike_sp[-args].u.string->size_shift); |
switch(Pike_sp[-args].u.string->size_shift) |
{ |
case 0: |
for(e=0;e<Pike_sp[-args].u.string->len;e++) |
STR0(s)[e]=STR0(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; |
break; |
|
case 1: |
for(e=0;e<Pike_sp[-args].u.string->len;e++) |
STR1(s)[e]=STR1(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; |
break; |
|
case 2: |
for(e=0;e<Pike_sp[-args].u.string->len;e++) |
STR2(s)[e]=STR2(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; |
break; |
} |
s=low_end_shared_string(s); |
pop_n_elems(args); |
push_string(s); |
break; |
} |
|
case T_INT: |
{ |
INT32 e; |
e=Pike_sp[-args].u.integer; |
e=((e & 0x55555555UL)<<1) + ((e & 0xaaaaaaaaUL)>>1); |
e=((e & 0x33333333UL)<<2) + ((e & 0xccccccccUL)>>2); |
e=((e & 0x0f0f0f0fUL)<<4) + ((e & 0xf0f0f0f0UL)>>4); |
e=((e & 0x00ff00ffUL)<<8) + ((e & 0xff00ff00UL)>>8); |
e=((e & 0x0000ffffUL)<<16)+ ((e & 0xffff0000UL)>>16); |
Pike_sp[-args].u.integer=e; |
pop_n_elems(args-1); |
break; |
} |
|
case T_ARRAY: |
{ |
struct array *a; |
a=reverse_array(Pike_sp[-args].u.array); |
pop_n_elems(args); |
push_array(a); |
break; |
} |
|
default: |
SIMPLE_BAD_ARG_ERROR("reverse", 1, "string|int|array"); |
} |
} |
|
struct tupel |
{ |
int prefix; |
struct pike_string *ind; |
struct pike_string *val; |
}; |
|
static int replace_sortfun(struct tupel *a,struct tupel *b) |
{ |
return DO_NOT_WARN((int)my_quick_strcmp(a->ind, b->ind)); |
} |
|
|
static int find_longest_prefix(char *str, |
ptrdiff_t len, |
int size_shift, |
struct tupel *v, |
INT32 a, |
INT32 b) |
{ |
INT32 c,match=-1; |
ptrdiff_t tmp; |
|
while(a<b) |
{ |
c=(a+b)/2; |
|
tmp=generic_quick_binary_strcmp(v[c].ind->str, |
v[c].ind->len, |
v[c].ind->size_shift, |
str, |
MINIMUM(len,v[c].ind->len), |
size_shift); |
if(tmp<0) |
{ |
INT32 match2=find_longest_prefix(str, |
len, |
size_shift, |
v, |
c+1, |
b); |
if(match2!=-1) return match2; |
|
while(1) |
{ |
if(v[c].prefix==-2) |
{ |
v[c].prefix=find_longest_prefix(v[c].ind->str, |
v[c].ind->len, |
v[c].ind->size_shift, |
v, |
0 , |
c); |
} |
c=v[c].prefix; |
if(c<a || c<match) return match; |
|
if(!generic_quick_binary_strcmp(v[c].ind->str, |
v[c].ind->len, |
v[c].ind->size_shift, |
str, |
MINIMUM(len,v[c].ind->len), |
size_shift)) |
return c; |
} |
} |
else if(tmp>0) |
{ |
b=c; |
} |
else |
{ |
a=c+1; |
match=c; |
} |
} |
return match; |
} |
|
|
static struct pike_string * replace_many(struct pike_string *str, |
struct array *from, |
struct array *to) |
{ |
INT32 e,num; |
ptrdiff_t s, length; |
struct string_builder ret; |
|
struct tupel *v; |
|
int set_start[256]; |
int set_end[256]; |
|
if(from->size != to->size) |
Pike_error("Replace must have equal-sized from and to arrays.\n"); |
|
if(!from->size) |
{ |
reference_shared_string(str); |
return str; |
} |
|
v=(struct tupel *)xalloc(sizeof(struct tupel)*from->size); |
|
for(num=e=0;e<from->size;e++) |
{ |
if(ITEM(from)[e].type != T_STRING) |
{ |
free((char *)v); |
Pike_error("Replace: from array is not array(string)\n"); |
} |
|
if(ITEM(to)[e].type != T_STRING) |
{ |
free((char *)v); |
Pike_error("Replace: to array is not array(string)\n"); |
} |
|
if(ITEM(from)[e].u.string->size_shift > str->size_shift) |
continue; |
|
v[num].ind=ITEM(from)[e].u.string; |
v[num].val=ITEM(to)[e].u.string; |
v[num].prefix=-2; |
num++; |
} |
|
fsort((char *)v,num,sizeof(struct tupel),(fsortfun)replace_sortfun); |
|
for(e=0;e<(INT32)NELEM(set_end);e++) |
set_end[e]=set_start[e]=0; |
|
for(e=0;e<num;e++) |
{ |
INT32 x; |
x=index_shared_string(v[num-1-e].ind,0); |
if(x<(INT32)NELEM(set_start)) set_start[x]=num-e-1; |
x=index_shared_string(v[e].ind,0); |
if(x<(INT32)NELEM(set_end)) set_end[x]=e+1; |
} |
|
init_string_builder(&ret,str->size_shift); |
|
length=str->len; |
|
for(s=0;length > 0;) |
{ |
INT32 a,b; |
ptrdiff_t ch; |
|
ch=index_shared_string(str,s); |
if(ch<(ptrdiff_t)NELEM(set_end)) b=set_end[ch]; else b=num; |
|
if(b) |
{ |
if(ch<(ptrdiff_t)NELEM(set_start)) a=set_start[ch]; else a=0; |
|
a=find_longest_prefix(str->str+(s << str->size_shift), |
length, |
str->size_shift, |
v, a, b); |
|
if(a!=-1) |
{ |
ch = v[a].ind->len; |
if(!ch) ch=1; |
s+=ch; |
length-=ch; |
string_builder_shared_strcat(&ret,v[a].val); |
continue; |
} |
} |
string_builder_putchar(&ret, |
DO_NOT_WARN((INT32)ch)); |
s++; |
length--; |
} |
|
free((char *)v); |
return finish_string_builder(&ret); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_replace(INT32 args) |
{ |
if(args < 3) |
{ |
if (args==2 && |
Pike_sp[1-args].type==T_MAPPING) |
{ |
stack_dup(); |
f_indices(1); |
stack_swap(); |
f_values(1); |
args++; |
} |
else |
SIMPLE_TOO_FEW_ARGS_ERROR("replace", 3); |
} |
|
switch(Pike_sp[-args].type) |
{ |
case T_ARRAY: |
{ |
array_replace(Pike_sp[-args].u.array,Pike_sp+1-args,Pike_sp+2-args); |
pop_n_elems(args-1); |
break; |
} |
|
case T_MAPPING: |
{ |
mapping_replace(Pike_sp[-args].u.mapping,Pike_sp+1-args,Pike_sp+2-args); |
pop_n_elems(args-1); |
break; |
} |
|
case T_STRING: |
{ |
struct pike_string *s; |
switch(Pike_sp[1-args].type) |
{ |
default: |
SIMPLE_BAD_ARG_ERROR("replace", 2, "string|array"); |
|
case T_STRING: |
if(Pike_sp[2-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("replace", 3, "string"); |
|
s=string_replace(Pike_sp[-args].u.string, |
Pike_sp[1-args].u.string, |
Pike_sp[2-args].u.string); |
break; |
|
case T_ARRAY: |
if(Pike_sp[2-args].type != T_ARRAY) |
SIMPLE_BAD_ARG_ERROR("replace", 3, "array"); |
|
s=replace_many(Pike_sp[-args].u.string, |
Pike_sp[1-args].u.array, |
Pike_sp[2-args].u.array); |
|
} |
pop_n_elems(args); |
push_string(s); |
break; |
} |
|
default: |
SIMPLE_BAD_ARG_ERROR("replace", 1, "array|mapping|string"); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_compile(INT32 args) |
{ |
struct program *p; |
struct object *o; |
int major=-1; |
int minor=-1; |
|
|
check_all_args("compile",args, |
BIT_STRING, |
BIT_VOID | BIT_INT | BIT_OBJECT, |
BIT_VOID | BIT_INT, |
BIT_VOID | BIT_INT, |
0); |
|
o=0; |
if (args > 1) |
if(Pike_sp[1-args].type == T_OBJECT) |
o=Pike_sp[1-args].u.object; |
|
if(args == 3) |
SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); |
|
if(args > 3) |
{ |
major=sp[2-args].u.integer; |
minor=sp[3-args].u.integer; |
} |
|
|
p = compile(Pike_sp[-args].u.string, o, major, minor); |
|
#ifdef PIKE_DEBUG |
if(!(p->flags & PROGRAM_FINISHED)) |
fatal("Got unfinished program from internal compile().\n"); |
#endif |
pop_n_elems(args); |
push_program(p); |
} |
|
|
|
|
|
|
|
|
|
|
|
#define SETFLAG(FLAGS,FLAG,ONOFF) \ |
FLAGS = (FLAGS & ~FLAG) | ( ONOFF ? FLAG : 0 ) |
void f_set_weak_flag(INT32 args) |
{ |
struct svalue *s; |
INT_TYPE ret; |
|
get_all_args("set_weak_flag",args,"%*%i",&s,&ret); |
|
switch(s->type) |
{ |
case T_ARRAY: |
SETFLAG(s->u.array->flags,ARRAY_WEAK_FLAG,ret); |
break; |
case T_MAPPING: { |
int flags = mapping_get_flags(s->u.mapping); |
SETFLAG(flags,MAPPING_FLAG_WEAK,ret); |
mapping_set_flags(s->u.mapping, flags); |
break; |
} |
case T_MULTISET: |
SETFLAG(s->u.multiset->ind->flags,(ARRAY_WEAK_FLAG|ARRAY_WEAK_SHRINK),ret); |
break; |
default: |
SIMPLE_BAD_ARG_ERROR("set_weak_flag",1,"array|mapping|multiset"); |
} |
pop_n_elems(args-1); |
} |
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_objectp(INT32 args) |
{ |
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("objectp", 1); |
if(Pike_sp[-args].type != T_OBJECT || !Pike_sp[-args].u.object->prog |
#ifdef AUTO_BIGNUM |
|| is_bignum_object(Pike_sp[-args].u.object) |
#endif |
) |
{ |
pop_n_elems(args); |
push_int(0); |
}else{ |
pop_n_elems(args); |
push_int(1); |
} |
} |
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_functionp(INT32 args) |
{ |
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("functionp", 1); |
if(Pike_sp[-args].type != T_FUNCTION || |
(Pike_sp[-args].subtype != FUNCTION_BUILTIN && !Pike_sp[-args].u.object->prog)) |
{ |
pop_n_elems(args); |
push_int(0); |
}else{ |
pop_n_elems(args); |
push_int(1); |
} |
} |
|
#ifndef HAVE_AND_USE_POLL |
#undef HAVE_POLL |
#endif |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_sleep(INT32 args) |
{ |
#define POLL_SLEEP_LIMIT 0.02 |
|
#ifdef HAVE_GETHRTIME |
hrtime_t t0,tv; |
#else |
struct timeval t0,tv; |
#endif |
|
double delay=0.0; |
double target; |
int do_microsleep; |
|
#ifdef HAVE_GETHRTIME |
t0=tv=gethrtime(); |
#define GET_TIME_ELAPSED tv=gethrtime() |
#define TIME_ELAPSED (tv-t0)*1e-9 |
#else |
GETTIMEOFDAY(&t0); |
tv=t0; |
#define GET_TIME_ELAPSED GETTIMEOFDAY(&tv) |
#define TIME_ELAPSED ((tv.tv_sec-t0.tv_sec) + (tv.tv_usec-t0.tv_usec)*1e-6) |
#endif |
|
#define FIX_LEFT() \ |
GET_TIME_ELAPSED; \ |
left = delay - TIME_ELAPSED; \ |
if (do_microsleep) left-=POLL_SLEEP_LIMIT; |
|
switch(Pike_sp[-args].type) |
{ |
case T_INT: |
delay=(double)Pike_sp[-args].u.integer; |
break; |
|
case T_FLOAT: |
delay=(double)Pike_sp[-args].u.float_number; |
break; |
} |
|
|
if(delay == 0.0) |
{ |
check_threads_etc(); |
pop_n_elems(args); |
return; |
} |
|
do_microsleep=delay<10; |
|
pop_n_elems(args); |
|
|
if (delay>POLL_SLEEP_LIMIT) |
{ |
while(1) |
{ |
double left; |
|
THREADS_ALLOW(); |
do { |
FIX_LEFT(); |
if(left<=0.0) break; |
|
#ifdef __NT__ |
Sleep(DO_NOT_WARN((int)(left*1000))); |
#elif defined(HAVE_POLL) |
poll(NULL,0,(int)(left*1000)); |
#else |
{ |
struct timeval t3; |
t3.tv_sec=left; |
t3.tv_usec=(int)((left - (int)left)*1e6); |
select(0,0,0,0,&t3); |
} |
#endif |
} while(0); |
THREADS_DISALLOW(); |
|
FIX_LEFT(); |
|
if(left<=0.0) |
{ |
break; |
}else{ |
check_signals(0,0,0); |
} |
} |
} |
|
if (do_microsleep) |
while (delay>TIME_ELAPSED) |
GET_TIME_ELAPSED; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_gc(INT32 args) |
{ |
INT32 tmp; |
pop_n_elems(args); |
push_int(do_gc()); |
} |
|
#ifdef TYPEP |
#undef TYPEP |
#endif |
|
#ifdef AUTO_BIGNUM |
|
* but it can wait a little. /Hubbe |
*/ |
|
#define TYPEP(ID,NAME,TYPE,TYPE_NAME) \ |
PMOD_EXPORT void ID(INT32 args) \ |
{ \ |
int t; \ |
if(args<1) \ |
SIMPLE_TOO_FEW_ARGS_ERROR(NAME, 1); \ |
if(Pike_sp[-args].type == T_OBJECT && Pike_sp[-args].u.object->prog) \ |
{ \ |
int fun=FIND_LFUN(Pike_sp[-args].u.object->prog,LFUN__IS_TYPE); \ |
if(fun != -1) \ |
{ \ |
push_constant_text(TYPE_NAME); \ |
apply_low(Pike_sp[-args-1].u.object,fun,1); \ |
stack_unlink(args); \ |
return; \ |
} \ |
} \ |
t=Pike_sp[-args].type == TYPE; \ |
pop_n_elems(args); \ |
push_int(t); \ |
} |
#else |
#define TYPEP(ID,NAME,TYPE) \ |
void ID(INT32 args) \ |
{ \ |
int t; \ |
if(args<1) SIMPLE_TOO_FEW_ARGS_ERROR(NAME, 1); \ |
t=Pike_sp[-args].type == TYPE; \ |
pop_n_elems(args); \ |
push_int(t); \ |
} |
#endif /* AUTO_BIGNUM */ |
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_programp(INT32 args) |
{ |
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("programp", 1); |
switch(Pike_sp[-args].type) |
{ |
case T_PROGRAM: |
pop_n_elems(args); |
push_int(1); |
return; |
|
case T_FUNCTION: |
if(program_from_function(Pike_sp-args)) |
{ |
pop_n_elems(args); |
push_int(1); |
return; |
} |
|
default: |
pop_n_elems(args); |
push_int(0); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef AUTO_BIGNUM |
TYPEP(f_intp, "intp", T_INT, "int") |
TYPEP(f_mappingp, "mappingp", T_MAPPING, "mapping") |
TYPEP(f_arrayp, "arrayp", T_ARRAY, "array") |
TYPEP(f_multisetp, "multisetp", T_MULTISET, "multiset") |
TYPEP(f_stringp, "stringp", T_STRING, "string") |
TYPEP(f_floatp, "floatp", T_FLOAT, "float") |
#else |
TYPEP(f_intp, "intp", T_INT) |
TYPEP(f_mappingp, "mappingp", T_MAPPING) |
TYPEP(f_arrayp, "arrayp", T_ARRAY) |
TYPEP(f_multisetp, "multisetp", T_MULTISET) |
TYPEP(f_stringp, "stringp", T_STRING) |
TYPEP(f_floatp, "floatp", T_FLOAT) |
#endif /* AUTO_BIGNUM */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_sort(INT32 args) |
{ |
INT32 e,*order; |
|
if(args < 1) |
SIMPLE_TOO_FEW_ARGS_ERROR("sort", 1); |
|
for(e=0;e<args;e++) |
{ |
if(Pike_sp[e-args].type != T_ARRAY) |
SIMPLE_BAD_ARG_ERROR("sort", e+1, "array"); |
|
if(Pike_sp[e-args].u.array->size != Pike_sp[-args].u.array->size) |
bad_arg_error("sort", Pike_sp-args, args, e+1, "array", Pike_sp+e-args, |
"Argument %d has wrong size.\n", (e+1)); |
} |
|
if(args > 1) |
{ |
order=get_alpha_order(Pike_sp[-args].u.array); |
for(e=0;e<args;e++) order_array(Pike_sp[e-args].u.array,order); |
free((char *)order); |
pop_n_elems(args-1); |
} else { |
sort_array_destructively(Pike_sp[-args].u.array); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_rows(INT32 args) |
{ |
INT32 e; |
struct array *a,*tmp; |
struct svalue *val; |
|
get_all_args("rows", args, "%*%a", &val, &tmp); |
|
|
if(tmp->refs == 1) |
{ |
struct svalue sval; |
tmp->type_field = BIT_MIXED | BIT_UNFINISHED; |
for(e=0;e<tmp->size;e++) |
{ |
index_no_free(&sval, val, ITEM(tmp)+e); |
free_svalue(ITEM(tmp)+e); |
ITEM(tmp)[e]=sval; |
} |
stack_swap(); |
pop_stack(); |
return; |
} |
|
push_array(a=allocate_array(tmp->size)); |
|
for(e=0;e<a->size;e++) |
index_no_free(ITEM(a)+e, val, ITEM(tmp)+e); |
|
Pike_sp--; |
dmalloc_touch_svalue(Pike_sp); |
pop_n_elems(args); |
push_array(a); |
} |
|
|
#ifdef PIKE_DEBUG |
|
*! |
*! Perform sanity checks. |
*! |
*! This function goes through most of the internal Pike structures and |
*! generates a fatal error if one of them is found to be out of order. |
*! It is only used for debugging. |
*! |
*! @note |
*! This function is only available if the Pike runtime has been compiled |
*! with RTL debug. |
*/ |
PMOD_EXPORT void f__verify_internals(INT32 args) |
{ |
INT32 tmp=d_flag; |
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, |
("_verify_internals: permission denied.\n")); |
d_flag=0x7fffffff; |
do_debug(); |
d_flag=tmp; |
do_gc(); |
pop_n_elems(args); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f__debug(INT32 args) |
{ |
INT_TYPE d; |
|
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, |
("_debug: permission denied.\n")); |
|
get_all_args("_debug", args, "%i", &d); |
pop_n_elems(args); |
push_int(d_flag); |
d_flag = d; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f__optimizer_debug(INT32 args) |
{ |
INT_TYPE l; |
|
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, |
("_optimizer_debug: permission denied.\n")); |
|
get_all_args("_optimizer_debug", args, "%i", &l); |
pop_n_elems(args); |
push_int(l_flag); |
l_flag = l; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f__assembler_debug(INT32 args) |
{ |
INT_TYPE l; |
|
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, |
("_assembler_debug: permission denied.\n")); |
|
get_all_args("_optimizer_debug", args, "%i", &l); |
pop_n_elems(args); |
push_int(a_flag); |
a_flag = l; |
} |
|
|
#ifdef YYDEBUG |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f__compiler_trace(INT32 args) |
{ |
extern int yydebug; |
INT_TYPE yyd; |
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, |
("_compiler_trace: permission denied.\n")); |
get_all_args("_compiler_trace", args, "%i", &yyd); |
pop_n_elems(args); |
push_int(yydebug); |
yydebug = yyd; |
} |
|
#endif /* YYDEBUG */ |
#endif |
|
#if defined(HAVE_LOCALTIME) || defined(HAVE_GMTIME) |
static void encode_struct_tm(struct tm *tm) |
{ |
push_string(make_shared_string("sec")); |
push_int(tm->tm_sec); |
push_string(make_shared_string("min")); |
push_int(tm->tm_min); |
push_string(make_shared_string("hour")); |
push_int(tm->tm_hour); |
|
push_string(make_shared_string("mday")); |
push_int(tm->tm_mday); |
push_string(make_shared_string("mon")); |
push_int(tm->tm_mon); |
push_string(make_shared_string("year")); |
push_int(tm->tm_year); |
|
push_string(make_shared_string("wday")); |
push_int(tm->tm_wday); |
push_string(make_shared_string("yday")); |
push_int(tm->tm_yday); |
push_string(make_shared_string("isdst")); |
push_int(tm->tm_isdst); |
} |
#endif |
|
#ifdef HAVE_GMTIME |
|
*! |
*! Convert seconds since 1970 into components. |
*! |
*! This function works like @[localtime()] but the result is |
*! not adjusted for the local time zone. |
*! |
*! @seealso |
*! @[localtime()], @[time()], @[ctime()], @[mktime()] |
*/ |
PMOD_EXPORT void f_gmtime(INT32 args) |
{ |
struct tm *tm; |
INT_TYPE tt; |
time_t t; |
|
get_all_args("gmtime", args, "%i", &tt); |
|
t = tt; |
tm = gmtime(&t); |
pop_n_elems(args); |
encode_struct_tm(tm); |
|
push_string(make_shared_string("timezone")); |
push_int(0); |
f_aggregate_mapping(20); |
} |
#endif |
|
#ifdef HAVE_LOCALTIME |
|
*! |
*! Convert seconds since 1970 into components. |
*! |
*! @returns |
*! This function returns a mapping with the following components: |
*! @mapping |
*! @member int(0..60) "sec" |
*! Seconds over the minute. |
*! @member int(0..59) "min" |
*! Minutes over the hour. |
*! @member int(0..23) "hour" |
*! Hour of the day. |
*! @member int(1..31) "mday" |
*! Day of the month. |
*! @member int(0..11) "mon" |
*! Month of the year. |
*! @member int(0..) "year" |
*! Year since 1900. |
*! @member int(0..6) "wday" |
*! Day of week (0 = Sunday). |
*! @member int(0..365) "yday" |
*! Day of the year. |
*! @member int(0..1) "isdst" |
*! Is daylight savings time. |
*! @member int "timezone" |
*! Offset from UTC. |
*! @endmapping |
*! |
*! @note |
*! The field @tt{"timezone"@} may not be available on all platforms. |
*! |
*! @seealso |
*! @[Calendar], @[gmtime()], @[time()], @[ctime()], @[mktime()] |
*/ |
PMOD_EXPORT void f_localtime(INT32 args) |
{ |
struct tm *tm; |
INT_TYPE tt; |
time_t t; |
|
get_all_args("localtime", args, "%i", &tt); |
|
t = tt; |
tm = localtime(&t); |
pop_n_elems(args); |
encode_struct_tm(tm); |
|
#ifdef HAVE_EXTERNAL_TIMEZONE |
push_string(make_shared_string("timezone")); |
push_int(timezone); |
f_aggregate_mapping(20); |
#else |
#ifdef STRUCT_TM_HAS_GMTOFF |
push_string(make_shared_string("timezone")); |
push_int(tm->tm_gmtoff); |
f_aggregate_mapping(20); |
#else |
f_aggregate_mapping(18); |
#endif |
#endif |
} |
#endif |
|
#ifdef HAVE_MKTIME |
|
*! @decl int mktime(int sec, int min, int hour, int mday, int mon, int year, @ |
*! int isdst, int tz) |
*! |
*! This function converts information about date and time into an integer |
*! which contains the number of seconds since the beginning of 1970. |
*! |
*! You can either call this function with a mapping containing the |
*! following elements: |
*! @mapping |
*! @member int(0..60) "sec" |
*! Seconds over the minute. |
*! @member int(0..59) "min" |
*! Minutes over the hour. |
*! @member int(0..23) "hour" |
*! Hour of the day. |
*! @member int(1..31) "mday" |
*! Day of the month. |
*! @member int(0..11) "mon" |
*! Month of the year. |
*! @member int(0..) "year" |
*! Year since 1900. |
*! @member int(0..1) "isdst" |
*! Is daylight savings time. |
*! @member int(-12..12) "timezone" |
*! The timezone offset from UTC in hours. |
*! @endmapping |
*! |
*! Or you can just send them all on one line as the second syntax suggests. |
*! |
*! @seealso |
*! @[time()], @[ctime()], @[localtime()], @[gmtime()] |
*/ |
PMOD_EXPORT void f_mktime (INT32 args) |
{ |
INT_TYPE sec, min, hour, mday, mon, year, isdst; |
struct tm date; |
struct svalue s; |
struct svalue * r; |
int retval; |
if (args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("mktime", 1); |
|
if(args == 1) |
{ |
MEMSET(&date, 0, sizeof(date)); |
|
push_text("sec"); |
push_text("min"); |
push_text("hour"); |
push_text("mday"); |
push_text("mon"); |
push_text("year"); |
push_text("isdst"); |
push_text("timezone"); |
f_aggregate(8); |
f_rows(2); |
Pike_sp--; |
dmalloc_touch_svalue(Pike_sp); |
push_array_items(Pike_sp->u.array); |
|
args=8; |
} |
|
get_all_args("mktime",args, "%i%i%i%i%i%i", |
&sec, &min, &hour, &mday, &mon, &year); |
|
MEMSET(&date, 0, sizeof(date)); |
date.tm_sec=sec; |
date.tm_min=min; |
date.tm_hour=hour; |
date.tm_mday=mday; |
date.tm_mon=mon; |
date.tm_year=year; |
|
if ((args > 6) && (Pike_sp[6-args].subtype == NUMBER_NUMBER)) |
{ |
date.tm_isdst = Pike_sp[6-args].u.integer; |
} else { |
date.tm_isdst = -1; |
} |
|
#if STRUCT_TM_HAS_GMTOFF |
if((args > 7) && (Pike_sp[7-args].subtype == NUMBER_NUMBER)) |
{ |
date.tm_gmtoff=Pike_sp[7-args].u.intger; |
}else{ |
time_t tmp = 0; |
data.tm_gmtoff=localtime(&tmp).tm_gmtoff; |
} |
retval=mktime(&date); |
#else |
#ifdef HAVE_EXTERNAL_TIMEZONE |
if((args > 7) && (Pike_sp[7-args].subtype == NUMBER_NUMBER)) |
{ |
retval=mktime(&date) + Pike_sp[7-args].u.integer - timezone; |
}else{ |
retval=mktime(&date); |
} |
#else |
retval=mktime(&date); |
#endif |
#endif |
|
if (retval == -1) |
PIKE_ERROR("mktime", "Cannot convert.\n", Pike_sp, args); |
pop_n_elems(args); |
push_int(retval); |
} |
|
#endif |
|
|
static ptrdiff_t low_parse_format(p_wchar0 *s, ptrdiff_t slen) |
{ |
ptrdiff_t i; |
ptrdiff_t offset = 0; |
int num_percent_percent = 0; |
struct svalue *old_sp = Pike_sp; |
|
|