|
|
|
|
|
|
|
#include "global.h" |
RCSID("$Id: builtin_functions.c,v 1.493 2003/05/15 15:33:30 mast 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 "pike_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" |
#include "language.h" |
#include "peep.h" |
#include "docode.h" |
#include "lex.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) |
SIMPLE_TOO_FEW_ARGS_ERROR("equal", 2); |
|
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) Pike_fatal("Negative args to f_aggregate() (%d)\n",args); |
#endif |
|
a=aggregate_array(args); |
push_array(a); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void f_hash_7_4(INT32 args) |
{ |
size_t i = 0; |
struct pike_string *s = Pike_sp[-args].u.string; |
|
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash_7_4",1); |
|
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("hash_7_4", 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_7_4",2,"int"); |
|
if(!Pike_sp[1-args].u.integer) |
PIKE_ERROR("hash_7_4", "Modulo by zero.\n", Pike_sp, args); |
|
i%=(unsigned INT32)Pike_sp[1-args].u.integer; |
} |
pop_n_elems(args); |
push_int64(i); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void f_hash_7_0( INT32 args ) |
{ |
struct pike_string *s = Pike_sp[-args].u.string; |
unsigned int i; |
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash_7_0",1); |
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("hash_7_0", 1, "string"); |
|
if( s->size_shift ) |
{ |
f_hash_7_4( args ); |
return; |
} |
|
i = DO_NOT_WARN((unsigned int)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_7_0",2,"int"); |
|
if(!Pike_sp[1-args].u.integer) |
PIKE_ERROR("hash_7_0", "Modulo by zero.\n", Pike_sp, args); |
|
i%=(unsigned INT32)Pike_sp[1-args].u.integer; |
} |
pop_n_elems(args); |
push_int( i ); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_hash(INT32 args) |
{ |
size_t i = 0; |
struct pike_string *s; |
|
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash",1); |
|
if(Pike_sp[-args].type != T_STRING) |
SIMPLE_BAD_ARG_ERROR("hash", 1, "string"); |
|
s = Pike_sp[-args].u.string; |
switch(s->size_shift) { |
case 0: |
i = simple_hashmem(STR0(s), s->len, 100); |
break; |
case 1: |
i = simple_hashmem1(STR1(s), s->len, 100); |
break; |
case 2: |
i = simple_hashmem2(STR2(s), s->len, 100); |
break; |
default: |
Pike_fatal("hash(): Unsupported string shift: %d\n", s->size_shift); |
break; |
} |
|
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); |
|
if(Pike_sp[1-args].u.integer < 0) |
PIKE_ERROR("hash", "Negative modulo.\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 { |
INT32 low; |
INT32 mode; |
INT32 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[] = { |
#include "case_info.h" |
{ 0x7fffffff, CIM_NONE, 0x0000, }, |
}; |
|
static struct case_info *find_ci(INT32 c) |
{ |
static struct case_info *cache = NULL; |
struct case_info *ci = cache; |
int lo = 0; |
int hi = NELEM(case_info); |
|
if ((c < 0) || (c > 0xeffff)) { |
|
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(INT32 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 > 0xefffff)) { |
|
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 {\ |
INT32 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: Pike_fatal("lower_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_LOWER_CASE_SHIFT0(C) do {\ |
INT32 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: Pike_fatal("lower_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_UPPER_CASE(C) do {\ |
INT32 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: Pike_fatal("upper_case(): Unknown case_info mode: %d\n", ci->mode); \ |
} \ |
} \ |
} while(0) |
|
#define DO_UPPER_CASE_SHIFT0(C) do {\ |
INT32 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: Pike_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 { |
Pike_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 { |
Pike_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_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] = DO_NOT_WARN((char)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: |
{ |
struct pike_string *haystack = Pike_sp[-args].u.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(haystack->len < start) |
bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp-args, |
"Start must not be greater than the " |
"length of the string.\n"); |
|
if(Pike_sp[1-args].type == T_STRING) { |
|
if (Pike_sp[1-args].u.string->len) { |
start = string_search(haystack, |
Pike_sp[1-args].u.string, |
start); |
} |
} else if (Pike_sp[1-args].type == T_INT) { |
INT_TYPE val = Pike_sp[1-args].u.integer; |
|
switch(Pike_sp[-args].u.string->size_shift) { |
case 0: |
{ |
p_wchar0 *str = STR0(haystack); |
if (val >= 256) { |
start = -1; |
break; |
} |
while (start < haystack->len) { |
if (str[start] == val) break; |
start++; |
} |
} |
break; |
case 1: |
{ |
p_wchar1 *str = STR1(haystack); |
if (val >= 65536) { |
start = -1; |
break; |
} |
while (start < haystack->len) { |
if (str[start] == val) break; |
start++; |
} |
} |
break; |
case 2: |
{ |
p_wchar2 *str = STR2(haystack); |
while (start < haystack->len) { |
if (str[start] == (p_wchar2)val) break; |
start++; |
} |
} |
break; |
default: |
Pike_fatal("search(): Unsupported string shift: %d!\n", |
haystack->size_shift); |
break; |
} |
if (start >= haystack->len) { |
start = -1; |
} |
} else { |
SIMPLE_BAD_ARG_ERROR("search", 2, "string | int"); |
} |
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) |
SIMPLE_TOO_FEW_ARGS_ERROR("has_index", 2); |
if(args > 2) |
pop_n_elems(args-2); |
|
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) |
SIMPLE_TOO_FEW_ARGS_ERROR("has_value", 2); |
if(args > 2) |
pop_n_elems(args-2); |
|
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_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); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define NT_COMBINE_PATH |
#include "combine_path.h" |
|
#define UNIX_COMBINE_PATH |
#include "combine_path.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_OBJECT || Pike_sp[-args].type==T_FUNCTION) |
&& !Pike_sp[-args].u.object->prog) |
{ |
pop_n_elems(args); |
push_int(NUMBER_DESTRUCTED); |
} |
else if(Pike_sp[-args].type != T_INT) |
{ |
pop_n_elems(args); |
push_int(0); |
} |
else |
{ |
pop_n_elems(args-1); |
Pike_sp[-1].u.integer=Pike_sp[-1].subtype; |
Pike_sp[-1].subtype=NUMBER_NUMBER; |
} |
} |
|
static int generate_zero_type(node *n) |
{ |
if(count_args(CDR(n)) != 1) return 0; |
if(do_docode(CDR(n),DO_NOT_COPY) != 1) |
Pike_fatal("Count args was wrong in generate_zero_type().\n"); |
emit0(F_ZERO_TYPE); |
return 1; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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]) { |
Pike_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) { |
Pike_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, i, num_surrogates = 0; |
int swab=0; |
p_wchar1 surr1, surr2, surrmask, *str0; |
|
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"); |
} |
|
|
str0 = (p_wchar1 *)in->str; |
len = in->len; |
if (len && (str0[0] == 0xfeff)) { |
|
swab = 0; |
str0 ++; |
len -= 2; |
} else if (len && (str0[0] == 0xfffe)) { |
|
swab = 1; |
str0 ++; |
len -= 2; |
} else { |
|
#if (PIKE_BYTEORDER == 4321) |
swab = 0; |
#else |
swab = 1; |
#endif /* PIKE_BYTEORDER == 4321 */ |
} |
|
|
if (swab) { |
surr1 = 0xd8; |
surr2 = 0xdc; |
surrmask = 0xfc; |
} else { |
surr1 = 0xd800; |
surr2 = 0xdc00; |
surrmask = 0xfc00; |
} |
|
|
for (i = len; i >= 4; i -= 2, str0++) |
if ( (str0[0]&surrmask) == surr1 && |
(str0[1]&surrmask) == surr2 ) |
num_surrogates ++; |
|
|
str0++; |
|
len = len / 2 - num_surrogates; |
|
out = begin_wide_shared_string(len, (num_surrogates? 2 : 1)); |
|
if (!swab) { |
|
if (num_surrogates) { |
|
|
p_wchar2 *str2 = STR2(out); |
|
for (i = len; i--; --str0) |
|
if ((str0[-1]&surrmask) == surr2 && num_surrogates && |
(str0[-2]&surrmask) == surr1) { |
|
str2[i] = ((str0[-2]&0x3ff)<<10) + (str0[-1]&0x3ff) + 0x10000; |
|
--str0; |
--num_surrogates; |
|
} else |
|
str2[i] = str0[-1]; |
|
} else |
|
|
|
|
MEMCPY(out->str, (char *)(str0-len), len*2); |
} else { |
|
|
if (num_surrogates) { |
|
|
p_wchar2 *str2 = STR2(out); |
|
for (i = len; i--; --str0) { |
|
if ((str0[-1]&surrmask) == surr2 && num_surrogates && |
(str0[-2]&surrmask) == surr1) { |
|
#if (PIKE_BYTEORDER == 4321) |
str2[i] = ((((unsigned char *)str0)[-3]&3)<<18) + |
(((unsigned char *)str0)[-4]<<10) + |
((((unsigned char *)str0)[-1]&3)<<8) + |
((unsigned char *)str0)[-2] + |
0x10000; |
#else /* PIKE_BYTEORDER != 4321 */ |
str2[i] = ((((unsigned char *)str0)[-4]&3)<<18) + |
(((unsigned char *)str0)[-3]<<10) + |
((((unsigned char *)str0)[-2]&3)<<8) + |
((unsigned char *)str0)[-1] + |
0x10000; |
#endif /* PIKE_BYTEORDER == 4321 */ |
--str0; |
--num_surrogates; |
|
} else { |
#if (PIKE_BYTEORDER == 4321) |
str2[i] = (((unsigned char *)str0)[-1]<<8) + |
((unsigned char *)str0)[-2]; |
#else /* PIKE_BYTEORDER != 4321 */ |
str2[i] = (((unsigned char *)str0)[-2]<<8) + |
((unsigned char *)str0)[-1]; |
#endif /* PIKE_BYTEORDER == 4321 */ |
} |
} |
} else { |
|
|
p_wchar1 *str1 = STR1(out); |
|
for (i = len; i--; --str0) { |
#if (PIKE_BYTEORDER == 4321) |
str1[i] = (((unsigned char *)str0)[-1]<<8) + |
((unsigned char *)str0)[-2]; |
#else /* PIKE_BYTEORDER != 4321 */ |
str1[i] = (((unsigned char *)str0)[-2]<<8) + |
((unsigned char *)str0)[-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++] = DO_NOT_WARN((char)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) { |
Pike_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) { |
Pike_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; |
|
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(type_to_string(t)); |
free_type(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; |
struct svalue *init = Pike_sp - args + 1; |
push_array (a); |
for(e=0;e<a->size;e++) |
copy_svalues_recursively_no_free(a->item+e, init, 1, 0); |
a->type_field = 1 << init->type; |
stack_pop_n_elems_keep_top (args); |
} |
else { |
a->type_field = BIT_INT; |
pop_n_elems(args); |
push_array(a); |
} |
} |
|
|
|
|
|
|
|
|
|
|
void f_this_object(INT32 args) |
{ |
int level; |
if (args) { |
if (Pike_sp[-args].type != T_INT || Pike_sp[-args].u.integer < 0) |
SIMPLE_BAD_ARG_ERROR ("this_object", 1, "a non-negative integer"); |
level = Pike_sp[-args].u.integer; |
} |
else |
level = 0; |
|
pop_n_elems(args); |
if(Pike_fp) |
{ |
struct object *o = Pike_fp->current_object; |
for (; level > 0; level--) { |
struct program *p = o->prog; |
if (!p) |
Pike_error ("Cannot get the parent object of a destructed object.\n"); |
if (!(p->flags & PROGRAM_USES_PARENT)) |
|
Pike_error ("Object lacks parent reference.\n"); |
o = PARENT_INFO(o)->parent; |
} |
ref_push_object(o); |
}else{ |
|
push_int(0); |
} |
} |
|
static node *optimize_this_object(node *n) |
{ |
int id; |
|
if (CDR (n)) { |
struct program_state *state = Pike_compiler; |
if (CDR (n)->token != F_CONSTANT) { |
|
|
int i; |
for (i = 0; i < compilation_depth; i++, state = state->previous) |
state->new_program->flags |= PROGRAM_USES_PARENT | PROGRAM_NEEDS_PARENT; |
return NULL; |
} |
else { |
int level; |
#ifdef PIKE_DEBUG |
if (CDR (n)->u.sval.type != T_INT || CDR (n)->u.sval.u.integer < 0) |
Pike_fatal ("The type check for this_object() failed.\n"); |
#endif |
level = CDR (n)->u.sval.u.integer; |
if (level > compilation_depth) { |
my_yyerror ("There is no surrounding class %d levels out.", level); |
return NULL; |
} |
for (; level > 0; level--, state = state->previous) |
state->new_program->flags |= PROGRAM_USES_PARENT | PROGRAM_NEEDS_PARENT; |
id = state->new_program->id; |
} |
} |
else id = Pike_compiler->new_program->id; |
|
free_type(n->type); |
type_stack_mark(); |
|
|
|
|
push_object_type(0, id); |
n->type = pop_unfinished_type(); |
if (n->parent) { |
n->parent->node_info |= OPT_TYPE_NOT_FIXED; |
} |
return NULL; |
} |
|
static int generate_this_object(node *n) |
{ |
int level; |
|
if (CDR (n)) { |
struct program_state *state = Pike_compiler; |
if (CDR (n)->token != F_CONSTANT) |
|
return 0; |
else { |
#ifdef PIKE_DEBUG |
if (CDR (n)->u.sval.type != T_INT || CDR (n)->u.sval.u.integer < 0) |
Pike_fatal ("The type check for this_object() failed.\n"); |
#endif |
level = CDR (n)->u.sval.u.integer; |
#ifdef PIKE_DEBUG |
if (level > compilation_depth) |
Pike_fatal ("this_object level too high. " |
"Expected this to be caught by optimize_this_object.\n"); |
#endif |
} |
} |
else level = 0; |
|
emit1(F_THIS_OBJECT, level); |
return 1; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"); |
|
#ifdef PIKE_DEBUG |
{ |
|
extern void exit_lex(void); |
exit_lex(); |
} |
#endif |
|
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) { |
if ((Pike_sp[-args].type == T_INT) && |
(!Pike_sp[-args].u.integer)) { |
pop_n_elems(args); |
return; |
} |
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 |
debug_malloc_touch(o); |
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].u.integer = DO_NOT_WARN((INT_TYPE)size); |
} |
a->type_field = BIT_INT; |
break; |
|
case T_MAPPING: |
a=mapping_indices(Pike_sp[-args].u.mapping); |
break; |
|
case T_MULTISET: |
#ifdef PIKE_NEW_MULTISETS |
a = multiset_indices (Pike_sp[-args].u.multiset); |
#else |
a=copy_array(Pike_sp[-args].u.multiset->ind); |
#endif |
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)) |
{ |
|
while(t && t->type == PIKE_T_NAME) { |
t = t->cdr; |
} |
|
|
if(t && (t->type == T_OBJECT)) |
{ |
struct program *p = id_to_program(((char *)t->cdr)-(char *)0); |
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_pike_type(deftype); |
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_TYPE(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_pike_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_TYPE(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_TYPE(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].u.integer = index_shared_string(Pike_sp[-args].u.string, size); |
} |
a->type_field = BIT_INT; |
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: |
#ifdef PIKE_NEW_MULTISETS |
a = multiset_values (Pike_sp[-args].u.multiset); |
#else |
size=Pike_sp[-args].u.multiset->ind->size; |
a=allocate_array_no_init(size,0); |
while(--size>=0) |
{ |
|
ITEM(a)[size].u.integer=1; |
} |
a->type_field = BIT_INT; |
#endif |
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; |
|
CHECK_SECURITY_OR_ERROR(SECURITY_BIT_SECURITY, ("next_object: permission denied.\n")); |
|
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 = o->prog; |
|
#if 0 |
|
* function can't double as a program (program_from_svalue returns |
* NULL for it). */ |
if (p == pike_trampoline_program) { |
struct pike_trampoline *t = (struct pike_trampoline *) o->storage; |
if (t->frame && t->frame->current_object) { |
add_ref (o = t->frame->current_object); |
pop_n_elems (args); |
push_function (o, t->func); |
return; |
} |
} |
#endif |
|
if(p) |
{ |
if((p->flags & PROGRAM_USES_PARENT) && |
PARENT_INFO(o)->parent && |
PARENT_INFO(o)->parent->prog) |
{ |
INT32 id=PARENT_INFO(o)->parent_identifier; |
o=PARENT_INFO(o)->parent; |
add_ref(o); |
pop_n_elems(args); |
push_function(o, id); |
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_pike_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 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 int replace_sortfun(struct tupel *a,struct tupel *b) |
{ |
return DO_NOT_WARN((int)my_quick_strcmp(a->ind, b->ind)); |
} |
|
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 >= 0) && (x<(INT32)NELEM(set_start))) |
set_start[x]=num-e-1; |
x=index_shared_string(v[e].ind,0); |
if((x >= 0) && (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 >= 0) && (ch<(ptrdiff_t)NELEM(set_end))) |
b=set_end[ch]; |
else |
b=num; |
|
if(b) |
{ |
if((ch >= 0) && (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"); |
} |
} |
|
node *optimize_replace(node *n) |
{ |
node **arg0 = my_get_arg(&_CDR(n), 0); |
struct pike_type *array_zero; |
struct pike_type *mapping_zero; |
|
MAKE_CONSTANT_TYPE(array_zero, tArr(tZero)); |
MAKE_CONSTANT_TYPE(mapping_zero, tMap(tZero, tZero)); |
|
if (arg0 && |
(pike_types_le(array_zero, (*arg0)->type) || |
pike_types_le(mapping_zero, (*arg0)->type))) { |
|
|
|
|
n->node_info |= OPT_SIDE_EFFECT; |
n->tree_info |= OPT_SIDE_EFFECT; |
} else { |
|
|
|
|
node **arg1 = my_get_arg(&_CDR(n), 1); |
node **arg2 = my_get_arg(&_CDR(n), 2); |
|
if (arg1 && pike_types_le((*arg1)->type, array_type_string) && |
arg2 && pike_types_le((*arg2)->type, array_type_string)) { |
|
if (!is_const(*arg0) && is_const(*arg1) && is_const(*arg2)) { |
|
struct svalue *save_sp = Pike_sp; |
JMP_BUF tmp; |
if (SETJMP(tmp)) { |
yywarning("Optimizer failure in replace()."); |
pop_n_elems(Pike_sp - save_sp); |
free_svalue(&throw_value); |
throw_value.type = T_INT; |
} else { |
extern struct program *multi_string_replace_program; |
INT16 lfun; |
struct object *replace_obj; |
node *ret = NULL; |
INT32 args = eval_low(*arg1,1); |
args += eval_low(*arg2,1); |
|
replace_obj = clone_object(multi_string_replace_program, args); |
|
push_object(replace_obj); |
if (replace_obj->prog && |
((lfun = FIND_LFUN(replace_obj->prog, LFUN_CALL)) != -1)) { |
Pike_sp[-1].subtype = lfun; |
Pike_sp[-1].type = PIKE_T_FUNCTION; |
ADD_NODE_REF2(*arg0, |
ret = mkapplynode(mkconstantsvaluenode(Pike_sp-1), |
*arg0); |
); |
|
UNSETJMP(tmp); |
pop_n_elems(Pike_sp - save_sp); |
|
free_type(array_zero); |
free_type(mapping_zero); |
|
return ret; |
} |
} |
UNSETJMP(tmp); |
pop_n_elems(Pike_sp - save_sp); |
} |
} |
} |
|
free_type(array_zero); |
free_type(mapping_zero); |
|
return NULL; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_compile(INT32 args) |
{ |
struct program *p=0; |
struct object *o; |
struct object *placeholder=0; |
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, |
BIT_VOID | BIT_INT | BIT_PROGRAM, |
BIT_VOID | BIT_INT | BIT_OBJECT, |
0); |
|
check_c_stack(65536); |
|
o=0; |
switch(args) |
{ |
case 3: |
SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); |
default: |
if(Pike_sp[5-args].type == T_OBJECT) |
placeholder=Pike_sp[5-args].u.object; |
|
case 5: |
if(Pike_sp[4-args].type == T_PROGRAM) |
p=Pike_sp[4-args].u.program; |
|
case 4: |
major=Pike_sp[2-args].u.integer; |
minor=Pike_sp[3-args].u.integer; |
|
case 2: |
if(Pike_sp[1-args].type == T_OBJECT) |
o=Pike_sp[1-args].u.object; |
|
case 0: case 1: break; |
} |
|
p = compile(Pike_sp[-args].u.string, o, major, minor, p, placeholder); |
|
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; |
int flags; |
|
get_all_args("set_weak_flag",args,"%*%i",&s,&ret); |
|
if (ret == 1) ret = PIKE_WEAK_BOTH; |
|
switch(s->type) |
{ |
case T_ARRAY: |
flags = array_get_flags(s->u.array); |
SETFLAG(flags,ARRAY_WEAK_FLAG,ret & PIKE_WEAK_VALUES); |
s->u.array = array_set_flags(s->u.array, flags); |
break; |
case T_MAPPING: |
flags = mapping_get_flags(s->u.mapping); |
flags = (flags & ~PIKE_WEAK_BOTH) | (ret & PIKE_WEAK_BOTH); |
mapping_set_flags(s->u.mapping, flags); |
break; |
case T_MULTISET: |
#ifdef PIKE_NEW_MULTISETS |
flags = multiset_get_flags (s->u.multiset); |
flags = (flags & ~PIKE_WEAK_BOTH) | (ret & PIKE_WEAK_BOTH); |
multiset_set_flags (s->u.multiset, flags); |
#else |
flags = array_get_flags(s->u.multiset->ind); |
SETFLAG(flags,(ARRAY_WEAK_FLAG|ARRAY_WEAK_SHRINK), ret & PIKE_WEAK_INDICES); |
s->u.multiset->ind = array_set_flags(s->u.multiset->ind, flags); |
#endif |
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) |
{ |
int res = 0; |
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)) |
res=1; |
pop_n_elems(args); |
push_int(res); |
} |
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_callablep(INT32 args) |
{ |
int res = 0; |
if(args<1) |
SIMPLE_TOO_FEW_ARGS_ERROR("callablep", 1); |
|
switch( Pike_sp[-args].type ) |
{ |
case T_FUNCTION: |
if( Pike_sp[-args].subtype != FUNCTION_BUILTIN |
&& !Pike_sp[-args].u.object->prog) |
break; |
res = 1; |
break; |
case T_PROGRAM: |
res = 1; |
break; |
case T_OBJECT: |
if( Pike_sp[-args].u.object->prog && |
FIND_LFUN( Pike_sp[-args].u.object->prog, LFUN_CALL ) != -1 ) |
res = 1; |
} |
pop_n_elems(args); |
push_int(res); |
} |
#ifndef HAVE_AND_USE_POLL |
#undef HAVE_POLL |
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_sleep(INT32 args) |
{ |
#ifdef HAVE_GETHRTIME |
hrtime_t t0,tv; |
#else |
struct timeval t0,tv; |
#endif |
|
double delay=0.0; |
int do_abort_on_signal; |
|
#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; |
|
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; |
} |
|
if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp + 1-args)) |
{ |
do_abort_on_signal=1; |
}else{ |
do_abort_on_signal=0; |
} |
|
pop_n_elems(args); |
|
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(); |
|
if(do_abort_on_signal) return; |
|
FIX_LEFT(); |
|
if(left<=0.0) |
{ |
break; |
}else{ |
check_threads_etc(); |
} |
} |
} |
|
#undef FIX_LEFT |
#undef GET_TIME_ELAPSED |
#undef TIME_ELAPSED |
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_delay(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; |
int do_microsleep; |
int do_abort_on_signal; |
|
#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; |
} |
|
if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp + 1-args)) |
{ |
do_microsleep=0; |
do_abort_on_signal=1; |
}else{ |
do_microsleep=delay<10; |
do_abort_on_signal=0; |
} |
|
pop_n_elems(args); |
|
if (delay>POLL_SLEEP_LIMIT || !do_microsleep) |
{ |
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(); |
|
if(do_abort_on_signal) return; |
|
FIX_LEFT(); |
|
if(left<=0.0) |
{ |
break; |
}else{ |
check_threads_etc(); |
} |
} |
} |
|
if (do_microsleep) |
while (delay>TIME_ELAPSED) |
GET_TIME_ELAPSED; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_gc(INT32 args) |
{ |
pop_n_elems(args); |
push_int(do_gc(NULL, 1)); |
} |
|
#ifdef TYPEP |
#undef TYPEP |
#endif |
|
|
#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); \ |
} |
|
|
|
|
|
|
|
|
|
|
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); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|