pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:1:
/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ #include "global.h"
-
#include <math.h>
+
#include "interpret.h" #include "svalue.h" #include "multiset.h" #include "mapping.h" #include "array.h" #include "stralloc.h" #include "pike_float.h" #include "opcodes.h" #include "operators.h" #include "pike_memory.h"
pike.git/src/operators.c:22:
#include "peep.h" #include "lex.h" #include "program.h" #include "object.h" #include "pike_types.h" #include "module_support.h" #include "pike_macros.h" #include "bignum.h" #include "builtin_functions.h" #include "cyclic.h"
-
#include "pike_security.h"
+
#include "pike_compiler.h"
-
#define sp Pike_sp
-
+
#define OP_DIVISION_BY_ZERO_ERROR(FUNC) \
-
math_error(FUNC,
sp-
2,
2,
0, "Division by zero.\n")
+
math_error(FUNC, 2, 0, "Division by zero.\n")
#define OP_MODULO_BY_ZERO_ERROR(FUNC) \
-
math_error(FUNC,
sp-
2,
2,
0, "Modulo by zero.\n")
+
math_error(FUNC, 2, 0, "Modulo by zero.\n")
-
/* The destructive multiset merge code is broken.
-
* l->msd gets -1 refs.
-
*
-
* Disable it for now.
-
* /grubba 2008-07-08
-
*/
-
#undef PIKE_MERGE_DESTR_A
-
#define PIKE_MERGE_DESTR_A 0
-
+
/* This calculation should always give some margin based on the size. */ /* It utilizes that log10(256) ~= 2.4 < 5/2. */ /* One extra char for the sign and one for the \0 terminator. */ #define MAX_INT_SPRINTF_LEN (2 + (SIZEOF_INT_TYPE * 5 + 1) / 2) /* Enough to hold a Pike float or int in textform */ #define MAX_NUM_BUF (MAXIMUM(MAX_INT_SPRINTF_LEN,MAX_FLOAT_SPRINTF_LEN))
-
+
static int has_lfun(enum LFUN lfun, int arg);
+
static int call_lfun(enum LFUN left, enum LFUN right);
+
static int call_lhs_lfun(enum LFUN lfun, int arg);
+
void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) {
-
#ifdef PIKE_SECURITY
-
if(TYPEOF(*what) <= MAX_COMPLEX)
-
if(!CHECK_DATA_SECURITY(what->u.array, SECURITY_BIT_INDEX))
-
Pike_error("Index permission denied.\n");
-
#endif
-
+
switch(TYPEOF(*what)) { case T_ARRAY: simple_array_index_no_free(to,what->u.array,ind); break; case T_MAPPING: mapping_index_no_free(to,what->u.mapping,ind); break;
pike.git/src/operators.c:129:
"with unknown method \"%S\".\n", val, ind->u.string); } else { Pike_error("Indexing the NULL value with \"%S\".\n", ind->u.string); } } break; }
-
/*
FALL_THROUGH
*/
+
/*
FALLTHRU
*/
default: index_error: if (TYPEOF(*ind) == T_INT) Pike_error ("Cannot index %s with %"PRINTPIKEINT"d.\n", (TYPEOF(*what) == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(TYPEOF(*what)), ind->u.integer); else if (TYPEOF(*ind) == T_FLOAT) Pike_error ("Cannot index %s with %"PRINTPIKEFLOAT"e.\n",
pike.git/src/operators.c:159:
Pike_error ("Cannot index %s with %s.\n", (TYPEOF(*what) == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(TYPEOF(*what)), get_name_of_type (TYPEOF(*ind))); } } PMOD_EXPORT void o_index(void) { struct svalue s;
-
index_no_free(&s,sp-2,sp-1);
+
index_no_free(&s,
Pike_
sp-2,
Pike_
sp-1);
pop_n_elems(2);
-
*sp=s;
-
dmalloc_touch_svalue(sp);
-
sp++;
+
*
Pike_
sp=s;
+
dmalloc_touch_svalue(
Pike_
sp);
+
Pike_
sp++;
dmalloc_touch_svalue(Pike_sp-1); } /*! @class MasterObject */ /*! @decl object cast_to_object(string str, string|void current_file) *! *! Called by the Pike runtime to cast strings to objects. *!
pike.git/src/operators.c:210:
*! @seealso *! @[cast_to_object()] */ /*! @endclass */ /* Special case for casting to int. */ PMOD_EXPORT void o_cast_to_int(void) {
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_OBJECT:
-
if(!sp[-1].u.object->prog) {
+
if(!
Pike_
sp[-1].u.object->prog) {
/* Casting a destructed object should be like casting a zero. */ pop_stack(); push_int (0); }
-
-
else
{
+
else
{
-
struct object *o =
sp[-1].u.object
;
-
struct pike_string *s;
-
struct program *p = o
->prog
->inherits[SUBTYPEOF(sp[-1])].prog;
-
int f
=
FIND_LFUN(p, LFUN_CAST);
-
if(f
=
=
-1)
-
Pike
_
error("No
cast method in object.\n"
)
;
-
REF_MAKE_CONST_STRING(s, "int")
;
-
push_string(s);
-
apply_low(o, f, 1);
-
stack_pop_keep_top();
-
}
+
if(
Pike_
sp[-1].u.object->prog ==
bignum
_
program
)
+
return
;
-
if(TYPEOF(sp[-1]) != PIKE_T_INT)
+
ref_push_string(literal_int_string);
+
if(
!call_lhs_lfun(LFUN_CAST,2))
+
Pike_error("No cast method in object <2>.\n");
+
stack_pop_keep_top(); /* pop object. */
+
+
if(
TYPEOF(
Pike_
sp[-1]) != PIKE_T_INT)
{
-
if(TYPEOF(sp[-1]) == T_OBJECT
&& sp[-1].u.object->prog
)
+
if(TYPEOF(
Pike_
sp[-1]) == T_OBJECT)
{
-
struct object *o = sp[-1].u.object;
-
int f = FIND_LFUN
(o->prog
->inherits[SUBTYPEOF(sp[-1])].prog,
-
LFUN__IS_TYPE)
;
-
if(
f !=
-
1
)
+
struct object *o =
Pike_
sp[-1].u.object;
+
if(
o->prog
==
bignum_program
)
+
return
;
+
else
if(
o->prog
)
{
-
struct pike
_string
*s
;
-
REF
_
MAKE
_
CONST_STRING
(
s
,
"int"
)
;
-
push_string(s);
-
apply
_
low
(
o, f,
1)
;
-
f=!UNSAFE_IS_ZERO(sp-1);
+
ref
_
push_
string
(literal_int_string)
;
+
if( call
_
lhs
_
lfun(LFUN
_
_IS_TYPE
,
2)
)
+
if(
!UNSAFE
_
IS_ZERO
(
Pike_sp-
1)
)
+
{
pop_stack();
-
if(f)
return;
+
return;
}
-
+
pop_stack();
}
-
+
}
Pike_error("Cast failed, wanted int, got %s\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
}
-
+
else if(SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED)
+
Pike_error("Cannot cast this object to int.\n");
}
-
+
break;
-
case T_FLOAT:
-
if
(
-
#ifdef
HAVE
_
ISINF
-
isinf(
sp[-1].u.float_number
) ||
-
#endif
-
#ifdef
HAVE_ISNAN
-
isnan
(
sp[-1].u.float
_
number
) ||
-
#endif
-
0
)
{
+
case T_FLOAT:
{
+
FLOAT
_
TYPE
f
=
Pike_
sp[-1].u.float_number
;
+
+
if
(
PIKE_ISINF
(
f
) ||
PIKE_ISNAN(f)
)
Pike_error("Can't cast infinites or NaN to int.\n");
-
}
else
{
-
int i=DO_NOT_WARN((int)(sp[-1]
.
u.float_number));
-
if((i < 0
?
-i : i) < floor(fabs(sp[-1].u.float_number)))
-
{
-
/*
Note:
This
includes
the
case
when i = 0x80000000, i.e.
-
the absolute value is not computable. */
+
/*
should
perhaps
convert
to
Int.Inf
now
that we have them? */
+
+
if
(
UNLIKELY
(
f
>
MAX_INT_TYPE
||
f
<
MIN
_
INT_TYPE
)) {
convert_stack_top_to_bignum();
-
return; /* FIXME: OK to return? Cast tests below indicates
-
we have to do this
,
at least for now... /Noring */
-
/* Yes
,
it is ok to return
,
it is actually an optimization :
)
-
* /Hubbe
-
*/
+
}
else
{
+
SET_SVAL(Pike_sp[-1],
T_INT
,
NUMBER_NUMBER
,
integer
,
f
)
;
}
-
else
-
{
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, i);
-
}
-
}
+
break;
-
+
}
case T_STRING: /* The generic function is rather slow, so I added this * code for benchmark purposes. :-) /per */
-
if( (sp[-1].u.string->len >= 10) || sp[-1].u.string->size_shift )
+
if( (
Pike_
sp[-1].u.string->len >= 10) ||
Pike_
sp[-1].u.string->size_shift )
convert_stack_top_string_to_inumber(10); else {
-
INT_TYPE i =
STRTOL
(sp[-1].u.string->str, 0, 10);
-
free_string(sp[-1].u.string);
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, i);
+
INT_TYPE i =
strtol
(
Pike_
sp[-1].u.string->str, 0, 10);
+
free_string(
Pike_
sp[-1].u.string);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, i);
} break; case PIKE_T_INT: break; default:
-
Pike_error("Cannot cast %s to int.\n", get_name_of_type(TYPEOF(sp[-1])));
+
Pike_error("Cannot cast %s to int.\n", get_name_of_type(TYPEOF(
Pike_
sp[-1])));
+
break;
} } /* Special case for casting to string. */ PMOD_EXPORT void o_cast_to_string(void) { struct pike_string *s;
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_OBJECT:
-
if(!sp[-1].u.object->prog) {
+
if(!
Pike_
sp[-1].u.object->prog) {
/* Casting a destructed object should be like casting a zero. */ pop_stack(); push_constant_text("0");
-
} else
{
+
} else
{
-
struct object *o = sp[-1].u.object;
-
int f = FIND
_
LFUN
(
o->prog->inherits[SUBTYPEOF(sp[-1])].prog, LFUN
_
CAST
);
-
if(
f == -1
)
+
ref
_
push_string
(
literal
_
string_string
);
+
if(
!call_lhs_lfun(LFUN_CAST,2
)
)
Pike_error("No cast method in object.\n");
-
push_constant_text("string");
-
apply_low(o, f, 1);
+
stack_pop_keep_top();
-
}
+
-
if(TYPEOF(sp[-1]) != PIKE_T_STRING)
+
if(TYPEOF(
Pike_
sp[-1]) != PIKE_T_STRING)
{
-
if(TYPEOF(sp[-1]) == T_OBJECT && sp[-1].u.object->prog)
+
if(TYPEOF(
Pike_
sp[-1])
==PIKE_T_INT
&& SUBTYPEOF(Pike_sp[-1])
==
NUMBER_UNDEFINED)
+
Pike_error("Cannot cast this object to string.\n");
+
if(TYPEOF(Pike_sp[-1]) ==
T_OBJECT &&
Pike_
sp[-1].u.object->prog)
{
-
struct object *o = sp[-1].u.object
;
-
int
f = FIND
_
LFUN
(
o->prog->inherits[SUBTYPEOF(sp[-1])].prog,
-
LFUN__IS_TYPE)
;
-
if(
f
!
=
-1)
+
ref_push_string(literal_string_string)
;
+
if(
call
_
lhs_lfun
( LFUN__IS_TYPE
,2
)
)
+
if( !
UNSAFE_IS_ZERO(Pike_sp
-1)
)
{
-
REF_MAKE_CONST_STRING(s, "string");
-
push_string(s);
-
apply_low(o, f, 1);
-
f=!UNSAFE_IS_ZERO(sp-1);
+
pop_stack();
-
if(f)
return;
+
return;
}
-
+
pop_stack();
} Pike_error("Cast failed, wanted string, got %s\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} } return; case T_ARRAY: { int i, alen;
-
struct array *a = sp[-1].u.array;
+
struct array *a =
Pike_
sp[-1].u.array;
int shift = 0; alen = a->size; for(i = 0; i<alen; i++) { INT_TYPE val; if (TYPEOF(a->item[i]) != T_INT) { Pike_error( "Can only cast array(int) to string, item %d is not an integer: %O\n", i, a->item + i); } val = a->item[i].u.integer; switch (shift) { /* Trust the compiler to strength reduce this. */ case 0: if ((unsigned INT32) val <= 0xff) break; shift = 1;
-
/*
FALL
THROUGH
*/
+
/*
FALLTHRU
*/
case 1: if ((unsigned INT32) val <= 0xffff) break; shift = 2;
-
/*
FALL
THROUGH
*/
+
/*
FALLTHRU
*/
case 2: #if SIZEOF_INT_TYPE > 4 if (val < MIN_INT32 || val > MAX_INT32)
-
Pike_error ("
cast:
Item %d is too large: %"PRINTPIKEINT"x.\n",
+
Pike_error ("Item %d is too large: %"PRINTPIKEINT"x.\n",
i, val); #endif break; } } s = begin_wide_shared_string(a->size, shift); switch(shift) {
-
default:
-
#ifdef PIKE_DEBUG
-
Pike_fatal("cast: Bad shift: %d.\n", shift);
-
break;
+
case 0:
-
#endif
+
for(i = a->size; i--; ) { s->str[i] = (p_wchar0) a->item[i].u.integer; } break; case 1: { p_wchar1 *str1 = STR1(s); for(i = a->size; i--; ) { str1[i] = (p_wchar1) a->item[i].u.integer; }
pike.git/src/operators.c:429:
} } break; } pop_stack(); push_string(end_shared_string(s)); } return; default:
-
Pike_error("Cannot cast %s to string.\n", get_name_of_type(TYPEOF(sp[-1])));
+
Pike_error("Cannot cast %s to string.\n", get_name_of_type(TYPEOF(
Pike_
sp[-1])));
+
break;
case PIKE_T_STRING: return; case T_FLOAT: { char buf[MAX_FLOAT_SPRINTF_LEN+1];
-
format_pike_float (buf, sp[-1].u.float_number);
+
format_pike_float (buf,
Pike_
sp[-1].u.float_number);
s = make_shared_string(buf); break; } case T_INT: { INT_TYPE org; char buf[MAX_INT_SPRINTF_LEN];
-
register
char*b = buf+sizeof buf-1;
-
register
unsigned INT_TYPE i;
-
org = sp[-1].u.integer;
+
char
*b = buf+sizeof buf-1;
+
unsigned INT_TYPE i;
+
org =
Pike_
sp[-1].u.integer;
*b-- = '\0'; i = org; if( org < 0 ) i = -i; goto jin; /* C as a macro assembler :-) */ do { i /= 10;
pike.git/src/operators.c:472:
if( org < 0 ) *b = '-'; else b++; s = make_shared_string(b); } break; }
-
SET_SVAL(sp[-1], PIKE_T_STRING, 0, string, s);
+
SET_SVAL(
Pike_
sp[-1], PIKE_T_STRING, 0, string, s);
} PMOD_EXPORT void o_cast(struct pike_type *type, INT32 run_time_type) {
-
if(run_time_type != TYPEOF(sp[-1]))
+
if(run_time_type != TYPEOF(
Pike_
sp[-1]))
{ if(run_time_type == T_MIXED) return;
-
if (TYPEOF(sp[-1]) == T_OBJECT && !sp[-1].u.object->prog) {
+
if (TYPEOF(
Pike_
sp[-1]) == T_OBJECT && !
Pike_
sp[-1].u.object->prog) {
/* Casting a destructed object should be like casting a zero. */ pop_stack(); push_int (0); }
-
if(TYPEOF(sp[-1]) == T_OBJECT)
+
if(TYPEOF(
Pike_
sp[-1]) == T_OBJECT)
{
-
struct object *o = sp[-1].u.object;
-
int f = FIND_LFUN(o->prog->inherits[SUBTYPEOF(sp[-1])].prog, LFUN_CAST);
+
struct object *o =
Pike_
sp[-1].u.object;
+
int f = FIND_LFUN(o->prog->inherits[SUBTYPEOF(
Pike_
sp[-1])].prog, LFUN_CAST);
if(f == -1) {
-
+
if (run_time_type == T_MAPPING) {
+
stack_dup();
+
f_indices(1);
+
stack_swap();
+
f_values(1);
+
f_mkmapping(2);
+
goto emulated_type_ok;
+
}
if (run_time_type != T_PROGRAM) { Pike_error("No cast method in object.\n"); } f_object_program(1); return; }
-
push_
string
(
describe
_type(type));
+
push_
static_text
(
get
_
name_of_
type(type
->type
));
apply_low(o, f, 1); if (run_time_type == T_PROGRAM) { if (IS_UNDEFINED(Pike_sp-1)) { pop_stack(); f_object_program(1); return; } } stack_pop_keep_top();
-
+
if(TYPEOF(Pike_sp[-1]) == T_INT &&
+
SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED)
+
Pike_error("Cannot cast this object to %s.\n",
+
get_name_of_type(type->type));
+
} else switch(run_time_type) { default: Pike_error("Cannot perform cast to that type.\n");
-
+
break;
-
case T_MIXED:
-
return;
-
+
case T_MULTISET:
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_ARRAY: { extern void f_mkmultiset(INT32); f_mkmultiset(1); break; } default: Pike_error("Cannot cast %s to multiset.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} break; case T_MAPPING:
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_ARRAY: {
-
struct array *a=sp[-1].u.array;
+
struct array *a=
Pike_
sp[-1].u.array;
struct array *b; struct mapping *m; INT32 i; m=allocate_mapping(a->size); /* MAP_SLOTS(a->size) */ push_mapping(m); for (i=0; i<a->size; i++) { if (TYPEOF(ITEM(a)[i]) != T_ARRAY) Pike_error("Cast array to mapping: " "element %d is not an array\n", i);
pike.git/src/operators.c:567:
"element %d is not an array of size 2\n", i); mapping_insert(m,ITEM(b)+0,ITEM(b)+1); } stack_swap(); pop_n_elems(1); break; } default: Pike_error("Cannot cast %s to mapping.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} break; case T_ARRAY:
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_MAPPING: {
-
struct array *a=mapping_to_array(sp[-1].u.mapping);
+
struct array *a=mapping_to_array(
Pike_
sp[-1].u.mapping);
pop_stack(); push_array(a); break; } case T_STRING: f_values(1); break; case T_MULTISET: f_indices(1); break; default: Pike_error("Cannot cast %s to array.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
-
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} break; case T_INT: o_cast_to_int(); return; case T_STRING: o_cast_to_string(); return; case T_FLOAT: { FLOAT_TYPE f = 0.0;
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_INT:
-
f=(FLOAT_TYPE)(sp[-1].u.integer);
+
f=(FLOAT_TYPE)(
Pike_
sp[-1].u.integer);
break; case T_STRING: f =
-
(FLOAT_TYPE)STRTOD_PCHARP(MKPCHARP(sp[-1].u.string->str,
-
sp[-1].u.string->size_shift),
+
(FLOAT_TYPE)STRTOD_PCHARP(MKPCHARP(
Pike_
sp[-1].u.string->str,
+
Pike_
sp[-1].u.string->size_shift),
0);
-
free_string(sp[-1].u.string);
+
free_string(
Pike_
sp[-1].u.string);
break; default: Pike_error("Cannot cast %s to float.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
}
-
SET_SVAL(sp[-1], T_FLOAT, 0, float_number, f);
+
SET_SVAL(
Pike_
sp[-1], T_FLOAT, 0, float_number, f);
break; } case T_OBJECT:
-
switch(TYPEOF(sp[-1]))
+
{
-
+
struct program *p = program_from_type(type);
+
if (p) {
+
struct svalue s;
+
SET_SVAL(s, T_PROGRAM, 0, program, p);
+
apply_svalue(&s, 1);
+
return;
+
}
+
}
+
switch(TYPEOF(Pike_sp[-1]))
+
{
case T_STRING: { struct pike_string *file; INT_TYPE lineno; if(Pike_fp->pc && (file = low_get_line(Pike_fp->pc, Pike_fp->context->prog, &lineno))) { push_string(file); }else{ push_int(0); } /* FIXME: Ought to allow compile_handler to override.
pike.git/src/operators.c:666:
frame->current_object); stack_pop_keep_top(); } else { SET_SVAL_TYPE(Pike_sp[-1], T_OBJECT); SET_SVAL_SUBTYPE(Pike_sp[-1], 0); } break; default: Pike_error("Cannot cast %s to object.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} break; case T_PROGRAM:
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_STRING: { struct pike_string *file; INT_TYPE lineno; if(Pike_fp->pc && (file = low_get_line(Pike_fp->pc, Pike_fp->context->prog, &lineno))) { push_string(file); }else{ push_int(0); } /* FIXME: Ought to allow compile_handler to override. */ APPLY_MASTER("cast_to_program",2); return; } case T_FUNCTION: {
-
struct program *p=program_from_function(sp-1);
+
struct program *p=program_from_function(
Pike_
sp-1);
if(p) { add_ref(p); pop_stack(); push_program(p); }else{ pop_stack(); push_int(0); } } return;
-
+
case PIKE_T_TYPE:
+
{
+
struct pike_type *t = Pike_sp[-1].u.type;
+
struct program *p = program_from_type(t);
+
pop_stack();
+
if (p) {
+
ref_push_program(p);
+
} else {
+
push_int(0);
+
}
+
return;
+
}
+
default: Pike_error("Cannot cast %s to a program.\n",
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} } }
-
if(run_time_type != TYPEOF(sp[-1]))
+
if(run_time_type != TYPEOF(
Pike_
sp[-1]))
{
-
switch(TYPEOF(sp[-1])) {
+
switch(TYPEOF(
Pike_
sp[-1])) {
case T_OBJECT:
-
if(sp[-1].u.object->prog)
+
if(
Pike_
sp[-1].u.object->prog)
{
-
struct object *o = sp[-1].u.object;
-
int f = FIND_LFUN(o->prog->inherits[SUBTYPEOF(sp[-1])].prog,
+
struct object *o =
Pike_
sp[-1].u.object;
+
int f = FIND_LFUN(o->prog->inherits[SUBTYPEOF(
Pike_
sp[-1])].prog,
LFUN__IS_TYPE); if( f != -1) {
-
push_text(get_name_of_type(run_time_type));
+
push_
static_
text(get_name_of_type(run_time_type));
apply_low(o, f, 1);
-
f=!UNSAFE_IS_ZERO(sp-1);
+
f=!UNSAFE_IS_ZERO(
Pike_
sp-1);
pop_stack(); if(f) goto emulated_type_ok; } } break; case T_FUNCTION: /* Check that the function actually is a program. */ if ((run_time_type == T_PROGRAM) &&
-
program_from_function(sp-1)) {
+
program_from_function(
Pike_
sp-1)) {
return; /* No need for further post-processing. */ } break; } Pike_error("Cast failed, wanted %s, got %s\n", get_name_of_type(run_time_type),
-
get_name_of_type(TYPEOF(sp[-1])));
+
get_name_of_type(TYPEOF(
Pike_
sp[-1])));
} emulated_type_ok: if (!type) return; switch(run_time_type) { case T_ARRAY: { struct pike_type *itype; INT32 run_time_itype; push_type_value(itype = index_type(type, int_type_string, 0)); run_time_itype = compile_type_to_runtime_type(itype); if(run_time_itype != T_MIXED) { struct array *a;
-
struct array *tmp=sp[-2].u.array;
+
struct array *tmp=
Pike_
sp[-2].u.array;
DECLARE_CYCLIC(); if((a=(struct array *)BEGIN_CYCLIC(tmp,0))) { ref_push_array(a); }else{ INT32 e; TYPE_FIELD types = 0; #ifdef PIKE_DEBUG
-
struct svalue *save_sp=sp+1;
+
struct svalue *save_sp=
Pike_
sp+1;
#endif push_array(a=allocate_array(tmp->size)); SET_CYCLIC_RET(a); for(e=0;e<a->size;e++) { push_svalue(tmp->item+e); o_cast(itype, run_time_itype); stack_pop_to_no_free (ITEM(a) + e); types |= 1 << TYPEOF(ITEM(a)[e]); } a->type_field = types; #ifdef PIKE_DEBUG
-
if(save_sp!=sp)
+
if(save_sp!=
Pike_
sp)
Pike_fatal("o_cast left stack droppings.\n"); #endif } END_CYCLIC();
-
assign_svalue(sp-3,sp-1);
+
assign_svalue(
Pike_
sp-3,
Pike_
sp-1);
pop_stack(); } pop_stack(); } break; case T_MULTISET: { struct pike_type *itype; INT32 run_time_itype; push_type_value(itype = key_type(type, 0)); run_time_itype = compile_type_to_runtime_type(itype); if(run_time_itype != T_MIXED) { struct multiset *m;
-
struct multiset *tmp=sp[-2].u.multiset;
+
struct multiset *tmp=
Pike_
sp[-2].u.multiset;
DECLARE_CYCLIC(); if((m=(struct multiset *)BEGIN_CYCLIC(tmp,0))) { ref_push_multiset(m); }else{ #ifdef PIKE_DEBUG
-
struct svalue *save_sp=sp+1;
+
struct svalue *save_sp=
Pike_
sp+1;
#endif ptrdiff_t nodepos;
-
if (multiset_indval (tmp))
-
Pike_error ("FIXME: Casting not implemented for multisets with values.\n");
+
push_multiset (m = allocate_multiset (multiset_sizeof (tmp), multiset_get_flags (tmp), multiset_get_cmp_less (tmp))); SET_CYCLIC_RET(m); if ((nodepos = multiset_first (tmp)) >= 0) { ONERROR uwp; SET_ONERROR (uwp, do_sub_msnode_ref, tmp); do { push_multiset_index (tmp, nodepos); o_cast(itype, run_time_itype);
-
multiset_insert
_2
(m, sp - 1
, NULL, 0
);
+
multiset_insert (m,
Pike_
sp - 1);
pop_stack(); } while ((nodepos = multiset_next (tmp, nodepos)) >= 0); UNSET_ONERROR (uwp); sub_msnode_ref (tmp); } #ifdef PIKE_DEBUG
-
if(save_sp!=sp)
+
if(save_sp!=
Pike_
sp)
Pike_fatal("o_cast left stack droppings.\n"); #endif } END_CYCLIC();
-
assign_svalue(sp-3,sp-1);
+
assign_svalue(
Pike_
sp-3,
Pike_
sp-1);
pop_stack(); } pop_stack(); } break; case T_MAPPING: { struct pike_type *itype, *vtype; INT32 run_time_itype;
pike.git/src/operators.c:868:
push_type_value(itype = key_type(type, 0)); run_time_itype = compile_type_to_runtime_type(itype); push_type_value(vtype = index_type(type, mixed_type_string, 0)); run_time_vtype = compile_type_to_runtime_type(vtype); if(run_time_itype != T_MIXED || run_time_vtype != T_MIXED) { struct mapping *m;
-
struct mapping *tmp=sp[-3].u.mapping;
+
struct mapping *tmp=
Pike_
sp[-3].u.mapping;
DECLARE_CYCLIC(); if((m=(struct mapping *)BEGIN_CYCLIC(tmp,0))) { ref_push_mapping(m); }else{ INT32 e; struct keypair *k; struct mapping_data *md; #ifdef PIKE_DEBUG
-
struct svalue *save_sp=sp+1;
+
struct svalue *save_sp=
Pike_
sp+1;
#endif push_mapping(m=allocate_mapping(m_sizeof(tmp))); SET_CYCLIC_RET(m); md = tmp->data; NEW_MAPPING_LOOP(md) { push_svalue(& k->ind); o_cast(itype, run_time_itype); push_svalue(& k->val); o_cast(vtype, run_time_vtype);
-
mapping_insert(m,sp-2,sp-1);
+
mapping_insert(m,
Pike_
sp-2,
Pike_
sp-1);
pop_n_elems(2); } #ifdef PIKE_DEBUG
-
if(save_sp!=sp)
+
if(save_sp!=
Pike_
sp)
Pike_fatal("o_cast left stack droppings.\n"); #endif } END_CYCLIC();
-
assign_svalue(sp-4,sp-1);
+
assign_svalue(
Pike_
sp-4,
Pike_
sp-1);
pop_stack(); } pop_n_elems(2); } } } PMOD_EXPORT void f_cast(void) { #ifdef PIKE_DEBUG
-
struct svalue *save_sp=sp;
-
if(TYPEOF(sp[-2]) != T_TYPE)
+
struct svalue *save_sp=
Pike_
sp;
+
if(TYPEOF(
Pike_
sp[-2]) != T_TYPE)
Pike_fatal("Cast expression destroyed stack or left droppings! (Type:%d)\n",
-
TYPEOF(sp[-2]));
+
TYPEOF(
Pike_
sp[-2]));
#endif
-
o_cast(sp[-2].u.type,
-
compile_type_to_runtime_type(sp[-2].u.type));
+
o_cast(
Pike_
sp[-2].u.type,
+
compile_type_to_runtime_type(
Pike_
sp[-2].u.type));
#ifdef PIKE_DEBUG
-
if(save_sp != sp)
+
if(save_sp !=
Pike_
sp)
Pike_fatal("Internal error: o_cast() left droppings on stack.\n"); #endif
-
free_svalue(sp-2);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc_touch_svalue(sp);
+
free_svalue(
Pike_
sp-2);
+
Pike_
sp[-2]=
Pike_
sp[-1];
+
Pike_
sp--;
+
dmalloc_touch_svalue(
Pike_
sp);
} /* Returns 1 if s is a valid in the type type. */ int low_check_soft_cast(struct svalue *s, struct pike_type *type) { loop: switch(type->type) { case T_MIXED: return 1; case T_ZERO: switch(TYPEOF(*s)) { case PIKE_T_INT: return !s->u.integer; case PIKE_T_FUNCTION: if (SUBTYPEOF(*s) == FUNCTION_BUILTIN) return 0;
-
/*
FALL_THROUGH
*/
+
/*
FALLTHRU
*/
case PIKE_T_OBJECT: return !s->u.object->prog; } return 0; case T_ASSIGN: case PIKE_T_NAME:
-
case PIKE_T_ATTRIBUTE:
+
type = type->cdr; goto loop;
-
+
case PIKE_T_ATTRIBUTE:
+
{
+
int ret;
+
if (!low_check_soft_cast(s, type->cdr)) return 0;
+
push_svalue(s);
+
ref_push_string((struct pike_string *)type->car);
+
SAFE_MAYBE_APPLY_MASTER("handle_attribute", 2);
+
ret = !SAFE_IS_ZERO(Pike_sp-1) || IS_UNDEFINED(Pike_sp-1);
+
pop_stack();
+
return ret;
+
}
case T_AND: if (!low_check_soft_cast(s, type->car)) return 0; type = type->cdr; goto loop; case T_OR: if (low_check_soft_cast(s, type->car)) return 1; type = type->cdr; goto loop; case T_NOT: return !low_check_soft_cast(s, type->car);
pike.git/src/operators.c:1035:
int lfun; if (!s->u.object->prog) return 0; if (type->type == PIKE_T_FUNCTION) { if ((lfun = FIND_LFUN(s->u.object->prog, LFUN_CALL)) != -1) { /* FIXME: Add code here. */ return 1; } } if ((lfun = FIND_LFUN(s->u.object->prog, LFUN__IS_TYPE)) != -1) { int ret;
-
push_text(get_name_of_type(type->type));
+
push_
static_
text(get_name_of_type(type->type));
apply_low(s->u.object, lfun, 1); ret = !UNSAFE_IS_ZERO(Pike_sp-1); pop_stack(); return ret; } return 0; } if ((TYPEOF(*s) == PIKE_T_FUNCTION) && (type->type == PIKE_T_PROGRAM)) { /* FIXME: Add code here. */ return 1;
pike.git/src/operators.c:1088:
ID_FROM_INT(Pike_fp->current_program, Pike_fp->fun)->name; if ((!name->size_shift) && (name->len < 100)) fname = name->str; } t1 = describe_type(type); SET_ONERROR(tmp1, do_free_string, t1); free_type(sval_type);
-
bad_arg_error(NULL,
Pike_sp
-1, 1,
1,
t1->str, Pike_sp-1,
+
bad_arg_error(NULL, -1, 1, t1->str, Pike_sp-1,
"%s(): Soft cast failed.\n%S", fname, s.s);
-
/* NOT_REACHED */
-
CALL_AND_UNSET_ONERROR(tmp1);
-
CALL_AND_UNSET_ONERROR(tmp0);
+
+
UNREACHABLE(
CALL_AND_UNSET_ONERROR(tmp1)
)
;
+
UNREACHABLE(
CALL_AND_UNSET_ONERROR(tmp0)
)
;
} } #define COMPARISON(ID,NAME,FUN) \ PMOD_EXPORT void ID(INT32 args) \ { \ int i; \ switch(args) \ { \ case 0: case 1: \
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR(NAME, 2); \
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR(NAME, 2);
\
case 2: \
-
i=FUN (sp-2,sp-1);
\
+
i=FUN (
Pike_
sp-2,
Pike_
sp-1); \
pop_n_elems(2); \ push_int(i); \ break; \ default: \ for(i=1;i<args;i++) \
-
if(! ( FUN (sp-args+i-1, sp-args+i)))
\
+
if(! ( FUN (
Pike_
sp-args+i-1,
Pike_
sp-args+i))) \
break; \ pop_n_elems(args); \ push_int(i==args); \ } \ } /*! @decl int(0..1) `!=(mixed arg1, mixed arg2, mixed ... extras) *! *! Inequality test. *!
pike.git/src/operators.c:1141:
*! Returns @expr{1@} if the test is successful, @expr{0@} *! otherwise. *! *! @seealso *! @[`==()] */ PMOD_EXPORT void f_ne(INT32 args) { f_eq(args);
-
o
_
not()
;
+
/* f
_
eq and friends always returns 1 or 0. */
+
Pike_sp[-1].u.integer = !Pike_sp[-1].u.integer
;
} /*! @decl int(0..1) `==(mixed arg1, mixed arg2, mixed ... extras) *! *! Equality test. *! *! Every expression with the @expr{==@} operator becomes a call to *! this function, i.e. @expr{a==b@} is the same as *! @expr{predef::`==(a,b)@}. *!
pike.git/src/operators.c:1175:
*! *! Otherwise, if the arguments are of different types, the test is *! unsuccessful. Function pointers to programs are automatically *! converted to program pointers if necessary, though. *! *! Otherwise the test depends on the type of the arguments: *! @mixed *! @type int *! Successful iff the two integers are numerically equal. *! @type float
-
*! Successful iff the two floats are numerically equal
or if
-
*!
both
are
NaN.
+
*! Successful iff the two floats are numerically equal
and
+
*!
not
NaN.
*! @type string *! Successful iff the two strings are identical, character for *! character. (Since all strings are kept unique, this is *! actually a test whether the arguments point to the same *! string, and it therefore run in constant time.) *! @type array|mapping|multiset|object|function|program|type *! Successful iff the two arguments point to the same instance. *! @endmixed *! *! @returns
pike.git/src/operators.c:1277:
*! otherwise. *! *! @note *! For total orders, e.g. integers, this is the inverse of @[`<()]. *! *! @seealso *! @[`<=()], @[`>()], @[`<()] */ COMPARISON(f_ge,"`>=",is_ge)
-
-
#define CALL_OPERATOR(OP, args) do { \
-
struct object *o_ = sp[-args].u.object; \
-
int i; \
-
if(!o_->prog) \
-
bad_arg_error(lfun_names[OP], sp-args, args, 1, "object", sp-args, \
-
"Called in destructed object.\n"); \
-
if((i = FIND_LFUN(o_->prog->inherits[SUBTYPEOF(sp[-args])].prog, \
-
OP)) == -1) \
-
bad_arg_error(lfun_names[OP], sp-args, args, 1, "object", sp-args, \
-
"Operator not in object.\n"); \
-
apply_low(o_, i, args-1); \
-
stack_pop_keep_top(); \
-
} while (0)
-
+
/* Helper function for calling ``-operators. * * Assumes o is at Pike_sp[e - args]. * * i is the resolved lfun to call. * * Returns the number of remaining elements on the stack. */ PMOD_EXPORT INT32 low_rop(struct object *o, int i, INT32 e, INT32 args) {
pike.git/src/operators.c:1353:
#endif /* PIKE_DEBUG */ apply_low(o, i, e); args -= e; /* Replace the object with the result. */ assign_svalue(Pike_sp-(args+1), Pike_sp-1); pop_stack(); return args; } }
-
/* Sift down large (absolute) values on the heap. */
-
static void
float
_
heap_sift_down
(
struct
svalue *svalues, int root, int nelems
)
+
static void
add
_
strings
(
INT32
args
)
{
-
FLOAT
_
ARG_TYPE
val
=
svalues[root].u.float
_
number
;
-
FLOAT
_
ARG_TYPE
abs
_
val
=
fabs(val)
;
-
int
child
;
+
struct pike
_
string
*r;
+
PCHARP buf;
+
ptrdiff
_
t tmp
;
+
int max
_
shift=0;
+
ptrdiff
_
t
size
=
0,e
;
+
int
num=0
;
-
while
(
(child
=
((root
<
<1
)
+1))
< nelems)
{
-
int
swap
=
root
;
-
FLOAT_ARG_TYPE
s
_
abs_val
;
-
if
(
(s
_
abs_val = fabs(svalues
[
child
].u.
float
_
number))
<
abs
_
val
)
{
-
swap = child;
-
} else {
-
s
_
abs_val
=
abs
_
val
;
+
for
(
e
=
-args;e
<
0;e++
)
+
{
+
if(Pike_sp[e].u.string->len
!
=
0) num++
;
+
size
+= Pike
_
sp[e].u.string->len
;
+
if(
Pike
_
sp
[
e
].u.
string->size
_
shift
>
max
_
shift
)
+
max_shift
=
Pike
_
sp[e].u.string->size
_
shift
;
}
-
child++;
-
if
(
(child
<
nelems
)
&&
-
(fabs(svalues[child].u.float
_
number) < s
_
abs_val
)
) {
-
swap = child
;
+
+
/*
All
strings
are
empty.
*/
+
if(
num
==
0
)
+
{
+
pop
_
n
_
elems(args-1
)
;
+
return
;
}
-
if
(
swap
==
root
)
break
;
-
svalues
[
root
] =
svalues
[
swap
];
-
root
=
swap
;
+
+
/*
Only
one string has length. */
+
if(
num
==
1
)
+
{
+
for(e=-args
;
e<0;e++)
+
{
+
if( Pike_sp
[
e
]
.u.string->len
)
+
{
+
if( e !
=
-args )
+
{
+
r = Pike_sp
[
e
]
.u.string
;
+
Pike_sp[e].u.string
=
Pike_sp[-args].u.string
;
+
Pike_sp[-args].u.string = r;
}
-
svalues[root].u.float_number = val;
+
}
-
+
}
+
pop_n_elems(args-1);
+
return;
+
}
-
+
tmp=Pike_sp[-args].u.string->len;
+
r=new_realloc_shared_string(Pike_sp[-args].u.string,size,max_shift);
+
mark_free_svalue (Pike_sp - args);
+
buf=MKPCHARP_STR_OFF(r,tmp);
+
for(e=-args+1;e<0;e++)
+
{
+
if( Pike_sp[e].u.string->len )
+
{
+
update_flags_for_add( r, Pike_sp[e].u.string );
+
pike_string_cpy(buf,Pike_sp[e].u.string);
+
INC_PCHARP(buf,Pike_sp[e].u.string->len);
+
}
+
free_string(Pike_sp[e].u.string);
+
}
+
Pike_sp -= args-1;
+
SET_SVAL(Pike_sp[-1], T_STRING, 0, string, low_end_shared_string(r));
+
}
+
+
static int pair_add()
+
{
+
if(TYPEOF(Pike_sp[-1]) == PIKE_T_OBJECT ||
+
TYPEOF(Pike_sp[-2]) == PIKE_T_OBJECT)
+
{
+
if(TYPEOF(Pike_sp[-2]) == PIKE_T_OBJECT &&
+
/* Note: pairwise add always has an extra reference! */
+
Pike_sp[-2].u.object->refs == 2 &&
+
call_lhs_lfun(LFUN_ADD_EQ,2))
+
return 1; /* optimized version of +. */
+
if(call_lfun(LFUN_ADD, LFUN_RADD))
+
return !IS_UNDEFINED(Pike_sp-1);
+
}
+
+
if (TYPEOF(Pike_sp[-2]) != TYPEOF(Pike_sp[-1]))
+
{
+
if(IS_UNDEFINED(Pike_sp-2))
+
{
+
stack_swap();
+
pop_stack();
+
return 1;
+
}
+
+
if(IS_UNDEFINED(Pike_sp-1))
+
{
+
pop_stack();
+
return 1;
+
}
+
+
/* string + X && X + string -> string */
+
if( TYPEOF(Pike_sp[-2]) == PIKE_T_STRING )
+
o_cast_to_string();
+
else if( TYPEOF(Pike_sp[-1]) == PIKE_T_STRING )
+
{
+
stack_swap();
+
o_cast_to_string();
+
stack_swap();
+
}
+
else if( TYPEOF(Pike_sp[-2]) == PIKE_T_FLOAT )
+
{
+
if( TYPEOF(Pike_sp[-1]) == PIKE_T_INT )
+
{
+
Pike_sp[-1].u.float_number = Pike_sp[-1].u.integer;
+
TYPEOF(Pike_sp[-1]) = PIKE_T_FLOAT;
+
}
+
}
+
else if( TYPEOF(Pike_sp[-1]) == PIKE_T_FLOAT )
+
{
+
if( TYPEOF(Pike_sp[-2]) == PIKE_T_INT )
+
{
+
Pike_sp[-2].u.float_number = Pike_sp[-2].u.integer;
+
TYPEOF(Pike_sp[-2]) = PIKE_T_FLOAT;
+
}
+
}
+
+
if (TYPEOF(Pike_sp[-2]) != TYPEOF(Pike_sp[-1]))
+
return 0;
+
}
+
+
/* types now identical. */
+
switch(TYPEOF(Pike_sp[-1]))
+
{
+
/*
+
Note: these cases mainly tend to happen when there is an object
+
in the argument list. otherwise pairwise addition is not done
+
using this code.
+
*/
+
case PIKE_T_INT:
+
{
+
INT_TYPE res;
+
if (DO_INT_TYPE_ADD_OVERFLOW(Pike_sp[-2].u.integer, Pike_sp[-1].u.integer, &res))
+
{
+
convert_svalue_to_bignum(Pike_sp-2);
+
call_lfun(LFUN_ADD,LFUN_RADD);
+
return 1;
+
}
+
Pike_sp[-2].u.integer = res;
+
Pike_sp--;
+
}
+
return 1;
+
case PIKE_T_FLOAT:
+
Pike_sp[-2].u.float_number += Pike_sp[-1].u.float_number;
+
Pike_sp--;
+
return 1;
+
case PIKE_T_STRING:
+
Pike_sp[-2].u.string = add_and_free_shared_strings(Pike_sp[-2].u.string,
+
Pike_sp[-1].u.string);
+
Pike_sp--;
+
return 1;
+
+
case PIKE_T_ARRAY:
+
push_array( add_arrays(Pike_sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_MAPPING:
+
push_mapping( add_mappings(Pike_sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_MULTISET:
+
push_multiset( add_multisets(Pike_sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_OBJECT:
+
return call_lfun(LFUN_ADD,LFUN_RADD);
+
}
+
return 0;
+
}
+
/*! @decl mixed `+(mixed arg) *! @decl mixed `+(object arg, mixed ... more) *! @decl int `+(int arg, int ... more) *! @decl float `+(float|int arg, float|int ... more) *! @decl string `+(string|float|int arg, string|float|int ... more) *! @decl array `+(array arg, array ... more) *! @decl mapping `+(mapping arg, mapping ... more) *! @decl multiset `+(multiset arg, multiset ... more) *! *! Addition/concatenation.
pike.git/src/operators.c:1456:
*! In Pike 7.0 and earlier the addition order was unspecified. *! *! The treatment of @[UNDEFINED] was new *! in Pike 7.0. *! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */ PMOD_EXPORT void f_add(INT32 args) {
-
INT_TYPE e
,size
;
-
TYPE_FIELD types;
+
INT_TYPE e;
+
TYPE_FIELD types
=0
;
-
tail
_
recurse:
+
if(!args)
+
SIMPLE
_
WRONG_NUM_ARGS_ERROR("`+", 1);
+
if (args == 1) return;
-
types=0;
-
for(e=-args;e<0;e++) types |= 1<<TYPEOF(sp[e]);
+
for(e=-args;e<0;e++) types |= 1<<TYPEOF(
Pike_
sp[e]);
switch(types) { default:
-
if(!args)
+
pairwise_add:
{
-
SIMPLE_TOO_FEW_ARGS_ERROR("`+", 1);
-
}else{
-
if(types & BIT_OBJECT)
-
{
-
struct
object
*
o;
-
struct program *p;
-
int i;
-
-
if (args
=
= 1)
-
return;
-
-
if(TYPEOF(sp[-args]) == T
_
OBJECT &&
sp
[
-args
].u.object->prog)
-
{
-
/* The first argument is an object. */
-
o = sp[-args].u.object
;
-
p = o->prog->inherits[SUBTYPEOF(sp[-args])].prog;
-
if(o->refs==1 &&
-
(i = FIND
_
LFUN(p, LFUN_ADD_EQ)) != -1)
-
{
-
apply_low(o, i, args-1);
-
stack_pop_keep_top();
-
return;
-
}
-
if((i = FIND_LFUN(p, LFUN_ADD)) != -1)
-
{
-
apply_low(o, i, args-1);
-
free_
svalue(
sp-2
);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc_touch_svalue(sp);
-
return;
-
}
-
}
-
+
struct
svalue
*
s
=
Pike
_sp-args;
+
push
_svalue(
s
);
for(e=1;e<args;e++) {
-
if(TYPEOF(sp[e-args]) == T
_
OBJECT &&
-
(
p = (o = sp[e-args].u.object
)
->prog) &&
-
(
i = FIND
_
LFUN
(
p->inherits[SUBTYPEOF(sp[e-args]
)
].prog,
-
LFUN_RADD
)
) != -1)
+
push
_
svalue
(
s+e
)
;
+
if
(
!pair
_
add
())
{
-
/*
There'
s
an
object
with
a
lfun::``+()
at
argument
@[e].
*/
-
if
((args
= low
_
rop
(
o
,
i,
e,
args))
>
1)
{
-
goto
tail
_
recurse
;
+
Pike_error("Addition
on
unsupported
types: %
s
+
%s\nm",
+
get
_
name_of_type
(
TYPEOF(*(s+e)))
,
+
get
_
name_of_type(TYPEOF(*s)))
;
}
-
+
}
+
assign_svalue(s,Pike_sp-1);
+
pop_n_elems(Pike_sp-s-1);
return; }
-
}
-
}
-
}
+
-
switch(TYPEOF(sp[-args]))
-
{
-
case T_PROGRAM:
-
case T_FUNCTION:
-
SIMPLE_BAD_ARG_ERROR("`+", 1,
-
"string|object|int|float|array|mapping|multiset");
-
}
-
bad_arg_error("`+", sp-args, args, 1,
-
"string|object|int|float|array|mapping|multiset", sp-args,
-
"Incompatible types\n");
-
return; /* compiler hint */
-
+
case BIT_STRING:
-
{
-
struct pike
_
string *r;
-
PCHARP buf;
-
ptrdiff_t tmp;
-
int max_shift=0;
-
if
(args
==1
)
return
;
-
-
size=0;
-
for(e=-args;e<0;e++)
-
{
-
size+=sp[e].u.string->len;
-
if(sp[e].u.string->size_shift > max_shift)
-
max_shift=sp[e].u.string->size_shift;
-
}
-
-
if(size == sp[-args].u.string->len)
-
{
-
pop_n_elems(args-1);
+
add
_
strings
(args);
return;
-
}
-
else if(args == 2 && (size == sp[-1].u.string->len))
-
{
-
stack_swap();
-
pop_stack();
-
return;
-
}
+
-
tmp=sp[-args].u.string->len;
-
r=new_realloc_shared_string(sp[-args].u.string,size,max_shift);
-
mark_free_svalue (sp - args);
-
buf=MKPCHARP_STR_OFF(r,tmp);
-
for(e=-args+1;e<0;e++)
-
{
-
if( sp[e].u.string->len )
-
{
-
update_flags_for_add( r, sp[e].u.string );
-
pike_string_cpy(buf,sp[e].u.string);
-
INC_PCHARP(buf,sp[e].u.string->len);
-
}
-
}
-
SET_SVAL(sp[-args], T_STRING, 0, string, low_end_shared_string(r));
-
-
for(e=-args+1;e<0;e++)
-
free_string(sp[e].u.string);
-
-
sp-=args-1;
-
-
break;
-
}
-
+
case BIT_STRING | BIT_INT: case BIT_STRING | BIT_FLOAT: case BIT_STRING | BIT_FLOAT | BIT_INT:
-
+
if ((TYPEOF(Pike_sp[-args]) != T_STRING) && (TYPEOF(Pike_sp[1-args]) != T_STRING))
{
-
struct
pike_string
*r;
-
PCHARP buf;
-
char buffer[MAX_NUM_BUF];
-
int max_shift=0;
-
-
if ((TYPEOF(sp[-args]) != T_STRING) && (TYPEOF(sp[1-args]) != T_STRING)) {
-
struct svalue *save_sp = sp;
-
/*
We
need
to
perform
a
normal
addition
first.
-
*/
-
for
(e=-args; e < 0; e++) {
-
if (TYPEOF(save
_
sp[e]) == T_STRING)
-
break
;
-
*(sp++) = save_sp[e];
-
dmalloc_touch_svalue(Pike_sp-1);
+
/
*
Note:
Could
easily
use
pairwise
add
until
at
first
string
. */
+
goto
pairwise
_
add
;
}
-
/* Perform the addition. */
-
f_add(args+e);
-
dmalloc_touch_svalue(Pike_sp-1);
-
save_sp[--e] = *(--sp);
-
#ifdef PIKE_DEBUG
-
if (sp != save_sp) {
-
Pike_fatal("f_add(): Lost track of stack %p != %p\n", sp, save_sp);
-
}
-
#endif /* PIKE_DEBUG */
-
/* Perform the rest of the addition. */
-
f_add(-e);
-
#ifdef PIKE_DEBUG
-
if (sp != save_sp + 1 + e) {
-
Pike_fatal("f_add(): Lost track of stack (2) %p != %p\n",
-
sp, save_sp + 1 + e);
-
}
-
#endif /* PIKE_DEBUG */
-
/* Adjust the stack. */
-
save_sp[-args] = sp[-1];
-
sp = save_sp + 1 - args;
-
return;
-
} else {
-
e = -args;
-
}
-
-
size=0;
+
for(e=-args;e<0;e++) {
-
switch
(TYPEOF(sp[e]))
+
if
(
TYPEOF(
Pike_
sp[e])
!= PIKE_T_STRING
)
{
-
case
T
_
STRING:
-
size+
=
sp[e].u.string->len;
-
if(sp[e].u.string->size
_
shift > max_shift)
-
max_shift=
sp[e]
.u.string->size_shift
;
-
break
;
-
-
case
T_INT:
-
size += MAX
_
INT
_
SPRINTF
_
LEN
;
-
break;
-
-
case
T
_
FLOAT:
-
size +
=
MAX
_
FLOAT_SPRINTF_LEN
;
-
break
;
+
*Pike
_
sp
=
Pike
_sp[e];
+
Pike_sp++
;
+
o
_
cast
_
to
_
string()
;
/*
free:s
old
Pike_sp[e]
*/
+
Pike
_
sp[e-1]
=
Pike
_
sp[-1]
;
+
Pike_sp--
;
} }
-
+
add_strings(args);
+
return;
-
r=begin_wide_shared_string(size,max_shift);
-
buf=MKPCHARP_STR(r);
-
size=0;
-
-
for(e=-args;e<0;e++)
-
{
-
switch(TYPEOF(sp[e]))
-
{
-
case T_STRING:
-
pike_string_cpy(buf,sp[e].u.string);
-
INC_PCHARP(buf,sp[e].u.string->len);
-
break;
-
-
case T_INT:
-
sprintf(buffer,"%"PRINTPIKEINT"d",sp[e].u.integer);
-
#ifdef PIKE_DEBUG
-
if (strlen (buffer) > MAX_INT_SPRINTF_LEN)
-
Pike_fatal ("Formatted integer %s is %"PRINTSIZET"u, "
-
"longer than assumed max %"PRINTSIZET"u.\n",
-
buffer, strlen (buffer), MAX_INT_SPRINTF_LEN);
-
#endif
-
goto append_buffer;
-
-
case T_FLOAT:
-
sprintf(buffer,"%.*"PRINTPIKEFLOAT"g",
-
PIKEFLOAT_DIG, sp[e].u.float_number);
-
/* See comment for T_FLOAT in o_cast_to_string. */
-
if (!strchr (buffer, '.') && !strchr (buffer, 'e'))
-
strcat (buffer, ".0");
-
#ifdef PIKE_DEBUG
-
if (strlen (buffer) > MAX_FLOAT_SPRINTF_LEN)
-
Pike_fatal ("Formatted float %s is %"PRINTSIZET"u, "
-
"longer than assumed max %"PRINTSIZET"u.\n",
-
buffer, strlen (buffer), MAX_FLOAT_SPRINTF_LEN);
-
#endif
-
-
append_buffer:
-
switch(max_shift)
-
{
-
case 0:
-
convert_0_to_0((p_wchar0 *)buf.ptr,buffer,strlen(buffer));
-
break;
-
-
case 1:
-
convert_0_to_1((p_wchar1 *)buf.ptr,(p_wchar0 *)buffer,
-
strlen(buffer));
-
break;
-
-
case 2:
-
convert_0_to_2((p_wchar2 *)buf.ptr,(p_wchar0 *)buffer,
-
strlen(buffer));
-
break;
-
-
}
-
INC_PCHARP(buf,strlen(buffer));
-
}
-
}
-
r = realloc_unlinked_string(r, SUBTRACT_PCHARP(buf, MKPCHARP_STR(r)));
-
r = low_end_shared_string(r);
-
pop_n_elems(args);
-
push_string(r);
-
break;
-
}
-
+
case BIT_INT: {
-
int
of = 0;
-
size =
0
;
-
for(e = -
args
; e < 0; e++)
+
INT_TYPE
size =
Pike_sp[-args].u.integer
;
+
for(e = -
args+1
; e < 0; e++)
{
-
size
=
DO_INT_TYPE_ADD_OVERFLOW(size, sp[e].u.integer, &
of
)
;
-
}
-
if(of
)
+
if
(
DO_INT_TYPE_ADD_OVERFLOW(size,
Pike_
sp[e].u.integer, &
size
))
{
-
convert_svalue_to_bignum(sp-args);
+
convert_svalue_to_bignum(
Pike_
sp-args);
f_add(args); return; }
-
sp-=args;
+
}
+
Pike_
sp-=args;
push_int(size); break;
-
+
}
-
+
case BIT_FLOAT:
-
if (args > 2)
{
-
/*
Attempt
to
minimize the accumulated summation error
-
* by adding the smallest (absolute) values first
.
-
*
-
* Large accumulated errors can occur eg when the
number
-
*
of
values to add is of the same order as the largest
-
*
number
representable
by the mantissa alone
.
ie when
-
* the sum differs by an order of magnitude from a
-
* typical term
.
-
*/
-
/* Heapify */
-
for(e
= args
>>
1;
e--;) {
-
float_heap_sift_down(
Pike_sp-
args,
e,
args)
;
+
{
+
double
res
=
Pike_sp[-args]
.
u.float_
number
;
+
for(e=args-1;
e>0;
e--
)
+
res
+=
Pike_sp[-e]
.
u
.
float_number;
+
Pike_sp
-
= args
-
1;
+
Pike_sp
[
-
1].u.float_number
=
res
;
}
-
while (args > 2) {
-
/* Pop the smallest element from the heap. */
-
FLOAT_ARG_TYPE top = Pike_sp[-args].u.float_number;
-
Pike_sp[-args] = Pike_sp[-1];
-
Pike_sp--;
-
args--;
-
float_heap_sift_down(Pike_sp-args, 0, args);
-
-
/* And add it to the second smallest. */
-
Pike_sp[-args].u.float_number += top;
-
float_heap_sift_down(Pike_sp-args, 0, args);
-
}
-
}
-
sp[-2].u.float_number += sp[-1].u.float_number;
-
sp--;
+
break; case BIT_FLOAT|BIT_INT: {
-
/*
For
improved
precision
;
partition the values
-
*
into
floats
followed
by
ints,
so that we
-
*
can
add
the
integers exactly.
-
*/
-
int i
=
args
-
1
;
-
e
=
0;
-
while
(e
<
i)
{
-
for
(
;e <
i
; i
-
-) {
-
if
(
TYPEOF(sp[i-args]
)
==
T_FLOAT)
break
;
+
double
res
=
0.0
;
+
int
i;
+
for(i=0;
i<args;
i++)
+
if
(TYPEOF(Pike_sp[i-args])
==
T_FLOAT)
+
res
+=
Pike_sp[
i
-
args
].u.float_number
;
+
else
+
res
+=
(
double)Pike_sp[
i
-args].u.integer
;
+
Pike_sp-=args;
+
push_float
(
res
)
;
+
return
;
}
-
for(;e < i; e++) {
-
if (TYPEOF(sp[e-args]) == T_INT) break;
-
}
-
if (e < i) {
-
/* Swap */
-
struct svalue sval = sp[e-args];
-
sp[e-args] = sp[i-args];
-
sp[i-args] = sval;
-
}
-
}
-
if (TYPEOF(sp[e-args]) == T_FLOAT) e++;
-
/* Sum the integers. */
-
if (args - e > 1) {
-
f_add(args-e);
-
}
-
args = e+1;
-
o_cast(float_type_string, PIKE_T_FLOAT);
+
-
/* Now all the values should be floats. */
-
goto tail_recurse;
-
}
-
-
#define ADD_WITH_UNDEFINED(TYPE, T_TYPEID, ADD_FUNC, PUSH_FUNC) do { \
-
int e; \
-
if (TYPEOF(sp[-args]) == T_INT) { \
-
if(IS_UNDEFINED(sp-args)) \
-
{ \
-
struct TYPE *x; \
-
\
-
for(e=1;e<args;e++) \
-
if(TYPEOF(sp[e-args]) != T_TYPEID) \
-
SIMPLE_ARG_TYPE_ERROR("`+", e+1, #TYPE); \
-
\
-
x = ADD_FUNC(sp-args+1,args-1); \
-
pop_n_elems(args); \
-
PUSH_FUNC(x); \
-
return; \
-
} \
-
\
-
for(e=1;e<args;e++) \
-
if (TYPEOF(sp[e-args]) != T_INT) \
-
SIMPLE_ARG_TYPE_ERROR("`+", e+1, "int"); \
-
} \
-
\
-
else { \
-
for(e=1;e<args;e++) \
-
if (TYPEOF(sp[e-args]) != T_TYPEID) \
-
SIMPLE_ARG_TYPE_ERROR("`+", e+1, #TYPE); \
-
} \
-
\
-
DO_IF_DEBUG (Pike_fatal ("Shouldn't be reached.\n")); \
-
break; \
-
} while (0)
-
+
#define ADD(TYPE, ADD_FUNC, PUSH_FUNC) do { \
-
struct TYPE *x = ADD_FUNC (sp - args, args);
\
+
struct TYPE *x = ADD_FUNC (
Pike_
sp - args, args); \
pop_n_elems (args); \ PUSH_FUNC (x); \ return; \ } while (0)
-
case
BIT
_
ARRAY|BIT
_INT
:
-
ADD
_
WITH_
UNDEFINED (
array
,
T_ARRAY
,
add
_
arrays,
push
_
array
);
+
#define
REMOVE_UNDEFINED(TYPE)
\
+
do { \
+
int to = -args, i=-args; \
+
for(; i<0; i++) \
+
{ \
+
if(TYPEOF(Pike
_
sp[i]) == PIKE
_
T_
INT
) \
+
{ \
+
if(!IS
_
UNDEFINED(Pike
_
sp+i))
\
+
SIMPLE_ARG_TYPE_ERROR
(
"`+"
,
args+i
,
#TYPE); \
+
} \
+
else if(to!=i) \
+
Pike
_
sp[to++]
= Pike
_
sp[i]; \
+
else to++; \
+
} \
+
for(i=to; i<0; i++
)
\
+
TYPEOF(Pike_sp[i])=PIKE_T_INT
;
\
+
Pike_sp += to; \
+
args += to; \
+
} while(0);
-
+
case BIT_ARRAY|BIT_INT:
+
REMOVE_UNDEFINED (array);
+
/* Fallthrough */
case BIT_ARRAY: ADD (array, add_arrays, push_array);
-
+
break;
case BIT_MAPPING|BIT_INT:
-
ADD
_
WITH_
UNDEFINED (mapping
, T_MAPPING, add_mappings, push_mapping
);
-
+
REMOVE
_UNDEFINED (mapping
);
+
/* Fallthrough */
case BIT_MAPPING: ADD (mapping, add_mappings, push_mapping);
-
+
break;
case BIT_MULTISET|BIT_INT:
-
ADD
_
WITH_
UNDEFINED (multiset
, T_MULTISET, add_multisets, push_multiset
);
-
+
REMOVE
_UNDEFINED (multiset
);
+
/* Fallthrough */
case BIT_MULTISET: ADD (multiset, add_multisets, push_multiset);
-
+
break;
-
#undef
ADD
_
WITH_
UNDEFINED
+
#undef
REMOVE
_UNDEFINED
#undef ADD } } static int generate_sum(node *n) { struct compilation *c = THIS_COMPILATION; node **first_arg, **second_arg, **third_arg; switch(count_args(CDR(n))) {
pike.git/src/operators.c:1958:
if(count_args(CDR(n))==2) { first_arg=my_get_arg(&_CDR(n), 0); second_arg=my_get_arg(&_CDR(n), 1); #ifdef PIKE_DEBUG if(!first_arg || !second_arg) Pike_fatal("Couldn't find argument!\n"); #endif
-
#if 0
-
/* Disabled these - boolean falsehood is not the same thing as
-
* equality with the integer 0. */
-
-
if(node_is_false(*first_arg) && !node_may_overload(*second_arg,LFUN_EQ))
-
{
-
ret=*second_arg;
-
ADD_NODE_REF(*second_arg);
-
return mkopernode("`!",ret,0);
-
}
-
-
if(node_is_false(*second_arg) && !node_may_overload(*first_arg,LFUN_EQ))
-
{
-
ret=*first_arg;
-
ADD_NODE_REF(*first_arg);
-
return mkopernode("`!",ret,0);
-
}
-
#endif
-
+
if (((*second_arg)->token == F_CONSTANT) && (TYPEOF((*second_arg)->u.sval) == T_STRING) && ((*first_arg)->token == F_RANGE)) { node *low = CADR (*first_arg), *high = CDDR (*first_arg); INT_TYPE c; if ((low->token == F_RANGE_OPEN || (low->token == F_RANGE_FROM_BEG && (CAR (low)->token == F_CONSTANT) && (TYPEOF(CAR (low)->u.sval) == T_INT) && (!(CAR (low)->u.sval.u.integer)))) &&
pike.git/src/operators.c:2219:
CAR(n)->u.sval.u.efun->function, f_eq, f_ne, f_lt, f_le, f_gt, f_ge); modify_stack_depth(-1); return 1; } return 0; } static int float_promote(void) {
-
if(TYPEOF(sp[-2]) == T_INT && TYPEOF(sp[-1]) == T_FLOAT)
+
if(TYPEOF(
Pike_
sp[-2]) == T_INT && TYPEOF(
Pike_
sp[-1]) == T_FLOAT)
{
-
SET_SVAL(sp[-2], T_FLOAT, 0, float_number, (FLOAT_TYPE)sp[-2].u.integer);
+
SET_SVAL(
Pike_
sp[-2], T_FLOAT, 0, float_number, (FLOAT_TYPE)
Pike_
sp[-2].u.integer);
return 1; }
-
else if(TYPEOF(sp[-1]) == T_INT && TYPEOF(sp[-2]) == T_FLOAT)
+
else if(TYPEOF(
Pike_
sp[-1]) == T_INT && TYPEOF(
Pike_
sp[-2]) == T_FLOAT)
{
-
SET_SVAL(sp[-1], T_FLOAT, 0, float_number, (FLOAT_TYPE)sp[-1].u.integer);
+
SET_SVAL(
Pike_
sp[-1], T_FLOAT, 0, float_number, (FLOAT_TYPE)
Pike_
sp[-1].u.integer);
return 1; }
-
if(is_bignum_object_in_svalue(sp-2) && TYPEOF(sp[-1]) == T_FLOAT)
+
if(is_bignum_object_in_svalue(
Pike_
sp-2) && TYPEOF(
Pike_
sp[-1]) == T_FLOAT)
{ stack_swap(); ref_push_type_value(float_type_string); stack_swap(); f_cast(); stack_swap(); return 1; }
-
else if(is_bignum_object_in_svalue(sp-1) && TYPEOF(sp[-2]) == T_FLOAT)
+
else if(is_bignum_object_in_svalue(
Pike_
sp-1) && TYPEOF(
Pike_
sp[-2]) == T_FLOAT)
{ ref_push_type_value(float_type_string); stack_swap(); f_cast(); return 1; } return 0; }
-
static int
call
_lfun(
int
left
, int
right
)
+
static int
has
_lfun(
enum
LFUN lfun
, int
arg
)
{
-
+
struct program *p;
+
+
if(TYPEOF(Pike_sp[-arg]) == T_OBJECT && (p = Pike_sp[-arg].u.object->prog))
+
return FIND_LFUN(p->inherits[SUBTYPEOF(Pike_sp[-arg])].prog, lfun);
+
return -1;
+
}
+
+
static int call_lhs_lfun( enum LFUN lfun, int arg )
+
{
+
int i = has_lfun(lfun,arg);
+
+
if(i != -1)
+
{
+
apply_low(Pike_sp[-arg].u.object, i, arg-1);
+
return 1;
+
}
+
return 0;
+
}
+
+
static int call_lfun(enum LFUN left, enum LFUN right)
+
{
struct object *o; struct program *p; int i;
-
if(TYPEOF(sp[-2]) == T_OBJECT &&
-
(p = (o = sp[-2].u.object)->prog) &&
-
(i = FIND_LFUN(p->inherits[SUBTYPEOF(sp[-2])].prog, left)) != -1)
+
if(TYPEOF(
Pike_
sp[-2]) == T_OBJECT &&
+
(p = (o =
Pike_
sp[-2].u.object)->prog) &&
+
(i = FIND_LFUN(p->inherits[SUBTYPEOF(
Pike_
sp[-2])].prog, left)) != -1)
{ apply_low(o, i, 1);
-
free_svalue(sp-2);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc_touch_svalue(sp);
+
free_svalue(
Pike_
sp-2);
+
Pike_
sp[-2]=
Pike_
sp[-1];
+
Pike_
sp--;
+
dmalloc_touch_svalue(
Pike_
sp);
return 1; }
-
if(TYPEOF(sp[-1]) == T_OBJECT &&
-
(p = (o = sp[-1].u.object)->prog) &&
-
(i = FIND_LFUN(p->inherits[SUBTYPEOF(sp[-1])].prog, right)) != -1)
+
if(TYPEOF(
Pike_
sp[-1]) == T_OBJECT &&
+
(p = (o =
Pike_
sp[-1].u.object)->prog) &&
+
(i = FIND_LFUN(p->inherits[SUBTYPEOF(
Pike_
sp[-1])].prog, right)) != -1)
{
-
push_svalue(sp-2);
+
push_svalue(
Pike_
sp-2);
apply_low(o, i, 1);
-
free_svalue(sp-3);
-
sp[-3]=sp[-1];
-
sp--;
-
dmalloc_touch_svalue(sp);
+
free_svalue(
Pike_
sp-3);
+
Pike_
sp[-3]=
Pike_
sp[-1];
+
Pike_
sp--;
+
dmalloc_touch_svalue(
Pike_
sp);
pop_stack(); return 1; } return 0; } struct mapping *merge_mapping_array_ordered(struct mapping *a, struct array *b, INT32 op); struct mapping *merge_mapping_array_unordered(struct mapping *a, struct array *b, INT32 op); PMOD_EXPORT void o_subtract(void) {
-
if (TYPEOF(sp[-2]) != TYPEOF(sp[-1]) && !float_promote())
+
if (TYPEOF(
Pike_
sp[-2]) != TYPEOF(
Pike_
sp[-1]) && !float_promote())
{ if(call_lfun(LFUN_SUBTRACT, LFUN_RSUBTRACT)) return;
-
if (TYPEOF(sp[-2]) == T_MAPPING)
-
switch (TYPEOF(sp[-1]))
+
if (TYPEOF(
Pike_
sp[-2]) == T_MAPPING)
+
switch (TYPEOF(
Pike_
sp[-1]))
{ case T_ARRAY: { struct mapping *m;
-
m=merge_mapping_array_unordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_unordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_SUB); pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct mapping *m;
-
int got_cmp_less = !!multiset_get_cmp_less (sp[-1].u.multiset);
-
struct array *ind = multiset_indices (sp[-1].u.multiset);
+
int got_cmp_less = !!multiset_get_cmp_less (
Pike_
sp[-1].u.multiset);
+
struct array *ind = multiset_indices (
Pike_
sp[-1].u.multiset);
pop_stack(); push_array (ind); if (got_cmp_less)
-
m=merge_mapping_array_unordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_unordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_SUB); else
-
m=merge_mapping_array_ordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_ordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_SUB); pop_n_elems(2); push_mapping(m); return; } }
-
bad_arg_error("`-",
sp-
2, 2,
2,
get_name_of_type(TYPEOF(sp[-2])),
-
sp-1, "Subtract on different types.\n");
+
bad_arg_error("`-", 2, 2, get_name_of_type(TYPEOF(
Pike_
sp[-2])),
+
Pike_
sp-1, "Subtract on different types.\n");
}
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_SUBTRACT,2);
-
break
;
+
if(!call
_
lfun
(LFUN_SUBTRACT,
LFUN_RSUBTRACT))
+
PIKE_ERROR("`-", "Subtract on objects without `- operator.\n", Pike_sp,
2);
+
return
;
case T_ARRAY: { struct array *a;
-
check_array_for_destruct(sp[-2].u.array);
-
check_array_for_destruct(sp[-1].u.array);
-
a = subtract_arrays(sp[-2].u.array, sp[-1].u.array);
+
check_array_for_destruct(
Pike_
sp[-2].u.array);
+
check_array_for_destruct(
Pike_
sp[-1].u.array);
+
a = subtract_arrays(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array);
pop_n_elems(2); push_array(a); return; } case T_MAPPING: { struct mapping *m;
-
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping,PIKE_ARRAY_OP_SUB);
+
m=merge_mappings(
Pike_
sp[-2].u.mapping,
Pike_
sp[-1].u.mapping,PIKE_ARRAY_OP_SUB);
pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct multiset *l;
-
if (sp[-2].u.multiset->refs == 1) {
-
l=merge_multisets(sp[-2].u.multiset,
sp[-1].u.multiset,
-
PIKE
_
ARRAY_OP_SUB | PIKE_MERGE_DESTR_A);
-
} else {
-
l=merge_multisets(
sp[-
2].u.multiset, sp[-
1].u.multiset,
+
l=merge_multisets(
Pike_
sp[-2].u.multiset,
Pike
_sp[-1].u.multiset,
PIKE_ARRAY_OP_SUB);
-
}
+
pop_n_elems(2); push_multiset(l); return; } case T_FLOAT:
-
sp--;
-
sp[-1].u.float_number -= sp[0].u.float_number;
+
Pike_
sp--;
+
Pike_
sp[-1].u.float_number -=
Pike_
sp[0].u.float_number;
return; case T_INT:
-
if(INT_TYPE_SUB_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+
if(INT_TYPE_SUB_OVERFLOW(
Pike_
sp[-2].u.integer,
Pike_
sp[-1].u.integer))
{ convert_stack_top_to_bignum();
-
f
_
minus
(
2
);
+
call
_
lfun
(
LFUN_SUBTRACT, LFUN_RSUBTRACT
);
return; }
-
sp--;
-
SET_SVAL(sp[-1], PIKE_T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer - sp[0].u.integer);
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], PIKE_T_INT, NUMBER_NUMBER, integer,
+
Pike_
sp[-1].u.integer -
Pike_
sp[0].u.integer);
return; case T_STRING: { struct pike_string *s,*ret; s=make_shared_string("");
-
ret=string_replace(sp[-2].u.string,sp[-1].u.string,s);
-
free_string(sp[-2].u.string);
-
free_string(sp[-1].u.string);
+
ret=string_replace(
Pike_
sp[-2].u.string,
Pike_
sp[-1].u.string,s);
+
free_string(
Pike_
sp[-2].u.string);
+
free_string(
Pike_
sp[-1].u.string);
free_string(s);
-
sp[-2].u.string=ret;
-
sp--;
+
Pike_
sp[-2].u.string=ret;
+
Pike_
sp--;
return; } /* FIXME: Support types? */ default: { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`-", 1,
+
SIMPLE_ARG_
TYPE_
ERROR("`-", 1,
"int|float|string|mapping|multiset|array|object"); } } } /*! @decl mixed `-(mixed arg1) *! @decl mixed `-(mixed arg1, mixed arg2, mixed ... extras) *! @decl mixed `-(object arg1, mixed arg2) *! @decl mixed `-(mixed arg1, object arg2) *! @decl int `-(int arg1, int arg2)
pike.git/src/operators.c:2470:
*! @mixed arg1 *! @type int|float *! The result is @expr{@[arg1] - @[arg2]@}, and is a float if *! either @[arg1] or @[arg2] is a float. *! @type string *! The result is @[arg1] with all nonoverlapping occurrences of *! the substring @[arg2] removed. In cases with two overlapping *! occurrences, the leftmost is removed. *! @type array|mapping|multiset *! The result is like @[arg1] but without the elements/indices
-
*! that match any in @[arg2] (according to @[`
==
]
and
,
in the
-
*! case of mappings, @[hash_value]).
+
*! that match any in @[arg2] (according to @[`
>
]
,
@[`<]
,
@[`==]
+
*!
and, in the
case of mappings, @[hash_value]).
*! @endmixed *! The function is not destructive on the arguments - the result is *! always a new instance. *! *! @note *! In Pike 7.0 and earlier the subtraction order was unspecified. *!
-
+
*! @note
+
*! If this operator is used with arrays or multisets containing objects
+
*! which implement @[lfun::`==()] but @b{not@} @[lfun::`>()] and
+
*! @[lfun::`<()], the result will be undefined.
+
*!
*! @seealso *! @[`+()] */ PMOD_EXPORT void f_minus(INT32 args) { switch(args) {
-
case 0: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`-", 1);
+
case 0: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`-", 1);
case 1: o_negate(); break; case 2: o_subtract(); break; default: { INT32 e; TYPE_FIELD types = 0;
-
struct svalue *s=sp-args;
+
struct svalue *s=
Pike_
sp-args;
-
for(e=-args;e<0;e++) types |= 1<<TYPEOF(sp[e]);
+
for(e=-args;e<0;e++) types |= 1<<TYPEOF(
Pike_
sp[e]);
if ((types | BIT_INT | BIT_FLOAT) == (BIT_INT | BIT_FLOAT)) { INT32 carry = 0; if (types == BIT_INT) { f_add(args-1); o_subtract(); break; } /* Take advantage of the precision control in f_add(). */ for(e = 1; e < args; e++) {
pike.git/src/operators.c:2533:
f_add(args); break; } push_svalue(s); for(e=1;e<args;e++) { push_svalue(s+e); o_subtract(); }
-
assign_svalue(s,sp-1);
-
pop_n_elems(sp-s-1);
+
assign_svalue(s,
Pike_
sp-1);
+
pop_n_elems(
Pike_
sp-s-1);
} } } static int generate_minus(node *n) { struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1:
pike.git/src/operators.c:2560:
do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_SUBTRACT); modify_stack_depth(-1); return 1; } return 0; } PMOD_EXPORT void o_and(void) {
-
if(TYPEOF(sp[-1]) != TYPEOF(sp[-2]))
+
if(
UNLIKELY(
TYPEOF(
Pike_
sp[-1]) != TYPEOF(
Pike_
sp[-2]))
)
{ if(call_lfun(LFUN_AND, LFUN_RAND)) return;
-
else if (((TYPEOF(sp[-1]) == T_TYPE) || (TYPEOF(sp[-1]) == T_PROGRAM) ||
-
(TYPEOF(sp[-1]) == T_FUNCTION)) &&
-
((TYPEOF(sp[-2]) == T_TYPE) || (TYPEOF(sp[-2]) == T_PROGRAM) ||
-
(TYPEOF(sp[-2]) == T_FUNCTION)))
+
else if (((TYPEOF(
Pike_
sp[-1]) == T_TYPE) || (TYPEOF(
Pike_
sp[-1]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-1]) == T_FUNCTION)) &&
+
((TYPEOF(
Pike_
sp[-2]) == T_TYPE) || (TYPEOF(
Pike_
sp[-2]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-2]) == T_FUNCTION)))
{
-
if (TYPEOF(sp[-2]) != T_TYPE)
+
if (TYPEOF(
Pike_
sp[-2]) != T_TYPE)
{
-
struct program *p = program_from_svalue(sp - 2);
+
struct program *p = program_from_svalue(
Pike_
sp - 2);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 1, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 2);
-
SET_SVAL(sp[-2], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 2);
+
SET_SVAL(
Pike_
sp[-2], T_TYPE, 0, type, pop_unfinished_type());
}
-
if (TYPEOF(sp[-1]) != T_TYPE)
+
if (TYPEOF(
Pike_
sp[-1]) != T_TYPE)
{
-
struct program *p = program_from_svalue(sp - 1);
+
struct program *p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 2, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 1);
-
SET_SVAL(sp[-1], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 1);
+
SET_SVAL(
Pike_
sp[-1], T_TYPE, 0, type, pop_unfinished_type());
} }
-
else if (TYPEOF(sp[-2]) == T_MAPPING)
-
switch (TYPEOF(sp[-1]))
+
else if (TYPEOF(
Pike_
sp[-2]) == T_MAPPING)
+
switch (TYPEOF(
Pike_
sp[-1]))
{ case T_ARRAY: { struct mapping *m;
-
m=merge_mapping_array_unordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_unordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_AND); pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct mapping *m;
-
int got_cmp_less = !!multiset_get_cmp_less (sp[-1].u.multiset);
-
struct array *ind = multiset_indices (sp[-1].u.multiset);
+
int got_cmp_less = !!multiset_get_cmp_less (
Pike_
sp[-1].u.multiset);
+
struct array *ind = multiset_indices (
Pike_
sp[-1].u.multiset);
pop_stack(); push_array (ind); if (got_cmp_less)
-
m=merge_mapping_array_unordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_unordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_AND); else
-
m=merge_mapping_array_ordered(sp[-2].u.mapping,
-
sp[-1].u.array,
+
m=merge_mapping_array_ordered(
Pike_
sp[-2].u.mapping,
+
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_AND); pop_n_elems(2); push_mapping(m); return; } default: { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 2, "mapping");
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 2, "mapping");
} } else { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 2, get_name_of_type(TYPEOF(sp[-2])));
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 2, get_name_of_type(TYPEOF(
Pike_
sp[-2])));
} }
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_AND,2);
-
break
;
+
if(!call
_
lfun
(LFUN_AND,
LFUN_RAND))
+
PIKE_ERROR("`&", "Bitwise and on objects without `& operator.\n", Pike_sp,
2);
+
return
;
case T_INT:
-
sp--;
-
SET_SVAL(sp[-1], PIKE_T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer & sp[0].u.integer);
-
break
;
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], PIKE_T_INT, NUMBER_NUMBER, integer,
+
Pike_
sp[-1].u.integer &
Pike_
sp[0].u.integer);
+
return
;
case T_MAPPING: { struct mapping *m;
-
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_AND);
+
m=merge_mappings(
Pike_
sp[-2].u.mapping,
Pike_
sp[-1].u.mapping, PIKE_ARRAY_OP_AND);
pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct multiset *l;
-
if (sp[-2].u.multiset->refs == 1) {
-
l=merge_multisets(sp[-2].u.multiset,
sp[-1].u.multiset,
-
PIKE
_
ARRAY_OP_AND | PIKE_MERGE_DESTR_A);
-
} else {
-
l=merge_multisets(
sp[-
2].u.multiset, sp[-
1].u.multiset,
+
l=merge_multisets(
Pike_
sp[-2].u.multiset,
Pike
_sp[-1].u.multiset,
PIKE_ARRAY_OP_AND);
-
}
+
pop_n_elems(2); push_multiset(l); return; } case T_ARRAY: { struct array *a;
-
a=and_arrays(sp[-2].u.array, sp[-1].u.array);
+
a=and_arrays(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array);
pop_n_elems(2); push_array(a); return; } case T_TYPE: { struct pike_type *t;
-
t = and_pike_types(sp[-2].u.type, sp[-1].u.type);
+
t = and_pike_types(
Pike_
sp[-2].u.type,
Pike_
sp[-1].u.type);
pop_n_elems(2); push_type_value(t); return; } case T_FUNCTION: case T_PROGRAM: { struct program *p; struct pike_type *a; struct pike_type *b; struct pike_type *t;
-
p = program_from_svalue(sp - 2);
+
p = program_from_svalue(
Pike_
sp - 2);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 1, "type");
} type_stack_mark(); push_object_type(0, p->id); a = pop_unfinished_type();
-
p = program_from_svalue(sp - 1);
+
p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`&", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`&", 2, "type");
} type_stack_mark(); push_object_type(0, p->id); b = pop_unfinished_type(); t = and_pike_types(a, b); pop_n_elems(2); push_type_value(t); free_type(a); free_type(b); return; } #define STRING_BITOP(OP,STROP) \ case T_STRING: \ { \ struct pike_string *s; \ ptrdiff_t len, i; \ \
-
len = sp[-2].u.string->len;
\
-
if (len != sp[-1].u.string->len)
\
-
PIKE_ERROR("`" #OP, "Bitwise "STROP \
-
" on strings of different lengths.\n", sp, 2);
\
-
if(!sp[-2].u.string->size_shift && !sp[-1].u.string->size_shift)
\
+
len =
Pike_
sp[-2].u.string->len; \
+
if (len !=
Pike_
sp[-1].u.string->len) \
+
PIKE_ERROR("`" #OP, "Bitwise "STROP \
+
" on strings of different lengths.\n",
Pike_
sp, 2); \
+
if(!
Pike_
sp[-2].u.string->size_shift && !
Pike_
sp[-1].u.string->size_shift) \
{ \ s = begin_shared_string(len); \ for (i=0; i<len; i++) \
-
s->str[i] = sp[-2].u.string->str[i] OP sp[-1].u.string->str[i];
\
+
s->str[i] =
Pike_
sp[-2].u.string->str[i] OP
Pike_
sp[-1].u.string->str[i]; \
}else{ \ s = begin_wide_shared_string(len, \
-
MAXIMUM(sp[-2].u.string->size_shift,
\
-
sp[-1].u.string->size_shift)); \
+
MAXIMUM(
Pike_
sp[-2].u.string->size_shift, \
+
Pike_
sp[-1].u.string->size_shift)); \
for (i=0; i<len; i++) \
-
low_set_index(s,i,index_shared_string(sp[-2].u.string,i) OP
\
-
index_shared_string(sp[-1].u.string,i));
\
+
low_set_index(s,i,index_shared_string(
Pike_
sp[-2].u.string,i) OP \
+
index_shared_string(
Pike_
sp[-1].u.string,i)); \
} \ pop_n_elems(2); \ push_string(end_shared_string(s)); \ return; \ } STRING_BITOP(&,"AND") default:
-
PIKE_ERROR("`&", "Bitwise AND on illegal type.\n", sp, 2);
+
PIKE_ERROR("`&", "Bitwise AND on illegal type.\n",
Pike_
sp, 2);
} } /* This function is used to speed up or/xor/and on * arrays multisets and mappings. This is done by * calling the operator for each pair of arguments * first, then recursively doing the same on the * results until only one value remains. */ static void r_speedup(INT32 args, void (*func)(void)) { struct svalue tmp; ONERROR err; switch(args) {
-
case 3: func();
-
case 2: func();
+
case 3: func();
/* FALLTHRU */
+
case 2: func();
/* FALLTHRU */
case 1: return; default: r_speedup((args+1)>>1,func); dmalloc_touch_svalue(Pike_sp-1);
-
tmp=*--sp;
+
tmp=*--
Pike_
sp;
SET_ONERROR(err,do_free_svalue,&tmp); r_speedup(args>>1,func); UNSET_ONERROR(err);
-
sp++[0]=tmp;
+
Pike_
sp++[0]=tmp;
func(); } } static void speedup(INT32 args, void (*func)(void)) {
-
switch(TYPEOF(sp[-args]))
+
switch(TYPEOF(
Pike_
sp[-args]))
{ /* Binary balanced tree method for types where * a op b may or may not be equal to b op a */ case T_ARRAY: case T_MAPPING: r_speedup(args,func); return; default:
pike.git/src/operators.c:2855:
*! @mixed arg1 *! @type int *! Bitwise and of @[arg1] and @[arg2]. *! @type string *! The result is a string where each character is the bitwise *! and of the characters in the same position in @[arg1] and *! @[arg2]. The arguments must be strings of the same length. *! @type array|mapping|multiset *! The result is like @[arg1] but only with the *! elements/indices that match any in @[arg2] (according to
-
*! @[`==] and, in the case of mappings, @[hash_value]).
+
*! @[`
>], @[`<], @[`
==] and, in the case of mappings,
+
*!
@[hash_value]).
*! @type type|program *! Type intersection of @[arg1] and @[arg2]. *! @endmixed *! The function is not destructive on the arguments - the result is *! always a new instance. *!
-
+
*! @note
+
*! If this operator is used with arrays or multisets containing objects
+
*! which implement @[lfun::`==()] but @b{not@} @[lfun::`>()] and
+
*! @[lfun::`<()], the result will be undefined.
+
*!
*! @seealso *! @[`|()], @[lfun::`&()], @[lfun::``&()] */ PMOD_EXPORT void f_and(INT32 args) { switch(args) {
-
case 0: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`&", 1);
+
case 0: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`&", 1);
case 1: return; case 2: o_and(); return; default:
-
if(TYPEOF(sp[-args]) == T_OBJECT)
-
{
-
CALL_OPERATOR(LFUN_AND, args);
-
}else{
+
speedup(args, o_and); } }
-
}
+
static int generate_and(node *n) { struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1;
pike.git/src/operators.c:2904:
modify_stack_depth(-1); return 1; default: return 0; } } PMOD_EXPORT void o_or(void) {
-
if(TYPEOF(sp[-1]) != TYPEOF(sp[-2]))
+
if(TYPEOF(
Pike_
sp[-1]) != TYPEOF(
Pike_
sp[-2]))
{ if(call_lfun(LFUN_OR, LFUN_ROR)) { return;
-
} else if (((TYPEOF(sp[-1]) == T_TYPE) || (TYPEOF(sp[-1]) == T_PROGRAM) ||
-
(TYPEOF(sp[-1]) == T_FUNCTION)) &&
-
((TYPEOF(sp[-2]) == T_TYPE) || (TYPEOF(sp[-2]) == T_PROGRAM) ||
-
(TYPEOF(sp[-2]) == T_FUNCTION))) {
-
if (TYPEOF(sp[-2]) != T_TYPE) {
-
struct program *p = program_from_svalue(sp - 2);
+
} else if (((TYPEOF(
Pike_
sp[-1]) == T_TYPE) ||
+
(TYPEOF(
Pike_
sp[-1]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-1]) == T_FUNCTION)) &&
+
((TYPEOF(
Pike_
sp[-2]) == T_TYPE) ||
+
(TYPEOF(
Pike_
sp[-2]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-2]) == T_FUNCTION))) {
+
if (TYPEOF(
Pike_
sp[-2]) != T_TYPE) {
+
struct program *p = program_from_svalue(
Pike_
sp - 2);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`|", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`|", 1, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 2);
-
SET_SVAL(sp[-2], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 2);
+
SET_SVAL(
Pike_
sp[-2], T_TYPE, 0, type, pop_unfinished_type());
}
-
if (TYPEOF(sp[-1]) != T_TYPE) {
-
struct program *p = program_from_svalue(sp - 1);
+
if (TYPEOF(
Pike_
sp[-1]) != T_TYPE) {
+
struct program *p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`|", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`|", 2, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 1);
-
SET_SVAL(sp[-1], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 1);
+
SET_SVAL(
Pike_
sp[-1], T_TYPE, 0, type, pop_unfinished_type());
} } else { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`|", 2, get_name_of_type(TYPEOF(sp[-2])));
+
SIMPLE_ARG_
TYPE_
ERROR("`|", 2, get_name_of_type(TYPEOF(
Pike_
sp[-2])));
} }
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_OR,2);
-
break
;
+
if(!call
_
lfun
(LFUN_OR,
LFUN_ROR))
+
PIKE_ERROR("`|", "Bitwise or on objects without `| operator.\n", Pike_sp,
2);
+
return
;
case T_INT:
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer | sp[0].u.integer);
-
break
;
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer,
+
Pike_
sp[-1].u.integer |
Pike_
sp[0].u.integer);
+
return
;
case T_MAPPING: { struct mapping *m;
-
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_OR);
+
m=merge_mappings(
Pike_
sp[-2].u.mapping,
Pike_
sp[-1].u.mapping, PIKE_ARRAY_OP_OR);
pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct multiset *l;
-
if (sp[-2].u.multiset->refs == 1) {
-
l=merge_multisets(sp[-2].u.multiset,
sp[-1].u.multiset,
-
PIKE
_
ARRAY_OP_OR_LEFT | PIKE_MERGE_DESTR_A);
-
} else {
-
l=merge_multisets(
sp[-
2].u.multiset, sp[-
1].u.multiset,
+
l=merge_multisets(
Pike_
sp[-2].u.multiset,
Pike
_sp[-1].u.multiset,
PIKE_ARRAY_OP_OR_LEFT);
-
}
+
pop_n_elems(2); push_multiset(l); return; } case T_ARRAY: {
-
if (sp[-1].u.array->size == 1) {
+
if (
Pike_
sp[-1].u.array->size == 1) {
/* Common case (typically the |= operator). */
-
int i = array_search(sp[-2].u.array, sp[-1].u.array->item, 0);
+
int i = array_search(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array->item, 0);
if (i == -1) { f_add(2); } else { pop_stack(); }
-
} else if ((sp[-2].u.array == sp[-1].u.array) &&
-
(sp[-1].u.array->refs == 2)) {
+
} else if ((
Pike_
sp[-2].u.array ==
Pike_
sp[-1].u.array) &&
+
(
Pike_
sp[-1].u.array->refs == 2)) {
/* Not common, but easy to detect... */ pop_stack(); } else { struct array *a;
-
a=merge_array_with_order(sp[-2].u.array, sp[-1].u.array,
+
a=merge_array_with_order(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array,
PIKE_ARRAY_OP_OR_LEFT); pop_n_elems(2); push_array(a); } return; } case T_TYPE: { struct pike_type *t;
-
t = or_pike_types(sp[-2].u.type, sp[-1].u.type, 0);
+
t = or_pike_types(
Pike_
sp[-2].u.type,
Pike_
sp[-1].u.type, 0);
pop_n_elems(2); push_type_value(t); return; } case T_FUNCTION: case T_PROGRAM: { struct program *p; struct pike_type *a; struct pike_type *b; struct pike_type *t;
-
p = program_from_svalue(sp - 2);
+
p = program_from_svalue(
Pike_
sp - 2);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`|", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`|", 1, "type");
} type_stack_mark(); push_object_type(0, p->id); a = pop_unfinished_type();
-
p = program_from_svalue(sp - 1);
+
p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`|", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`|", 2, "type");
} type_stack_mark(); push_object_type(0, p->id); b = pop_unfinished_type(); t = or_pike_types(a, b, 0); pop_n_elems(2); push_type_value(t); free_type(a); free_type(b); return; } STRING_BITOP(|,"OR") default:
-
PIKE_ERROR("`|", "Bitwise OR on illegal type.\n", sp, 2);
+
PIKE_ERROR("`|", "Bitwise OR on illegal type.\n",
Pike_
sp, 2);
} } /*! @decl mixed `|(mixed arg1) *! @decl mixed `|(mixed arg1, mixed arg2, mixed ... extras) *! @decl mixed `|(object arg1, mixed arg2) *! @decl mixed `|(mixed arg1, object arg2) *! @decl int `|(int arg1, int arg2) *! @decl string `|(string arg1, string arg2) *! @decl array `|(array arg1, array arg2)
pike.git/src/operators.c:3093:
*! @mixed arg1 *! @type int *! Bitwise or of @[arg1] and @[arg2]. *! @type string *! The result is a string where each character is the bitwise *! or of the characters in the same position in @[arg1] and *! @[arg2]. The arguments must be strings of the same length. *! @type array *! The result is an array with the elements in @[arg1] *! concatenated with those in @[arg2] that doesn't occur in
-
*! @[arg1] (according to @[`==]). The order
between the
-
*! elements that come from the same argument is kept.
+
*! @[arg1] (according to @[`
>], @[`<], @[`
==]). The order
+
*!
between the
elements that come from the same argument is kept.
*! *! Every element in @[arg1] is only matched once against an *! element in @[arg2], so if @[arg2] contains several elements *! that are equal to each other and are more than their *! counterparts in @[arg1], the rightmost remaining elements in *! @[arg2] are kept. *! @type mapping *! The result is like @[arg1] but extended with the entries *! from @[arg2]. If the same index (according to @[hash_value] *! and @[`==]) occur in both, the value from @[arg2] is used. *! @type multiset *! The result is like @[arg1] but extended with the entries in *! @[arg2] that doesn't already occur in @[arg1] (according to
-
*! @[`==]). Subsequences with orderwise equal
entries (i.e.
-
*! where @[`<] returns false) are handled just
like the array
-
*! case above.
+
*! @[`
>], @[`<] and @[`
==]). Subsequences with orderwise equal
+
*!
entries (i.e.
where @[`<] returns false) are handled just
+
*!
like the array
case above.
*! @type type|program *! Type union of @[arg1] and @[arg2]. *! @endmixed *! The function is not destructive on the arguments - the result is *! always a new instance. *!
-
+
*! @note
+
*! If this operator is used with arrays or multisets containing objects
+
*! which implement @[lfun::`==()] but @b{not@} @[lfun::`>()] and
+
*! @[lfun::`<()], the result will be undefined.
+
*!
*! @seealso *! @[`&()], @[lfun::`|()], @[lfun::``|()] */ PMOD_EXPORT void f_or(INT32 args) { switch(args) {
-
case 0: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`|", 1);
+
case 0: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`|", 1);
case 1: return; case 2: o_or(); return; default:
-
if(TYPEOF(sp[-args]) == T_OBJECT)
-
{
-
CALL_OPERATOR(LFUN_OR, args);
-
} else {
+
speedup(args, o_or); } }
-
}
+
static int generate_or(node *n) { struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1;
pike.git/src/operators.c:3160:
return 1; default: return 0; } } PMOD_EXPORT void o_xor(void) {
-
if(TYPEOF(sp[-1]) != TYPEOF(sp[-2]))
+
if(TYPEOF(
Pike_
sp[-1]) != TYPEOF(
Pike_
sp[-2]))
{ if(call_lfun(LFUN_XOR, LFUN_RXOR)) { return;
-
} else if (((TYPEOF(sp[-1]) == T_TYPE) || (TYPEOF(sp[-1]) == T_PROGRAM) ||
-
(TYPEOF(sp[-1]) == T_FUNCTION)) &&
-
((TYPEOF(sp[-2]) == T_TYPE) || (TYPEOF(sp[-2]) == T_PROGRAM) ||
-
(TYPEOF(sp[-2]) == T_FUNCTION))) {
-
if (TYPEOF(sp[-2]) != T_TYPE) {
-
struct program *p = program_from_svalue(sp - 2);
+
} else if (((TYPEOF(
Pike_
sp[-1]) == T_TYPE) ||
+
(TYPEOF(
Pike_
sp[-1]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-1]) == T_FUNCTION)) &&
+
((TYPEOF(
Pike_
sp[-2]) == T_TYPE) ||
+
(TYPEOF(
Pike_
sp[-2]) == T_PROGRAM) ||
+
(TYPEOF(
Pike_
sp[-2]) == T_FUNCTION))) {
+
if (TYPEOF(
Pike_
sp[-2]) != T_TYPE) {
+
struct program *p = program_from_svalue(
Pike_
sp - 2);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`^", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`^", 1, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 2);
-
SET_SVAL(sp[-2], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 2);
+
SET_SVAL(
Pike_
sp[-2], T_TYPE, 0, type, pop_unfinished_type());
}
-
if (TYPEOF(sp[-1]) != T_TYPE) {
-
struct program *p = program_from_svalue(sp - 1);
+
if (TYPEOF(
Pike_
sp[-1]) != T_TYPE) {
+
struct program *p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`^", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`^", 2, "type");
} type_stack_mark(); push_object_type(0, p->id);
-
free_svalue(sp - 1);
-
SET_SVAL(sp[-1], T_TYPE, 0, type, pop_unfinished_type());
+
free_svalue(
Pike_
sp - 1);
+
SET_SVAL(
Pike_
sp[-1], T_TYPE, 0, type, pop_unfinished_type());
} } else { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`^", 2, get_name_of_type(TYPEOF(sp[-2])));
+
SIMPLE_ARG_
TYPE_
ERROR("`^", 2, get_name_of_type(TYPEOF(
Pike_
sp[-2])));
} }
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_XOR,2);
-
break
;
+
if(!call
_
lfun
(LFUN_XOR,
LFUN_RXOR))
+
PIKE_ERROR("`^", "Bitwise xor on objects without `^ operator.\n", Pike_sp,
2);
+
return
;
case T_INT:
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer ^ sp[0].u.integer);
-
break
;
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer,
+
Pike_
sp[-1].u.integer ^
Pike_
sp[0].u.integer);
+
return
;
case T_MAPPING: { struct mapping *m;
-
m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_XOR);
+
m=merge_mappings(
Pike_
sp[-2].u.mapping,
Pike_
sp[-1].u.mapping, PIKE_ARRAY_OP_XOR);
pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct multiset *l;
-
if (sp[-2].u.multiset->refs == 1) {
-
l=merge_multisets(sp[-2].u.multiset,
sp[-1].u.multiset,
-
PIKE
_
ARRAY_OP_XOR | PIKE_MERGE_DESTR_A);
-
} else {
-
l=merge_multisets(
sp[-
2].u.multiset, sp[-
1].u.multiset,
+
l=merge_multisets(
Pike_
sp[-2].u.multiset,
Pike
_sp[-1].u.multiset,
PIKE_ARRAY_OP_XOR);
-
}
+
pop_n_elems(2); push_multiset(l); return; } case T_ARRAY: { struct array *a;
-
a=merge_array_with_order(sp[-2].u.array, sp[-1].u.array, PIKE_ARRAY_OP_XOR);
+
a=merge_array_with_order(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array, PIKE_ARRAY_OP_XOR);
pop_n_elems(2); push_array(a); return; } case T_FUNCTION: case T_PROGRAM: { struct program *p;
-
p = program_from_svalue(sp - 1);
+
p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`^", 2, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`^", 2, "type");
} type_stack_mark(); push_object_type(0, p->id); pop_stack(); push_type_value(pop_unfinished_type()); stack_swap();
-
p = program_from_svalue(sp - 1);
+
p = program_from_svalue(
Pike_
sp - 1);
if (!p) { int args = 2; stack_swap();
-
SIMPLE_
BAD_
ARG_ERROR("`^", 1, "type");
+
SIMPLE_ARG_
TYPE_
ERROR("`^", 1, "type");
} type_stack_mark(); push_object_type(0, p->id); pop_stack(); push_type_value(pop_unfinished_type()); }
-
/*
FALL_THROUGH
*/
+
/*
FALLTHRU
*/
case T_TYPE: { /* a ^ b == (a&~b)|(~a&b) */ struct pike_type *a; struct pike_type *b;
-
copy_pike_type(a, sp[-2].u.type);
-
copy_pike_type(b, sp[-1].u.type);
+
copy_pike_type(a,
Pike_
sp[-2].u.type);
+
copy_pike_type(b,
Pike_
sp[-1].u.type);
o_compl(); /* ~b */ o_and(); /* a&~b */ push_type_value(a); o_compl(); /* ~a */ push_type_value(b); o_and(); /* ~a&b */ o_or(); /* (a&~b)|(~a&b) */ return; } STRING_BITOP(^,"XOR") default:
-
PIKE_ERROR("`^", "Bitwise XOR on illegal type.\n", sp, 2);
+
PIKE_ERROR("`^", "Bitwise XOR on illegal type.\n",
Pike_
sp, 2);
} } /*! @decl mixed `^(mixed arg1) *! @decl mixed `^(mixed arg1, mixed arg2, mixed ... extras) *! @decl mixed `^(object arg1, mixed arg2) *! @decl mixed `^(mixed arg1, object arg2) *! @decl int `^(int arg1, int arg2) *! @decl string `^(string arg1, string arg2) *! @decl array `^(array arg1, array arg2)
pike.git/src/operators.c:3337:
*! @type int *! Bitwise exclusive or of @[arg1] and @[arg2]. *! @type string *! The result is a string where each character is the bitwise *! exclusive or of the characters in the same position in *! @[arg1] and @[arg2]. The arguments must be strings of the *! same length. *! @type array *! The result is an array with the elements in @[arg1] that *! doesn't occur in @[arg2] concatenated with those in @[arg2]
-
*! that doesn't occur in @[arg1] (according to @[`
==
]
).
The
-
*! order between the elements that come from the
same argument
-
*! is kept.
+
*! that doesn't occur in @[arg1] (according to @[`
>
]
,
@[`<] and
+
*!
@[`==]). The
order between the elements that come from the
+
*!
same argument
is kept.
*! *! Every element is only matched once against an element in the *! other array, so if one contains several elements that are *! equal to each other and are more than their counterparts in *! the other array, the rightmost remaining elements are kept. *! @type mapping *! The result is like @[arg1] but with the entries from @[arg1] *! and @[arg2] whose indices are different between them *! (according to @[hash_value] and @[`==]). *! @type multiset *! The result is like @[arg1] but with the entries from @[arg1] *! and @[arg2] that are different between them (according to
-
*! @[
hash_value
] and @[`==]). Subsequences with orderwise equal
+
*! @[
`>
]
,
@[`<]
and @[`==]). Subsequences with orderwise equal
*! entries (i.e. where @[`<] returns false) are handled just *! like the array case above. *! @type type|program *! The result is a type computed like this: *! @expr{(@[arg1]&~@[arg2])|(~@[arg1]&@[arg2])@}. *! @endmixed *! The function is not destructive on the arguments - the result is *! always a new instance. *!
-
+
*! @note
+
*! If this operator is used with arrays or multisets containing objects
+
*! which implement @[lfun::`==()] but @b{not@} @[lfun::`>()] and
+
*! @[lfun::`<()], the result will be undefined.
+
*!
*! @seealso *! @[`&()], @[`|()], @[lfun::`^()], @[lfun::``^()] */ PMOD_EXPORT void f_xor(INT32 args) { switch(args) {
-
case 0: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`^", 1);
+
case 0: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`^", 1);
case 1: return; case 2: o_xor(); return; default:
-
if(TYPEOF(sp[-args]) == T_OBJECT)
-
{
-
CALL_OPERATOR(LFUN_XOR, args);
-
} else {
+
speedup(args, o_xor); } }
-
}
+
static int generate_xor(node *n) { struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1;
pike.git/src/operators.c:3404:
modify_stack_depth(-1); return 1; default: return 0; } } PMOD_EXPORT void o_lsh(void) {
-
if ((TYPEOF(sp[-
1
]) == T_
INT
)
&&
(TYPEOF(sp[-
2
]) == T_INT)
&&
-
INT_TYPE_LSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+
int args = 2;
+
if ((TYPEOF(
Pike_
sp[-
2
]) == T_
OBJECT
)
||
+
(TYPEOF(
Pike_
sp[-
1
]) == T_
OBJECT))
+
goto call_lfun;
+
+
if ((TYPEOF(Pike_sp[-1]) != T_
INT)
|| (Pike_sp[-1].u.integer < 0)) {
+
SIMPLE_ARG_TYPE_ERROR("`<<",
2,
"int(0..)|object");
+
}
+
+
switch(TYPEOF(Pike_sp[-2])) {
+
case T_
INT
:
+
if (!INT
_TYPE_LSH_OVERFLOW(
Pike_
sp[-2].u.integer,
Pike_
sp[-1].u.integer))
+
break;
convert_stack_top_to_bignum();
-
if(TYPEOF(sp[-1])
!=
T_INT
||
TYPEOF(sp[-2])
!=
T_
INT)
-
{
-
int args = 2;
+
/*
FALLTHRU
*/
+
+
case
T_
OBJECT:
+
call_lfun:
if(call_lfun(LFUN_LSH, LFUN_RLSH)) return;
-
if(TYPEOF(sp[-2]) != T_INT)
-
SIMPLE_
BAD_
ARG_ERROR("`<<", 1, "int|object");
-
SIMPLE_
BAD_
ARG_ERROR("`<<", 2, "int(0..)|object");
+
if(TYPEOF(
Pike_
sp[-2]) != T_INT)
+
SIMPLE_ARG_
TYPE_
ERROR("`<<", 1, "int|
float|
object");
+
SIMPLE_ARG_
TYPE_
ERROR("`<<", 2, "int(0..)|object");
+
break;
+
+
case T_FLOAT:
+
Pike_sp--;
+
Pike_sp[-1].u.float_number = ldexp(Pike_sp[-1].u.float_number,
+
Pike_sp->u.integer);
+
return;
+
+
default:
+
SIMPLE_ARG_TYPE_ERROR("`<<", 1, "int|float|object");
+
break;
}
-
if
(sp[-1]
.u.integer
<
0)
{
-
int
args
=
2;
-
SIMPLE
_
BAD_ARG_ERROR("`
<<
",
2, "int(0
.
.
)
|object")
;
+
Pike_sp--;
+
SET_SVAL
(
Pike_
sp[-1]
,
T_INT,
NUMBER_NUMBER,
integer,
+
Pike
_
sp[-1].u.integer
<<
Pike_sp->u
.
integer
);
}
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer << sp->u.integer);
-
}
+
-
/*! @decl int `<<(int arg1, int arg2)
-
*! @decl mixed `<<(object arg1, int|object arg2)
+
/*! @decl int `<<(int arg1, int
(0..)
arg2)
+
*! @decl mixed `<<(object arg1, int
(0..)
|object arg2)
*! @decl mixed `<<(int arg1, object arg2)
-
+
*! @decl mixed `<<(float arg1, int(0..) arg2)
*! *! Left shift. *! *! Every expression with the @expr{<<@} operator becomes a call to *! this function, i.e. @expr{a<<b@} is the same as *! @expr{predef::`<<(a,b)@}. *! *! If @[arg1] is an object that implements @[lfun::`<<()], that *! function will be called with @[arg2] as the single argument. *! *! If @[arg2] is an object that implements @[lfun::``<<()], that *! function will be called with @[arg1] as the single argument. *!
-
+
*! If @[arg1] is a float and @[arg2] is a non-negative integer,
+
*! @[arg1] will be multiplied by @expr{1<<@[arg2]@}.
+
*!
*! Otherwise @[arg1] will be shifted @[arg2] bits left. *! *! @seealso *! @[`>>()] */ PMOD_EXPORT void f_lsh(INT32 args) {
-
if(args != 2)
{
-
/* FIXME: Not appropriate if too many args. */
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`<<", 2);
-
}
+
if(args != 2)
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`<<", 2);
o_lsh(); } static int generate_lsh(node *n) { struct compilation *c = THIS_COMPILATION; if(count_args(CDR(n))==2) { do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_LSH); modify_stack_depth(-1); return 1; } return 0; } PMOD_EXPORT void o_rsh(void) {
-
if(TYPEOF(sp[-2]) != T_INT || TYPEOF(sp[-1]) != T_INT)
-
{
+
int args = 2;
-
+
if ((TYPEOF(Pike_sp[-2]) == T_OBJECT) || (TYPEOF(Pike_sp[-1]) == T_OBJECT))
+
{
if(call_lfun(LFUN_RSH, LFUN_RRSH)) return;
-
if(TYPEOF(sp[-2]) != T_INT)
-
SIMPLE_
BAD_
ARG_ERROR("`>>", 1, "int|object");
-
SIMPLE_
BAD_
ARG_ERROR("`>>", 2, "int(0..)|object");
+
if(TYPEOF(
Pike_
sp[-2]) != T_INT)
+
SIMPLE_ARG_
TYPE_
ERROR("`>>", 1, "int|object");
+
SIMPLE_ARG_
TYPE_
ERROR("`>>", 2, "int(0..)|object");
}
-
if (sp[-1].u.integer < 0) {
-
int args = 2;
-
SIMPLE_
BAD_
ARG_ERROR("`>>", 2, "int(0..)|object");
+
if (
(TYPEOF(Pike_
sp[-1]
) != T_INT) || (Pike_sp[-1]
.u.integer < 0)
)
{
+
SIMPLE_ARG_
TYPE_
ERROR("`>>", 2, "int(0..)|object");
}
-
if( INT_TYPE_RSH_OVERFLOW(sp[-
2
].u.integer, sp
[
-
1].
u.integer) )
+
Pike_sp--;
+
switch(TYPEOF(Pike_sp[-1])) {
+
case T_INT:
+
if( INT_TYPE_RSH_OVERFLOW(
Pike_
sp[-
1
].u.integer,
Pike_
sp-
>
u.integer) )
{
-
sp--;
-
if (sp[-1].u.integer < 0) {
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, -1);
+
if (
Pike_
sp[-1].u.integer < 0) {
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, -1);
} else {
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, 0);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, 0);
} return; }
-
+
break;
+
case T_FLOAT:
+
Pike_sp[-1].u.float_number = ldexp(Pike_sp[-1].u.float_number,
+
-Pike_sp->u.integer);
+
return;
+
default:
+
SIMPLE_ARG_TYPE_ERROR("`>>", 1, "int|float|object");
+
break;
+
}
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,
-
sp[-1].u.integer >> sp->u.integer);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer,
+
Pike_
sp[-1].u.integer >>
Pike_
sp->u.integer);
}
-
/*! @decl int `>>(int arg1, int arg2)
-
*! @decl mixed `>>(object arg1, int|object arg2)
+
/*! @decl int `>>(int arg1, int
(0..)
arg2)
+
*! @decl mixed `>>(object arg1, int
(0..)
|object arg2)
*! @decl mixed `>>(int arg1, object arg2)
-
+
*! @decl float `>>(float arg1, int(0..) arg2)
*! *! Right shift. *! *! Every expression with the @expr{>>@} operator becomes a call to *! this function, i.e. @expr{a>>b@} is the same as *! @expr{predef::`>>(a,b)@}. *! *! If @[arg1] is an object that implements @[lfun::`>>()], that *! function will be called with @[arg2] as the single argument. *! *! If @[arg2] is an object that implements @[lfun::``>>()], that *! function will be called with @[arg1] as the single argument. *!
-
+
*! If @[arg1] is a float and @[arg2] is a non-negative integer,
+
*! @[arg1] will be divided by @expr{1<<@[arg2]@}.
+
*!
*! Otherwise @[arg1] will be shifted @[arg2] bits right. *! *! @seealso *! @[`<<()] */ PMOD_EXPORT void f_rsh(INT32 args) {
-
if(args != 2)
{
-
/* FIXME: Not appropriate if too many args. */
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`>>", 2);
-
}
+
if(args != 2)
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`>>", 2);
o_rsh(); } static int generate_rsh(node *n) { if(count_args(CDR(n))==2) { struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_RSH);
pike.git/src/operators.c:3552:
return 1; } return 0; } #define TWO_TYPES(X,Y) (((X)<<8)|(Y)) PMOD_EXPORT void o_multiply(void) { int args = 2;
-
switch(TWO_TYPES(TYPEOF(sp[-2]), TYPEOF(sp[-1])))
+
switch(TWO_TYPES(TYPEOF(
Pike_
sp[-2]), TYPEOF(
Pike_
sp[-1])))
{ case TWO_TYPES(T_ARRAY, T_INT): { struct array *ret; struct svalue *pos; INT32 e;
-
if(sp[-1].u.integer < 0)
-
SIMPLE_
BAD_
ARG_ERROR("`*", 2, "int(0..)");
-
ret=allocate_array(sp[-2].u.array->size * sp[-1].u.integer);
+
if(
Pike_
sp[-1].u.integer < 0)
+
SIMPLE_ARG_
TYPE_
ERROR("`*", 2, "int(0..)");
+
ret=allocate_array(
Pike_
sp[-2].u.array->size *
Pike_
sp[-1].u.integer);
pos=ret->item;
-
for(e=0;e<sp[-1].u.integer;e++,pos+=sp[-2].u.array->size)
+
for(e=0;e<
Pike_
sp[-1].u.integer;e++,pos+=
Pike_
sp[-2].u.array->size)
assign_svalues_no_free(pos,
-
sp[-2].u.array->item,
-
sp[-2].u.array->size,
-
sp[-2].u.array->type_field);
-
ret->type_field=sp[-2].u.array->type_field;
+
Pike_
sp[-2].u.array->item,
+
Pike_
sp[-2].u.array->size,
+
Pike_
sp[-2].u.array->type_field);
+
ret->type_field=
Pike_
sp[-2].u.array->type_field;
pop_n_elems(2); push_array(ret); return; } case TWO_TYPES(T_ARRAY, T_FLOAT): { struct array *src; struct array *ret; struct svalue *pos; ptrdiff_t asize, delta;
-
if(sp[-1].u.float_number < 0)
-
SIMPLE_
BAD_
ARG_ERROR("`*", 2, "float(0..)");
+
if(
Pike_
sp[-1].u.float_number < 0)
+
SIMPLE_ARG_
TYPE_
ERROR("`*", 2, "float(0..)");
-
src = sp[-2].u.array;
+
src =
Pike_
sp[-2].u.array;
delta = src->size;
-
asize = (ptrdiff_t)floor(delta * sp[-1].u.float_number + 0.5);
+
asize = (ptrdiff_t)floor(delta *
Pike_
sp[-1].u.float_number + 0.5);
ret = allocate_array(asize); pos = ret->item; if (asize > delta) { ret->type_field = src->type_field; assign_svalues_no_free(pos, src->item, delta, src->type_field); pos += delta; asize -= delta;
pike.git/src/operators.c:3624:
return; } case TWO_TYPES(T_STRING, T_FLOAT): { struct pike_string *src; struct pike_string *ret; char *pos; ptrdiff_t len, delta;
-
if(sp[-1].u.float_number < 0)
-
SIMPLE_
BAD_
ARG_ERROR("`*", 2, "float(0..)");
-
src = sp[-2].u.string;
-
len = (ptrdiff_t)floor(src->len * sp[-1].u.float_number + 0.5);
+
if(
Pike_
sp[-1].u.float_number < 0)
+
SIMPLE_ARG_
TYPE_
ERROR("`*", 2, "float(0..)");
+
src =
Pike_
sp[-2].u.string;
+
len = (ptrdiff_t)floor(src->len *
Pike_
sp[-1].u.float_number + 0.5);
ret = begin_wide_shared_string(len, src->size_shift); len <<= src->size_shift; delta = src->len << src->size_shift; pos = ret->str; if (len > delta) {
-
MEMCPY
(pos, src->str, delta);
+
memcpy
(pos, src->str, delta);
pos += delta; len -= delta; while (len > delta) {
-
MEMCPY
(pos, ret->str, delta);
+
memcpy
(pos, ret->str, delta);
pos += delta; len -= delta; delta <<= 1; } if (len) {
-
MEMCPY
(pos, ret->str, len);
+
memcpy
(pos, ret->str, len);
} } else if (len) {
-
MEMCPY
(pos, src->str, len);
+
memcpy
(pos, src->str, len);
} pop_n_elems(2); push_string(low_end_shared_string(ret)); return; } case TWO_TYPES(T_STRING, T_INT): { struct pike_string *ret; char *pos; INT_TYPE e; ptrdiff_t len;
-
if(sp[-1].u.integer < 0)
-
SIMPLE_
BAD_
ARG_ERROR("`*", 2, "int(0..)");
-
ret=begin_wide_shared_string(sp[-2].u.string->len * sp[-1].u.integer,
-
sp[-2].u.string->size_shift);
+
if(
Pike_
sp[-1].u.integer < 0)
+
SIMPLE_ARG_
TYPE_
ERROR("`*", 2, "int(0..)");
+
ret=begin_wide_shared_string(
Pike_
sp[-2].u.string->len *
Pike_
sp[-1].u.integer,
+
Pike_
sp[-2].u.string->size_shift);
pos=ret->str;
-
len=sp[-2].u.string->len << sp[-2].u.string->size_shift;
-
for(e=0;e<sp[-1].u.integer;e++,pos+=len)
-
MEMCPY
(pos,sp[-2].u.string->str,len);
+
len=
Pike_
sp[-2].u.string->len <<
Pike_
sp[-2].u.string->size_shift;
+
for(e=0;e<
Pike_
sp[-1].u.integer;e++,pos+=len)
+
memcpy
(pos,
Pike_
sp[-2].u.string->str,len);
pop_n_elems(2); push_string(low_end_shared_string(ret)); return; } case TWO_TYPES(T_ARRAY,T_STRING): { struct pike_string *ret;
-
ret=implode(sp[-2].u.array,sp[-1].u.string);
-
free_string(sp[-1].u.string);
-
free_array(sp[-2].u.array);
-
SET_SVAL(sp[-2], T_STRING, 0, string, ret);
-
sp--;
+
ret=implode(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.string);
+
free_string(
Pike_
sp[-1].u.string);
+
free_array(
Pike_
sp[-2].u.array);
+
SET_SVAL(
Pike_
sp[-2], T_STRING, 0, string, ret);
+
Pike_
sp--;
return; } case TWO_TYPES(T_ARRAY,T_ARRAY): { struct array *ret;
-
ret=implode_array(sp[-2].u.array, sp[-1].u.array);
+
ret=implode_array(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array);
pop_n_elems(2); push_array(ret); return; } case TWO_TYPES(T_FLOAT,T_FLOAT):
-
sp--;
-
sp[-1].u.float_number *= sp[0].u.float_number;
+
Pike_
sp--;
+
Pike_
sp[-1].u.float_number *=
Pike_
sp[0].u.float_number;
return; case TWO_TYPES(T_FLOAT,T_INT):
-
sp--;
-
sp[-1].u.float_number *= (FLOAT_TYPE)sp[0].u.integer;
+
Pike_
sp--;
+
Pike_
sp[-1].u.float_number *= (FLOAT_TYPE)
Pike_
sp[0].u.integer;
return; case TWO_TYPES(T_INT,T_FLOAT):
-
sp--;
-
sp[-1].u.float_number=
-
(FLOAT_TYPE) sp[-1].u.integer * sp[0].u.float_number;
-
SET_SVAL_TYPE(sp[-1], T_FLOAT);
+
Pike_
sp--;
+
Pike_
sp[-1].u.float_number=
+
(FLOAT_TYPE)
Pike_
sp[-1].u.integer *
Pike_
sp[0].u.float_number;
+
SET_SVAL_TYPE(
Pike_
sp[-1], T_FLOAT);
return; case TWO_TYPES(T_INT,T_INT): { INT_TYPE res;
-
int of = 0;
+
-
res
=
DO_INT_TYPE_MUL_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer, &
of
)
;
-
-
if(of
)
+
if
(
DO_INT_TYPE_MUL_OVERFLOW(
Pike_
sp[-2].u.integer,
Pike_
sp[-1].u.integer, &
res
))
{ convert_stack_top_to_bignum(); goto do_lfun_multiply; }
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, res);
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, res);
return; } default: do_lfun_multiply:
-
if(call_lfun(LFUN_MULTIPLY, LFUN_RMULTIPLY))
+
if(
!
call_lfun(LFUN_MULTIPLY, LFUN_RMULTIPLY))
+
PIKE_ERROR("`*", "Multiplication on objects without `* operator.\n", Pike_sp, 2);
return;
-
+
}
+
}
-
PIKE
_ERROR("`*",
"Bad
arguments
.
\n"
, sp, 2);
+
+
+
+
+
/*!
@decl
object|int|float
`**(object|int|float
arg1, object|int|float arg2)
+
*!
+
*! Exponentiation. Raise arg1 to the power of arg2.
+
*!
+
*/
+
PMOD
_
EXPORT void f_exponent(INT32 args)
+
{
+
double a, b;
+
+
if(args != 2 )
+
SIMPLE_WRONG_NUM_ARGS_
ERROR("`*
*
",
2);
+
+
switch( TWO_TYPES(TYPEOF(Pike_sp[-2]), TYPEOF(Pike_sp[-1])) )
+
{
+
case TWO_TYPES(T_FLOAT,T_FLOAT):
+
a = Pike_sp[-2]
.
u.float_number;
+
b = Pike_sp[-1].u.float_number;
+
goto res_is_powf;
+
+
case TWO_TYPES(T_FLOAT
,
T_INT):
+
a = Pike_
sp
[-2].u.float_number;
+
b = (double)Pike_sp[-1].u.integer;
+
goto res_is_powf;
+
+
case TWO_TYPES(T_INT
,
T_FLOAT):
+
a = (double)Pike_sp[-
2
].u.integer;
+
b = (double
)
Pike_sp[-1].u.float_number
;
+
+
res_is_powf:
+
{
+
Pike_sp-=2;
+
push_float( pow( a, b ) );
+
return;
}
-
+
default:
+
stack_swap();
+
convert_stack_top_to_bignum();
+
stack_swap();
+
/* FALLTHRU *//* again (this is the slow path).. */
+
+
case TWO_TYPES(T_OBJECT,T_INT):
+
case TWO_TYPES(T_OBJECT,T_FLOAT):
+
case TWO_TYPES(T_OBJECT,T_OBJECT):
+
case TWO_TYPES(T_INT,T_OBJECT):
+
case TWO_TYPES(T_FLOAT,T_OBJECT):
+
if( !call_lfun( LFUN_POW, LFUN_RPOW ) )
+
{
+
if( TYPEOF(Pike_sp[-2]) != PIKE_T_OBJECT )
+
{
+
stack_swap();
+
convert_stack_top_to_bignum();
+
stack_swap();
+
if( call_lfun( LFUN_POW, LFUN_RPOW ) )
+
return;
}
-
+
Pike_error("Illegal argument 1 to `** (object missing implementation of `**).\n");
+
}
+
return;
+
}
+
}
-
+
/*! @decl mixed `*(mixed arg1) *! @decl mixed `*(object arg1, mixed arg2, mixed ... extras) *! @decl mixed `*(mixed arg1, object arg2) *! @decl array `*(array arg1, int arg2) *! @decl array `*(array arg1, float arg2) *! @decl string `*(string arg1, int arg2) *! @decl string `*(string arg1, float arg2) *! @decl string `*(array(string) arg1, string arg2) *! @decl array `*(array(array) arg1, array arg2) *! @decl float `*(float arg1, int|float arg2)
pike.git/src/operators.c:3798:
*! @note *! In Pike 7.0 and earlier the multiplication order was unspecified. *! *! @seealso *! @[`+()], @[`-()], @[`/()], @[lfun::`*()], @[lfun::``*()] */ PMOD_EXPORT void f_multiply(INT32 args) { switch(args) {
-
case 0: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`*", 1);
+
case 0: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`*", 1);
case 1: return; case 2: o_multiply(); return; default:
-
if(TYPEOF(sp[-args]) == T_OBJECT)
+
{
-
CALL_OPERATOR(LFUN_MULTIPLY, args);
-
} else {
+
INT32 i = -args, j = -1; /* Reverse the arguments */ while(i < j) {
-
struct svalue tmp = sp[i];
-
sp[i++] = sp[j];
-
sp[j--] = tmp;
+
struct svalue tmp =
Pike_
sp[i];
+
Pike_
sp[i++] =
Pike_
sp[j];
+
Pike_
sp[j--] = tmp;
} while(--args > 0) { /* Restore the order, and multiply */ stack_swap(); o_multiply(); } } } }
pike.git/src/operators.c:3844:
modify_stack_depth(-1); return 1; default: return 0; } } PMOD_EXPORT void o_divide(void) {
-
if(TYPEOF(sp[-2]) != TYPEOF(sp[-1]) && !float_promote())
+
if(TYPEOF(
Pike_
sp[-2]) != TYPEOF(
Pike_
sp[-1]) && !float_promote())
{ if(call_lfun(LFUN_DIVIDE, LFUN_RDIVIDE)) return;
-
switch(TWO_TYPES(TYPEOF(sp[-2]), TYPEOF(sp[-1])))
+
switch(TWO_TYPES(TYPEOF(
Pike_
sp[-2]), TYPEOF(
Pike_
sp[-1])))
{ case TWO_TYPES(T_STRING,T_INT): { struct array *a; INT_TYPE len; ptrdiff_t size,e,pos=0;
-
len=sp[-1].u.integer;
+
len=
Pike_
sp[-1].u.integer;
if(!len) OP_DIVISION_BY_ZERO_ERROR("`/"); if(len<0) { len=-len;
-
size=sp[-2].u.string->len / len;
-
pos+=sp[-2].u.string->len % len;
+
size=
Pike_
sp[-2].u.string->len / len;
+
pos+=
Pike_
sp[-2].u.string->len % len;
}else{
-
size=sp[-2].u.string->len / len;
+
size=
Pike_
sp[-2].u.string->len / len;
} a=allocate_array(size); for(e=0;e<size;e++) { SET_SVAL(a->item[e], T_STRING, 0, string,
-
string_slice(sp[-2].u.string, pos,len));
+
string_slice(
Pike_
sp[-2].u.string, pos,len));
pos+=len; } a->type_field=BIT_STRING; pop_n_elems(2); push_array(a); return; } case TWO_TYPES(T_STRING,T_FLOAT): { struct array *a; ptrdiff_t size, pos, last, e; FLOAT_ARG_TYPE len;
-
len=sp[-1].u.float_number;
+
len=
Pike_
sp[-1].u.float_number;
if(len==0.0) OP_DIVISION_BY_ZERO_ERROR("`/"); if(len<0) { len=-len;
-
size=(ptrdiff_t)ceil( ((double)sp[-2].u.string->len) / len);
+
size=(ptrdiff_t)ceil( ((double)
Pike_
sp[-2].u.string->len) / len);
a=allocate_array(size);
-
for(last=sp[-2].u.string->len,e=0;e<size-1;e++)
+
for(last=
Pike_
sp[-2].u.string->len,e=0;e<size-1;e++)
{
-
pos=sp[-2].u.string->len - (ptrdiff_t)((e+1)*len+0.5);
+
pos=
Pike_
sp[-2].u.string->len - (ptrdiff_t)((e+1)*len+0.5);
SET_SVAL(a->item[size-1-e], T_STRING, 0, string,
-
string_slice(sp[-2].u.string, pos, last-pos));
+
string_slice(
Pike_
sp[-2].u.string, pos, last-pos));
last=pos; } pos=0; SET_SVAL(a->item[0], T_STRING, 0, string,
-
string_slice(sp[-2].u.string, pos, last-pos));
+
string_slice(
Pike_
sp[-2].u.string, pos, last-pos));
}else{
-
size=(ptrdiff_t)ceil( ((double)sp[-2].u.string->len) / len);
+
size=(ptrdiff_t)ceil( ((double)
Pike_
sp[-2].u.string->len) / len);
a=allocate_array(size); for(last=0,e=0;e<size-1;e++) {
-
pos =
DO_NOT_WARN
(
(
ptrdiff_t)((e+1)*len+0.5)
)
;
+
pos = (ptrdiff_t)((e+1)*len+0.5);
SET_SVAL(a->item[e], T_STRING, 0, string,
-
string_slice(sp[-2].u.string, last, pos-last));
+
string_slice(
Pike_
sp[-2].u.string, last, pos-last));
last=pos; }
-
pos=sp[-2].u.string->len;
+
pos=
Pike_
sp[-2].u.string->len;
SET_SVAL(a->item[e], T_STRING, 0, string,
-
string_slice(sp[-2].u.string, last, pos-last));
+
string_slice(
Pike_
sp[-2].u.string, last, pos-last));
} a->type_field=BIT_STRING; pop_n_elems(2); push_array(a); return; } case TWO_TYPES(T_ARRAY, T_INT): { struct array *a; ptrdiff_t size,e,pos;
-
INT_TYPE len=sp[-1].u.integer;
+
INT_TYPE len=
Pike_
sp[-1].u.integer;
if(!len) OP_DIVISION_BY_ZERO_ERROR("`/"); if (!Pike_sp[-2].u.array->size) { pop_n_elems (2); ref_push_array (&empty_array); return; } if(len<0) { len = -len;
-
pos = sp[-2].u.array->size % len;
+
pos =
Pike_
sp[-2].u.array->size % len;
}else{ pos = 0; }
-
size = sp[-2].u.array->size / len;
+
size =
Pike_
sp[-2].u.array->size / len;
a=allocate_array(size); for(e=0;e<size;e++) { SET_SVAL(a->item[e], T_ARRAY, 0, array,
-
friendly_slice_array(sp[-2].u.array, pos, pos+len));
+
friendly_slice_array(
Pike_
sp[-2].u.array, pos, pos+len));
pos+=len; } a->type_field=BIT_ARRAY; pop_n_elems(2); push_array(a); return; } case TWO_TYPES(T_ARRAY,T_FLOAT): { struct array *a; ptrdiff_t last,pos,e,size; FLOAT_ARG_TYPE len;
-
len=sp[-1].u.float_number;
+
len=
Pike_
sp[-1].u.float_number;
if(len==0.0) OP_DIVISION_BY_ZERO_ERROR("`/"); if (!Pike_sp[-2].u.array->size) { pop_n_elems (2); ref_push_array (&empty_array); return; } if(len<0) { len=-len;
-
size = (ptrdiff_t)ceil( ((double)sp[-2].u.array->size) / len);
+
size = (ptrdiff_t)ceil( ((double)
Pike_
sp[-2].u.array->size) / len);
a=allocate_array(size);
-
for(last=sp[-2].u.array->size,e=0;e<size-1;e++)
+
for(last=
Pike_
sp[-2].u.array->size,e=0;e<size-1;e++)
{
-
pos=sp[-2].u.array->size - (ptrdiff_t)((e+1)*len+0.5);
+
pos=
Pike_
sp[-2].u.array->size - (ptrdiff_t)((e+1)*len+0.5);
SET_SVAL(a->item[size-1-e], T_ARRAY, 0, array,
-
friendly_slice_array(sp[-2].u.array, pos, last));
+
friendly_slice_array(
Pike_
sp[-2].u.array, pos, last));
last=pos; } SET_SVAL(a->item[0], T_ARRAY, 0, array,
-
slice_array(sp[-2].u.array, 0, last));
+
slice_array(
Pike_
sp[-2].u.array, 0, last));
}else{
-
size = (ptrdiff_t)ceil( ((double)sp[-2].u.array->size) / len);
+
size = (ptrdiff_t)ceil( ((double)
Pike_
sp[-2].u.array->size) / len);
a=allocate_array(size); for(last=0,e=0;e<size-1;e++) { pos = (ptrdiff_t)((e+1)*len+0.5); SET_SVAL(a->item[e], T_ARRAY, 0, array,
-
friendly_slice_array(sp[-2].u.array, last, pos));
+
friendly_slice_array(
Pike_
sp[-2].u.array, last, pos));
last=pos; } SET_SVAL(a->item[e], T_ARRAY, 0, array,
-
slice_array(sp[-2].u.array, last, sp[-2].u.array->size));
+
slice_array(
Pike_
sp[-2].u.array, last,
Pike_
sp[-2].u.array->size));
} a->type_field=BIT_ARRAY; pop_n_elems(2); push_array(a); return; } }
-
PIKE_ERROR("`/", "Division on different types.\n", sp, 2);
+
PIKE_ERROR("`/", "Division on different types.\n",
Pike_
sp, 2);
}
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
do
_lfun_
division:
-
CALL
_
OPERATOR
(
LFUN
_
DIVIDE
,2);
-
break
;
+
if(!call
_lfun
(LFUN
_
DIVIDE,LFUN_RDIVIDE))
+
PIKE
_
ERROR
(
"`/", "Division on objects without `/ operator.\n", Pike
_
sp
,
2);
+
return
;
case T_STRING: { struct array *ret;
-
ret=explode(sp[-2].u.string,sp[-1].u.string);
-
free_string(sp[-2].u.string);
-
free_string(sp[-1].u.string);
-
SET_SVAL(sp[-2], T_ARRAY, 0, array, ret);
-
sp--;
+
ret=explode(
Pike_
sp[-2].u.string,
Pike_
sp[-1].u.string);
+
free_string(
Pike_
sp[-2].u.string);
+
free_string(
Pike_
sp[-1].u.string);
+
SET_SVAL(
Pike_
sp[-2], T_ARRAY, 0, array, ret);
+
Pike_
sp--;
return; } case T_ARRAY: {
-
struct array *ret=explode_array(sp[-2].u.array, sp[-1].u.array);
+
struct array *ret=explode_array(
Pike_
sp[-2].u.array,
Pike_
sp[-1].u.array);
pop_n_elems(2); push_array(ret); return; } case T_FLOAT:
-
if(sp[-1].u.float_number == 0.0)
+
if(
Pike_
sp[-1].u.float_number == 0.0)
OP_DIVISION_BY_ZERO_ERROR("`/");
-
sp--;
-
sp[-1].u.float_number /= sp[0].u.float_number;
+
Pike_
sp--;
+
Pike_
sp[-1].u.float_number /=
Pike_
sp[0].u.float_number;
return; case T_INT: { INT_TYPE tmp;
-
if (sp[-1].u.integer == 0)
+
if (
Pike_
sp[-1].u.integer == 0)
OP_DIVISION_BY_ZERO_ERROR("`/");
-
if(INT_TYPE_DIV_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
+
if(INT_TYPE_DIV_OVERFLOW(
Pike_
sp[-2].u.integer,
Pike_
sp[-1].u.integer))
{ stack_swap(); convert_stack_top_to_bignum(); stack_swap();
-
goto do
_lfun_
division
;
+
call
_lfun
(LFUN
_
DIVIDE,LFUN_RDIVIDE)
;
+
return;
} else
-
tmp = sp[-2].u.integer/sp[-1].u.integer;
-
sp--;
+
tmp =
Pike_
sp[-2].u.integer/
Pike_
sp[-1].u.integer;
+
Pike_
sp--;
/* What is this trying to solve? /Noring */ /* It fixes rounding towards negative infinity. /mast */
-
if((sp[-1].u.integer<0) != (sp[0].u.integer<0))
-
if(tmp*sp[0].u.integer!=sp[-1].u.integer)
+
if((
Pike_
sp[-1].u.integer<0) != (
Pike_
sp[0].u.integer<0))
+
if(tmp*
Pike_
sp[0].u.integer!=
Pike_
sp[-1].u.integer)
tmp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, tmp);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, tmp);
return; } default:
-
PIKE_ERROR("`/", "Bad argument 1.\n", sp, 2);
+
PIKE_ERROR("`/", "Bad argument 1.\n",
Pike_
sp, 2);
} } /*! @decl mixed `/(object arg1, mixed arg2) *! @decl mixed `/(mixed arg1, object arg2) *! @decl array(string) `/(string arg1, int arg2) *! @decl array(string) `/(string arg1, float arg2) *! @decl array(array) `/(array arg1, int arg2) *! @decl array(array) `/(array arg1, float arg2) *! @decl array(string) `/(string arg1, string arg2)
pike.git/src/operators.c:4160:
*! zero is not special. This also means that / and % are compatible, so *! that a = b*(a/b) + a%b for all a and b. *! @seealso *! @[`%] */ PMOD_EXPORT void f_divide(INT32 args) { switch(args) { case 0:
-
case 1: SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`/", 2);
+
case 1: SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`/", 2);
case 2: o_divide(); break; default: { INT32 e;
-
struct svalue *s=sp-args;
+
struct svalue *s=
Pike_
sp-args;
push_svalue(s); for(e=1;e<args;e++) { push_svalue(s+e); o_divide(); }
-
assign_svalue(s,sp-1);
-
pop_n_elems(sp-s-1);
+
assign_svalue(s,
Pike_
sp-1);
+
pop_n_elems(
Pike_
sp-s-1);
} } } static int generate_divide(node *n) { if(count_args(CDR(n))==2) { struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_DIVIDE); modify_stack_depth(-1); return 1; } return 0; } PMOD_EXPORT void o_mod(void) {
-
if(TYPEOF(sp[-2]) != TYPEOF(sp[-1]) && !float_promote())
+
if(TYPEOF(
Pike_
sp[-2]) != TYPEOF(
Pike_
sp[-1]) && !float_promote())
{ do_lfun_modulo: if(call_lfun(LFUN_MOD, LFUN_RMOD)) return;
-
switch(TWO_TYPES(TYPEOF(sp[-2]), TYPEOF(sp[-1])))
+
switch(TWO_TYPES(TYPEOF(
Pike_
sp[-2]), TYPEOF(
Pike_
sp[-1])))
{ case TWO_TYPES(T_STRING,T_INT): {
-
struct pike_string *s=sp[-2].u.string;
+
struct pike_string *s=
Pike_
sp[-2].u.string;
ptrdiff_t tmp,base;
-
if(!sp[-1].u.integer)
+
if(!
Pike_
sp[-1].u.integer)
OP_MODULO_BY_ZERO_ERROR("`%");
-
if(sp[-1].u.integer<0)
+
if(
Pike_
sp[-1].u.integer<0)
{
-
tmp=s->len % -sp[-1].u.integer;
+
tmp=s->len % -
Pike_
sp[-1].u.integer;
base=0; }else{
-
tmp=s->len % sp[-1].u.integer;
+
tmp=s->len %
Pike_
sp[-1].u.integer;
base=s->len - tmp; } s=string_slice(s, base, tmp); pop_n_elems(2); push_string(s); return; } case TWO_TYPES(T_ARRAY,T_INT): {
-
struct array *a=sp[-2].u.array;
+
struct array *a=
Pike_
sp[-2].u.array;
ptrdiff_t tmp,base;
-
if(!sp[-1].u.integer)
+
if(!
Pike_
sp[-1].u.integer)
OP_MODULO_BY_ZERO_ERROR("`%");
-
if(sp[-1].u.integer<0)
+
if(
Pike_
sp[-1].u.integer<0)
{
-
tmp=a->size % -sp[-1].u.integer;
+
tmp=a->size % -
Pike_
sp[-1].u.integer;
base=0; }else{
-
tmp=a->size % sp[-1].u.integer;
+
tmp=a->size %
Pike_
sp[-1].u.integer;
base=a->size - tmp; } a=slice_array(a,base,base+tmp); pop_n_elems(2); push_array(a); return; } }
-
PIKE_ERROR("`%", "Modulo on different types.\n", sp, 2);
+
PIKE_ERROR("`%", "Modulo on different types.\n",
Pike_
sp, 2);
}
-
switch(TYPEOF(sp[-2]))
+
switch(TYPEOF(
Pike_
sp[-2]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_MOD,2);
-
break
;
+
if(!call
_
lfun
(LFUN_MOD,
LFUN_RMOD))
+
PIKE_ERROR("`%", "Modulo on objects without `% operator.\n", Pike_sp,
2);
+
return
;
case T_FLOAT: { FLOAT_TYPE foo;
-
if(sp[-1].u.float_number == 0.0)
+
if(
Pike_
sp[-1].u.float_number == 0.0)
OP_MODULO_BY_ZERO_ERROR("`%");
-
sp--;
-
foo =
DO_NOT_WARN
(
(
FLOAT_TYPE)(sp[-1].u.float_number /
-
sp[0].u.float_number)
)
;
-
foo =
DO_NOT_WARN
(
(
FLOAT_TYPE)(sp[-1].u.float_number -
-
sp[0].u.float_number * floor(foo))
)
;
-
sp[-1].u.float_number=foo;
+
Pike_
sp--;
+
foo = (FLOAT_TYPE)(
Pike_
sp[-1].u.float_number /
Pike_
sp[0].u.float_number);
+
foo = (FLOAT_TYPE)(
Pike_
sp[-1].u.float_number -
+
Pike_
sp[0].u.float_number * floor(foo));
+
Pike_
sp[-1].u.float_number=foo;
return; } case T_INT: { int of = 0;
-
INT_TYPE a = sp[-2].u.integer,
-
b = sp[-1].u.integer;
+
INT_TYPE a =
Pike_
sp[-2].u.integer,
+
b =
Pike_
sp[-1].u.integer;
INT_TYPE res; if (b == 0) OP_MODULO_BY_ZERO_ERROR("`%"); if(a>=0) { if(b>=0) { res = a % b; }else{ /* res = ((a+~b)%-b)-~b */
-
res
= DO_INT_TYPE_ADD_OVERFLOW(a, ~b, &
of
)
;
-
res
=
DO_INT_TYPE_MOD_OVERFLOW(res, b, &
of
)
;
-
res
=
DO_INT_TYPE_SUB_OVERFLOW(res, ~b, &
of
);
+
of
= DO_INT_TYPE_ADD_OVERFLOW(a, ~b, &
res
)
+
||
DO_INT_TYPE_MOD_OVERFLOW(res, b, &
res
)
+
||
DO_INT_TYPE_SUB_OVERFLOW(res, ~b, &
res
);
} }else{ if(b>=0) { /* res = b+~((~a) % b) */
-
res
= DO_INT_TYPE_MOD_OVERFLOW(~a, b, &
of
)
;
-
res
=
DO_INT_TYPE_ADD_OVERFLOW(b, ~res, &
of
);
+
of
= DO_INT_TYPE_MOD_OVERFLOW(~a, b, &
res
)
+
||
DO_INT_TYPE_ADD_OVERFLOW(b, ~res, &
res
);
}else{ /* a % b and a % -b are equivalent, if overflow does not * happen * res = -(-a % -b) = a % b; */
-
res
= DO_INT_TYPE_MOD_OVERFLOW(a, b, &
of
);
+
of
= DO_INT_TYPE_MOD_OVERFLOW(a, b, &
res
);
} } if (of) { stack_swap(); convert_stack_top_to_bignum(); stack_swap(); goto do_lfun_modulo; }
-
sp--;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, res);
+
Pike_
sp--;
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, res);
return; } default:
-
PIKE_ERROR("`%", "Bad argument 1.\n", sp, 2);
+
PIKE_ERROR("`%", "Bad argument 1.\n",
Pike_
sp, 2);
} } /*! @decl mixed `%(object arg1, mixed arg2) *! @decl mixed `%(mixed arg1, object arg2) *! @decl string `%(string arg1, int arg2) *! @decl array `%(array arg1, int arg2) *! @decl float `%(float arg1, float|int arg2) *! @decl float `%(int arg1, float arg2) *! @decl int `%(int arg1, int arg2)
pike.git/src/operators.c:4354:
*! @type int|float *! The result will be *! @expr{@[arg1] - @[arg2]*@[floor](@[arg1]/@[arg2])@}. *! The result will be a float if either @[arg1] or @[arg2] is *! a float, and an int otherwise. *! @endmixed *! *! For numbers, this means that *! @ol *! @item
-
*!
a
%
b
always has the same sign as
b
(typically
b
is positive;
-
*! array size, rsa modulo, etc, and
a
varies a lot more than
b
).
+
*!
@expr{a
%
b@}
always has the same sign as
@expr{b@}
+
*!
(typically
@expr{b@}
is positive;
+
*! array size, rsa modulo, etc, and
@expr{a@}
varies a
+
*!
lot more than
@expr{b@}
).
*! @item
-
*! The function
f
(x) = x %
n
behaves in a sane way;
as x increases,
-
*!
f
(x) cycles through the values
0
,1, ..., n-1, 0, .... Nothing
+
*! The function
@expr{f
(x) = x %
n@}
behaves in a sane way;
+
*!
as @expr{x@} increases, @expr{f
(x)
@}
cycles through the
+
*!
values
@expr{0
,1, ..., n-1, 0, ...
@}
. Nothing
*! strange happens when you cross zero. *! @item
-
*! The % operator implements the binary "mod" operation,
as defined
-
*! by Donald Knuth (see the Art of Computer Programming,
1.2.4). It
-
*! should be noted that Pike treats %-by-0 as an error
rather than
-
*! returning 0, though.
+
*! The
@expr{
%
@}
operator implements the binary "mod" operation,
+
*!
as defined
by Donald Knuth (see the Art of Computer Programming,
+
*!
1.2.4). It should be noted that Pike treats %-by-0 as an error
+
*!
rather than
returning 0, though.
*! @item
-
*! / and % are compatible, so that
a
= b*(a/b) + a%
b
for all
a
and
b
.
+
*!
@expr{
/
@}
and
@expr{
%
@}
are compatible, so that
+
*!
@expr{a
=
=
b*
@[floor]
(a/b) + a%
b@}
for all
@expr{a@}
and
@expr{b@}
.
*! @endol *! @seealso
-
*! @[`/]
+
*! @[`/]
, @[floor()]
*/ PMOD_EXPORT void f_mod(INT32 args) {
-
if(args != 2)
{
-
/* FIXME: Not appropriate when too many args. */
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`%", 2);
-
}
+
if(args != 2)
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`%", 2);
o_mod(); } static int generate_mod(node *n) { if(count_args(CDR(n))==2) { struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_MOD); modify_stack_depth(-1); return 1; } return 0; } PMOD_EXPORT void o_not(void) {
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_INT:
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, !sp[-1].u.integer);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, !
Pike_
sp[-1].u.integer);
break; case T_FUNCTION: case T_OBJECT:
-
if(UNSAFE_IS_ZERO(sp-1))
+
if(UNSAFE_IS_ZERO(
Pike_
sp-1))
{ pop_stack(); push_int(1); }else{ pop_stack(); push_int(0); } break; default:
-
free_svalue(sp-1);
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, 0);
+
free_svalue(
Pike_
sp-1);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, 0);
} } /*! @decl int(0..1) `!(object|function arg) *! @decl int(1..1) `!(int(0..0) arg) *! @decl int(0..0) `!(mixed arg) *! *! Logical not. *! *! Every expression with the @expr{!@} operator becomes a call to
pike.git/src/operators.c:4451:
*! Otherwise @expr{0@} (zero) will be returned. *! *! @note *! No float is considered false, not even @expr{0.0@}. *! *! @seealso *! @[`==()], @[`!=()], @[lfun::`!()] */ PMOD_EXPORT void f_not(INT32 args) {
-
if(args != 1)
{
-
/* FIXME: Not appropriate with too many args. */
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`!", 1);
-
}
+
if(args != 1)
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`!", 1);
o_not(); } static int generate_not(node *n) { if(count_args(CDR(n))==1) { struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_NOT); return 1; } return 0; } PMOD_EXPORT void o_compl(void) {
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_OBJECT:
-
CALL
_
OPERATOR
(LFUN_COMPL,1);
+
if(!call
_
lhs_lfun
(LFUN_COMPL,1)
)
+
PIKE_ERROR("`~", "Complement on object without `~ operator.\n", Pike_sp, 1)
;
+
stack_pop_keep_top();
break; case T_INT:
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, ~sp[-1].u.integer);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, ~
Pike_
sp[-1].u.integer);
break; case T_FLOAT:
-
sp[-1].u.float_number = (FLOAT_TYPE) -1.0 - sp[-1].u.float_number;
+
Pike_
sp[-1].u.float_number = (FLOAT_TYPE) -1.0 -
Pike_
sp[-1].u.float_number;
break; case T_TYPE: type_stack_mark();
-
if (sp[-1].u.type->type == T_NOT) {
-
push_finished_type(sp[-1].u.type->car);
+
if (
Pike_
sp[-1].u.type->type == T_NOT) {
+
push_finished_type(
Pike_
sp[-1].u.type->car);
} else {
-
push_finished_type(sp[-1].u.type);
+
push_finished_type(
Pike_
sp[-1].u.type);
push_type(T_NOT); } pop_stack(); push_type_value(pop_unfinished_type()); break; case T_FUNCTION: case T_PROGRAM: { /* !object(p) */
-
struct program *p = program_from_svalue(sp - 1);
+
struct program *p = program_from_svalue(
Pike_
sp - 1);
if (!p) {
-
PIKE_ERROR("`~", "Bad argument.\n", sp, 1);
+
PIKE_ERROR("`~", "Bad argument.\n",
Pike_
sp, 1);
} type_stack_mark(); push_object_type(0, p->id); push_type(T_NOT); pop_stack(); push_type_value(pop_unfinished_type()); } break; case T_STRING: { struct pike_string *s; ptrdiff_t len, i;
-
if(sp[-1].u.string->size_shift) {
-
bad_arg_error("`~",
sp-
1, 1,
1,
"string(0)", sp-1,
+
if(
Pike_
sp[-1].u.string->size_shift) {
+
bad_arg_error("`~", 1, 1, "string(0)",
Pike_
sp-1,
"Expected 8-bit string.\n"); }
-
len = sp[-1].u.string->len;
+
len =
Pike_
sp[-1].u.string->len;
s = begin_shared_string(len); for (i=0; i<len; i++)
-
s->str[i] = ~ sp[-1].u.string->str[i];
+
s->str[i] = ~
Pike_
sp[-1].u.string->str[i];
pop_n_elems(1); push_string(end_shared_string(s)); break; } default:
-
PIKE_ERROR("`~", "Bad argument.\n", sp, 1);
+
PIKE_ERROR("`~", "Bad argument.\n",
Pike_
sp, 1);
} } /*! @decl mixed `~(object arg) *! @decl int `~(int arg) *! @decl float `~(float arg) *! @decl type `~(type|program arg) *! @decl string `~(string arg) *! *! Complement/inversion.
pike.git/src/operators.c:4572:
*! If @[arg] only contains characters in the range 0 - 255 (8-bit), *! a string containing the corresponding 8-bit inverses will be *! returned. *! @endmixed *! *! @seealso *! @[`!()], @[lfun::`~()] */ PMOD_EXPORT void f_compl(INT32 args) {
-
if(args != 1)
{
-
/* FIXME: Not appropriate with too many args. */
-
SIMPLE_
TOO
_
FEW
_ARGS_ERROR("`~", 1);
-
}
+
if(args != 1)
+
SIMPLE_
WRONG
_
NUM
_ARGS_ERROR("`~", 1);
o_compl(); } static int generate_compl(node *n) { if(count_args(CDR(n))==1) { struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_COMPL); return 1; } return 0; } PMOD_EXPORT void o_negate(void) {
-
switch(TYPEOF(sp[-1]))
+
switch(TYPEOF(
Pike_
sp[-1]))
{ case T_OBJECT: do_lfun_negate:
-
CALL
_
OPERATOR
(LFUN_SUBTRACT,1);
+
if(!call
_
lhs_lfun
(LFUN_SUBTRACT,1)
)
+
PIKE_ERROR("`-", "Negate on object without `- operator.\n", Pike_sp, 1)
;
+
stack_pop_keep_top();
break; case T_FLOAT:
-
sp[-1].u.float_number=-sp[-1].u.float_number;
+
Pike_
sp[-1].u.float_number=-
Pike_
sp[-1].u.float_number;
return; case T_INT:
-
if(INT_TYPE_NEG_OVERFLOW(sp[-1].u.integer))
+
if(INT_TYPE_NEG_OVERFLOW(
Pike_
sp[-1].u.integer))
{ convert_stack_top_to_bignum(); goto do_lfun_negate; }
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, -sp[-1].u.integer);
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, -
Pike_
sp[-1].u.integer);
return; default:
-
PIKE_ERROR("`-", "Bad argument to unary minus.\n", sp, 1);
+
PIKE_ERROR("`-", "Bad argument to unary minus.\n",
Pike_
sp, 1);
} } static void string_or_array_range (int bound_types, struct svalue *ind, INT_TYPE low, INT_TYPE high) /* ind is modified to point to the range. low and high are INT_TYPE to * avoid truncation problems when they come from int svalues. */ {
pike.git/src/operators.c:4714:
* o[..] => o->`[] (0, Pike.NATIVE_MAX) */ if (bound_types & (RANGE_LOW_FROM_END|RANGE_HIGH_FROM_END)) { int f2 = FIND_LFUN (o->prog, LFUN__SIZEOF); if (f2 == -1) return 2; apply_low (o, f2, 0); push_int (1); o_subtract();
-
move_svalue (&end_pos, --sp);
+
move_svalue (&end_pos, --
Pike_
sp);
SET_ONERROR (uwp, do_free_svalue, &end_pos); } switch (bound_types & (RANGE_LOW_FROM_BEG|RANGE_LOW_FROM_END|RANGE_LOW_OPEN)) { case RANGE_LOW_FROM_BEG:
-
move_svalue (sp++, low);
+
move_svalue (
Pike_
sp++, low);
mark_free_svalue (low); break; case RANGE_LOW_OPEN: push_int (0); break; default: push_svalue (&end_pos);
-
move_svalue (sp++, low);
+
move_svalue (
Pike_
sp++, low);
mark_free_svalue (low); o_subtract(); break; } switch (bound_types & (RANGE_HIGH_FROM_BEG|RANGE_HIGH_FROM_END|RANGE_HIGH_OPEN)) { case RANGE_HIGH_FROM_BEG:
-
move_svalue (sp++, high);
+
move_svalue (
Pike_
sp++, high);
mark_free_svalue (high); break; case RANGE_HIGH_OPEN: push_int (MAX_INT_TYPE); break; default: push_svalue (&end_pos);
-
move_svalue (sp++, high);
+
move_svalue (
Pike_
sp++, high);
mark_free_svalue (high); o_subtract(); break; } if (bound_types & (RANGE_LOW_FROM_END|RANGE_HIGH_FROM_END)) { UNSET_ONERROR (uwp); free_svalue (&end_pos); /* Anything might have happened during the calls to * LFUN__SIZEOF and o_subtract above. */
pike.git/src/operators.c:4782:
case RANGE_LOW_FROM_END|RANGE_HIGH_FROM_END: return "arg1[<arg2..<arg3]"; case RANGE_LOW_FROM_END|RANGE_HIGH_OPEN: return "arg1[<arg2..]"; case RANGE_LOW_OPEN|RANGE_HIGH_FROM_BEG: return "arg1[..arg2]"; case RANGE_LOW_OPEN|RANGE_HIGH_FROM_END: return "arg1[..<arg2]"; case RANGE_LOW_OPEN|RANGE_HIGH_OPEN: return "arg1[..]"; #ifdef PIKE_DEBUG default: Pike_fatal ("Unexpected bound_types.\n"); #endif }
-
return "Unexpected bound_types";
/* Make compiler quiet */
+
UNREACHABLE(
return "Unexpected bound_types"
)
;
} PMOD_EXPORT void o_range2 (int bound_types) /* This takes between one and three args depending on whether * RANGE_LOW_OPEN and/or RANGE_HIGH_OPEN is set in bound_types. */ { struct svalue *ind, *low, *high;
-
high = bound_types & RANGE_HIGH_OPEN ? sp : sp - 1;
+
high = bound_types & RANGE_HIGH_OPEN ?
Pike_
sp :
Pike_
sp - 1;
low = bound_types & RANGE_LOW_OPEN ? high : high - 1; ind = low - 1; switch (TYPEOF(*ind)) { case T_OBJECT: { struct object *o = ind->u.object; int f; if (!o->prog) bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, 1, "object", ind,
+
Pike_
sp - ind, 1, "object", ind,
"Cannot call `[..] in destructed object.\n"); if ((f = FIND_LFUN(o->prog->inherits[SUBTYPEOF(*ind)].prog, LFUN_RANGE)) != -1) { struct svalue h; if (!(bound_types & RANGE_HIGH_OPEN)) { move_svalue (&h, high);
-
sp = high;
+
Pike_
sp = high;
} if (bound_types & RANGE_LOW_FROM_BEG) push_int (INDEX_FROM_BEG); else if (bound_types & RANGE_LOW_OPEN) { push_int (0); push_int (OPEN_BOUND); } else push_int (INDEX_FROM_END); if (bound_types & RANGE_HIGH_FROM_BEG) {
-
move_svalue (sp++, &h);
+
move_svalue (
Pike_
sp++, &h);
push_int (INDEX_FROM_BEG); } else if (bound_types & RANGE_HIGH_OPEN) { push_int (0); push_int (OPEN_BOUND); } else {
-
move_svalue (sp++, &h);
+
move_svalue (
Pike_
sp++, &h);
push_int (INDEX_FROM_END); } apply_low (o, f, 4); stack_pop_keep_top(); } else switch (call_old_range_lfun (bound_types, o, low, high)) { case 1: bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, 1, "object", ind,
+
Pike_
sp - ind, 1, "object", ind,
"Object got neither `[..] nor `[].\n");
-
+
break;
case 2: bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, 1, "object", ind,
+
Pike_
sp - ind, 1, "object", ind,
"Object got no `[..] and there is no _sizeof to " "translate the from-the-end index to use `[].\n");
-
+
break;
case 3: bad_arg_error (range_func_name (bound_types),
-
ind,
3, 1, "object", ind,
+
3, 1, "object", ind,
"Cannot call `[..] in destructed object.\n");
-
+
break;
default: free_svalue (ind);
-
move_svalue (ind, sp - 1);
+
move_svalue (ind,
Pike_
sp - 1);
/* low and high have lost their refs in call_old_range_lfun. */
-
sp = ind + 1;
+
Pike_
sp = ind + 1;
+
break;
} break; } case T_STRING: case T_ARRAY: { INT_TYPE l=0, h=0; if (!(bound_types & RANGE_LOW_OPEN)) { if (TYPEOF(*low) != T_INT) bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, 2, "int", low,
+
Pike_
sp - ind, 2, "int", low,
"Bad lower bound. Expected int, got %s.\n", get_name_of_type (TYPEOF(*low))); l = low->u.integer; } if (!(bound_types & RANGE_HIGH_OPEN)) { if (TYPEOF(*high) != T_INT) bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, high - ind + 1, "int", high,
+
Pike_
sp - ind, high - ind + 1, "int", high,
"Bad upper bound. Expected int, got %s.\n", get_name_of_type (TYPEOF(*high))); h = high->u.integer; } /* Can pop off the bounds without fuzz since they're simple integers. */
-
sp = ind + 1;
+
Pike_
sp = ind + 1;
string_or_array_range (bound_types, ind, l, h); break; } default: bad_arg_error (range_func_name (bound_types),
-
ind,
sp - ind, 1, "string|array|object", ind,
+
Pike_
sp - ind, 1, "string|array|object", ind,
"Cannot use [..] on a %s. Expected string, array or object.\n", get_name_of_type (TYPEOF(*ind))); } } /*! @decl mixed `[..](object arg, mixed start, int start_type, mixed end, int end_type) *! @decl string `[..](string arg, int start, int start_type, int end, int end_type) *! @decl array `[..](array arg, int start, int start_type, int end, int end_type) *! *! Extracts a subrange.
pike.git/src/operators.c:5007:
*! @endmixed *! *! @seealso *! @[lfun::`[..]], @[`[]] */ PMOD_EXPORT void f_range(INT32 args) { struct svalue *ind; if (args != 5) SIMPLE_WRONG_NUM_ARGS_ERROR ("predef::`[..]", 5);
-
ind = sp - 5;
+
ind =
Pike_
sp - 5;
#define CALC_BOUND_TYPES(bound_types) do { \ if (TYPEOF(ind[2]) != T_INT) \ SIMPLE_ARG_TYPE_ERROR ("predef::`[..]", 3, "int"); \ switch (ind[2].u.integer) { \ case INDEX_FROM_BEG: bound_types = RANGE_LOW_FROM_BEG; break; \ case INDEX_FROM_END: bound_types = RANGE_LOW_FROM_END; break; \ case OPEN_BOUND: bound_types = RANGE_LOW_OPEN; break; \ default: \ SIMPLE_ARG_ERROR ("predef::`[..]", 3, "Unrecognized bound type."); \
pike.git/src/operators.c:5052:
stack_pop_keep_top(); } else { int bound_types; CALC_BOUND_TYPES (bound_types); switch (call_old_range_lfun (bound_types, o, ind + 1, ind + 3)) { case 1: SIMPLE_ARG_ERROR ("predef::`[..]", 1, "Object got neither `[..] nor `[].\n");
+
break;
case 2: SIMPLE_ARG_ERROR ("predef::`[..]", 1, "Object got no `[..] and there is no _sizeof to " "translate the from-the-end index to use `[].\n");
-
+
break;
case 3: SIMPLE_ARG_ERROR ("predef::`[..]", 1, "Cannot call `[..] in destructed object.\n");
-
+
break;
default: free_svalue (ind);
-
move_svalue (ind, sp - 1);
+
move_svalue (ind,
Pike_
sp - 1);
/* The bound types are simple integers and the bounds * themselves have lost their refs in call_old_range_lfun. */
-
sp = ind + 1;
+
Pike_
sp = ind + 1;
+
break;
} } break; } case T_STRING: case T_ARRAY: { INT_TYPE l=0, h=0; int bound_types;
pike.git/src/operators.c:5188:
*! this function. *! *! @seealso *! @[`->()], @[lfun::`[]()], @[`[]=], @[`[..]] */ PMOD_EXPORT void f_index(INT32 args) { switch(args) { case 2:
-
if(TYPEOF(sp[-1]) == T_STRING) SET_SVAL_SUBTYPE(sp[-1], 0);
+
if(TYPEOF(
Pike_
sp[-1]) == T_STRING) SET_SVAL_SUBTYPE(
Pike_
sp[-1], 0);
o_index(); break; case 3:
-
move_svalue (sp, sp - 1);
-
sp += 2;
-
SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, INDEX_FROM_BEG);
-
sp[-3] = sp[-1];
+
move_svalue (
Pike_
sp,
Pike_
sp - 1);
+
Pike_
sp += 2;
+
SET_SVAL(
Pike_
sp[-1], T_INT, NUMBER_NUMBER, integer, INDEX_FROM_BEG);
+
Pike_
sp[-3] =
Pike_
sp[-1];
f_range (5); break; default: SIMPLE_WRONG_NUM_ARGS_ERROR ("predef::`[]", args); break; } } /*! @decl mixed `->(object arg, string index) *! @decl mixed `->(int arg, string index)
pike.git/src/operators.c:5265:
*! *! @seealso *! @[`[]()], @[lfun::`->()], @[::`->()], @[`->=] */ PMOD_EXPORT void f_arrow(INT32 args) { switch(args) { case 0: case 1:
-
PIKE_ERROR("`->", "Too few arguments.\n", sp, args);
+
PIKE_ERROR("`->", "Too few arguments.\n",
Pike_
sp, args);
break; case 2:
-
if(TYPEOF(sp[-1]) == T_STRING)
-
SET_SVAL_SUBTYPE(sp[-1], 1);
+
if(TYPEOF(
Pike_
sp[-1]) == T_STRING)
+
SET_SVAL_SUBTYPE(
Pike_
sp[-1], 1);
o_index(); break; default:
-
PIKE_ERROR("`->", "Too many arguments.\n", sp, args);
+
PIKE_ERROR("`->", "Too many arguments.\n",
Pike_
sp, args);
} } /*! @decl mixed `[]=(object arg, mixed index, mixed val) *! @decl mixed `[]=(object arg, string index, mixed val) *! @decl mixed `[]=(array arg, int index, mixed val) *! @decl mixed `[]=(mapping arg, mixed index, mixed val) *! @decl int(0..1) `[]=(multiset arg, mixed index, int(0..1) val) *! *! Index assignment.
pike.git/src/operators.c:5321:
*! *! @seealso *! @[`->=()], @[lfun::`[]=()], @[`[]] */ PMOD_EXPORT void f_index_assign(INT32 args) { switch (args) { case 0: case 1: case 2:
-
PIKE_ERROR("`[]=", "Too few arguments.\n", sp, args);
+
PIKE_ERROR("`[]=", "Too few arguments.\n",
Pike_
sp, args);
break; case 3:
-
if(TYPEOF(sp[-2]) == T_STRING) SET_SVAL_SUBTYPE(sp[-2], 0);
-
assign_lvalue (sp-3, sp-1);
+
if(TYPEOF(
Pike_
sp[-2]) == T_STRING) SET_SVAL_SUBTYPE(
Pike_
sp[-2], 0);
+
assign_lvalue (
Pike_
sp-3,
Pike_
sp-1);
stack_pop_n_elems_keep_top (2); break; default:
-
PIKE_ERROR("`[]=", "Too many arguments.\n", sp, args);
+
PIKE_ERROR("`[]=", "Too many arguments.\n",
Pike_
sp, args);
} } /*! @decl mixed `->=(object arg, string index, mixed val) *! @decl mixed `->=(mapping arg, string index, mixed val) *! @decl int(0..1) `->=(multiset arg, string index, int(0..1) val) *! *! Arrow index assignment. *! *! Every lvalue expression with the @expr{->@} operator becomes a
pike.git/src/operators.c:5384:
*! *! @seealso *! @[`[]=()], @[lfun::`->=()], @[`->] */ PMOD_EXPORT void f_arrow_assign(INT32 args) { switch (args) { case 0: case 1: case 2:
-
PIKE_ERROR("`->=", "Too few arguments.\n", sp, args);
+
PIKE_ERROR("`->=", "Too few arguments.\n",
Pike_
sp, args);
break; case 3:
-
if(TYPEOF(sp[-2]) == T_STRING) SET_SVAL_SUBTYPE(sp[-2], 1);
-
assign_lvalue (sp-3, sp-1);
-
assign_svalue (sp-3, sp-1);
+
if(TYPEOF(
Pike_
sp[-2]) == T_STRING) SET_SVAL_SUBTYPE(
Pike_
sp[-2], 1);
+
assign_lvalue (
Pike_
sp-3,
Pike_
sp-1);
+
assign_svalue (
Pike_
sp-3,
Pike_
sp-1);
pop_n_elems (args-1); break; default:
-
PIKE_ERROR("`->=", "Too many arguments.\n", sp, args);
+
PIKE_ERROR("`->=", "Too many arguments.\n",
Pike_
sp, args);
} } /*! @decl int sizeof(string arg) *! @decl int sizeof(array arg) *! @decl int sizeof(mapping arg) *! @decl int sizeof(multiset arg) *! @decl int sizeof(object arg) *! *! Size query.
pike.git/src/operators.c:5427:
*! symbols in @[arg] will be returned. *! @endmixed *! *! @seealso *! @[lfun::_sizeof()] */ PMOD_EXPORT void f_sizeof(INT32 args) { INT32 tmp; if(args<1)
-
PIKE_ERROR("sizeof", "Too few arguments.\n", sp, args);
+
PIKE_ERROR("sizeof", "Too few arguments.\n",
Pike_
sp, args);
-
tmp=pike_sizeof(sp-args);
+
tmp=pike_sizeof(
Pike_
sp-args);
pop_n_elems(args); push_int(tmp); } static node *optimize_sizeof(node *n) { if (CDR(n) && (CDR(n)->token == F_APPLY) && (CADR(n)) && (CADR(n)->token == F_CONSTANT) && (TYPEOF(CADR(n)->u.sval) == T_FUNCTION) &&
pike.git/src/operators.c:5512:
} return NULL; } static int generate_sizeof(node *n) { struct compilation *c = THIS_COMPILATION; if(count_args(CDR(n)) != 1) return 0; if(do_docode(CDR(n),DO_NOT_COPY) != 1) Pike_fatal("Count args was wrong in sizeof().\n");
+
if( pike_types_le( my_get_arg(&CDR(n), 0)[0]->type, string_type_string ) )
+
emit0(F_SIZEOF_STRING);
+
/* else if( pike_types_le( my_get_arg(&CDR(n), 0)[0]->type, array_type_string ) ) */
+
/* emit0(F_SIZEOF_ARRAY); */
+
else
emit0(F_SIZEOF); return 1; } extern int generate_call_function(node *n); /*! @decl void _Static_assert(int constant_expression, string constant_message) *! *! Perform a compile-time assertion check. *!
pike.git/src/operators.c:5582:
#define THIS ((struct string_assignment_storage *)(CURRENT_STORAGE)) /*! @decl int `[](int i) *! *! String index operator. */ static void f_string_assignment_index(INT32 args) { ptrdiff_t len; INT_TYPE i, p;
-
get_all_args(
"string[]"
, args, "%i", &p);
+
get_all_args(
NULL
, args, "%i", &p);
if (!THIS->s) { Pike_error("Indexing uninitialized string_assignment.\n"); } len = THIS->s->len; i = p < 0 ? p + len : p; if(i<0 || i>=len) Pike_error("Index %"PRINTPIKEINT"d is out of string range " "%"PRINTPTRDIFFT"d..%"PRINTPTRDIFFT"d.\n",
pike.git/src/operators.c:5610:
/*! @decl int `[]=(int i, int j) *! *! String assign index operator. */ static void f_string_assignment_assign_index(INT32 args) { INT_TYPE p, i, j; union anything *u; ptrdiff_t len;
-
get_all_args(
"string[]="
,args,"%i%i",&p,&j);
+
get_all_args(
NULL
,
args,
"%i%i",
&p,
&j);
if((u=get_pointer_if_this_type(THIS->lval, T_STRING))) { len = u->string->len; i = p < 0 ? p + len : p; if(i<0 || i>=len) Pike_error("Index %"PRINTPIKEINT"d is out of string range " "%"PRINTPTRDIFFT"d..%"PRINTPTRDIFFT"d.\n", p, -len, len - 1); if (THIS->s) free_string(THIS->s); u->string=modify_shared_string(u->string,i,j); copy_shared_string(THIS->s, u->string); } else{
-
lvalue_to_svalue_no_free(sp,THIS->lval);
-
sp++;
+
lvalue_to_svalue_no_free(
Pike_
sp,THIS->lval);
+
Pike_
sp++;
dmalloc_touch_svalue(Pike_sp-1);
-
if(TYPEOF(sp[-1]) != T_STRING) Pike_error("string[]= failed.\n");
-
len = sp[-1].u.string->len;
+
if(TYPEOF(
Pike_
sp[-1]) != T_STRING) Pike_error("string[]= failed.\n");
+
len =
Pike_
sp[-1].u.string->len;
i = p < 0 ? p + len : p; if(i<0 || i>=len) Pike_error("Index %"PRINTPIKEINT"d is out of string range " "%"PRINTPTRDIFFT"d..%"PRINTPTRDIFFT"d.\n", p, -len, len - 1);
-
sp[-1].u.string=modify_shared_string(sp[-1].u.string,i,j);
-
assign_lvalue(THIS->lval, sp-1);
+
Pike_
sp[-1].u.string=modify_shared_string(
Pike_
sp[-1].u.string,i,j);
+
assign_lvalue(THIS->lval,
Pike_
sp-1);
pop_stack(); } pop_n_elems(args); push_int(j); } static void init_string_assignment_storage(struct object *UNUSED(o)) {
pike.git/src/operators.c:5678:
tFunc(tObj tMix tRangeBound tMix tRangeBound, tMix)), OPT_TRY_OPTIMIZE); ADD_INT_CONSTANT ("INDEX_FROM_BEG", INDEX_FROM_BEG, 0); ADD_INT_CONSTANT ("INDEX_FROM_END", INDEX_FROM_END, 0); ADD_INT_CONSTANT ("OPEN_BOUND", OPEN_BOUND, 0); ADD_EFUN ("`[]", f_index, tOr9(tFunc(tObj tMix tOr(tVoid,tMix), tMix), tFunc(tInt tString, tFunction),
-
tFunc(
tStr
tInt,
tInt
),
+
tFunc(
tNStr(tSetvar(0,tInt))
tInt,
tVar(0
)
)
,
tFunc(tArr(tSetvar(0,tMix)) tMix, tVar(0)), tFunc(tMap(tMix,tSetvar(1,tMix)) tMix, tVar(1)), tFunc(tMultiset tMix, tInt01), tFunc(tPrg(tObj) tString, tMix), tFunc(tStr tInt tInt, tStr), tFunc(tArr(tSetvar(2,tMix)) tInt tInt, tArr(tVar(2)))), OPT_TRY_OPTIMIZE); /* function(array(object|mapping|multiset|array),string:array(mixed))|function(object|mapping|multiset|program,string:mixed) */ ADD_EFUN2("`->",f_arrow,tOr(tFunc(tArr(tOr4(tObj,tMapping,tMultiset,tArray)) tStr,tArr(tMix)),tFunc(tOr4(tObj,tMapping,tMultiset,tPrg(tObj)) tStr,tMix)),OPT_TRY_OPTIMIZE,0,0);
pike.git/src/operators.c:5742:
#define CMP_TYPE "!function(!(object|mixed)...:mixed)&function(mixed...:int(0..1))|function(int|float...:int(0..1))|function(string...:int(0..1))|function(type|program,type|program,type|program...:int(0..1))" add_efun2("`<", f_lt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`<=",f_le,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`>", f_gt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`>=",f_ge,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); ADD_EFUN2("`+",f_add, tOr7(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix), tFuncV(tNone,tMix,tMix)),
-
tFuncV(tInt,tInt,tInt),
+
tOr3(
tFuncV(
tIntPos,tIntPos,tIntPos),
+
tFuncV(tIntNeg,tIntNeg,tIntNeg),
+
tIfnot(tFuncV(tNone, tNot(tIntNeg), tMix),
+
tIfnot(tFuncV(tNone, tNot(tIntPos), tMix),
+
tFuncV(
tInt,
tInt,
tInt)
)))
,
tIfnot(tFuncV(tNone, tNot(tFlt), tMix), tFuncV(tOr(tInt,tFlt),tOr(tInt,tFlt),tFlt)), tIfnot(tFuncV(tNone, tNot(tStr), tMix), tFuncV(tOr3(tSetvar(0, tStr),tInt,tFlt), tOr3(tSetvar(1, tStr),tInt,tFlt),tOr(tVar(0),tVar(1)))), tFuncV(tSetvar(0,tArray),tSetvar(1,tArray), tOr(tVar(0),tVar(1))), tFuncV(tSetvar(0,tMapping),tSetvar(1,tMapping), tOr(tVar(0),tVar(1))), tFuncV(tSetvar(0,tMultiset),tSetvar(1,tMultiset), tOr(tVar(0),tVar(1)))), OPT_TRY_OPTIMIZE,optimize_binary,generate_sum); ADD_EFUN2("`-",f_minus, tOr7(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix), tFuncV(tNone,tMix,tMix)),
-
tFuncV(tInt,tInt,tInt),
+
tOr4(
tFuncV(
tIntNeg,tIntPos,tIntNeg),
+
tFuncV(tIntPos,tIntNeg,tIntPos),
+
tIfnot(tFuncV(tNot(tIntPos), tNot(tIntPos), tMix),
+
tFuncV(
tInt,
tInt,
tInt)
)
,
+
tIfnot(tFuncV(tNot(tIntNeg), tNot(tIntNeg), tMix),
+
tFuncV(tInt, tInt, tInt))),
tIfnot(tFuncV(tNone,tNot(tFlt),tMix), tFuncV(tOr(tInt,tFlt),tOr(tInt,tFlt),tFlt)), tFuncV(tArr(tSetvar(0,tMix)),tArray,tArr(tVar(0))), tFuncV(tMap(tSetvar(1,tMix),tSetvar(2,tMix)), tOr3(tMapping,tArray,tMultiset), tMap(tVar(1),tVar(2))), tFunc(tSet(tSetvar(3,tMix)) tMultiset,tSet(tVar(3))), tFuncV(tSetvar(0,tStr),tStr,tVar(0))), OPT_TRY_OPTIMIZE,0,generate_minus);
pike.git/src/operators.c:5834:
tFuncV(tSetvar(3,tMultiset),tSetvar(4,tMultiset),tOr(tVar(3),tVar(4))), \ tFuncV(tSetvar(5,tArray),tSetvar(6,tArray),tOr(tVar(5),tVar(6))), \ tFuncV(tString,tString,tString), \ tFuncV(tOr(tType(tMix),tPrg(tObj)),tOr(tType(tMix),tPrg(tObj)),tType(tMix))) ADD_EFUN2("`|",f_or,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_or); ADD_EFUN2("`^",f_xor,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_xor); #define SHIFT_TYPE \
-
tOr
(
tAnd
(
tNot(
tFuncV(tNone, tNot(tObj), tMix)
)
, \
-
tOr(tFunc(tMix tObj,tMix),
\
+
tOr3
(
tIfnot
(tFuncV(tNone, tNot(tObj), tMix),
\
+
tOr(tFunc(tMix tObj,tMix), \
tFunc(tObj tMix,tMix))), \
-
tFunc(
tInt
tInt
,
tInt
))
+
tOr3(
tFunc(
tInt1Plus
tIntPos
,
tIntPos
)
, \
+
tFunc(tInt0 tIntPos, tInt0
)
, \
+
tFunc(tIntMinus tIntPos, tIntNeg)), \
+
tIfnot(tFuncV(tNot(tFloat), tNot(tIntPos), tMix), \
+
tFunc(tAnd(tFloat, tNot(tInt0)) tIntPos, tFloat)))
ADD_EFUN2("`<<", f_lsh, SHIFT_TYPE, OPT_TRY_OPTIMIZE, may_have_side_effects, generate_lsh); ADD_EFUN2("`>>", f_rsh, SHIFT_TYPE, OPT_TRY_OPTIMIZE, may_have_side_effects, generate_rsh); /* !function(!object...:mixed)&function(mixed...:mixed)|" "function(array(array(1=mixed)),array(1=mixed):array(1))|" "function(int...:int)|" "!function(int...:mixed)&function(float|int...:float)|" "function(string*,string:string)|" "function(array(0=mixed),int:array(0))|" "function(array(0=mixed),float:array(0))|" "function(string,int:string) "function(string,float:string) */
-
+
ADD_EFUN2("`**", f_exponent,
+
tOr7(tFunc(tInt tInt,tInt),
+
tFunc(tFloat tFloat, tFloat),
+
tFunc(tOr(tInt,tFloat) tObj, tOr3(tFloat,tInt,tFloat)),
+
tFunc(tInt tFloat, tFloat),
+
tFunc(tObj tMix, tOr3(tFloat,tInt,tObj)),
+
tFunc(tMix tObj, tOr3(tFloat,tInt,tObj)),
+
tFunc(tFloat tInt, tFloat)),
+
OPT_TRY_OPTIMIZE,0,0);
+
ADD_EFUN2("`*", f_multiply, tOr9(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix), tFuncV(tNone,tOr(tMix,tVoid),tMix)), tFunc(tArr(tArr(tSetvar(1,tMix))) tArr(tSetvar(1,tMix)),tArr(tVar(1))),
-
tFuncV(
tInt
,
tInt
,
tInt
),
+
tOr4(
tFuncV(
tIntPos
,
tIntPos
,
tIntPos
),
+
tFuncV(tIntNeg,tIntNeg,tIntPos),
+
tFuncV(tIntPos,tIntNeg,tIntNeg),
+
tFuncV(tIntNeg,tIntPos,tIntNeg)),
tIfnot(tFuncV(tNone,tNot(tFlt),tMix), tFuncV(tOr(tFlt,tInt),tOr(tFlt,tInt),tFlt)), tFunc(tArr(tStr) tStr,tStr), tFunc(tArr(tSetvar(0,tMix)) tInt,tArr(tVar(0))), tFunc(tArr(tSetvar(0,tMix)) tFlt,tArr(tVar(0))), tFunc(tSetvar(0, tStr) tInt,tVar(0)), tFunc(tSetvar(0, tStr) tFlt,tVar(0))), OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); /* !function(!object...:mixed)&function(mixed...:mixed)|" "function(int,int...:int)|" "!function(int...:mixed)&function(float|int...:float)|" "function(array(0=mixed),array|int|float...:array(array(0)))|" "function(string,string|int|float...:array(string)) */ ADD_EFUN2("`/", f_divide, tOr5(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix), tFuncV(tNone,tMix,tMix)),
-
tFuncV(
tInt
,
tInt
,
tInt
),
+
tOr4(
tFuncV(
tIntPos
,
tIntPos,tIntPos),
+
tFuncV(tIntNeg
,
tIntNeg,tIntPos),
+
tFuncV(tIntPos,tIntNeg,tIntNeg
),
+
tFuncV(tIntNeg,tIntPos,tIntNeg)),
tIfnot(tFuncV(tNone, tNot(tFlt), tMix), tFuncV(tOr(tFlt,tInt),tOr(tFlt,tInt),tFlt)), tFuncV(tArr(tSetvar(0,tMix)), tOr3(tArray,tInt,tFlt), tArr(tArr(tVar(0)))), tFuncV(tStr,tOr3(tStr,tInt,tFlt),tArr(tStr))), OPT_TRY_OPTIMIZE,0,generate_divide); /* function(mixed,object:mixed)|" "function(object,mixed:mixed)|" "function(int,int:int)|" "function(string,int:string)|" "function(array(0=mixed),int:array(0))|" "!function(int,int:mixed)&function(int|float,int|float:float) */ ADD_EFUN2("`%", f_mod,
-
tOr6
(tFunc(tMix tObj,tMix),
+
tOr7
(tFunc(tMix tObj,tMix),
tFunc(tObj tMix,tMix),
-
tFunc(tInt
tInt
,tInt),
+
tFunc(tInt
tIntPos, tIntPos),
+
tFunc(
tInt
tIntNeg
,
tIntNeg
),
tFunc(tStr tInt,tStr), tFunc(tArr(tSetvar(0,tMix)) tInt,tArr(tVar(0))), tIfnot(tFuncV(tNone, tNot(tFlt), tMix), tFunc(tOr(tInt,tFlt) tOr(tInt,tFlt),tFlt))), OPT_TRY_OPTIMIZE,0,generate_mod); /* function(object:mixed)|function(int:int)|function(float:float)|function(string:string) */ ADD_EFUN2("`~",f_compl,
-
tOr6
(tFunc(tObj,tMix),
-
tFunc(
tInt
,
tInt
),
+
tOr7
(tFunc(tObj,tMix),
+
tFunc(
tIntPos
,
tIntMinus
),
+
tFunc(tIntMinus,tIntPos),
tFunc(tFlt,tFlt), tFunc(tStr,tStr), tFunc(tType(tSetvar(0, tMix)), tType(tNot(tVar(0)))), tFunc(tPrg(tObj), tType(tMix))), OPT_TRY_OPTIMIZE,0,generate_compl); /* function(string|multiset|array|mapping|object:int(0..)) */ ADD_EFUN2("sizeof", f_sizeof, tFunc(tOr5(tStr,tMultiset,tArray,tMapping,tObj),tIntPos), OPT_TRY_OPTIMIZE, optimize_sizeof, generate_sizeof); ADD_EFUN2("strlen", f_sizeof, tFunc(tStr,tIntPos), OPT_TRY_OPTIMIZE, optimize_sizeof, generate_sizeof); /* function(mixed,mixed ...:mixed) */ ADD_EFUN2("`()",f_call_function,tFuncV(tMix,tMix,tMix),OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function); /* This one should be removed */ /* function(mixed,mixed ...:mixed) */
-
ADD_EFUN2("call_function",f_call_function,tFuncV(tMix,tMix,tMix),OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function);
+
ADD_EFUN2("call_function",f_call_function,
tAttr("deprecated",
tFuncV(tMix,tMix,tMix)
)
,OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function);
/* From the 201x C standard */ ADD_EFUN2("_Static_assert", NULL, tFunc(tInt tStr, tVoid), OPT_TRY_OPTIMIZE, NULL, generate__Static_assert); start_new_program(); ADD_STORAGE(struct string_assignment_storage); /* function(int:int) */ ADD_FUNCTION2("`[]", f_string_assignment_index, tFunc(tInt,tInt), 0,