|
|
|
|
|
|
|
#include "global.h" |
#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 "pike_security.h" |
#include "builtin_functions.h" |
#include "bignum.h" |
#include "peep.h" |
#include "docode.h" |
#include "lex.h" |
#include "pike_float.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; |
a=aggregate_array(args); |
push_array(a); |
} |
|
static node *optimize_f_aggregate(node *n) |
{ |
|
|
|
|
|
|
|
|
node *args = CDR(n); |
node *new_args = NULL; |
node *add_args = NULL; |
int count; |
if (!args) return NULL; |
args->parent = NULL; |
for (count = 0; args->token == F_ARG_LIST; args = CAR(args)) { |
if (CDR(args) && CDR(args)->token == F_PUSH_ARRAY) { |
|
count += 16; |
} else { |
count++; |
} |
if (!CAR(args)) break; |
CAR(args)->parent = args; |
} |
if (args->token == F_PUSH_ARRAY) { |
|
count += 16; |
} else if (args->token != F_ARG_LIST) { |
count++; |
} |
|
|
if (count <= 32) { |
CDR(n)->parent = n; |
return NULL; |
} |
|
|
|
|
|
|
|
count = 0; |
if (args->token != F_ARG_LIST) { |
if (args->token == F_PUSH_ARRAY) { |
|
add_args = copy_node(CAR(args)); |
} else { |
new_args = copy_node(args); |
count = 1; |
} |
args = args->parent; |
} |
|
for(; args; args = args->parent) { |
if (CDR(args)->token == F_PUSH_ARRAY) { |
if (count) { |
add_args = mknode(F_ARG_LIST, add_args, |
mkapplynode(copy_node(CAR(n)), new_args)); |
new_args = NULL; |
count = 0; |
} |
add_args = mknode(F_ARG_LIST, add_args, copy_node(CADR(args))); |
} else { |
new_args = mknode(F_ARG_LIST, new_args, copy_node(CDR(args))); |
count++; |
if (count > 31) { |
add_args = mknode(F_ARG_LIST, add_args, |
mkapplynode(copy_node(CAR(n)), new_args)); |
new_args = NULL; |
count = 0; |
} |
} |
} |
if (count) { |
add_args = mknode(F_ARG_LIST, add_args, |
mkapplynode(copy_node(CAR(n)), new_args)); |
new_args = NULL; |
count = 0; |
} |
CDR(n)->parent = n; |
return mkefuncallnode("`+", add_args); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 <= 0) |
PIKE_ERROR("hash", "Modulo < 1.\n", Pike_sp, args); |
|
i%=(unsigned INT32)Pike_sp[1-args].u.integer; |
} |
pop_n_elems(args); |
push_int64(i); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_hash_value(INT32 args) |
{ |
unsigned INT32 h; |
|
if(!args) |
SIMPLE_TOO_FEW_ARGS_ERROR("hash_value",1); |
|
h = hash_svalue (Pike_sp - args); |
pop_n_elems (args); |
push_int (h); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
INT16 mode; |
INT16 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; \ |
if(c<0xb5){if(c >= 'A' && c <= 'Z' ) C=c+0x20;}else {\ |
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; \ |
if(c<0xb5){if(c >= 'A' && c <= 'Z' ) C=c+0x20;}else {\ |
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; \ |
if(c<0xb5){if(c >= 'a' && c <= 'z' ) C=c-0x20;}else {\ |
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; \ |
if(c<0xb5){if(c >= 'a' && c <= 'z' ) C=c-0x20;}else {\ |
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; |
|
check_all_args("lower_case", args, BIT_STRING|BIT_INT, 0); |
|
if (Pike_sp[-args].type == T_INT) { |
|
DO_LOWER_CASE(Pike_sp[-args].u.integer); |
pop_n_elems(args-1); |
return; |
} |
|
orig = Pike_sp[-args].u.string; |
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; |
check_all_args("upper_case", args, BIT_STRING|BIT_INT, 0); |
|
if (Pike_sp[-args].type == T_INT) { |
|
DO_UPPER_CASE(Pike_sp[-args].u.integer); |
pop_n_elems(args-1); |
return; |
} |
|
orig = Pike_sp[-args].u.string; |
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 { |
|
|
|
int j = orig->len; |
struct pike_string *wret = begin_wide_shared_string(j, 1); |
p_wchar1 *wstr = STR1(wret); |
|
|
while(--j>i) |
wstr[j] = str[j]; |
|
|
i++; |
while(i--) |
switch( str[i] ) { |
case 0xff: wstr[i] = 0x178; break; |
case 0xb5: wstr[i] = 0x39c; break; |
default: |
DO_UPPER_CASE_SHIFT0(str[i]); |
wstr[i] = str[i]; |
break; |
} |
|
|
do_really_free_pike_string(ret); |
ret = wret; |
break; |
} |
} |
} 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)); |
} |
|
|
|
|
|
PMOD_EXPORT void f_random_string(INT32 args) |
{ |
struct pike_string *ret; |
INT_TYPE len, e; |
get_all_args("random_string",args,"%+",&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; |
|
case T_OBJECT: |
{ |
struct program *p; |
if ((p = (Pike_sp[-args].u.object->prog))) { |
struct object *o = Pike_sp[-args].u.object; |
int id_level = p->inherits[Pike_sp[-args].subtype].identifier_level; |
int id; |
int next, ind; |
p = p->inherits[Pike_sp[-args].subtype].prog; |
|
|
id = low_find_lfun(p, LFUN__SEARCH); |
|
if (id >= 0) { |
apply_low(o, id + id_level, args-1); |
stack_pop_n_elems_keep_top(1); |
return; |
} |
|
|
if (((id = find_identifier("value", p)) >= 0) && |
((next = find_identifier("next", p)) >= 0) && |
((ind = find_identifier("index", p)) >= 0)) { |
|
|
id += id_level; |
next += id_level; |
ind += id_level; |
|
|
if (args > 2) { |
int fun = find_identifier("set_index", p); |
if (fun < 0) |
Pike_error ("Cannot call unknown function \"%s\".\n", fun); |
apply_low(o, fun + id_level, args-2); |
pop_stack(); |
} |
|
|
|
while(1) { |
apply_low(o, id, 0); |
if (is_eq(Pike_sp-2, Pike_sp-1)) { |
|
apply_low(o, ind, 0); |
stack_pop_n_elems_keep_top(3); |
return; |
} |
apply_low(o, next, 0); |
if (UNSAFE_IS_ZERO(Pike_sp-1)) { |
|
pop_n_elems(4); |
|
|
|
push_undefined(); |
return; |
} |
pop_n_elems(2); |
} |
} |
} |
} |
|
default: |
SIMPLE_BAD_ARG_ERROR("search", 1, "string|array|mapping|object"); |
} |
} |
|
|
|
|
|
|
PMOD_EXPORT void f_has_prefix(INT32 args) |
{ |
struct pike_string *a, *b; |
|
if(args<2) |
SIMPLE_TOO_FEW_ARGS_ERROR("has_prefix", 2); |
if(Pike_sp[-args].type!=T_STRING) |
SIMPLE_ARG_TYPE_ERROR("has_prefix", 1, "string"); |
if(Pike_sp[1-args].type!=T_STRING) |
SIMPLE_ARG_TYPE_ERROR("has_prefix", 2, "string"); |
|
a = Pike_sp[-args].u.string; |
b = Pike_sp[1-args].u.string; |
|
|
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; |
|
if(args<2) |
SIMPLE_TOO_FEW_ARGS_ERROR("has_suffix", 2); |
if(Pike_sp[-args].type!=T_STRING) |
SIMPLE_ARG_TYPE_ERROR("has_suffix", 1, "string"); |
if(Pike_sp[1-args].type!=T_STRING) |
SIMPLE_ARG_TYPE_ERROR("has_suffix", 2, "string"); |
|
a = Pike_sp[-args].u.string; |
b = Pike_sp[1-args].u.string; |
|
|
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: |
case T_PROGRAM: |
|
|
|
|
|
|
|
|
|
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); |
break; |
|
default: |
SIMPLE_ARG_TYPE_ERROR ("has_index", 1, |
"string|array|mapping|multiset|object|program"); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_PROGRAM: |
case T_OBJECT: |
|
|
|
|
|
|
|
|
|
|
|
|
case T_MULTISET: |
|
|
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); |
break; |
|
default: |
SIMPLE_ARG_TYPE_ERROR ("has_value", 1, "string|array|mapping|object|program"); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_add_constant(INT32 args) |
{ |
ASSERT_SECURITY_ROOT("add_constant"); |
|
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" |
|
#define AMIGAOS_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); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_string_to_utf8(INT32 args) |
{ |
ptrdiff_t len; |
struct pike_string *in; |
struct pike_string *out; |
ptrdiff_t i,j; |
INT_TYPE extended = 0; |
|
get_all_args("string_to_utf8", args, "%W.%i", &in, &extended); |
|
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 (!extended && c > 0x10ffff) |
bad_arg_error ("string_to_utf8", Pike_sp - args, args, 1, |
NULL, Pike_sp - args, |
"Character 0x%08x at index %"PRINTPTRDIFFT"d is " |
"outside the allowed range.\n", |
c, i); |
if (c & ~0x1fffff) { |
|
len++; |
if (c & ~0x3ffffff) { |
|
len++; |
if (c & ~0x7fffffff) { |
|
len++; |
|
} |
} |
} |
} |
else if (!extended && c >= 0xd800 && c <= 0xdfff) |
bad_arg_error ("string_to_utf8", Pike_sp - args, args, 1, |
NULL, Pike_sp - args, |
"Character 0x%08x at index %"PRINTPTRDIFFT"d is " |
"in the surrogate range and therefore invalid.\n", |
c, i); |
} |
} |
} |
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: " |
"%"PRINTPTRDIFFT"d != %"PRINTPTRDIFFT"d\n", len, 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; |
ptrdiff_t len = 0; |
int shift = 0; |
ptrdiff_t i,j=0; |
INT_TYPE extended = 0; |
|
get_all_args("utf8_to_string", args, "%S.%i", &in, &extended); |
|
for(i=0; i < in->len; i++) { |
unsigned int c = STR0(in)[i]; |
len++; |
if (c & 0x80) { |
int cont = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((c & 0xc0) == 0x80) { |
bad_arg_error ("utf8_to_string", Pike_sp - args, args, 1, |
NULL, Pike_sp - args, |
"Invalid continuation character 0x%02x " |
"at index %"PRINTPTRDIFFT"d.\n", |
c, i); |
} |
|
#define GET_CONT_CHAR(in, i, c) do { \ |
i++; \ |
if (i >= in->len) \ |
bad_arg_error ("utf8_to_string", Pike_sp - args, args, 1, \ |
NULL, Pike_sp - args, \ |
"Truncated UTF-8 sequence at end of string.\n"); \ |
c = STR0 (in)[i]; \ |
if ((c & 0xc0) != 0x80) \ |
bad_arg_error ("utf8_to_string", Pike_sp - args, args, 1, \ |
NULL, Pike_sp - args, \ |
"Expected continuation character at index %d, " \ |
"got 0x%02x.\n", \ |
i, c); \ |
} while (0) |
|
#define UTF8_SEQ_ERROR(prefix, c, i, problem) do { \ |
bad_arg_error ("utf8_to_string", Pike_sp - args, args, 1, \ |
NULL, Pike_sp - args, \ |
"UTF-8 sequence beginning with %s0x%02x " \ |
"at index %"PRINTPTRDIFFT"d %s.\n", \ |
prefix, c, i, problem); \ |
} while (0) |
|
if ((c & 0xe0) == 0xc0) { |
|
if (!(c & 0x1e)) |
UTF8_SEQ_ERROR ("", c, i, "is a non-shortest form"); |
cont = 1; |
if (c & 0x1c) { |
if (shift < 1) { |
shift = 1; |
} |
} |
} |
|
else if ((c & 0xf0) == 0xe0) { |
|
if (c == 0xe0) { |
GET_CONT_CHAR (in, i, c); |
if (!(c & 0x20)) |
UTF8_SEQ_ERROR ("0xe0 ", c, i - 1, "is a non-shortest form"); |
cont = 1; |
} |
else if (!extended && c == 0xed) { |
GET_CONT_CHAR (in, i, c); |
if (c > 0x9f) |
UTF8_SEQ_ERROR ("0xed ", c, i - 1, "would decode to " |
"an invalid surrogate character"); |
cont = 1; |
} |
else |
cont = 2; |
if (shift < 1) { |
shift = 1; |
} |
} |
|
else { |
if ((c & 0xf8) == 0xf0) { |
|
if (c == 0xf0) { |
GET_CONT_CHAR (in, i, c); |
if (!(c & 0x30)) |
UTF8_SEQ_ERROR ("0xf0 ", c, i - 1, "is a non-shortest form"); |
cont = 2; |
} |
else if (!extended) { |
if (c > 0xf4) |
UTF8_SEQ_ERROR ("", c, i, "would decode to " |
"a character outside the valid UTF-8 range"); |
else if (c == 0xf4) { |
GET_CONT_CHAR (in, i, c); |
if (c > 0x8f) |
UTF8_SEQ_ERROR ("0xf4 ", c, i - 1, "would decode to " |
"a character outside the valid UTF-8 range"); |
cont = 2; |
} |
else |
cont = 3; |
} |
else |
cont = 3; |
} |
|
else if (c == 0xff) |
bad_arg_error ("utf8_to_string", Pike_sp - args, args, 1, |
NULL, Pike_sp - args, |
"Invalid character 0xff at index %"PRINTPTRDIFFT"d.\n", |
i); |
|
else if (!extended) |
UTF8_SEQ_ERROR ("", c, i, "would decode to " |
"a character outside the valid UTF-8 range"); |
|
else { |
if ((c & 0xfc) == 0xf8) { |
|
if (c == 0xf8) { |
GET_CONT_CHAR (in, i, c); |
if (!(c & 0x38)) |
UTF8_SEQ_ERROR ("0xf8 ", c, i - 1, "is a non-shortest form"); |
cont = 3; |
} |
else |
cont = 4; |
} else if ((c & 0xfe) == 0xfc) { |
|
if (c == 0xfc) { |
GET_CONT_CHAR (in, i, c); |
if (!(c & 0x3c)) |
UTF8_SEQ_ERROR ("0xfc ", c, i - 1, "is a non-shortest form"); |
cont = 4; |
} |
else |
cont = 5; |
} else if (c == 0xfe) { |
|
GET_CONT_CHAR (in, i, c); |
if (!(c & 0x3e)) |
UTF8_SEQ_ERROR ("0xfe ", c, i - 1, "is a non-shortest form"); |
else if (c & 0x3c) |
UTF8_SEQ_ERROR ("0xfe ", c, i - 1, "would decode to " |
"a too large character value"); |
cont = 5; |
} |
} |
|
if (shift < 2) |
shift = 2; |
} |
|
while(cont--) |
GET_CONT_CHAR (in, i, c); |
|
#undef GET_CONT_CHAR |
#undef UTF8_SEQ_ERROR |
} |
} |
if (len == in->len) { |
|
pop_n_elems(args-1); |
return; |
} |
|
out = begin_wide_shared_string(len, shift); |
|
switch (shift) { |
case 0: { |
p_wchar0 *out_str = STR0 (out); |
for(i=0; i < in->len;) { |
unsigned int c = STR0(in)[i++]; |
|
if (c & 0x80) { |
|
unsigned int c2 = STR0(in)[i++] & 0x3f; |
c &= 0x1f; |
c = (c << 6) | c2; |
} |
out_str[j++] = c; |
} |
break; |
} |
|
case 1: { |
p_wchar1 *out_str = STR1 (out); |
for(i=0; i < in->len;) { |
unsigned int c = STR0(in)[i++]; |
|
if (c & 0x80) { |
if ((c & 0xe0) == 0xc0) { |
|
unsigned int c2 = STR0(in)[i++] & 0x3f; |
c &= 0x1f; |
c = (c << 6) | c2; |
} else { |
|
unsigned int c2 = STR0(in)[i++] & 0x3f; |
unsigned int c3 = STR0(in)[i++] & 0x3f; |
c &= 0x0f; |
c = (c << 12) | (c2 << 6) | c3; |
} |
} |
out_str[j++] = c; |
} |
break; |
} |
|
case 2: { |
p_wchar2 *out_str = STR2 (out); |
for(i=0; i < in->len;) { |
unsigned int c = STR0(in)[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 int c2 = STR0(in)[i++] & 0x3f; |
c = (c << 6) | c2; |
} |
} |
out_str[j++] = c; |
} |
break; |
} |
} |
|
#ifdef PIKE_DEBUG |
if (j != len) { |
Pike_fatal("utf8_to_string(): Calculated and actual lengths differ: " |
"%"PRINTPTRDIFFT"d != %"PRINTPTRDIFFT"d\n", |
len, j); |
} |
#endif /* PIKE_DEBUG */ |
out = low_end_shared_string(out); |
#ifdef PIKE_DEBUG |
check_string (out); |
#endif |
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_get_active_compilation_handler(INT32 args) |
{ |
pop_n_elems(args); |
if (compat_handler) { |
ref_push_object(compat_handler); |
} else { |
push_int(0); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_get_active_error_handler(INT32 args) |
{ |
pop_n_elems(args); |
if (error_handler) { |
ref_push_object(error_handler); |
} else { |
push_int(0); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_allocate(INT32 args) |
{ |
INT_TYPE size; |
struct array *a; |
struct svalue *init; |
|
get_all_args("allocate", args, "%+.%*", &size, &init); |
if (size > MAX_INT32) |
SIMPLE_ARG_ERROR ("allocate", 1, "Integer too large to use as array size."); |
|
a=allocate_array(size); |
if(args>1) |
{ |
INT32 e; |
push_array (a); |
for(e=0;e<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, l; |
struct object *o; |
|
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); |
|
o = Pike_fp->current_object; |
for (l = 0; l < level; l++) { |
struct program *p = o->prog; |
if (!p) |
Pike_error ("Object %d level(s) up is destructed - cannot get the parent.\n", l); |
if (!(p->flags & PROGRAM_USES_PARENT)) |
|
Pike_error ("Object %d level(s) up lacks parent reference.\n", l); |
o = PARENT_INFO(o)->parent; |
} |
ref_push_object(o); |
} |
|
static node *optimize_this_object(node *n) |
{ |
int level = 0; |
|
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 i; |
#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; |
for (i = MINIMUM(level, compilation_depth); i; |
i--, state = state->previous) { |
state->new_program->flags |= |
PROGRAM_USES_PARENT | PROGRAM_NEEDS_PARENT; |
} |
} |
} |
|
|
|
|
|
|
if (!level) { |
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; |
} |
|
static int generate_this_object(node *n) |
{ |
int level; |
|
if (CDR (n)) { |
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; |
} |
} |
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; |
ASSERT_SECURITY_ROOT("exit"); |
|
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; |
|
if(args>1 && Pike_sp[1-args].type==T_STRING) { |
apply_svalue(simple_mapping_string_lookup(get_builtin_constants(), |
"werror"), args-1); |
pop_stack(); |
args=1; |
} |
|
assign_svalue(&throw_value, Pike_sp-args); |
throw_severity=THROW_EXIT; |
pike_throw(); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
void f__exit(INT32 args) |
{ |
int code; |
ASSERT_SECURITY_ROOT("_exit"); |
|
get_all_args("_exit", args, "%d", &code); |
|
#ifdef PIKE_DEBUG |
{ |
|
exit_opcodes(); |
} |
#endif |
|
exit(code); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PMOD_EXPORT void f_time(INT32 args) |
{ |
if(!args || (Pike_sp[-args].type == T_INT && Pike_sp[-args].u.integer == 0)) |
{ |
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, *pwd, *saltp; |
char *choise = |
"cbhisjKlm4k65p7qrJfLMNQOPxwzyAaBDFgnoWXYCZ0123tvdHueEGISRTUV89./"; |
|
get_all_args("crypt", args, "%s.%s", &pwd, &saltp); |
|
if(args>1) |
{ |
if( Pike_sp[1-args].u.string->len < 2 ) |
{ |
pop_n_elems(args); |
push_int(0); |
return; |
} |
} 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(pwd, saltp); |
#else |
#ifdef HAVE__CRYPT |
ret = (char *)_crypt(pwd, saltp); |
#else |
ret = pwd; |
#endif |
#endif |
if(args < 2) |
{ |
pop_n_elems(args); |
push_text(ret); |
}else{ |
int i; |
i=!strcmp(ret,saltp); |
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_object (o, DESTRUCT_EXPLICIT); |
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: |
a = multiset_indices (Pike_sp[-args].u.multiset); |
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(CDR_TO_INT(t)); |
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: |
a = multiset_values (Pike_sp[-args].u.multiset); |
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) { |
|