cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
54db6c1999-03-27Henrik Grubbström (Grubba) /**/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
b788cd1998-07-04Henrik Grubbström (Grubba) #include <math.h>
79d2b42001-05-19Henrik Grubbström (Grubba) RCSID("$Id: operators.c,v 1.137 2001/05/19 21:37:32 grubba Exp $");
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h" #include "svalue.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h" #include "array.h" #include "stralloc.h" #include "opcodes.h" #include "operators.h" #include "language.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) #include "docode.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "constants.h"
8a630c1996-04-13Fredrik Hübinette (Hubbe) #include "peep.h" #include "lex.h"
07c0731996-06-21Fredrik Hübinette (Hubbe) #include "program.h" #include "object.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "pike_types.h"
19aaeb1998-05-25Fredrik Hübinette (Hubbe) #include "module_support.h"
0bc4cf1998-10-13Fredrik Hübinette (Hubbe) #include "pike_macros.h"
fda0de1999-10-08Fredrik Noring #include "bignum.h"
89c4452000-04-12Henrik Grubbström (Grubba) #include "builtin_functions.h"
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
54db6c1999-03-27Henrik Grubbström (Grubba) #define OP_DIVISION_BY_ZERO_ERROR(FUNC) \ math_error(FUNC, sp-2, 2, 0, "Division by zero.\n") #define OP_MODULO_BY_ZERO_ERROR(FUNC) \ math_error(FUNC, sp-2, 2, 0, "Modulo by zero.\n")
5b4dd31998-02-23Fredrik Hübinette (Hubbe) #define COMPARISON(ID,NAME,FUN) \
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void ID(INT32 args) \
5b4dd31998-02-23Fredrik Hübinette (Hubbe) { \ int i; \ switch(args) \ { \ case 0: case 1: \
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_TOO_FEW_ARGS_ERROR(NAME, 2); \
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  case 2: \ i=FUN (sp-2,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))) \ break; \ pop_n_elems(args); \ push_int(i==args); \ } \
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) }
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl int(0..1) `!=(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Inequality operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{0@} (zero) if all the arguments are equal, and *! @tt{1@} otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! This is the inverse of @[`==()].
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`==()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_ne(INT32 args)
5b4dd31998-02-23Fredrik Hübinette (Hubbe) { f_eq(args); o_not(); }
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl int(0..1) `==(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Equality operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{1@} if all the arguments are equal, and *! @tt{0@} (zero) otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`!=()] */
5b4dd31998-02-23Fredrik Hübinette (Hubbe) COMPARISON(f_eq,"`==", is_eq)
f09ec92001-02-07Henrik Grubbström (Grubba)  /*! @decl int(0..1) `<(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Less than operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{1@} if the arguments are strictly increasing, and *! @tt{0@} (zero) otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`<=()], @[`>()], @[`>=()] */
5b4dd31998-02-23Fredrik Hübinette (Hubbe) COMPARISON(f_lt,"`<" , is_lt)
f09ec92001-02-07Henrik Grubbström (Grubba)  /*! @decl int(0..1) `<=(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Less or equal operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{1@} if the arguments are not strictly decreasing, and *! @tt{0@} (zero) otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! This is the inverse of @[`>()].
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`<()], @[`>()], @[`>=()] */
5b4dd31998-02-23Fredrik Hübinette (Hubbe) COMPARISON(f_le,"`<=",!is_gt)
f09ec92001-02-07Henrik Grubbström (Grubba)  /*! @decl int(0..1) `>(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Greater than operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{1@} if the arguments are strictly decreasing, and *! @tt{0@} (zero) otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`<()], @[`<=()], @[`>=()] */
5b4dd31998-02-23Fredrik Hübinette (Hubbe) COMPARISON(f_gt,"`>" , is_gt)
f09ec92001-02-07Henrik Grubbström (Grubba)  /*! @decl int(0..1) `>=(mixed arg1, mixed arg2, mixed ... extras) *! *! Greater or equal operator. *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! Returns @tt{1@} if the arguments are not strictly increasing, and *! @tt{0@} (zero) otherwise.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! This is the inverse of @[`<()].
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`<=()], @[`>()], @[`<()] */
5b4dd31998-02-23Fredrik Hübinette (Hubbe) COMPARISON(f_ge,"`>=",!is_lt)
5267b71995-08-09Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe) #define CALL_OPERATOR(OP, args) \ if(!sp[-args].u.object->prog) \
54db6c1999-03-27Henrik Grubbström (Grubba)  bad_arg_error(lfun_names[OP], sp-args, args, 1, "object", sp-args, \ "Called in destructed object.\n"); \
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(FIND_LFUN(sp[-args].u.object->prog,OP) == -1) \
54db6c1999-03-27Henrik Grubbström (Grubba)  bad_arg_error(lfun_names[OP], sp-args, args, 1, "object", sp-args, \ "Operator not in object.\n"); \
07c0731996-06-21Fredrik Hübinette (Hubbe)  apply_lfun(sp[-args].u.object, OP, args-1); \ free_svalue(sp-2); \ sp[-2]=sp[-1]; \
41e2cb1999-10-24Henrik Grubbström (Grubba)  sp--; \ dmalloc_touch_svalue(sp);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl mixed `+(mixed arg1) *! @decl mixed `+(object arg1, mixed ... extras) *! @decl string `+(string arg1, string|int|float arg2) *! @decl string `+(int|float arg1, string arg2) *! @decl int `+(int arg1, int arg2) *! @decl float `+(float arg1, int|float arg2) *! @decl float `+(int|float arg1, float arg2) *! @decl array `+(array arg1, array arg2) *! @decl mapping `+(mapping arg1, mapping arg2) *! @decl multiset `+(multiset arg1, multiset arg2) *! @decl mixed `+(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Addition operator. *! *! @returns *! If there's only a single argument, that argument will be returned. *! *! If @[arg1] is an object and it has an @[lfun::`+()], *! that function will be called with the rest of the arguments, *! and the result returned. *! *! Otherwise if any of the other arguments is an object that has *! an @[lfun::``+()] the first such function fill be called *! with the arguments leading up to it, and @[`+()] be called recursively *! with the result and the rest of the srguments. *! *! If there are two arguments the result will be: *! @mixed @[arg1] *! @type string *! @[arg2] will be converted to a string, and the result the *! strings concatenated. *! @type int *! @type float *! @mixed @[arg2] *! @type string *! @[arg1] will be converted to string, and the result the *! strings concatenated. *! @type int *! @type float *! The result will be @code{@[arg1] + @[arg2]@}, and will *! be a float if either @[arg1] or @[arg2] is a float. *! @endmixed *! @type array *! The arrays will be concatenated. *! @type mapping *! The mappings will be joined. *! @type multiset *! The multisets will be added. *! @endmixed *! *! Otherwise if there are more than 2 arguments the result will be: *! @code{`+(`+(@[arg1], @[arg2]), @@@[extras])@}
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @note *! In Pike 7.0 and earlier the addition order was unspecified. *! *! If @[arg1] is @tt{UNDEFINED@} it will behave as the empty *! array/mapping/multiset if needed. This behaviour was new *! in Pike 7.0. *! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_add(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
70b4311998-02-27Fredrik Hübinette (Hubbe)  INT_TYPE e,size;
5267b71995-08-09Fredrik Hübinette (Hubbe)  TYPE_FIELD types; types=0; for(e=-args;e<0;e++) types|=1<<sp[e].type; switch(types) { default:
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(!args)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_TOO_FEW_ARGS_ERROR("`+", 1);
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }else{ if(types & BIT_OBJECT)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ee37801999-02-09Fredrik Hübinette (Hubbe)  if(sp[-args].type == T_OBJECT && sp[-args].u.object->prog)
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  {
ee37801999-02-09Fredrik Hübinette (Hubbe)  if(sp[-args].u.object->refs==1 && FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD_EQ) != -1) { apply_lfun(sp[-args].u.object, LFUN_ADD_EQ, args-1);
110b3f1999-10-29Fredrik Hübinette (Hubbe)  stack_unlink(1);
ee37801999-02-09Fredrik Hübinette (Hubbe)  return; } if(FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD) != -1) { apply_lfun(sp[-args].u.object, LFUN_ADD, args-1); free_svalue(sp-2); sp[-2]=sp[-1]; sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
ee37801999-02-09Fredrik Hübinette (Hubbe)  return; }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  } for(e=1;e<args;e++) { if(sp[e-args].type == T_OBJECT && sp[e-args].u.object->prog &&
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  FIND_LFUN(sp[e-args].u.object->prog,LFUN_RADD) != -1)
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  { struct svalue *tmp=sp+e-args; check_stack(e); assign_svalues_no_free(sp, sp-args, e, -1); sp+=e; apply_lfun(tmp->u.object, LFUN_RADD, e);
a7b26a2000-03-01Fredrik Hübinette (Hubbe)  if(args - e > 1)
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  { assign_svalue(tmp, sp-1); pop_stack(); f_add(args - e); assign_svalue(sp-e-1,sp-1); pop_n_elems(e); }else{ assign_svalue(sp-args-1,sp-1); pop_n_elems(args); } return; } } } }
07c0731996-06-21Fredrik Hübinette (Hubbe) 
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  switch(sp[-args].type) {
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_PROGRAM: case T_FUNCTION:
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`+", 1, "string|object|int|float|array|mapping|multiset");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
54db6c1999-03-27Henrik Grubbström (Grubba)  bad_arg_error("`+", sp-args, args, 1, "string|object|int|float|array|mapping|multiset", sp-args, "Incompatible types\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; /* compiler hint */ case BIT_STRING: {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *r;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  PCHARP buf;
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t tmp;
3e625c1998-10-11Fredrik Hübinette (Hubbe)  int max_shift=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
3e625c1998-10-11Fredrik Hübinette (Hubbe)  if(args==1) return; size=0; for(e=-args;e<0;e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
3e625c1998-10-11Fredrik Hübinette (Hubbe)  size+=sp[e].u.string->len; if(sp[e].u.string->size_shift > max_shift) max_shift=sp[e].u.string->size_shift;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
66769e1999-11-04Fredrik Hübinette (Hubbe)  if(size == sp[-args].u.string->len) { pop_n_elems(args-1); return; }
3e625c1998-10-11Fredrik Hübinette (Hubbe)  tmp=sp[-args].u.string->len; r=new_realloc_shared_string(sp[-args].u.string,size,max_shift); sp[-args].type=T_INT;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  buf=MKPCHARP_STR_OFF(r,tmp);
3e625c1998-10-11Fredrik Hübinette (Hubbe)  for(e=-args+1;e<0;e++) {
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  pike_string_cpy(buf,sp[e].u.string); INC_PCHARP(buf,sp[e].u.string->len);
3e625c1998-10-11Fredrik Hübinette (Hubbe)  }
d029c12001-02-03Fredrik Hübinette (Hubbe)  sp[-args].u.string=low_end_shared_string(r);
3e625c1998-10-11Fredrik Hübinette (Hubbe)  sp[-args].type=T_STRING; for(e=-args+1;e<0;e++) free_string(sp[e].u.string); sp-=args-1;
8a630c1996-04-13Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; } case BIT_STRING | BIT_INT: case BIT_STRING | BIT_FLOAT: case BIT_STRING | BIT_FLOAT | BIT_INT: {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *r;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  PCHARP buf;
3e625c1998-10-11Fredrik Hübinette (Hubbe)  char buffer[50]; int max_shift=0;
d67c6d2000-09-22Henrik Grubbström (Grubba)  if ((sp[-args].type != T_STRING) && (sp[1-args].type != T_STRING)) { struct svalue *save_sp = sp; /* We need to perform a normal addition first. */ for (e=-args; e < 0; e++) { if (save_sp[e].type == T_STRING) break; *(sp++) = save_sp[e]; } /* Perform the addition. */ f_add(args+e); save_sp[--e] = *(--sp); #ifdef PIKE_DEBUG if (sp != save_sp) { 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) { 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; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  size=0; for(e=-args;e<0;e++) { switch(sp[e].type) { case T_STRING: size+=sp[e].u.string->len;
3e625c1998-10-11Fredrik Hübinette (Hubbe)  if(sp[e].u.string->size_shift > max_shift) max_shift=sp[e].u.string->size_shift;
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case T_INT: size+=14; break; case T_FLOAT: size+=22; break; } }
3e625c1998-10-11Fredrik Hübinette (Hubbe)  r=begin_wide_shared_string(size,max_shift);
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  buf=MKPCHARP_STR(r);
5267b71995-08-09Fredrik Hübinette (Hubbe)  size=0; for(e=-args;e<0;e++) { switch(sp[e].type) { case T_STRING:
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  pike_string_cpy(buf,sp[e].u.string); INC_PCHARP(buf,sp[e].u.string->len);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case T_INT:
3e625c1998-10-11Fredrik Hübinette (Hubbe)  sprintf(buffer,"%ld",(long)sp[e].u.integer); goto append_buffer;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_FLOAT:
3e625c1998-10-11Fredrik Hübinette (Hubbe)  sprintf(buffer,"%f",(double)sp[e].u.float_number); append_buffer: switch(max_shift) {
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  case 0: convert_0_to_0((p_wchar0 *)buf.ptr,buffer,strlen(buffer)); break; case 1:
01a9572000-02-03Henrik Grubbström (Grubba)  convert_0_to_1((p_wchar1 *)buf.ptr,(p_wchar0 *)buffer, strlen(buffer));
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  break; case 2:
01a9572000-02-03Henrik Grubbström (Grubba)  convert_0_to_2((p_wchar2 *)buf.ptr,(p_wchar0 *)buffer, strlen(buffer));
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  break;
3e625c1998-10-11Fredrik Hübinette (Hubbe)  }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  INC_PCHARP(buf,strlen(buffer));
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  r->len=SUBTRACT_PCHARP(buf,MKPCHARP_STR(r));
3e625c1998-10-11Fredrik Hübinette (Hubbe)  low_set_index(r,r->len,0);
ba52802001-02-03Fredrik Hübinette (Hubbe)  r=low_end_shared_string(r);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_string(r); break; } case BIT_INT:
fda0de1999-10-08Fredrik Noring #ifdef AUTO_BIGNUM size = 0; for(e = -args; e < 0; e++) {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  if(INT_TYPE_ADD_OVERFLOW(sp[e].u.integer, size))
fda0de1999-10-08Fredrik Noring  {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  convert_svalue_to_bignum(sp-args); f_add(args); return;
fda0de1999-10-08Fredrik Noring  } else {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  size += sp[e].u.integer;
fda0de1999-10-08Fredrik Noring  } }
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  sp-=args; push_int(size);
fda0de1999-10-08Fredrik Noring #else
5267b71995-08-09Fredrik Hübinette (Hubbe)  size=0; for(e=-args; e<0; e++) size+=sp[e].u.integer; sp-=args-1; sp[-1].u.integer=size;
fda0de1999-10-08Fredrik Noring #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case BIT_FLOAT: { FLOAT_TYPE sum; sum=0.0; for(e=-args; e<0; e++) sum+=sp[e].u.float_number; sp-=args-1; sp[-1].u.float_number=sum; break; }
482fb51999-03-12Per Hedbor  case BIT_FLOAT|BIT_INT:
bce86c1996-02-25Fredrik Hübinette (Hubbe)  { FLOAT_TYPE sum; sum=0.0; for(e=-args; e<0; e++) { if(sp[e].type==T_FLOAT) { sum+=sp[e].u.float_number; }else{ sum+=(FLOAT_TYPE)sp[e].u.integer; } } sp-=args-1;
a650f21996-03-22Fredrik Hübinette (Hubbe)  sp[-1].type=T_FLOAT;
bce86c1996-02-25Fredrik Hübinette (Hubbe)  sp[-1].u.float_number=sum; break; }
ee37801999-02-09Fredrik Hübinette (Hubbe)  case BIT_ARRAY|BIT_INT: { if(IS_UNDEFINED(sp-args)) { int e; struct array *a; for(e=1;e<args;e++) if(sp[e-args].type != T_ARRAY)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`+", e+1, "array");
482fb51999-03-12Per Hedbor 
ee37801999-02-09Fredrik Hübinette (Hubbe)  a=add_arrays(sp-args+1,args-1); pop_n_elems(args); push_array(a); return; }
54db6c1999-03-27Henrik Grubbström (Grubba)  if (sp[-args].type == T_INT) { int e; for(e=1;e<args;e++) if (sp[e-args].type != T_INT) SIMPLE_BAD_ARG_ERROR("`+", e+1, "int"); } else { int e; for(e=0;e<args;e++) if (sp[e-args].type != T_ARRAY) SIMPLE_BAD_ARG_ERROR("`+", e+1, "array"); } /* Probably not reached, but... */ bad_arg_error("`+", sp-args, args, 1, "array", sp-args, "trying to add integers and arrays.\n");
ee37801999-02-09Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  case BIT_ARRAY: { struct array *a; a=add_arrays(sp-args,args); pop_n_elems(args); push_array(a); break; }
482fb51999-03-12Per Hedbor  case BIT_MAPPING|BIT_INT: { if(IS_UNDEFINED(sp-args)) { int e; struct mapping *a; for(e=1;e<args;e++) if(sp[e-args].type != T_MAPPING)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`+", e+1, "mapping");
482fb51999-03-12Per Hedbor  a=add_mappings(sp-args+1,args-1); pop_n_elems(args); push_mapping(a); return; }
54db6c1999-03-27Henrik Grubbström (Grubba)  if (sp[-args].type == T_INT) { int e; for(e=1;e<args;e++) if (sp[e-args].type != T_INT) SIMPLE_BAD_ARG_ERROR("`+", e+1, "int"); } else { int e; for(e=0;e<args;e++) if (sp[e-args].type != T_MAPPING) SIMPLE_BAD_ARG_ERROR("`+", e+1, "mapping"); } /* Probably not reached, but... */ bad_arg_error("`+", sp-args, args, 1, "mapping", sp-args, "Trying to add integers and mappings.\n");
482fb51999-03-12Per Hedbor  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  case BIT_MAPPING: { struct mapping *m; m = add_mappings(sp - args, args); pop_n_elems(args); push_mapping(m); break; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  case BIT_MULTISET:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct multiset *l;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe)  l = add_multisets(sp - args, args);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_multiset(l);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; } } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) static int generate_sum(node *n) {
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  node **first_arg, **second_arg;
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2:
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  first_arg=my_get_arg(&_CDR(n), 0); second_arg=my_get_arg(&_CDR(n), 1);
5e44422001-02-25Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);
a2b70a2000-04-30Fredrik Hübinette (Hubbe)  if(first_arg[0]->type == float_type_string && second_arg[0]->type == float_type_string) { emit0(F_ADD_FLOATS); } else if(first_arg[0]->type == int_type_string && second_arg[0]->type == int_type_string) { emit0(F_ADD_INTS); } else { emit0(F_ADD); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
e104411998-06-05Fredrik Hübinette (Hubbe) static node *optimize_eq(node *n) { node **first_arg, **second_arg, *ret; if(count_args(CDR(n))==2) {
f807f01999-11-11Henrik Grubbström (Grubba)  first_arg=my_get_arg(&_CDR(n), 0);
177c561999-11-11Henrik Grubbström (Grubba)  second_arg=my_get_arg(&_CDR(n), 1);
e104411998-06-05Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e104411998-06-05Fredrik Hübinette (Hubbe)  if(!first_arg || !second_arg) fatal("Couldn't find argument!\n"); #endif if(node_is_false(*first_arg) && !node_may_overload(*second_arg,LFUN_EQ)) { ret=*second_arg;
01b2c21999-11-22Henrik Grubbström (Grubba)  ADD_NODE_REF(*second_arg);
e104411998-06-05Fredrik Hübinette (Hubbe)  return mkopernode("`!",ret,0); } if(node_is_false(*second_arg) && !node_may_overload(*first_arg,LFUN_EQ)) { ret=*first_arg;
01b2c21999-11-22Henrik Grubbström (Grubba)  ADD_NODE_REF(*first_arg);
e104411998-06-05Fredrik Hübinette (Hubbe)  return mkopernode("`!",ret,0); }
ffa4522001-05-11Henrik Grubbström (Grubba)  if (((*second_arg)->token == F_CONSTANT) && ((*second_arg)->u.sval.type == T_STRING) && ((*first_arg)->token == F_RANGE) && (CADR(*first_arg)->token == F_CONSTANT) && (CADR(*first_arg)->u.sval.type == T_INT) && (!(CADR(*first_arg)->u.sval.u.integer)) && (CDDR(*first_arg)->token == F_CONSTANT) && (CDDR(*first_arg)->u.sval.type == T_INT)) { /* str[..c] == "foo" */ INT_TYPE c = CDDR(*first_arg)->u.sval.u.integer; if ((*second_arg)->u.sval.u.string->len == c+1) { /* str[..2] == "foo" * ==> * has_prefix(str, "foo"); */ ADD_NODE_REF2(CAR(*first_arg), ADD_NODE_REF2(*second_arg, ret = mkopernode("has_prefix", CAR(*first_arg), *second_arg); )); return ret; } else if ((*second_arg)->u.sval.u.string->len <= c) { /* str[..4] == "foo" * ==> * str == "foo" */ /* FIXME: Warn? */ ADD_NODE_REF2(CAR(*first_arg), ADD_NODE_REF2(*second_arg, ret = mkopernode("`==", CAR(*first_arg), *second_arg); )); return ret; } else { /* str[..1] == "foo" * ==> * (str, 0) */ /* FIXME: Warn? */ ADD_NODE_REF2(CAR(*first_arg), ret = mknode(F_COMMA_EXPR, CAR(*first_arg), mkintnode(0)); ); return ret; } }
e104411998-06-05Fredrik Hübinette (Hubbe)  } return 0; } static node *optimize_not(node *n) { node **first_arg, **more_args; int e; if(count_args(CDR(n))==1) {
f807f01999-11-11Henrik Grubbström (Grubba)  first_arg=my_get_arg(&_CDR(n), 0);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e104411998-06-05Fredrik Hübinette (Hubbe)  if(!first_arg) fatal("Couldn't find argument!\n"); #endif if(node_is_true(*first_arg)) return mkintnode(0); if(node_is_false(*first_arg)) return mkintnode(1);
f807f01999-11-11Henrik Grubbström (Grubba) #define TMP_OPT(X,Y) do { \ if((more_args=is_call_to(*first_arg, X))) \ { \ node *tmp=*more_args; \
ea71c22000-11-11Fredrik Hübinette (Hubbe)  if(count_args(*more_args) > 2) return 0; \
01b2c21999-11-22Henrik Grubbström (Grubba)  ADD_NODE_REF(*more_args); \
f807f01999-11-11Henrik Grubbström (Grubba)  return mkopernode(Y,tmp,0); \ } } while(0)
e104411998-06-05Fredrik Hübinette (Hubbe)  TMP_OPT(f_eq, "`!="); TMP_OPT(f_ne, "`=="); TMP_OPT(f_lt, "`>="); TMP_OPT(f_gt, "`<="); TMP_OPT(f_le, "`>"); TMP_OPT(f_ge, "`<"); #undef TMP_OPT
89c4452000-04-12Henrik Grubbström (Grubba)  if((more_args = is_call_to(*first_arg, f_search)) && (count_args(*more_args) == 2)) { node *search_args = *more_args; if ((search_args->token == F_ARG_LIST) && CAR(search_args) && (CAR(search_args)->type == string_type_string) && CDR(search_args) && (CDR(search_args)->type == string_type_string)) { /* !search(string a, string b) => has_prefix(a, b) */ ADD_NODE_REF(*more_args); return mkefuncallnode("has_prefix", search_args); } }
e104411998-06-05Fredrik Hübinette (Hubbe)  } return 0; }
6930181996-02-25Fredrik Hübinette (Hubbe) static node *optimize_binary(node *n) { node **first_arg, **second_arg, *ret; if(count_args(CDR(n))==2) {
f807f01999-11-11Henrik Grubbström (Grubba)  first_arg=my_get_arg(&_CDR(n), 0); second_arg=my_get_arg(&_CDR(n), 1);
6930181996-02-25Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
6930181996-02-25Fredrik Hübinette (Hubbe)  if(!first_arg || !second_arg) fatal("Couldn't find argument!\n"); #endif
bce86c1996-02-25Fredrik Hübinette (Hubbe)  if((*second_arg)->type == (*first_arg)->type && compile_type_to_runtime_type((*second_arg)->type) != T_MIXED)
6930181996-02-25Fredrik Hübinette (Hubbe)  { if((*first_arg)->token == F_APPLY && CAR(*first_arg)->token == F_CONSTANT && is_eq(& CAR(*first_arg)->u.sval, & CAR(n)->u.sval)) {
8f2fa42000-10-03Henrik Grubbström (Grubba)  ADD_NODE_REF2(CAR(n), ADD_NODE_REF2(CDR(*first_arg), ADD_NODE_REF2(*second_arg, ret = mknode(F_APPLY, CAR(n), mknode(F_ARG_LIST, CDR(*first_arg), *second_arg)) )));
6930181996-02-25Fredrik Hübinette (Hubbe)  return ret; } if((*second_arg)->token == F_APPLY && CAR(*second_arg)->token == F_CONSTANT && is_eq(& CAR(*second_arg)->u.sval, & CAR(n)->u.sval)) {
8f2fa42000-10-03Henrik Grubbström (Grubba)  ADD_NODE_REF2(CAR(n), ADD_NODE_REF2(*first_arg, ADD_NODE_REF2(CDR(*second_arg), ret = mknode(F_APPLY, CAR(n), mknode(F_ARG_LIST, *first_arg, CDR(*second_arg))) )));
6930181996-02-25Fredrik Hübinette (Hubbe)  return ret; } } } return 0; }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) static int generate_comparison(node *n) { if(count_args(CDR(n))==2) {
4c573c1996-08-03Fredrik Hübinette (Hubbe)  if(do_docode(CDR(n),DO_NOT_COPY) != 2) fatal("Count args was wrong in generate_comparison.\n");
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(CAR(n)->u.sval.u.efun->function == f_eq)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_EQ);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_ne)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_NE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_lt)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_LT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_le)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_LE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_gt)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_GT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_ge)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_GE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else fatal("Couldn't generate comparison!\n"); return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) static int float_promote(void)
bce86c1996-02-25Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type==T_INT && sp[-1].type==T_FLOAT)
bce86c1996-02-25Fredrik Hübinette (Hubbe)  { sp[-2].u.float_number=(FLOAT_TYPE)sp[-2].u.integer; sp[-2].type=T_FLOAT;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return 1;
bce86c1996-02-25Fredrik Hübinette (Hubbe)  }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  else if(sp[-1].type==T_INT && sp[-2].type==T_FLOAT)
bce86c1996-02-25Fredrik Hübinette (Hubbe)  { sp[-1].u.float_number=(FLOAT_TYPE)sp[-1].u.integer; sp[-1].type=T_FLOAT;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return 1; }
e924491999-12-14Fredrik Hübinette (Hubbe)  #ifdef AUTO_BIGNUM if(is_bignum_object_in_svalue(sp-2) && sp[-1].type==T_FLOAT) { stack_swap();
b103b32001-02-20Henrik Grubbström (Grubba)  ref_push_type_value(float_type_string);
e924491999-12-14Fredrik Hübinette (Hubbe)  stack_swap(); f_cast(); stack_swap(); return 1; } else if(is_bignum_object_in_svalue(sp-1) && sp[-2].type==T_FLOAT) {
b103b32001-02-20Henrik Grubbström (Grubba)  ref_push_type_value(float_type_string);
e924491999-12-14Fredrik Hübinette (Hubbe)  stack_swap(); f_cast(); return 1; } #endif
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return 0; } static int call_lfun(int left, int right) { if(sp[-2].type == T_OBJECT && sp[-2].u.object->prog &&
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  FIND_LFUN(sp[-2].u.object->prog,left) != -1)
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  { apply_lfun(sp[-2].u.object, left, 1); free_svalue(sp-2); sp[-2]=sp[-1]; sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return 1;
bce86c1996-02-25Fredrik Hübinette (Hubbe)  }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type == T_OBJECT && sp[-1].u.object->prog &&
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  FIND_LFUN(sp[-1].u.object->prog,right) != -1)
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  { push_svalue(sp-2); apply_lfun(sp[-2].u.object, right, 1); free_svalue(sp-3); sp[-3]=sp[-1]; sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  pop_stack(); return 1; } return 0;
bce86c1996-02-25Fredrik Hübinette (Hubbe) }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
aa17e32000-04-12Mirar (Pontus Hagland) 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);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_subtract(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if (sp[-2].type != sp[-1].type && !float_promote()) { if(call_lfun(LFUN_SUBTRACT, LFUN_RSUBTRACT)) return;
aa17e32000-04-12Mirar (Pontus Hagland)  if (sp[-2].type==T_MAPPING) switch (sp[-1].type) { case T_ARRAY: { struct mapping *m; m=merge_mapping_array_unordered(sp[-2].u.mapping, sp[-1].u.array, PIKE_ARRAY_OP_SUB); pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct mapping *m; m=merge_mapping_array_ordered(sp[-2].u.mapping, sp[-1].u.multiset->ind, PIKE_ARRAY_OP_SUB); pop_n_elems(2); push_mapping(m); return; } }
b341a61999-11-04Fredrik Hübinette (Hubbe)  bad_arg_error("`-", sp-2, 2, 2, get_name_of_type(sp[-2].type),
54db6c1999-03-27Henrik Grubbström (Grubba)  sp-1, "Subtract on different types.\n");
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  switch(sp[-2].type)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_SUBTRACT,2); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  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); pop_n_elems(2); push_array(a); return; } case T_MAPPING: { struct mapping *m;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping,PIKE_ARRAY_OP_SUB);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_mapping(m); return; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct multiset *l;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  l=merge_multisets(sp[-2].u.multiset, sp[-1].u.multiset, PIKE_ARRAY_OP_SUB);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_multiset(l);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } case T_FLOAT: sp--; sp[-1].u.float_number -= sp[0].u.float_number; return; case T_INT:
ff0d461999-10-15Fredrik Noring #ifdef AUTO_BIGNUM if(INT_TYPE_SUB_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) { convert_stack_top_to_bignum(); f_minus(2); return; } #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; sp[-1].u.integer -= sp[0].u.integer; return; case T_STRING: {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *s,*ret;
5267b71995-08-09Fredrik Hübinette (Hubbe)  s=make_shared_string("");
fb5c4f1996-03-24Fredrik Hübinette (Hubbe)  ret=string_replace(sp[-2].u.string,sp[-1].u.string,s); free_string(sp[-2].u.string);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_string(sp[-1].u.string); free_string(s);
fb5c4f1996-03-24Fredrik Hübinette (Hubbe)  sp[-2].u.string=ret; sp--;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } default:
54db6c1999-03-27Henrik Grubbström (Grubba)  { int args = 2; SIMPLE_BAD_ARG_ERROR("`-", 1, "int|float|string|mapping|multiset|array|object"); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl mixed `-(mixed arg1) *! @decl mixed `-(object arg1, mixed arg2) *! @decl mixed `-(mixed arg1, mixed arg2) *! @decl mapping `-(mapping arg1, array arg2) *! @decl mapping `-(mapping arg1, multiset arg2) *! @decl mapping `-(mapping arg1, mapping arg2) *! @decl array `-(array arg1, array arg2) *! @decl multiset `-(multiset arg1, multiset arg2) *! @decl float `-(float arg1, int|float arg2) *! @decl float `-(int arg1, float arg2) *! @decl int `-(int arg1, int arg2) *! @decl string `-(string arg1, string arg2) *! @decl mixed `-(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Negation/subtraction operator. *! *! @returns *! If there's only a single argument, that argument will be returned *! negated. If @[arg1] was an object, @code{@[arg1]::`-()@} will be called *! without arguments. *! *! If there are more than two arguments the result will be: *! @code{`-(`-(@[arg1], @[arg2]), @@@[extras])@}. *! *! If @[arg1] is an object that overloads @tt{`-()@}, that function will *! be called with @[arg2] as the single argument. *! *! If @[arg2] is an object that overloads @tt{``-()@}, that function will *! be called with @[arg1] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type mapping *! @mixed @[arg2] *! @type array *! The result will be @[arg1] with all occurrances of *! @[arg2] removed. *! @type multiset *! @type mapping *! The result will be @[arg1] with all occurrences of *! @code{@[indices](@[arg2])@} removed. *! @endmixed *! @type array *! @type multiset *! The result will be the elements of @[arg1] that are not in @[arg2]. *! @type float *! @type int *! The result will be @code{@[arg1] - @[arg2]@}, and will be a float *! if either @[arg1] or @[arg2] is a float. *! @type string *! Result will be the string @[arg1] with all occurrances of the *! substring @[arg2] removed. *! @endmixed
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @note *! In Pike 7.0 and earlier the subtraction order was unspecified. *! *! @seealso *! @[`+()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_minus(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { switch(args) {
54db6c1999-03-27Henrik Grubbström (Grubba)  case 0: SIMPLE_TOO_FEW_ARGS_ERROR("`-", 1);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  case 1: o_negate(); break; case 2: o_subtract(); break; default: { INT32 e; struct svalue *s=sp-args; 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); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  } } static int generate_minus(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),DO_NOT_COPY);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_NEGATE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; case 2:
5e44422001-02-25Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_SUBTRACT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_and(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) {
aa17e32000-04-12Mirar (Pontus Hagland)  if(call_lfun(LFUN_AND, LFUN_RAND)) return; else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) || (sp[-1].type == T_FUNCTION)) && ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) || (sp[-2].type == T_FUNCTION))) { if (sp[-2].type != T_TYPE) { struct program *p = program_from_svalue(sp - 2); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`&", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
aa17e32000-04-12Mirar (Pontus Hagland)  free_svalue(sp - 2);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-2].u.type = pop_unfinished_type();
aa17e32000-04-12Mirar (Pontus Hagland)  sp[-2].type = T_TYPE;
dc7d491999-12-15Henrik Grubbström (Grubba)  }
aa17e32000-04-12Mirar (Pontus Hagland)  if (sp[-1].type != T_TYPE) { struct program *p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`&", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
aa17e32000-04-12Mirar (Pontus Hagland)  free_svalue(sp - 1);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-1].u.type = pop_unfinished_type();
aa17e32000-04-12Mirar (Pontus Hagland)  sp[-1].type = T_TYPE;
dc7d491999-12-15Henrik Grubbström (Grubba)  }
aa17e32000-04-12Mirar (Pontus Hagland)  } else if (sp[-2].type==T_MAPPING) switch (sp[-1].type) { case T_ARRAY: { struct mapping *m; m=merge_mapping_array_unordered(sp[-2].u.mapping, sp[-1].u.array, PIKE_ARRAY_OP_AND); pop_n_elems(2); push_mapping(m); return; } case T_MULTISET: { struct mapping *m; m=merge_mapping_array_ordered(sp[-2].u.mapping, sp[-1].u.multiset->ind, PIKE_ARRAY_OP_AND); pop_n_elems(2); push_mapping(m); return; } } else { int args = 2; SIMPLE_BAD_ARG_ERROR("`&", 2, get_name_of_type(sp[-2].type)); }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(sp[-2].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_AND,2); break;
fc0bb51997-02-13Niels Möller 
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_INT: sp--; sp[-1].u.integer &= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_AND);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_mapping(m); return; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct multiset *l;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  l=merge_multisets(sp[-2].u.multiset, sp[-1].u.multiset, PIKE_ARRAY_OP_AND);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_multiset(l);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } case T_ARRAY: { struct array *a; a=and_arrays(sp[-2].u.array, sp[-1].u.array); pop_n_elems(2); push_array(a); return; }
fc0bb51997-02-13Niels Möller 
3db0d21999-12-13Henrik Grubbström (Grubba)  case T_TYPE: {
07f5432001-02-21Henrik Grubbström (Grubba)  struct pike_type *t; t = and_pike_types(sp[-2].u.type, sp[-1].u.type);
3db0d21999-12-13Henrik Grubbström (Grubba)  pop_n_elems(2);
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(t);
3db0d21999-12-13Henrik Grubbström (Grubba)  return; }
dc7d491999-12-15Henrik Grubbström (Grubba)  case T_FUNCTION: case T_PROGRAM: { struct program *p;
07f5432001-02-21Henrik Grubbström (Grubba)  struct pike_type *a; struct pike_type *b; struct pike_type *t;
dc7d491999-12-15Henrik Grubbström (Grubba)  p = program_from_svalue(sp - 2); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`&", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  a = pop_unfinished_type(); p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`&", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  b = pop_unfinished_type(); t = and_pike_types(a, b); pop_n_elems(2);
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(t); free_type(a); free_type(b);
dc7d491999-12-15Henrik Grubbström (Grubba)  return; }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe) #define STRING_BITOP(OP,STROP) \ case T_STRING: \ { \ struct pike_string *s; \
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t len, i; \
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  \ 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) \ { \ 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]; \ }else{ \ s = begin_wide_shared_string(len, \ MAXIMUM(sp[-2].u.string->size_shift, \ 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)); \ } \ pop_n_elems(2); \ push_string(end_shared_string(s)); \ return; \ } STRING_BITOP(&,"AND")
5267b71995-08-09Fredrik Hübinette (Hubbe)  default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`&", "Bitwise and on illegal type.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
3c04e81997-03-13Fredrik Hübinette (Hubbe) /* 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. */
adbb781998-09-18Fredrik Hübinette (Hubbe) static void r_speedup(INT32 args, void (*func)(void)) { int num; struct svalue tmp; ONERROR err; switch(args) { case 3: func(); case 2: func(); case 1: return; default: r_speedup((args+1)>>1,func); tmp=*--sp; SET_ONERROR(err,do_free_svalue,&tmp); r_speedup(args>>1,func); UNSET_ONERROR(err); sp++[0]=tmp; func(); } }
3c04e81997-03-13Fredrik Hübinette (Hubbe) static void speedup(INT32 args, void (*func)(void)) { switch(sp[-args].type) {
c2769b1999-10-01Fredrik Hübinette (Hubbe)  /* This method can be used for types where a op b === b op a */
adbb781998-09-18Fredrik Hübinette (Hubbe)  case T_MULTISET:
3c04e81997-03-13Fredrik Hübinette (Hubbe)  {
adbb781998-09-18Fredrik Hübinette (Hubbe)  int e=-1; while(args > 1)
3c04e81997-03-13Fredrik Hübinette (Hubbe)  {
adbb781998-09-18Fredrik Hübinette (Hubbe)  struct svalue tmp; func(); args--; e++; if(e - args >= -1) { e=0; }else{ tmp=sp[e-args]; sp[e-args]=sp[-1]; sp[-1]=tmp; }
3c04e81997-03-13Fredrik Hübinette (Hubbe)  }
adbb781998-09-18Fredrik Hübinette (Hubbe)  return;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  }
adbb781998-09-18Fredrik Hübinette (Hubbe) 
c2769b1999-10-01Fredrik Hübinette (Hubbe)  /* Binary balanced tree method for types where * a op b may or may not be equal to b op a */ case T_ARRAY:
adbb781998-09-18Fredrik Hübinette (Hubbe)  case T_MAPPING: r_speedup(args,func); return;
3c04e81997-03-13Fredrik Hübinette (Hubbe) 
adbb781998-09-18Fredrik Hübinette (Hubbe)  default: while(--args > 0) func();
3c04e81997-03-13Fredrik Hübinette (Hubbe)  } }
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl mixed `&(mixed arg1) *! @decl mixed `&(object arg1, mixed arg2) *! @decl mixed `&(mixed arg1, object arg2) *! @decl int `&(int arg1, int arg2) *! @decl array `&(array arg1, array arg2) *! @decl multiset `&(multiset arg1, multiset arg2) *! @decl mapping `&(mapping arg1, mapping arg2) *! @decl string `&(string arg1, string arg2) *! @decl type `&(type|program arg1, type|program arg2) *! @decl mapping `&(mapping arg1, array arg2) *! @decl mapping `&(array arg1, mapping arg2) *! @decl mapping `&(mapping arg1, multiset arg2) *! @decl mapping `&(multiset arg1, mapping arg2) *! @decl mixed `&(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Bitwise and/intersection operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! If there's a single argument, that argument will be returned.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If there are more than two arguments, the result will be: *! @code{`&(`&(@[arg1], @[arg2]), @@@[extras])@}.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg1] is an object that has an @[lfun::`&()], that function *! will be called with @[arg2] as the single argument.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg2] is an object that has an @[lfun::``&()], that function *! will be called with @[arg1] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type int *! The result will be the bitwise and of @[arg1] and @[arg2]. *! @type array *! @type multiset *! @type mapping *! The result will be the elements of @[arg1] and @[arg2] that *! occurr in both. *! @type type *! @type program *! The result will be the type intersection of @[arg1] and @[arg2]. *! @type string *! The result will be the string where the elements of @[arg1] *! and @[arg2] have been pairwise bitwise anded. *! @endmixed
f09ec92001-02-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[`|()], @[lfun::`&()], @[lfun::``&()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_and(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { switch(args) {
54db6c1999-03-27Henrik Grubbström (Grubba)  case 0: SIMPLE_TOO_FEW_ARGS_ERROR("`&", 1);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  case 1: return; case 2: o_and(); return;
07c0731996-06-21Fredrik Hübinette (Hubbe)  default: if(sp[-args].type == T_OBJECT) { CALL_OPERATOR(LFUN_AND, args); }else{
3c04e81997-03-13Fredrik Hübinette (Hubbe)  speedup(args, o_and);
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  } } static int generate_and(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2: do_docode(CDR(n),0);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_AND);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_or(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) {
dc7d491999-12-15Henrik Grubbström (Grubba)  if(call_lfun(LFUN_OR, LFUN_ROR)) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return;
dc7d491999-12-15Henrik Grubbström (Grubba)  } else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) || (sp[-1].type == T_FUNCTION)) && ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) || (sp[-2].type == T_FUNCTION))) { if (sp[-2].type != T_TYPE) { struct program *p = program_from_svalue(sp - 2); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`|", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  free_svalue(sp - 2);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-2].u.type = pop_unfinished_type();
dc7d491999-12-15Henrik Grubbström (Grubba)  sp[-2].type = T_TYPE; } if (sp[-1].type != T_TYPE) { struct program *p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`|", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  free_svalue(sp - 1);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-1].u.type = pop_unfinished_type();
dc7d491999-12-15Henrik Grubbström (Grubba)  sp[-1].type = T_TYPE; } } else {
54db6c1999-03-27Henrik Grubbström (Grubba)  int args = 2;
b341a61999-11-04Fredrik Hübinette (Hubbe)  SIMPLE_BAD_ARG_ERROR("`|", 2, get_name_of_type(sp[-2].type));
54db6c1999-03-27Henrik Grubbström (Grubba)  }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(sp[-2].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_OR,2); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_INT: sp--; sp[-1].u.integer |= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_OR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_mapping(m); return; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct multiset *l;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  l=merge_multisets(sp[-2].u.multiset, sp[-1].u.multiset, PIKE_ARRAY_OP_OR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_multiset(l);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } case T_ARRAY: { struct array *a;
7b1a741999-08-14Fredrik Hübinette (Hubbe)  a=merge_array_with_order(sp[-2].u.array, sp[-1].u.array, PIKE_ARRAY_OP_OR);
c1d3f21999-08-16Fredrik Hübinette (Hubbe)  pop_n_elems(2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_array(a); return; }
3db0d21999-12-13Henrik Grubbström (Grubba)  case T_TYPE: {
07f5432001-02-21Henrik Grubbström (Grubba)  struct pike_type *t; t = or_pike_types(sp[-2].u.type, sp[-1].u.type, 0);
3db0d21999-12-13Henrik Grubbström (Grubba)  pop_n_elems(2);
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(t);
3db0d21999-12-13Henrik Grubbström (Grubba)  return; }
dc7d491999-12-15Henrik Grubbström (Grubba)  case T_FUNCTION: case T_PROGRAM: { struct program *p;
07f5432001-02-21Henrik Grubbström (Grubba)  struct pike_type *a; struct pike_type *b; struct pike_type *t;
dc7d491999-12-15Henrik Grubbström (Grubba)  p = program_from_svalue(sp - 2); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`|", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  a = pop_unfinished_type(); p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`|", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  b = pop_unfinished_type(); t = or_pike_types(a, b, 0); pop_n_elems(2);
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(t); free_type(a); free_type(b);
dc7d491999-12-15Henrik Grubbström (Grubba)  return; }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  STRING_BITOP(|,"OR")
fc0bb51997-02-13Niels Möller 
5267b71995-08-09Fredrik Hübinette (Hubbe)  default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`|", "Bitwise or on illegal type.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
b90e552001-02-08Henrik Grubbström (Grubba) /*! @decl mixed `|(mixed arg1) *! @decl mixed `|(object arg1, mixed arg2) *! @decl mixed `|(mixed arg1, object arg2) *! @decl int `|(int arg1, int arg2) *! @decl mapping `|(mapping arg1, mapping arg2) *! @decl multiset `|(multiset arg1, multiset arg2) *! @decl array `|(array arg1, array arg2) *! @decl string `|(string arg1, atring arg2) *! @decl type `|(program|type arg1, program|type arg2) *! @decl mixed `|(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Bitwise or/join operator.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! If there's a single argument, that argument will be returned.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If there are more than two arguments, the result will be: *! @code{`|(`|(@[arg1], @[arg2]), @@@[extras])@}.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg1] is an object that has an @[lfun::`|()], that function *! will be called with @[arg2] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg2] is an object that has an @[lfun::``|()], that function *! will be called with @[arg1] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type int *! The result will be the binary or of @[arg1] and @[arg2]. *! @type mapping *! @type multiset *! The result will be the join of @[arg1] and @[arg2]. *! @type array *! The result will be the concatenation of @[arg1] and @[arg2]. *! @type string *! The result will be the pairwise bitwose or of @[arg1] and @[arg2]. *! @type type *! @type program *! The result will be the type join of @[arg1] and @[arg2]. *! @endmixed
b90e552001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`&()], @[lfun::`|()], @[lfun::``|()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_or(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { switch(args) {
54db6c1999-03-27Henrik Grubbström (Grubba)  case 0: SIMPLE_TOO_FEW_ARGS_ERROR("`|", 1);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  case 1: return; case 2: o_or(); return;
07c0731996-06-21Fredrik Hübinette (Hubbe)  default: if(sp[-args].type==T_OBJECT) { CALL_OPERATOR(LFUN_OR, args); } else {
3c04e81997-03-13Fredrik Hübinette (Hubbe)  speedup(args, o_or);
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  } } static int generate_or(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2: do_docode(CDR(n),0);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_OR);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_xor(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) {
dc7d491999-12-15Henrik Grubbström (Grubba)  if(call_lfun(LFUN_XOR, LFUN_RXOR)) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  return;
dc7d491999-12-15Henrik Grubbström (Grubba)  } else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) || (sp[-1].type == T_FUNCTION)) && ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) || (sp[-2].type == T_FUNCTION))) { if (sp[-2].type != T_TYPE) { struct program *p = program_from_svalue(sp - 2); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`^", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  free_svalue(sp - 2);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-2].u.type = pop_unfinished_type();
dc7d491999-12-15Henrik Grubbström (Grubba)  sp[-2].type = T_TYPE; } if (sp[-1].type != T_TYPE) { struct program *p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`^", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  free_svalue(sp - 1);
07f5432001-02-21Henrik Grubbström (Grubba)  sp[-1].u.type = pop_unfinished_type();
dc7d491999-12-15Henrik Grubbström (Grubba)  sp[-1].type = T_TYPE; } } else {
54db6c1999-03-27Henrik Grubbström (Grubba)  int args = 2;
b341a61999-11-04Fredrik Hübinette (Hubbe)  SIMPLE_BAD_ARG_ERROR("`^", 2, get_name_of_type(sp[-2].type));
54db6c1999-03-27Henrik Grubbström (Grubba)  }
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(sp[-2].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_XOR,2); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_INT: sp--; sp[-1].u.integer ^= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, PIKE_ARRAY_OP_XOR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_mapping(m); return; }
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct multiset *l;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  l=merge_multisets(sp[-2].u.multiset, sp[-1].u.multiset, PIKE_ARRAY_OP_XOR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2);
06983f1996-09-22Fredrik Hübinette (Hubbe)  push_multiset(l);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; } case T_ARRAY: { struct array *a;
7b1a741999-08-14Fredrik Hübinette (Hubbe)  a=merge_array_with_order(sp[-2].u.array, sp[-1].u.array, PIKE_ARRAY_OP_XOR);
c1d3f21999-08-16Fredrik Hübinette (Hubbe)  pop_n_elems(2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_array(a); return; }
fc0bb51997-02-13Niels Möller 
dc7d491999-12-15Henrik Grubbström (Grubba)  case T_FUNCTION: case T_PROGRAM: { struct program *p; p = program_from_svalue(sp - 1); if (!p) { int args = 2; SIMPLE_BAD_ARG_ERROR("`^", 2, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  pop_stack();
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(pop_unfinished_type());
dc7d491999-12-15Henrik Grubbström (Grubba)  stack_swap(); p = program_from_svalue(sp - 1); if (!p) { int args = 2; stack_swap(); SIMPLE_BAD_ARG_ERROR("`^", 1, "type"); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  pop_stack();
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(pop_unfinished_type());
dc7d491999-12-15Henrik Grubbström (Grubba)  } /* FALL_THROUGH */
3db0d21999-12-13Henrik Grubbström (Grubba)  case T_TYPE: {
0e801c1999-12-13Henrik Grubbström (Grubba)  /* a ^ b == (a&~b)|(~a&b) */
07f5432001-02-21Henrik Grubbström (Grubba)  struct pike_type *a; struct pike_type *b;
be6fec2001-04-01Henrik Grubbström (Grubba)  copy_pike_type(a, sp[-2].u.type); copy_pike_type(b, sp[-1].u.type);
0e801c1999-12-13Henrik Grubbström (Grubba)  o_compl(); /* ~b */ o_and(); /* a&~b */
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(a);
0e801c1999-12-13Henrik Grubbström (Grubba)  o_compl(); /* ~a */
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(b);
0e801c1999-12-13Henrik Grubbström (Grubba)  o_and(); /* ~a&b */ o_or(); /* (a&~b)|(~a&b) */
3db0d21999-12-13Henrik Grubbström (Grubba)  return; }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  STRING_BITOP(^,"XOR")
fc0bb51997-02-13Niels Möller 
5267b71995-08-09Fredrik Hübinette (Hubbe)  default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`^", "Bitwise XOR on illegal type.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
b90e552001-02-08Henrik Grubbström (Grubba) /*! @decl mixed `^(mixed arg1) *! @decl mixed `^(object arg1, mixed arg2) *! @decl mixed `^(mixed arg1, object arg2) *! @decl int `^(int arg1, int arg2) *! @decl mapping `^(mapping arg1, mapping arg2) *! @decl multiset `^(multiset arg1, multiset arg2) *! @decl array `^(array arg1, array arg2) *! @decl string `^(string arg1, atring arg2) *! @decl type `^(program|type arg1, program|type arg2) *! @decl mixed `^(mixed arg1, mixed arg2, mixed ... extras) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Exclusive or operator.
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! If there's a single argument, that argument will be returned.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If there are more than two arguments, the result will be: *! @code{`^(`^(@[arg1], @[arg2]), @@@[extras])@}.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg1] is an object that has an @[lfun::`^()], that function *! will be called with @[arg2] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg2] is an object that has an @[lfun::``^()], that function *! will be called with @[arg1] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type int *! The result will be the bitwise xor of @[arg1] and @[arg2]. *! @type mapping *! @type multiset *! @type array *! The result will be the elements of @[arg1] and @[arg2] that *! only occurr in one of them. *! @type string *! The result will be the pairwise bitwise xor of @[arg1] and @[arg2]. *! @type type *! @type program *! The result will be the result of *! @code{(@[arg1]&~@[arg2])|(~@[arg1]&@[arg2])@}. *! @endmixed
b90e552001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`&()], @[`|()], @[lfun::`^()], @[lfun::``^()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_xor(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { switch(args) {
54db6c1999-03-27Henrik Grubbström (Grubba)  case 0: SIMPLE_TOO_FEW_ARGS_ERROR("`^", 1);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  case 1: return; case 2: o_xor(); return;
07c0731996-06-21Fredrik Hübinette (Hubbe)  default: if(sp[-args].type==T_OBJECT) { CALL_OPERATOR(LFUN_XOR, args); } else {
3c04e81997-03-13Fredrik Hübinette (Hubbe)  speedup(args, o_xor);
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  } } static int generate_xor(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2: do_docode(CDR(n),0);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_XOR);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_lsh(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
ff0d461999-10-15Fredrik Noring #ifdef AUTO_BIGNUM if(INT_TYPE_LSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) convert_stack_top_to_bignum(); #endif /* AUTO_BIGNUM */
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != T_INT || sp[-2].type != T_INT)
07c0731996-06-21Fredrik Hübinette (Hubbe)  {
54db6c1999-03-27Henrik Grubbström (Grubba)  int args = 2;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(call_lfun(LFUN_LSH, LFUN_RLSH))
07c0731996-06-21Fredrik Hübinette (Hubbe)  return;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type != T_INT)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`<<", 1, "int|object"); SIMPLE_BAD_ARG_ERROR("`<<", 2, "int|object");
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
34d4be2001-03-18Henrik Grubbström (Grubba) #ifndef AUTO_BIGNUM if (sp[-1].u.integer > 31) { sp--; sp[-1].u.integer = 0; return; } #endif /* !AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--;
8a630c1996-04-13Fredrik Hübinette (Hubbe)  sp[-1].u.integer = sp[-1].u.integer << sp->u.integer;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
b90e552001-02-08Henrik Grubbström (Grubba) /*! @decl int `<<(int arg1, int arg2) *! @decl mixed `<<(object arg1, int|object arg2) *! @decl mixed `<<(int arg1, object arg2)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Left shift operator.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg1] is an object that implements @[lfun::`<<()], that *! function will be called with @[arg2] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg2] is an object that implements @[lfun::``<<()], that *! function will be called with @[arg1] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Otherwise @[arg1] will be shifted @[arg2] bits left.
b90e552001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`>>()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_lsh(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  if(args != 2) { /* FIXME: Not appropriate if too many args. */ SIMPLE_TOO_FEW_ARGS_ERROR("`<<", 2); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_lsh(); } static int generate_lsh(node *n) { if(count_args(CDR(n))==2) {
5e44422001-02-25Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_LSH);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_rsh(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type != T_INT || sp[-1].type != T_INT)
07c0731996-06-21Fredrik Hübinette (Hubbe)  {
54db6c1999-03-27Henrik Grubbström (Grubba)  int args = 2;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(call_lfun(LFUN_RSH, LFUN_RRSH))
07c0731996-06-21Fredrik Hübinette (Hubbe)  return;
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type != T_INT)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`>>", 1, "int|object"); SIMPLE_BAD_ARG_ERROR("`>>", 2, "int|object");
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
ff0d461999-10-15Fredrik Noring  #ifdef AUTO_BIGNUM if(INT_TYPE_RSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) { sp--; sp[-1].u.integer = 0; return; }
34d4be2001-03-18Henrik Grubbström (Grubba) #else /* !AUTO_BIGNUM */ if (sp[-1].u.integer > 31) { sp--; if (sp[-1].u.integer < 0) { sp[-1].u.integer = -1; } else { sp[-1].u.integer = 0; } return; }
ff0d461999-10-15Fredrik Noring #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--;
8a630c1996-04-13Fredrik Hübinette (Hubbe)  sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
b90e552001-02-08Henrik Grubbström (Grubba) /*! @decl int `>>(int arg1, int arg2) *! @decl mixed `>>(object arg1, int|object arg2) *! @decl mixed `>>(int arg1, object arg2)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Right shift operator.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg1] is an object that implements @[lfun::`>>()], that *! function will be called with @[arg2] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg2] is an object that implements @[lfun::``>>()], that *! function will be called with @[arg1] as the single argument.
b90e552001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Otherwise @[arg1] will be shifted @[arg2] bits left.
b90e552001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`<<()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_rsh(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  if(args != 2) { /* FIXME: Not appropriate if too many args. */ SIMPLE_TOO_FEW_ARGS_ERROR("`>>", 2); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_rsh(); } static int generate_rsh(node *n) { if(count_args(CDR(n))==2)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_RSH);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
bce86c1996-02-25Fredrik Hübinette (Hubbe)  #define TWO_TYPES(X,Y) (((X)<<8)|(Y))
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_multiply(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  int args = 2;
bce86c1996-02-25Fredrik Hübinette (Hubbe)  switch(TWO_TYPES(sp[-2].type,sp[-1].type))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
1b61661998-02-19Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_ARRAY, T_INT): { struct array *ret; struct svalue *pos; INT32 e; if(sp[-1].u.integer < 0)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`*", 2, "int(0..)");
1b61661998-02-19Fredrik Hübinette (Hubbe)  ret=allocate_array(sp[-2].u.array->size * sp[-1].u.integer); pos=ret->item; for(e=0;e<sp[-1].u.integer;e++,pos+=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; pop_n_elems(2); push_array(ret); return; }
3a3bc32000-09-26Henrik Wallin  case TWO_TYPES(T_ARRAY, T_FLOAT): {
7c46f22000-10-15Henrik Grubbström (Grubba)  struct array *src;
3a3bc32000-09-26Henrik Wallin  struct array *ret; struct svalue *pos;
7c46f22000-10-15Henrik Grubbström (Grubba)  ptrdiff_t asize, delta;
3a3bc32000-09-26Henrik Wallin  if(sp[-1].u.float_number < 0) SIMPLE_BAD_ARG_ERROR("`*", 2, "float(0..)");
7c46f22000-10-15Henrik Grubbström (Grubba)  src = sp[-2].u.array; delta = src->size; asize = (ptrdiff_t)floor(delta * sp[-1].u.float_number + 0.5); ret = allocate_array(asize); pos = ret->item;
fa95e62000-10-15Henrik Grubbström (Grubba)  if (asize > delta) {
3ee2ea2000-10-15Henrik Grubbström (Grubba)  ret->type_field = src->type_field;
3a3bc32000-09-26Henrik Wallin  assign_svalues_no_free(pos,
7c46f22000-10-15Henrik Grubbström (Grubba)  src->item, delta, src->type_field); pos += delta; asize -= delta;
fa95e62000-10-15Henrik Grubbström (Grubba)  while (asize > delta) {
7c46f22000-10-15Henrik Grubbström (Grubba)  assign_svalues_no_free(pos, ret->item, delta, ret->type_field); pos += delta; asize -= delta; delta <<= 1; } if (asize) { assign_svalues_no_free(pos, ret->item, asize, ret->type_field); } } else if (asize) {
3a3bc32000-09-26Henrik Wallin  assign_svalues_no_free(pos,
7c46f22000-10-15Henrik Grubbström (Grubba)  src->item, asize, src->type_field);
3ee2ea2000-10-15Henrik Grubbström (Grubba)  array_fix_type_field(ret);
7c46f22000-10-15Henrik Grubbström (Grubba)  }
3a3bc32000-09-26Henrik Wallin  pop_n_elems(2); push_array(ret); return; } case TWO_TYPES(T_STRING, T_FLOAT): {
7c46f22000-10-15Henrik Grubbström (Grubba)  struct pike_string *src;
3a3bc32000-09-26Henrik Wallin  struct pike_string *ret; char *pos;
7c46f22000-10-15Henrik Grubbström (Grubba)  ptrdiff_t len, delta;
3a3bc32000-09-26Henrik Wallin  if(sp[-1].u.float_number < 0) SIMPLE_BAD_ARG_ERROR("`*", 2, "float(0..)");
7c46f22000-10-15Henrik Grubbström (Grubba)  src = sp[-2].u.string; len = (ptrdiff_t)floor(src->len * 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;
fa95e62000-10-15Henrik Grubbström (Grubba)  if (len > delta) {
7c46f22000-10-15Henrik Grubbström (Grubba)  MEMCPY(pos, src->str, delta); pos += delta; len -= delta;
fa95e62000-10-15Henrik Grubbström (Grubba)  while (len > delta) {
7c46f22000-10-15Henrik Grubbström (Grubba)  MEMCPY(pos, ret->str, delta); pos += delta; len -= delta; delta <<= 1; } if (len) { MEMCPY(pos, ret->str, len); } } else if (len) { MEMCPY(pos, src->str, len);
fc3a642000-09-26Henrik Wallin  }
3a3bc32000-09-26Henrik Wallin  pop_n_elems(2); push_string(low_end_shared_string(ret)); return; }
1b61661998-02-19Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_STRING, T_INT): { struct pike_string *ret; char *pos;
e4b2252000-08-09Henrik Grubbström (Grubba)  INT_TYPE e; ptrdiff_t len;
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(sp[-1].u.integer < 0)
54db6c1999-03-27Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("`*", 2, "int(0..)");
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  ret=begin_wide_shared_string(sp[-2].u.string->len * sp[-1].u.integer, sp[-2].u.string->size_shift);
1b61661998-02-19Fredrik Hübinette (Hubbe)  pos=ret->str;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  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);
1b61661998-02-19Fredrik Hübinette (Hubbe)  pop_n_elems(2);
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  push_string(low_end_shared_string(ret));
1b61661998-02-19Fredrik Hübinette (Hubbe)  return; }
bce86c1996-02-25Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_ARRAY,T_STRING):
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *ret;
fb5c4f1996-03-24Fredrik Hübinette (Hubbe)  ret=implode(sp[-2].u.array,sp[-1].u.string); free_string(sp[-1].u.string); free_array(sp[-2].u.array); sp[-2].type=T_STRING; sp[-2].u.string=ret;
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; return; }
f5466b1997-02-18Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_ARRAY,T_ARRAY): { struct array *ret; ret=implode_array(sp[-2].u.array, sp[-1].u.array); pop_n_elems(2); push_array(ret);
1b61661998-02-19Fredrik Hübinette (Hubbe)  return;
f5466b1997-02-18Fredrik Hübinette (Hubbe)  }
bce86c1996-02-25Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_FLOAT,T_FLOAT):
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; sp[-1].u.float_number *= sp[0].u.float_number; return;
bce86c1996-02-25Fredrik Hübinette (Hubbe)  case TWO_TYPES(T_FLOAT,T_INT): sp--; sp[-1].u.float_number *= (FLOAT_TYPE)sp[0].u.integer; return; case TWO_TYPES(T_INT,T_FLOAT): sp--; sp[-1].u.float_number= (FLOAT_TYPE) sp[-1].u.integer * (FLOAT_TYPE)sp[0].u.float_number; sp[-1].type=T_FLOAT; return; case TWO_TYPES(T_INT,T_INT):
fda0de1999-10-08Fredrik Noring #ifdef AUTO_BIGNUM
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  if(INT_TYPE_MUL_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer))
fda0de1999-10-08Fredrik Noring  {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  convert_stack_top_to_bignum(); goto do_lfun_multiply;
fda0de1999-10-08Fredrik Noring  } #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; sp[-1].u.integer *= sp[0].u.integer; return; default:
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  do_lfun_multiply:
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(call_lfun(LFUN_MULTIPLY, LFUN_RMULTIPLY))
07c0731996-06-21Fredrik Hübinette (Hubbe)  return;
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`*", "Bad arguments.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
b90e552001-02-08Henrik Grubbström (Grubba) /*! @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) *! @decl float `*(int arg1, float arg2) *! @decl int `*(int arg1, int arg2) *! @decl mixed `*(mixed arg1, mixed arg2, mixed ... extras)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Multiplication operator. *! *! @returns *! If there's only a single argument, that argument will be returned. *! *! If the first argument is an object that implements @[lfun::`*()], *! that function will be called with the rest of the arguments. *! *! If there are more than two arguments, the result will be *! @code{`*(`*(@[arg1], @[arg2]), @@@[extras])@}. *! *! If @[arg2] is an object that implements @[lfun::``*()], that *! function will be called with @[arg1] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type array *! @mixed @[arg2] *! @type int *! @type float *! The result will be @[arg1] concatenated @[arg2] times. *! @type string *! @type array *! The result will be the elements of @[arg1] concatenated with *! @[arg2] interspersed. *! @endmixed *! @type string *! The result will be @[arg1] concatenated @[arg2] times. *! @type int *! @type float *! The result will be @code{@[arg1] * @[arg2]@}, and will be a *! float if either @[arg1] or @[arg2] is a float. *! @endmixed
b90e552001-02-08Henrik Grubbström (Grubba)  *! *! @note *! In Pike 7.0 and earlier the multiplication order was unspecified. *! *! @seealso *! @[`+()], @[`-()], [`/()], @[lfun::`*()], @[lfun::``*()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_multiply(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) { switch(args) {
54db6c1999-03-27Henrik Grubbström (Grubba)  case 0: SIMPLE_TOO_FEW_ARGS_ERROR("`*", 1);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  case 1: return; case 2: o_multiply(); return;
07c0731996-06-21Fredrik Hübinette (Hubbe)  default: if(sp[-args].type==T_OBJECT) { CALL_OPERATOR(LFUN_MULTIPLY, args); } else {
0c60972000-09-22Henrik Grubbström (Grubba)  INT32 i = -args, j = -1; /* Reverse the arguments */ while(i < j) { struct svalue tmp = sp[i]; sp[i++] = sp[j]; sp[j--] = tmp; } while(--args > 0) { /* Restore the order, and multiply */ stack_swap(); o_multiply(); }
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  } } static int generate_multiply(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2: do_docode(CDR(n),0);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_MULTIPLY);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_divide(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type!=sp[-1].type && !float_promote()) { if(call_lfun(LFUN_DIVIDE, LFUN_RDIVIDE)) return;
1b61661998-02-19Fredrik Hübinette (Hubbe)  switch(TWO_TYPES(sp[-2].type,sp[-1].type)) { case TWO_TYPES(T_STRING,T_INT): { struct array *a;
e4b2252000-08-09Henrik Grubbström (Grubba)  INT_TYPE len; ptrdiff_t size,e,pos=0;
1b61661998-02-19Fredrik Hübinette (Hubbe)  len=sp[-1].u.integer; if(!len)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) { len=-len;
d429a71998-02-24Fredrik Hübinette (Hubbe)  size=sp[-2].u.string->len / len; pos+=sp[-2].u.string->len % len; }else{ size=sp[-2].u.string->len / len;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } a=allocate_array(size); for(e=0;e<size;e++) {
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  a->item[e].u.string=string_slice(sp[-2].u.string, pos,len);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a->item[e].type=T_STRING; 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;
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t size, pos, last, e;
1b61661998-02-19Fredrik Hübinette (Hubbe)  double len; len=sp[-1].u.float_number; if(len==0.0)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) { len=-len;
e4b2252000-08-09Henrik Grubbström (Grubba)  size=(ptrdiff_t)ceil( ((double)sp[-2].u.string->len) / len);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=allocate_array(size);
d429a71998-02-24Fredrik Hübinette (Hubbe)  for(last=sp[-2].u.string->len,e=0;e<size-1;e++)
1b61661998-02-19Fredrik Hübinette (Hubbe)  {
61014a2000-09-26Henrik Wallin  pos=sp[-2].u.string->len - (ptrdiff_t)((e+1)*len+0.5);
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  a->item[size-1-e].u.string=string_slice(sp[-2].u.string, pos, last-pos);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[size-1-e].type=T_STRING;
1b61661998-02-19Fredrik Hübinette (Hubbe)  last=pos; } pos=0;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  a->item[0].u.string=string_slice(sp[-2].u.string, pos, last-pos);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[0].type=T_STRING;
1b61661998-02-19Fredrik Hübinette (Hubbe)  }else{
080b1a2000-08-10Henrik Grubbström (Grubba)  size=(ptrdiff_t)ceil( ((double)sp[-2].u.string->len) / len);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=allocate_array(size);
d429a71998-02-24Fredrik Hübinette (Hubbe)  for(last=0,e=0;e<size-1;e++)
1b61661998-02-19Fredrik Hübinette (Hubbe)  {
61014a2000-09-26Henrik Wallin  pos = DO_NOT_WARN((ptrdiff_t)((e+1)*len+0.5));
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  a->item[e].u.string=string_slice(sp[-2].u.string, last, pos-last);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[e].type=T_STRING;
1b61661998-02-19Fredrik Hübinette (Hubbe)  last=pos; }
d429a71998-02-24Fredrik Hübinette (Hubbe)  pos=sp[-2].u.string->len;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  a->item[e].u.string=string_slice(sp[-2].u.string, last, pos-last);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[e].type=T_STRING;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } a->type_field=BIT_STRING; pop_n_elems(2); push_array(a);
d429a71998-02-24Fredrik Hübinette (Hubbe)  return;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } case TWO_TYPES(T_ARRAY, T_INT): { struct array *a;
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t size,e,len,pos;
1b61661998-02-19Fredrik Hübinette (Hubbe)  len=sp[-1].u.integer; if(!len)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
6e27f61998-07-31Fredrik Hübinette (Hubbe) 
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) {
6f49401998-07-31Henrik Grubbström (Grubba)  len = -len; pos = sp[-2].u.array->size % len;
d429a71998-02-24Fredrik Hübinette (Hubbe)  }else{
6f49401998-07-31Henrik Grubbström (Grubba)  pos = 0;
1b61661998-02-19Fredrik Hübinette (Hubbe)  }
6f49401998-07-31Henrik Grubbström (Grubba)  size = sp[-2].u.array->size / len;
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=allocate_array(size); for(e=0;e<size;e++) { a->item[e].u.array=friendly_slice_array(sp[-2].u.array, pos, pos+len); pos+=len;
6e27f61998-07-31Fredrik Hübinette (Hubbe)  a->item[e].type=T_ARRAY;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } a->type_field=BIT_ARRAY; pop_n_elems(2); push_array(a); return; } case TWO_TYPES(T_ARRAY,T_FLOAT): { struct array *a;
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t last,pos,e,size;
1b61661998-02-19Fredrik Hübinette (Hubbe)  double len; len=sp[-1].u.float_number; if(len==0.0)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) { len=-len;
e4b2252000-08-09Henrik Grubbström (Grubba)  size = (ptrdiff_t)ceil( ((double)sp[-2].u.array->size) / len);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=allocate_array(size);
d429a71998-02-24Fredrik Hübinette (Hubbe)  for(last=sp[-2].u.array->size,e=0;e<size-1;e++)
1b61661998-02-19Fredrik Hübinette (Hubbe)  {
61014a2000-09-26Henrik Wallin  pos=sp[-2].u.array->size - (ptrdiff_t)((e+1)*len+0.5);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[size-1-e].u.array=friendly_slice_array(sp[-2].u.array,
1b61661998-02-19Fredrik Hübinette (Hubbe)  pos, last);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[size-1-e].type=T_ARRAY;
1b61661998-02-19Fredrik Hübinette (Hubbe)  last=pos; }
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[0].u.array=slice_array(sp[-2].u.array,
1b61661998-02-19Fredrik Hübinette (Hubbe)  0, last);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[0].type=T_ARRAY;
1b61661998-02-19Fredrik Hübinette (Hubbe)  }else{
080b1a2000-08-10Henrik Grubbström (Grubba)  size = (ptrdiff_t)ceil( ((double)sp[-2].u.array->size) / len);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=allocate_array(size);
d429a71998-02-24Fredrik Hübinette (Hubbe)  for(last=0,e=0;e<size-1;e++)
1b61661998-02-19Fredrik Hübinette (Hubbe)  {
61014a2000-09-26Henrik Wallin  pos = (ptrdiff_t)((e+1)*len+0.5);
1b61661998-02-19Fredrik Hübinette (Hubbe)  a->item[e].u.array=friendly_slice_array(sp[-2].u.array, last, pos);
d429a71998-02-24Fredrik Hübinette (Hubbe)  a->item[e].type=T_ARRAY;
1b61661998-02-19Fredrik Hübinette (Hubbe)  last=pos; } a->item[e].u.array=slice_array(sp[-2].u.array, last,
d429a71998-02-24Fredrik Hübinette (Hubbe)  sp[-2].u.array->size); a->item[e].type=T_ARRAY;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } a->type_field=BIT_ARRAY; pop_n_elems(2); push_array(a);
d429a71998-02-24Fredrik Hübinette (Hubbe)  return;
1b61661998-02-19Fredrik Hübinette (Hubbe)  } }
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division on different types.\n", sp, 2);
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(sp[-2].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT:
08b9801999-10-30Fredrik Noring  do_lfun_division:
07c0731996-06-21Fredrik Hübinette (Hubbe)  CALL_OPERATOR(LFUN_DIVIDE,2); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_STRING: { struct array *ret;
fb5c4f1996-03-24Fredrik Hübinette (Hubbe)  ret=explode(sp[-2].u.string,sp[-1].u.string); free_string(sp[-2].u.string);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_string(sp[-1].u.string);
fb5c4f1996-03-24Fredrik Hübinette (Hubbe)  sp[-2].type=T_ARRAY; sp[-2].u.array=ret; sp--;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; }
f5466b1997-02-18Fredrik Hübinette (Hubbe)  case T_ARRAY: { struct array *ret=explode_array(sp[-2].u.array, sp[-1].u.array); pop_n_elems(2); push_array(ret); return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_FLOAT: if(sp[-1].u.float_number == 0.0)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; sp[-1].u.float_number /= sp[0].u.float_number; return; case T_INT:
806a2c1997-04-28Fredrik Hübinette (Hubbe)  {
e4b2252000-08-09Henrik Grubbström (Grubba)  INT_TYPE tmp;
08b9801999-10-30Fredrik Noring 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if (sp[-1].u.integer == 0)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_DIVISION_BY_ZERO_ERROR("`/");
806a2c1997-04-28Fredrik Hübinette (Hubbe) 
08b9801999-10-30Fredrik Noring  if(INT_TYPE_DIV_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) { #ifdef AUTO_BIGNUM stack_swap(); convert_stack_top_to_bignum(); stack_swap(); goto do_lfun_division; #else /* It's not possible to do MININT/-1 (it gives FPU exception on some CPU:s), thus we return what MININT*-1 returns: MININT. */ tmp = sp[-2].u.integer; #endif /* AUTO_BIGNUM */ } else tmp = sp[-2].u.integer/sp[-1].u.integer; sp--;
c93f0e1997-12-03Fredrik Hübinette (Hubbe) 
08b9801999-10-30Fredrik Noring  /* What is this trying to solve? /Noring */
c93f0e1997-12-03Fredrik Hübinette (Hubbe)  if((sp[-1].u.integer<0) != (sp[0].u.integer<0)) if(tmp*sp[0].u.integer!=sp[-1].u.integer)
806a2c1997-04-28Fredrik Hübinette (Hubbe)  tmp--; sp[-1].u.integer=tmp;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return;
806a2c1997-04-28Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Bad argument 1.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @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, atring arg2) *! @decl array(array) `/(array arg1, array arg2) *! @decl float `/(float arg1, int|float arg2) *! @decl float `/(int arg1, float arg2) *! @decl int `/(int arg1, int arg2) *! @decl mixed `/(mixed arg1, mixed arg2, mixed ... extras)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Division operator. *! *! @returns *! If there are more than two arguments, the result will be *! @code{`/(`/(@[arg1], @[arg2]), @@@[extras])@}. *! *! 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. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type string *! @mixed @[arg2] *! @type int *! @type float *! The result will be and array of @[arg1] split in segments *! of length @[arg2]. If @[arg2] is negative the splitting *! will start from the end of @[arg1]. *! @type string *! The result will be an array of @[arg1] split at each *! occurrence of @[arg2]. Note that the segments that *! matched against @[arg2] will not be in the result. *! @endmixed *! @type array *! @mixed @[arg2] *! @type int *! @type float *! The result will be and array of @[arg1] split in segments *! of length @[arg2]. If @[arg2] is negative the splitting *! will start from the end of @[arg1]. *! @type array *! The result will be an array of @[arg1] split at each *! occurrence of @[arg2]. Note that the elements that *! matched against @[arg2] will not be in the result. *! @endmixed *! @type float *! @type int *! The result will be @code{@[arg1] / @[arg2]@}. If both arguments *! are int, the result will be truncated to an int. Otherwise the *! result will be a float. *! @endmixed
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_divide(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) {
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  switch(args) { case 0:
54db6c1999-03-27Henrik Grubbström (Grubba)  case 1: SIMPLE_TOO_FEW_ARGS_ERROR("`/", 2);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  case 2: o_divide(); break; default: { INT32 e; struct svalue *s=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); } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) } static int generate_divide(node *n) { if(count_args(CDR(n))==2) {
5e44422001-02-25Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_DIVIDE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_mod(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-2].type != sp[-1].type && !float_promote()) { if(call_lfun(LFUN_MOD, LFUN_RMOD)) return;
1b61661998-02-19Fredrik Hübinette (Hubbe)  switch(TWO_TYPES(sp[-2].type,sp[-1].type)) { case TWO_TYPES(T_STRING,T_INT): { struct pike_string *s=sp[-2].u.string;
e4b2252000-08-09Henrik Grubbström (Grubba)  ptrdiff_t tmp,base;
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(!sp[-1].u.integer)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_MODULO_BY_ZERO_ERROR("`%");
1b61661998-02-19Fredrik Hübinette (Hubbe) 
d429a71998-02-24Fredrik Hübinette (Hubbe)  tmp=sp[-1].u.integer; if(tmp<0) { tmp=s->len % -tmp; base=0; }else{ tmp=s->len % tmp; base=s->len - tmp; }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  s=string_slice(s, base, tmp);
1b61661998-02-19Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_string(s); return; } case TWO_TYPES(T_ARRAY,T_INT): { struct array *a=sp[-2].u.array; INT32 tmp,base; if(!sp[-1].u.integer)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_MODULO_BY_ZERO_ERROR("`%");
1b61661998-02-19Fredrik Hübinette (Hubbe) 
d429a71998-02-24Fredrik Hübinette (Hubbe)  tmp=sp[-1].u.integer; if(tmp<0) { tmp=a->size % -tmp; base=0; }else{ tmp=a->size % tmp; base=a->size - tmp; }
1b61661998-02-19Fredrik Hübinette (Hubbe)  a=slice_array(a,base,base+tmp); pop_n_elems(2); push_array(a); return; } }
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Modulo on different types.\n", sp, 2);
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  switch(sp[-2].type)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_MOD,2); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_FLOAT: { FLOAT_TYPE foo; if(sp[-1].u.float_number == 0.0)
54db6c1999-03-27Henrik Grubbström (Grubba)  OP_MODULO_BY_ZERO_ERROR("`%");
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; foo=sp[-1].u.float_number / sp[0].u.float_number; foo=sp[-1].u.float_number - sp[0].u.float_number * floor(foo); sp[-1].u.float_number=foo; return; } case T_INT:
54db6c1999-03-27Henrik Grubbström (Grubba)  if (sp[-1].u.integer == 0) OP_MODULO_BY_ZERO_ERROR("`%");
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--;
806a2c1997-04-28Fredrik Hübinette (Hubbe)  if(sp[-1].u.integer>=0) { if(sp[0].u.integer>=0) { sp[-1].u.integer %= sp[0].u.integer; }else{
9024ae1997-09-11Fredrik Hübinette (Hubbe)  sp[-1].u.integer=((sp[-1].u.integer+~sp[0].u.integer)%-sp[0].u.integer)-~sp[0].u.integer;
806a2c1997-04-28Fredrik Hübinette (Hubbe)  } }else{ if(sp[0].u.integer>=0) {
9024ae1997-09-11Fredrik Hübinette (Hubbe)  sp[-1].u.integer=sp[0].u.integer+~((~sp[-1].u.integer) % sp[0].u.integer);
806a2c1997-04-28Fredrik Hübinette (Hubbe)  }else{ sp[-1].u.integer=-(-sp[-1].u.integer % -sp[0].u.integer); } }
5267b71995-08-09Fredrik Hübinette (Hubbe)  return; default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Bad argument 1.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @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)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Modulo operator. *! *! @returns *! If @[arg1] is an object that implements @[lfun::`%()] then *! that function will be called with @[arg2] as the single argument. *! *! If @[arg2] is an object that implements @[lfun::``%()] then *! that function will be called with @[arg2] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg1] *! @type string *! @type array *! If @[arg2] is positive, the result will be the last *! @code{`%(@[sizeof](@[arg1]), @[arg2])@} elements of @[arg1]. *! If @[arg2] is negative, the result will be the first *! @code{`%(@[sizeof](@[arg1]), -@[arg2])@} elements of @[arg1]. *! @type int *! @type float *! The result will be *! @code{@[arg1] - @[arg2]*@[floor](@[arg1]/@[arg2])@}. *! The result will be a float if either @[arg1] or @[arg2] is *! a float, and an int otherwise. *! @endmixed
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_mod(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  if(args != 2) { /* FIXME: Not appropriate when too many args. */ SIMPLE_TOO_FEW_ARGS_ERROR("`%", 2); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_mod(); } static int generate_mod(node *n) { if(count_args(CDR(n))==2)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
5e44422001-02-25Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_MOD);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_not(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  switch(sp[-1].type)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_INT:
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp[-1].u.integer = !sp[-1].u.integer;
07c0731996-06-21Fredrik Hübinette (Hubbe)  break; case T_FUNCTION: case T_OBJECT: if(IS_ZERO(sp-1)) { pop_stack(); push_int(1); }else{ pop_stack(); push_int(0); } break; default: free_svalue(sp-1); sp[-1].type=T_INT; sp[-1].u.integer=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @decl int(0..1) `!(object|function arg) *! @decl int(1..1) `!(int(0..0) arg) *! @decl int(0..0) `!(mixed arg)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Negation operator.
8d1b862001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @returns *! If @[arg] is an object that implements @[lfun::`!()], that function *! will be called.
8d1b862001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg] is @tt{0@} (zero), a destructed object, or a function in a *! destructed object, @tt{1@} will be returned.
8d1b862001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Otherwise @tt{0@} (zero) will be returned.
8d1b862001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`==()], @[`!=()], @[lfun::`!()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_not(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  if(args != 1) { /* FIXME: Not appropriate with too many args. */ SIMPLE_TOO_FEW_ARGS_ERROR("`!", 1); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_not(); } static int generate_not(node *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(count_args(CDR(n))==1) { do_docode(CDR(n),DO_NOT_COPY);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_NOT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_compl(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(sp[-1].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: CALL_OPERATOR(LFUN_COMPL,1); break;
8a630c1996-04-13Fredrik Hübinette (Hubbe)  case T_INT: sp[-1].u.integer = ~ sp[-1].u.integer; break; case T_FLOAT: sp[-1].u.float_number = -1.0 - sp[-1].u.float_number; break;
0e801c1999-12-13Henrik Grubbström (Grubba)  case T_TYPE: type_stack_mark();
1a94cc2001-02-26Henrik Grubbström (Grubba) #ifdef USE_PIKE_TYPE if (sp[-1].u.type->type == T_NOT) { push_finished_type(sp[-1].u.type->car);
dc7d491999-12-15Henrik Grubbström (Grubba)  } else {
1a94cc2001-02-26Henrik Grubbström (Grubba)  push_finished_type(sp[-1].u.type);
dc7d491999-12-15Henrik Grubbström (Grubba)  push_type(T_NOT); }
1a94cc2001-02-26Henrik Grubbström (Grubba) #else /* !USE_PIKE_TYPE */ if (EXTRACT_UCHAR(sp[-1].u.type->str) == T_NOT) { push_unfinished_type(sp[-1].u.type->str + 1); } else { push_finished_type(sp[-1].u.type); push_type(T_NOT); } #endif /* USE_PIKE_TYPE */
0e801c1999-12-13Henrik Grubbström (Grubba)  pop_stack();
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(pop_unfinished_type());
0e801c1999-12-13Henrik Grubbström (Grubba)  break;
dc7d491999-12-15Henrik Grubbström (Grubba)  case T_FUNCTION: case T_PROGRAM: { /* !object(p) */ struct program *p = program_from_svalue(sp - 1); if (!p) { PIKE_ERROR("`~", "Bad argument.\n", sp, 1); } type_stack_mark();
3611422001-02-20Henrik Grubbström (Grubba)  push_object_type(0, p->id);
dc7d491999-12-15Henrik Grubbström (Grubba)  push_type(T_NOT); pop_stack();
07f5432001-02-21Henrik Grubbström (Grubba)  push_type_value(pop_unfinished_type());
dc7d491999-12-15Henrik Grubbström (Grubba)  } break;
fc0bb51997-02-13Niels Möller  case T_STRING: { struct pike_string *s;
080b1a2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t len, i;
fc0bb51997-02-13Niels Möller 
54db6c1999-03-27Henrik Grubbström (Grubba)  if(sp[-1].u.string->size_shift) { bad_arg_error("`~", sp-1, 1, 1, "string(0)", sp-1, "Expected 8-bit string.\n"); }
0bc4cf1998-10-13Fredrik Hübinette (Hubbe) 
fc0bb51997-02-13Niels Möller  len = 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]; pop_n_elems(1); push_string(end_shared_string(s)); break; }
8a630c1996-04-13Fredrik Hübinette (Hubbe)  default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`~", "Bad argument.\n", sp, 1);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @decl mixed `~(object arg) *! @decl int `~(int arg) *! @decl float `~(float arg) *! @decl type `~(type|program arg) *! @decl string `~(string arg)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Complement operator. *! *! @returns *! The result will be as follows: *! @mixed @[arg] *! @type object *! If @[arg] implements @[lfun::`~()], that function will be called. *! @type int *! The bitwise inverse of @[arg] will be returned. *! @type float *! The result will be @code{-1.0 - @[arg]@}. *! @type type *! @type program *! The type inverse of @[arg] will be returned. *! @type string *! If @[arg1] only contains characters in the range 0 - 255 (8-bit), *! a string containing the corresponding 8-bit inverses will be *! returned. *! @endmixed
8d1b862001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`!()], @[lfun::`~()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_compl(INT32 args)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) {
54db6c1999-03-27Henrik Grubbström (Grubba)  if(args != 1) { /* FIXME: Not appropriate with too many args. */ SIMPLE_TOO_FEW_ARGS_ERROR("`~", 1); }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_compl(); } static int generate_compl(node *n) { if(count_args(CDR(n))==1) { do_docode(CDR(n),DO_NOT_COPY);
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_COMPL);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_negate(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(sp[-1].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT:
ff0d461999-10-15Fredrik Noring  do_lfun_negate:
07c0731996-06-21Fredrik Hübinette (Hubbe)  CALL_OPERATOR(LFUN_SUBTRACT,1); break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_FLOAT: sp[-1].u.float_number=-sp[-1].u.float_number; return; case T_INT:
ff0d461999-10-15Fredrik Noring #ifdef AUTO_BIGNUM if(INT_TYPE_NEG_OVERFLOW(sp[-1].u.integer)) { convert_stack_top_to_bignum(); goto do_lfun_negate; } #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp[-1].u.integer = - sp[-1].u.integer; return; default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`-", "Bad argument to unary minus.\n", sp, 1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void o_range(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
146a322000-08-03Henrik Grubbström (Grubba)  ptrdiff_t from,to;
8a586b1997-01-27Fredrik Hübinette (Hubbe)  if(sp[-3].type==T_OBJECT) {
8856131997-10-10Fredrik Hübinette (Hubbe)  CALL_OPERATOR(LFUN_INDEX, 3);
8a586b1997-01-27Fredrik Hübinette (Hubbe)  return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(sp[-2].type != T_INT)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`[]", "Bad argument 2 to [ .. ]\n", sp, 3);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(sp[-1].type != T_INT)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`[]", "Bad argument 3 to [ .. ]\n", sp, 3);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
146a322000-08-03Henrik Grubbström (Grubba)  from = sp[-2].u.integer; if(from<0) from = 0; to = sp[-1].u.integer; if(to<from-1) to = from-1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp-=2; switch(sp[-1].type) { case T_STRING: {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *s;
22e81d2000-08-03Henrik Grubbström (Grubba)  if(to >= sp[-1].u.string->len-1)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { if(from==0) return;
146a322000-08-03Henrik Grubbström (Grubba)  to = sp[-1].u.string->len-1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(from>to+1) from=to+1; }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
62260a1996-11-26Fredrik Hübinette (Hubbe)  if(from < 0 || (to-from+1) < 0) fatal("Error in o_range.\n"); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
3e625c1998-10-11Fredrik Hübinette (Hubbe)  s=string_slice(sp[-1].u.string, from, to-from+1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_string(sp[-1].u.string); sp[-1].u.string=s; break; } case T_ARRAY: { struct array *a;
22e81d2000-08-03Henrik Grubbström (Grubba)  if(to >= sp[-1].u.array->size-1)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
146a322000-08-03Henrik Grubbström (Grubba)  to = sp[-1].u.array->size-1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(from>to+1) from=to+1; }
e4b2252000-08-09Henrik Grubbström (Grubba)  a = slice_array(sp[-1].u.array, from, to+1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_array(sp[-1].u.array); sp[-1].u.array=a; break; } default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`[]", "[ .. ] on non-scalar type.\n", sp, 3);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @decl mixed `[](object arg, mixed index) *! @decl mixed `[](object arg, string index) *! @decl mixed `[](int arg, string index) *! @decl mixed `[](array arg, int index) *! @decl mixed `[](array arg, mixed index) *! @decl mixed `[](mapping arg, mixed index) *! @decl int(0..1) `[](multiset arg, mixed index) *! @decl int `[](string arg, int index) *! @decl mixed `[](program arg, string index) *! @decl mixed `[](object arg, mixed start, mixed end) *! @decl string `[](string arg, int start, int end) *! @decl array `[](array arg, int start, int end)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Index and range operator. *! *! @returns *! If @[arg] is an object that implements @[lfun::`[]()], that function *! will be called with the rest of the arguments. *! *! If there are 2 arguments the result will be as follows: *! @mixed @[arg] *! @type object *! The non-static (ie public) symbol named @[index] will be looked up *! in @[arg]. *! @type int *! The bignum function named @[index] will be looked up in @[arg]. *! @type array *! If @[index] is an int, index number @[index] of @[arg] will be *! returned. Otherwise an array of all elements in @[arg] indexed *! with @[index] will be returned. *! @type mapping *! If @[index] exists in @[arg] the corresponding value will be *! returned. Otherwise @tt{UNDEFINED@} will be returned. *! @type multiset *! If @[index] exists in @[arg], @tt{1@} will be returned. *! Otherwise @tt{UNDEFINED@} will be returned. *! @type string *! The character (int) at index @[index] in @[arg] will be returned. *! @type program *! The non-static (ie public) constant symbol @[index] will be *! looked up in @[arg]. *! @endmixed *! *! Otherwise if there are 3 arguments the result will be as follows: *! @mixed @[arg] *! @type string *! A string with the characters between @[start] and @[end] (inclusive) *! in @[arg] will be returned. *! @type array *! An array with the elements between @[start] and @[end] (inclusive) *! in @[arg] will be returned. *! @endmixed
8d1b862001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`->()], @[lfun::`[]()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_index(INT32 args)
9f68471997-03-08Fredrik Hübinette (Hubbe) { switch(args) { case 0: case 1:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`[]", "Too few arguments.\n", sp, args);
9f68471997-03-08Fredrik Hübinette (Hubbe)  break; case 2: if(sp[-1].type==T_STRING) sp[-1].subtype=0; o_index(); break; case 3: o_range(); break; default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`[]", "Too many arguments.\n", sp, args);
9f68471997-03-08Fredrik Hübinette (Hubbe)  } }
8d1b862001-02-08Henrik Grubbström (Grubba) /*! @decl mixed `->(object arg, string index) *! @decl mixed `->(int arg, string index) *! @decl mixed `->(array arg, string index) *! @decl mixed `->(mapping arg, string index) *! @decl int(0..1) `->(multiset arg, string index) *! @decl mixed `->(program arg, string index)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Arrow index operator. *! *! This function behaves much like @[`[]()], just that the index is always *! a string. *! *! @returns *! If @[arg] is an object that implements @[lfun::`->()], that function *! will be called with @[index] as the single argument. *! *! Otherwise the result will be as follows: *! @mixed @[arg] *! @type object *! The non-static (ie public) symbol named @[index] will be looked up *! in @[arg]. *! @type int *! The bignum function named @[index] will be looked up in @[arg]. *! @type array *! An array of all elements in @[arg] arrow indexed with @[index] *! will be returned. *! @type mapping *! If @[index] exists in @[arg] the corresponding value will be *! returned. Otherwise @tt{UNDEFINED@} will be returned. *! @type multiset *! If @[index] exists in @[arg], @tt{1@} will be returned. *! Otherwise @tt{UNDEFINED@} will be returned. *! @type program *! The non-static (ie public) constant symbol @[index] will be *! looked up in @[arg]. *! @endmixed
8d1b862001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[`[]()], @[lfun::`->()], @[::`->()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_arrow(INT32 args)
9f68471997-03-08Fredrik Hübinette (Hubbe) { switch(args) { case 0: case 1:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`->", "Too few arguments.\n", sp, args);
9f68471997-03-08Fredrik Hübinette (Hubbe)  break; case 2: if(sp[-1].type==T_STRING) sp[-1].subtype=1; o_index(); break; default:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`->", "Too many arguments.\n", sp, args);
9f68471997-03-08Fredrik Hübinette (Hubbe)  } }
d07e182001-02-08Henrik Grubbström (Grubba) /*! @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)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Index assign operator.
d07e182001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg] is an object that implements @[lfun::`[]=()], that function *! will be called with @[index] and @[val] as the arguments.
d07e182001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @mixed @[arg] *! @type object *! The non-static (ie public) variable named @[index] will be looked up *! in @[arg], and assigned @[val]. *! @type array *! @type mapping *! Index @[index] in @[arg] will be assigned @[val]. *! @type multiset *! If @[val] is @tt{0@} (zero), one occurrance of @[index] in *! @[arg] will be removed. Otherwise @[index] will be added *! to @[arg] if it is not already there. *! @endmixed
d07e182001-02-08Henrik Grubbström (Grubba)  *! *! @returns *! @[val] will be returned. *! *! @seealso *! @[`->=()], @[lfun::`[]=()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_index_assign(INT32 args)
912f171999-08-16Martin Stjernholm { switch (args) { case 0: case 1: case 2: PIKE_ERROR("`[]=", "Too few arguments.\n", sp, args); break; case 3:
4856a81999-08-17Martin Stjernholm  if(sp[-2].type==T_STRING) sp[-2].subtype=0; assign_lvalue (sp-3, sp-1);
912f171999-08-16Martin Stjernholm  assign_svalue (sp-3, sp-1); pop_n_elems (args-1); break; default: PIKE_ERROR("`[]=", "Too many arguments.\n", sp, args); } }
d07e182001-02-08Henrik Grubbström (Grubba) /*! @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)
f09ec92001-02-07Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Arrow assign operator.
d07e182001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! This function behaves much like @[`[]=()], just that the index is always *! a string.
d07e182001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! If @[arg] is an object that implements @[lfun::`->=()], that function *! will be called with @[index] and @[val] as the arguments.
d07e182001-02-08Henrik Grubbström (Grubba)  *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! @mixed @[arg] *! @type object *! The non-static (ie public) variable named @[index] will be looked up *! in @[arg], and assigned @[val]. *! @type array *! @type mapping *! Index @[index] in @[arg] will be assigned @[val]. *! @type multiset *! If @[val] is @tt{0@} (zero), one occurrance of @[index] in *! @[arg] will be removed. Otherwise @[index] will be added *! to @[arg] if it is not already there. *! @endmixed
d07e182001-02-08Henrik Grubbström (Grubba)  *! *! @returns *! @[val] will be returned. *! *! @seealso *! @[`[]=()], @[lfun::`->=()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_arrow_assign(INT32 args)
4856a81999-08-17Martin Stjernholm { switch (args) { case 0: case 1: case 2: PIKE_ERROR("`->=", "Too few arguments.\n", sp, args); break; case 3: if(sp[-2].type==T_STRING) sp[-2].subtype=1; assign_lvalue (sp-3, sp-1); assign_svalue (sp-3, sp-1); pop_n_elems (args-1); break; default: PIKE_ERROR("`->=", "Too many arguments.\n", sp, args); } }
d07e182001-02-08Henrik Grubbström (Grubba) /*! @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) *!
28984e2001-05-09Henrik Grubbström (Grubba)  *! Sizeof operator. *! *! @returns *! The result will be as follows: *! @mixed @[arg] *! @type string *! The number of characters in @[arg] will be returned. *! @type array *! @type multiset *! The number of elements in @[arg] will be returned. *! @type mapping *! The number of key-value pairs in @[arg] will be returned. *! @type object *! If @[arg] implements @[lfun::_sizeof()], that function will *! be called. Otherwise the number of non-static (ie public) *! symbols in @[arg] will be returned. *! @endmixed
d07e182001-02-08Henrik Grubbström (Grubba)  *! *! @seealso *! @[lfun::_sizeof()]
f09ec92001-02-07Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_sizeof(INT32 args)
4c573c1996-08-03Fredrik Hübinette (Hubbe) { INT32 tmp; if(args<1)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("sizeof", "Too few arguments.\n", sp, args);
4c573c1996-08-03Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe)  tmp=pike_sizeof(sp-args);
4c573c1996-08-03Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(tmp); }
79d2b42001-05-19Henrik Grubbström (Grubba) static node *optimize_sizeof(node *n) { if (CDR(n) && (CDR(n)->token == F_APPLY) && (CADR(n)) && (CADR(n)->token == F_CONSTANT) && (CADR(n)->u.sval.type == T_FUNCTION) && (CADR(n)->u.sval.subtype == FUNCTION_BUILTIN)) { extern struct program *string_split_iterator_program; /* sizeof(efun(...)) */ if ((CADR(n)->u.sval.u.efun->function == f_divide) && CDDR(n) && (CDDR(n)->token == F_ARG_LIST) && CADDR(n) && (CADDR(n)->type == string_type_string) && CDDDR(n) && (CDDDR(n)->token == F_CONSTANT) && (CDDDR(n)->u.sval.type == T_STRING) && (CDDDR(n)->u.sval.u.string->len == 1)) { p_wchar2 split = index_shared_string(CDDDR(n)->u.sval.u.string, 0); /* sizeof(`/(str, "x")) */ ADD_NODE_REF2(CADDR(n), return mkefuncallnode("sizeof", mkapplynode(mkprgnode(string_split_iterator_program), mknode(F_ARG_LIST, CADDR(n), mkintnode(split)))); ); } if ((CADR(n)->u.sval.u.efun->function == f_minus) && CDDR(n) && (CDDR(n)->token == F_ARG_LIST) && CADDR(n) && (CADDR(n)->token == F_APPLY) && CAADDR(n) && (CAADDR(n)->token == F_CONSTANT) && (CAADDR(n)->u.sval.type == T_FUNCTION) && (CAADDR(n)->u.sval.subtype == FUNCTION_BUILTIN) && (CAADDR(n)->u.sval.u.efun->function == f_divide) && CDADDR(n) && (CDADDR(n)->token == F_ARG_LIST) && CADADDR(n) && (CADADDR(n)->type == string_type_string) && CDDADDR(n) && (CDDADDR(n)->token == F_CONSTANT) && (CDDADDR(n)->u.sval.type == T_STRING) && (CDDADDR(n)->u.sval.u.string->len == 1) && CDDDR(n)) { /* sizeof(`-(`/(str, "x"), y)) */ if (((CDDDR(n)->token == F_CONSTANT) && (CDDDR(n)->u.sval.type == T_ARRAY) && (CDDDR(n)->u.sval.u.array->size == 1) && (CDDDR(n)->u.sval.u.array->item[0].type == T_STRING) && (CDDDR(n)->u.sval.u.array->item[0].u.string->len == 0)) || ((CDDDR(n)->token == F_APPLY) && CADDDR(n) && (CADDDR(n)->token == F_CONSTANT) && (CADDDR(n)->u.sval.type == T_FUNCTION) && (CADDDR(n)->u.sval.subtype == FUNCTION_BUILTIN) && (CADDDR(n)->u.sval.u.efun->function == f_allocate) && CDDDDR(n) && (CDDDDR(n)->token == F_ARG_LIST) && CADDDDR(n) && (CADDDDR(n)->token == F_CONSTANT) && (CADDDDR(n)->u.sval.type == T_INT) && (CADDDDR(n)->u.sval.u.integer == 1) && CDDDDDR(n) && (CDDDDDR(n)->token == F_CONSTANT) && (CDDDDDR(n)->u.sval.type == T_STRING) && (CDDDDDR(n)->u.sval.u.string->len == 0))) { /* sizeof(`-(`/(str, "x"), ({""}))) */ p_wchar2 split = index_shared_string(CDDADDR(n)->u.sval.u.string, 0); ADD_NODE_REF2(CADADDR(n), return mkefuncallnode("sizeof", mkapplynode(mkprgnode(string_split_iterator_program), mknode(F_ARG_LIST, CADADDR(n), mknode(F_ARG_LIST, mkintnode(split), mkintnode(1))))); ); } } } return NULL; }
4c573c1996-08-03Fredrik Hübinette (Hubbe) static int generate_sizeof(node *n) { node **arg; if(count_args(CDR(n)) != 1) return 0; if(do_docode(CDR(n),DO_NOT_COPY) != 1) fatal("Count args was wrong in sizeof().\n");
a96ce92000-04-19Fredrik Hübinette (Hubbe)  emit0(F_SIZEOF);
4c573c1996-08-03Fredrik Hübinette (Hubbe)  return 1; }
4f20e92001-01-25Fredrik Hübinette (Hubbe) extern int generate_call_function(node *n);
f09ec92001-02-07Henrik Grubbström (Grubba)  /*! @class string_assignment */
19aaeb1998-05-25Fredrik Hübinette (Hubbe) struct program *string_assignment_program; #undef THIS
60d9872000-03-23Fredrik Hübinette (Hubbe) #define THIS ((struct string_assignment_storage *)(CURRENT_STORAGE))
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl int `[](int i, int j) *! *! String index operator. */
19aaeb1998-05-25Fredrik Hübinette (Hubbe) static void f_string_assignment_index(INT32 args) {
65a5492000-08-10Per Hedbor  INT_TYPE i;
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  get_all_args("string[]",args,"%i",&i); if(i<0) i+=THIS->s->len; if(i<0) i+=THIS->s->len; if(i<0 || i>=THIS->s->len)
18099a2001-03-04Mirar (Pontus Hagland)  Pike_error("Index %"PRINTPIKEINT"d is out of range 0 - %ld.\n", i, PTRDIFF_T_TO_LONG(THIS->s->len - 1));
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  else
b987f91998-10-12Fredrik Hübinette (Hubbe)  i=index_shared_string(THIS->s,i);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); }
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @decl int `[]=(int i, int j) *! *! String assign index operator. */
19aaeb1998-05-25Fredrik Hübinette (Hubbe) static void f_string_assignment_assign_index(INT32 args) {
65a5492000-08-10Per Hedbor  INT_TYPE i,j;
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  union anything *u; get_all_args("string[]=",args,"%i%i",&i,&j); if((u=get_pointer_if_this_type(THIS->lval, T_STRING))) { free_string(THIS->s); if(i<0) i+=u->string->len; if(i<0 || i>=u->string->len)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("String index out of range %ld\n",(long)i);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  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++;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if(sp[-1].type != T_STRING) Pike_error("string[]= failed.\n");
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  if(i<0) i+=sp[-1].u.string->len; if(i<0 || i>=sp[-1].u.string->len)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("String index out of range %ld\n",(long)i);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  sp[-1].u.string=modify_shared_string(sp[-1].u.string,i,j); assign_lvalue(THIS->lval, sp-1); pop_stack(); } pop_n_elems(args); push_int(j); } static void init_string_assignment_storage(struct object *o) { THIS->lval[0].type=T_INT; THIS->lval[1].type=T_INT; THIS->s=0; } static void exit_string_assignment_storage(struct object *o) { free_svalues(THIS->lval, 2, BIT_MIXED); if(THIS->s) free_string(THIS->s); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
f09ec92001-02-07Henrik Grubbström (Grubba) /*! @endclass */
be478c1997-08-30Henrik Grubbström (Grubba) void init_operators(void)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) {
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string,int:int)|function(object,string:mixed)|function(array(0=mixed),int:0)|function(mapping(mixed:1=mixed),mixed:1)|function(multiset,mixed:int)|function(string,int,int:string)|function(array(2=mixed),int,int:array(2))|function(program:mixed) */
8c953a2001-03-28Henrik Grubbström (Grubba)  ADD_EFUN2("`[]",f_index,tOr7(tFunc(tStr tInt,tInt),tFunc(tObj tStr,tMix),tFunc(tArr(tSetvar(0,tMix)) tInt,tVar(0)),tFunc(tMap(tMix,tSetvar(1,tMix)) tMix,tVar(1)),tFunc(tMultiset tMix,tInt),tFunc(tStr tInt tInt,tStr),tOr(tFunc(tArr(tSetvar(2,tMix)) tInt tInt,tArr(tVar(2))),tFunc(tPrg(tObj),tMix))),OPT_TRY_OPTIMIZE,0,0);
9f68471997-03-08Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(array(object|mapping|multiset|array),string:array(mixed))|function(object|mapping|multiset|program,string:mixed) */
8c953a2001-03-28Henrik Grubbström (Grubba)  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);
9f68471997-03-08Fredrik Hübinette (Hubbe) 
912f171999-08-16Martin Stjernholm  ADD_EFUN("`[]=", f_index_assign,
4856a81999-08-17Martin Stjernholm  tOr4(tFunc(tObj tStr tSetvar(0,tMix), tVar(0)),
912f171999-08-16Martin Stjernholm  tFunc(tArr(tSetvar(1,tMix)) tInt tVar(1), tVar(1)), tFunc(tMap(tSetvar(2,tMix), tSetvar(3,tMix)) tVar(2) tVar(3), tVar(3)), tFunc(tSet(tSetvar(4,tMix)) tVar(4) tSetvar(5,tMix), tVar(5))),
6f1d412000-04-08Henrik Grubbström (Grubba)  OPT_SIDE_EFFECT|OPT_TRY_OPTIMIZE);
912f171999-08-16Martin Stjernholm 
4856a81999-08-17Martin Stjernholm  ADD_EFUN("`->=", f_arrow_assign, tOr3(tFunc(tArr(tOr4(tArray,tObj,tMultiset,tMapping)) tStr tSetvar(0,tMix), tVar(0)), tFunc(tOr(tObj, tMultiset) tStr tSetvar(1,tMix), tVar(1)), tFunc(tMap(tMix, tSetvar(2,tMix)) tStr tVar(2), tVar(2))),
6f1d412000-04-08Henrik Grubbström (Grubba)  OPT_SIDE_EFFECT|OPT_TRY_OPTIMIZE);
4856a81999-08-17Martin Stjernholm 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(mixed...:int) */
563fdc1999-12-27Henrik Grubbström (Grubba)  ADD_EFUN2("`==",f_eq, tOr5(tFuncV(tOr(tInt,tFloat) tOr(tInt,tFloat), tOr(tInt,tFloat),tInt01),
9bab981999-12-27Henrik Grubbström (Grubba)  tFuncV(tSetvar(0,tOr4(tString,tMapping,tMultiset,tArray)) tVar(0), tVar(0),tInt01),
8c953a2001-03-28Henrik Grubbström (Grubba)  tFuncV(tOr3(tObj,tPrg(tObj),tFunction) tMix,tMix,tInt01), tFuncV(tMix tOr3(tObj,tPrg(tObj),tFunction),tMix,tInt01),
54f8ac2001-03-17Henrik Grubbström (Grubba)  tFuncV(tType(tMix) tType(tMix),
8c953a2001-03-28Henrik Grubbström (Grubba)  tOr3(tPrg(tObj),tFunction,tType(tMix)),tInt01)),
25c28d1999-12-29Henrik Grubbström (Grubba)  OPT_WEAK_TYPE|OPT_TRY_OPTIMIZE,optimize_eq,generate_comparison);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(mixed...:int) */
563fdc1999-12-27Henrik Grubbström (Grubba)  ADD_EFUN2("`!=",f_ne, tOr5(tFuncV(tOr(tInt,tFloat) tOr(tInt,tFloat), tOr(tInt,tFloat),tInt01),
9bab981999-12-27Henrik Grubbström (Grubba)  tFuncV(tSetvar(0,tOr4(tString,tMapping,tMultiset,tArray)) tVar(0), tVar(0),tInt01),
8c953a2001-03-28Henrik Grubbström (Grubba)  tFuncV(tOr3(tObj,tPrg(tObj),tFunction) tMix,tMix,tInt01), tFuncV(tMix tOr3(tObj,tPrg(tObj),tFunction),tMix,tInt01),
54f8ac2001-03-17Henrik Grubbström (Grubba)  tFuncV(tType(tMix) tType(tMix),
8c953a2001-03-28Henrik Grubbström (Grubba)  tOr3(tPrg(tObj),tFunction,tType(tMix)),tInt01)),
25c28d1999-12-29Henrik Grubbström (Grubba)  OPT_WEAK_TYPE|OPT_TRY_OPTIMIZE,0,generate_comparison);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(mixed:int) */
563fdc1999-12-27Henrik Grubbström (Grubba)  ADD_EFUN2("`!",f_not,tFuncV(tMix,tVoid,tInt01), OPT_TRY_OPTIMIZE,optimize_not,generate_not);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
dc7d491999-12-15Henrik Grubbström (Grubba) #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))"
07c0731996-06-21Fredrik Hübinette (Hubbe)  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);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
76db651999-05-25Mirar (Pontus Hagland)  ADD_EFUN2("`+",f_add,
5da6a21999-12-11Henrik Grubbström (Grubba)  tOr7(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix),tFunction),
ad08af1999-05-25Mirar (Pontus Hagland)  tFuncV(tInt,tInt,tInt),
db1efe2000-12-15Henrik Grubbström (Grubba)  tIfnot(tFuncV(tNone, tNot(tFlt), tMix),
ad08af1999-05-25Mirar (Pontus Hagland)  tFuncV(tOr(tInt,tFlt),tOr(tInt,tFlt),tFlt)),
db1efe2000-12-15Henrik Grubbström (Grubba)  tIfnot(tFuncV(tNone, tNot(tStr), tMix),
ad08af1999-05-25Mirar (Pontus Hagland)  tFuncV(tOr3(tStr,tInt,tFlt), tOr3(tStr,tInt,tFlt),tStr)), 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)))),
9e52381998-03-01Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,optimize_binary,generate_sum);
76db651999-05-25Mirar (Pontus Hagland)  ADD_EFUN2("`-",f_minus,
5da6a21999-12-11Henrik Grubbström (Grubba)  tOr7(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix),tFunction),
76db651999-05-25Mirar (Pontus Hagland)  tFuncV(tInt,tInt,tInt),
4106cc2000-12-08Henrik Grubbström (Grubba)  tIfnot(tFuncV(tNone,tNot(tFlt),tMix),
76db651999-05-25Mirar (Pontus Hagland)  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)),
aa17e32000-04-12Mirar (Pontus Hagland)  tOr3(tMapping,tArray,tMultiset), tMap(tVar(1),tVar(2))),
76db651999-05-25Mirar (Pontus Hagland)  tFunc(tSet(tSetvar(3,tMix)) tMultiset,tSet(tVar(3))), tFuncV(tStr,tStr,tStr)),
1eaa381998-03-04Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,0,generate_minus);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
aa17e32000-04-12Mirar (Pontus Hagland) /* object & mixed -> mixed mixed & object -> mixed int & int -> int array & array -> array multiset & multiset -> multiset mapping & mapping -> mapping string & string -> string type|program & type|program -> type|program mapping & array -> mapping array & mapping -> mapping mapping & multiset -> mapping multiset & mapping -> mapping */ #define F_AND_TYPE(Z) \ tOr(tFunc(tSetvar(0,Z),tVar(0)), \ tIfnot(tFunc(Z,tMix), \ tFuncV(tSetvar(1,Z),tSetvar(2,Z), \ tOr(tVar(1),tVar(2)))))
ef2b4e1999-12-18Martin Stjernholm  ADD_EFUN2("`&",f_and,
aa17e32000-04-12Mirar (Pontus Hagland)  tOr4( tFunc(tSetvar(0,tMix),tVar(0)), tOr(tFuncV(tMix tObj,tMix,tMix), tFuncV(tObj tMix,tMix,tMix)), tOr6( F_AND_TYPE(tInt), F_AND_TYPE(tArray), F_AND_TYPE(tMapping), F_AND_TYPE(tMultiset), F_AND_TYPE(tString),
8c953a2001-03-28Henrik Grubbström (Grubba)  F_AND_TYPE(tOr(tType(tMix),tPrg(tObj))) ),
aa17e32000-04-12Mirar (Pontus Hagland) 
db1efe2000-12-15Henrik Grubbström (Grubba)  tIfnot(tFuncV(tNone, tNot(tMapping), tMix),
aa17e32000-04-12Mirar (Pontus Hagland)  tFuncV(tNone, tOr3(tArray,tMultiset,tSetvar(4,tMapping)), tVar(4)) ) ),
ef2b4e1999-12-18Martin Stjernholm  OPT_TRY_OPTIMIZE,optimize_binary,generate_and); #define LOG_TYPE \ tOr7(tOr(tFuncV(tMix tObj,tMix,tMix), \ tFuncV(tObj,tMix,tMix)), \ tFuncV(tInt,tInt,tInt), \ tFuncV(tSetvar(1,tMapping),tSetvar(2,tMapping),tOr(tVar(1),tVar(2))), \ 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), \
8c953a2001-03-28Henrik Grubbström (Grubba)  tFuncV(tOr(tType(tMix),tPrg(tObj)),tOr(tType(tMix),tPrg(tObj)),tType(tMix)))
ef2b4e1999-12-18Martin Stjernholm  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(tOr(tFuncV(tMix tObj,tMix,tMix), \ tFuncV(tObj tMix,tMix,tMix)), \ tFuncV(tInt,tInt,tInt)) ADD_EFUN2("`<<",f_lsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_lsh); ADD_EFUN2("`>>",f_rsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_rsh);
07c0731996-06-21Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* !function(!object...:mixed)&function(mixed...:mixed)|"
1eaa381998-03-04Fredrik Hübinette (Hubbe)  "function(array(array(1=mixed)),array(1=mixed):array(1))|"
1b61661998-02-19Fredrik Hübinette (Hubbe)  "function(int...:int)|" "!function(int...:mixed)&function(float|int...:float)|" "function(string*,string:string)|"
1eaa381998-03-04Fredrik Hübinette (Hubbe)  "function(array(0=mixed),int:array(0))|"
3a3bc32000-09-26Henrik Wallin  "function(array(0=mixed),float:array(0))|" "function(string,int:string) "function(string,float:string) */
4106cc2000-12-08Henrik Grubbström (Grubba)  ADD_EFUN2("`*", f_multiply,
3a3bc32000-09-26Henrik Wallin  tOr9(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix),tFunction),
ad08af1999-05-25Mirar (Pontus Hagland)  tFunc(tArr(tArr(tSetvar(1,tMix))) tArr(tSetvar(1,tMix)),tArr(tVar(1))), tFuncV(tInt,tInt,tInt),
4106cc2000-12-08Henrik Grubbström (Grubba)  tIfnot(tFuncV(tNone,tNot(tFlt),tMix),
ad08af1999-05-25Mirar (Pontus Hagland)  tFuncV(tOr(tFlt,tInt),tOr(tFlt,tInt),tFlt)), tFunc(tArr(tStr) tStr,tStr), tFunc(tArr(tSetvar(0,tMix)) tInt,tArr(tVar(0))),
3a3bc32000-09-26Henrik Wallin  tFunc(tArr(tSetvar(0,tMix)) tFlt,tArr(tVar(0))), tFunc(tStr tInt,tStr), tFunc(tStr tFlt,tStr)),
1b61661998-02-19Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* !function(!object...:mixed)&function(mixed...:mixed)|"
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  "function(int,int...:int)|" "!function(int...:mixed)&function(float|int...:float)|"
1eaa381998-03-04Fredrik Hübinette (Hubbe)  "function(array(0=mixed),array|int|float...:array(array(0)))|"
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  "function(string,string|int|float...:array(string)) */
4106cc2000-12-08Henrik Grubbström (Grubba)  ADD_EFUN2("`/", f_divide, tOr5(tIfnot(tFuncV(tNone,tNot(tOr(tObj,tMix)),tMix),tFunction), tFuncV(tInt, tInt, tInt), 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))),
1b61661998-02-19Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,0,generate_divide);
07c0731996-06-21Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(mixed,object:mixed)|"
d429a71998-02-24Fredrik Hübinette (Hubbe)  "function(object,mixed:mixed)|" "function(int,int:int)|" "function(string,int:string)|"
1eaa381998-03-04Fredrik Hübinette (Hubbe)  "function(array(0=mixed),int:array(0))|"
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  "!function(int,int:mixed)&function(int|float,int|float:float) */
db1efe2000-12-15Henrik Grubbström (Grubba)  ADD_EFUN2("`%", f_mod, tOr6(tFunc(tMix tObj,tMix), tFunc(tObj tMix,tMix), tFunc(tInt tInt,tInt), 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))),
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,0,generate_mod);
07c0731996-06-21Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(object:mixed)|function(int:int)|function(float:float)|function(string:string) */
0e801c1999-12-13Henrik Grubbström (Grubba)  ADD_EFUN2("`~",f_compl,
0158bf2001-03-17Henrik Grubbström (Grubba)  tOr6(tFunc(tObj,tMix),
0e801c1999-12-13Henrik Grubbström (Grubba)  tFunc(tInt,tInt), tFunc(tFlt,tFlt), tFunc(tStr,tStr),
0158bf2001-03-17Henrik Grubbström (Grubba)  tFunc(tType(tSetvar(0, tMix)), tType(tNot(tVar(0)))),
8c953a2001-03-28Henrik Grubbström (Grubba)  tFunc(tPrg(tObj), tType(tMix))),
0e801c1999-12-13Henrik Grubbström (Grubba)  OPT_TRY_OPTIMIZE,0,generate_compl);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string|multiset|array|mapping|object:int) */
57773f2001-02-05Henrik Grubbström (Grubba)  ADD_EFUN2("sizeof", f_sizeof, tFunc(tOr5(tStr,tMultiset,tArray,tMapping,tObj),tInt),
79d2b42001-05-19Henrik Grubbström (Grubba)  OPT_TRY_OPTIMIZE, optimize_sizeof, generate_sizeof);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(mixed,mixed ...:mixed) */ ADD_EFUN2("`()",f_call_function,tFuncV(tMix,tMix,tMix),OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  /* This one should be removed */
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* 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);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct string_assignment_storage);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(int:int) */
2ff9602000-08-31Henrik Grubbström (Grubba)  ADD_FUNCTION2("`[]", f_string_assignment_index, tFunc(tInt,tInt), 0, OPT_EXTERNAL_DEPEND);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(int,int:int) */
2ff9602000-08-31Henrik Grubbström (Grubba)  ADD_FUNCTION2("`[]=", f_string_assignment_assign_index, tFunc(tInt tInt,tInt), 0, OPT_SIDE_EFFECT);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  set_init_callback(init_string_assignment_storage); set_exit_callback(exit_string_assignment_storage); string_assignment_program=end_program(); }
aa711e1998-06-06Henrik Grubbström (Grubba) void exit_operators(void)
19aaeb1998-05-25Fredrik Hübinette (Hubbe) { if(string_assignment_program) { free_program(string_assignment_program); string_assignment_program=0; }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) }