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. \*/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
b788cd1998-07-04Henrik Grubbström (Grubba) #include <math.h>
ee37801999-02-09Fredrik Hübinette (Hubbe) RCSID("$Id: operators.c,v 1.46 1999/02/10 01:29:07 hubbe 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"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "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"
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
5b4dd31998-02-23Fredrik Hübinette (Hubbe) #define COMPARISON(ID,NAME,FUN) \ void ID(INT32 args) \ { \ int i; \ switch(args) \ { \ case 0: case 1: \
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR(NAME, "Too few arguments\n", sp, args); \
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) }
5b4dd31998-02-23Fredrik Hübinette (Hubbe) void f_ne(INT32 args) { f_eq(args); o_not(); } COMPARISON(f_eq,"`==", is_eq) COMPARISON(f_lt,"`<" , is_lt) COMPARISON(f_le,"`<=",!is_gt) COMPARISON(f_gt,"`>" , is_gt) 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) \
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR(lfun_names[OP], "Called in destructed object.\n", sp, args); \
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(FIND_LFUN(sp[-args].u.object->prog,OP) == -1) \
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR(lfun_names[OP], "Operator not in object.\n", sp, args); \
07c0731996-06-21Fredrik Hübinette (Hubbe)  apply_lfun(sp[-args].u.object, OP, args-1); \ free_svalue(sp-2); \ sp[-2]=sp[-1]; \ sp--;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 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)  {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`+", "Too few arguments\n", sp, args);
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); pop_stack(); 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--; 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); if(args - e > 2) { 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:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`+", "Bad argument 1\n", sp, args);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`+", "Incompatible types\n", sp, args);
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;
8d28be1997-02-10Fredrik Hübinette (Hubbe)  INT32 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)  }
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)  } sp[-args].u.string=end_shared_string(r); 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;
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: convert_0_to_1((p_wchar1 *)buf.ptr,buffer,strlen(buffer)); break; case 2: convert_0_to_2((p_wchar2 *)buf.ptr,buffer,strlen(buffer)); 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); r=end_shared_string(r);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_string(r); break; } case BIT_INT: size=0; for(e=-args; e<0; e++) size+=sp[e].u.integer; sp-=args-1; sp[-1].u.integer=size; 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; }
bce86c1996-02-25Fredrik Hübinette (Hubbe)  case BIT_FLOAT | BIT_INT: { 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) error("`+: trying to add integers and arrays.\n"); a=add_arrays(sp-args+1,args-1); pop_n_elems(args); push_array(a); return; } error("`+: trying to add integers and arrays.\n"); }
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; } 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) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2: do_docode(CDR(n),DO_NOT_COPY);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(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) { first_arg=my_get_arg(&CDR(n), 0); second_arg=my_get_arg(&CDR(n), 1);
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; *second_arg=0; return mkopernode("`!",ret,0); } if(node_is_false(*second_arg) && !node_may_overload(*first_arg,LFUN_EQ)) { ret=*first_arg; *first_arg=0; return mkopernode("`!",ret,0); } } return 0; } static node *optimize_not(node *n) { node **first_arg, **more_args; int e; if(count_args(CDR(n))==1) { 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); #define TMP_OPT(X,Y) do { \ if((more_args=is_call_to(*first_arg, X))) \ { \ node *tmp=*more_args; \ *more_args=0; \ return mkopernode(Y,tmp,0); \ } } while(0) 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 } 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) { first_arg=my_get_arg(&CDR(n), 0); second_arg=my_get_arg(&CDR(n), 1);
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)) { ret=mknode(F_APPLY, CAR(n), mknode(F_ARG_LIST, CDR(*first_arg), *second_arg)); CAR(n)=0; CDR(*first_arg)=0; *second_arg=0; 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)) { ret=mknode(F_APPLY, CAR(n), mknode(F_ARG_LIST, *first_arg, CDR(*second_arg))); CAR(n)=0; *first_arg=0; CDR(*second_arg)=0; 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)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_EQ);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_ne)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_NE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_lt)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_LT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_le)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_LE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_gt)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_GT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  else if(CAR(n)->u.sval.u.efun->function == f_ge)
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(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; } 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--; 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--; pop_stack(); return 1; } return 0;
bce86c1996-02-25Fredrik Hübinette (Hubbe) }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
be478c1997-08-30Henrik Grubbström (Grubba) 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;
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`-", "Subtract 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_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: 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:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`-", "Bad argument 1.\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_minus(INT32 args) { switch(args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 0: PIKE_ERROR("`-", "Too few arguments.\n", sp, 0);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_NEGATE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; case 2: do_docode(CDR(n),DO_NOT_COPY);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_SUBTRACT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) void o_and(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) { if(call_lfun(LFUN_AND, LFUN_RAND)) return;
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`&", "Bitwise and 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: 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 
0bc4cf1998-10-13Fredrik Hübinette (Hubbe) #define STRING_BITOP(OP,STROP) \ case T_STRING: \ { \ struct pike_string *s; \ INT32 len, i; \ \ len = sp[-2].u.string->len; \ if (len != sp[-1].u.string->len) \ PIKE_ERROR("`" #OP, "Bitwise "STROP \ " on strings of different lengths.\n", sp, 2); \ if(!sp[-2].u.string->size_shift && !sp[-1].u.string->size_shift) \ { \ 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) {
adbb781998-09-18Fredrik Hübinette (Hubbe)  case T_ARRAY: 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)  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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_and(INT32 args) { switch(args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 0: PIKE_ERROR("`&", "Too few arguments.\n", sp, 0);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_AND);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
be478c1997-08-30Henrik Grubbström (Grubba) void o_or(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) { if(call_lfun(LFUN_OR, LFUN_ROR)) return;
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`|", "Bitwise or 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: 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;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, PIKE_ARRAY_OP_OR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_array(a); 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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_or(INT32 args) { switch(args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 0: PIKE_ERROR("`|", "Too few arguments.\n", sp, 0);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_OR);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
be478c1997-08-30Henrik Grubbström (Grubba) void o_xor(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != sp[-2].type) { if(call_lfun(LFUN_XOR, LFUN_RXOR)) return;
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`^", "Bitwise XOR 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: 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;
71f3a21998-11-22Fredrik Hübinette (Hubbe)  a=merge_array_without_order(sp[-2].u.array, sp[-1].u.array, PIKE_ARRAY_OP_XOR);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(2); push_array(a); return; }
fc0bb51997-02-13Niels Möller 
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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_xor(INT32 args) { switch(args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 0: PIKE_ERROR("`^", "Too few arguments.\n", sp, 0);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_XOR);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0; } }
be478c1997-08-30Henrik Grubbström (Grubba) void o_lsh(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  if(sp[-1].type != T_INT || sp[-2].type != T_INT)
07c0731996-06-21Fredrik Hübinette (Hubbe)  {
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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`<<", "Bad argument 1.\n", sp, 2); PIKE_ERROR("`<<", "Bad argument 2.\n", sp, 2);
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
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) }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_lsh(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(args != 2)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`<<", "Bad number of args.\n", sp, args);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  o_lsh(); } static int generate_lsh(node *n) { if(count_args(CDR(n))==2) { do_docode(CDR(n),DO_NOT_COPY);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_LSH);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) 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)  {
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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`>>", "Bad argument 1.\n", sp, 2); PIKE_ERROR("`>>", "Bad argument 2.\n", sp, 2);
07c0731996-06-21Fredrik Hübinette (Hubbe)  }
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) }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_rsh(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(args != 2)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`>>", "Bad number of args.\n", sp, args);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(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))
be478c1997-08-30Henrik Grubbström (Grubba) void o_multiply(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`*", "Cannot multiply array by negative number.\n", sp, 2);
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; } case TWO_TYPES(T_STRING, T_INT): { struct pike_string *ret; char *pos;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  INT32 e,len;
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(sp[-1].u.integer < 0)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`*", "Cannot multiply string by negative number.\n", sp, 2);
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):
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--; sp[-1].u.integer *= sp[0].u.integer; return; default:
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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_multiply(INT32 args) { switch(args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 0: PIKE_ERROR("`*", "Too few arguments.\n", sp, 0);
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 { while(--args > 0) o_multiply(); }
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_MULTIPLY);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; default: return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
be478c1997-08-30Henrik Grubbström (Grubba) 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;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  INT32 size,e,len,pos=0;
1b61661998-02-19Fredrik Hübinette (Hubbe)  len=sp[-1].u.integer; if(!len)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero.\n", sp, 2);
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; INT32 last,pos,e,size; double len; len=sp[-1].u.float_number; if(len==0.0)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero.\n", sp, 2);
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) { len=-len; size=(INT32)ceil( ((double)sp[-2].u.string->len) / len); 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)  { pos=sp[-2].u.string->len - (INT32)((e+1)*len);
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{ size=(INT32)ceil( ((double)sp[-2].u.string->len) / len); 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)  { pos=(INT32)((e+1)*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)  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;
6e27f61998-07-31Fredrik Hübinette (Hubbe)  INT32 size,e,len,pos;
1b61661998-02-19Fredrik Hübinette (Hubbe)  len=sp[-1].u.integer; if(!len)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero.\n", sp, 2);
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; INT32 last,pos,e,size; double len; len=sp[-1].u.float_number; if(len==0.0)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero.\n", sp, 2);
1b61661998-02-19Fredrik Hübinette (Hubbe)  if(len<0) { len=-len; size=(INT32)ceil( ((double)sp[-2].u.array->size) / len); 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)  { pos=sp[-2].u.array->size - (INT32)((e+1)*len);
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{ size=(INT32)ceil( ((double)sp[-2].u.array->size) / len); 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)  { pos=(INT32)((e+1)*len); 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: 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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero.\n", sp, 2);
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)  { INT32 tmp;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if (sp[-1].u.integer == 0)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`/", "Division by zero\n", sp, 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  sp--;
806a2c1997-04-28Fredrik Hübinette (Hubbe) 
c93f0e1997-12-03Fredrik Hübinette (Hubbe)  tmp=sp[-1].u.integer/sp[0].u.integer; 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--;
c93f0e1997-12-03Fredrik Hübinette (Hubbe) 
806a2c1997-04-28Fredrik Hübinette (Hubbe)  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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_divide(INT32 args) {
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  switch(args) { case 0:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  case 1: PIKE_ERROR("`/", "Too few arguments to `/\n", sp, args);
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) { do_docode(CDR(n),DO_NOT_COPY);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_DIVIDE);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) 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; INT32 tmp,base; if(!sp[-1].u.integer)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Modulo by zero.\n", sp, 2);
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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Modulo by zero.\n", sp, 2);
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)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Modulo by zero.\n", sp, 2);
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:
aa366d1998-04-16Fredrik Hübinette (Hubbe)  if (sp[-1].u.integer == 0) PIKE_ERROR("`%", "Modulo by zero.\n", sp, 2);
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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_mod(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  if(args != 2)
aa366d1998-04-16Fredrik Hübinette (Hubbe)  PIKE_ERROR("`%", "Bad number of args\n", sp, args);
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)  {
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  do_docode(CDR(n),DO_NOT_COPY);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_MOD);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) 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)  } }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_not(INT32 args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  if(args != 1) PIKE_ERROR("`!", "Bad number of args.\n", sp, args);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_NOT);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) 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;
fc0bb51997-02-13Niels Möller  case T_STRING: { struct pike_string *s; INT32 len, i;
0bc4cf1998-10-13Fredrik Hübinette (Hubbe)  if(sp[-1].u.string->size_shift) error("`~ cannot handle wide strings.\n");
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) }
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) void f_compl(INT32 args) {
aa366d1998-04-16Fredrik Hübinette (Hubbe)  if(args != 1) PIKE_ERROR("`~", "Bad number of args.\n", sp, args);
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);
8a630c1996-04-13Fredrik Hübinette (Hubbe)  emit2(F_COMPL);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  return 1; } return 0; }
be478c1997-08-30Henrik Grubbström (Grubba) void o_negate(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { switch(sp[-1].type) {
07c0731996-06-21Fredrik Hübinette (Hubbe)  case T_OBJECT: 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: 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)  } }
be478c1997-08-30Henrik Grubbström (Grubba) void o_range(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 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)  from=sp[-2].u.integer; if(from<0) from=0; to=sp[-1].u.integer; if(to<from-1) to=from-1; sp-=2; switch(sp[-1].type) { case T_STRING: {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *s;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(to>=sp[-1].u.string->len-1) { if(from==0) return; to=sp[-1].u.string->len-1; 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; if(to>=sp[-1].u.array->size-1) { to=sp[-1].u.array->size-1; if(from>to+1) from=to+1; } a=slice_array(sp[-1].u.array,from,to+1); 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) 
9f68471997-03-08Fredrik Hübinette (Hubbe) void f_index(INT32 args) { 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)  } } void f_arrow(INT32 args) { 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)  } }
4c573c1996-08-03Fredrik Hübinette (Hubbe) void f_sizeof(INT32 args) { 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); } 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"); emit2(F_SIZEOF); return 1; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) static int generate_call_function(node *n) { node **arg; emit2(F_MARK); do_docode(CDR(n),DO_NOT_COPY); emit2(F_CALL_FUNCTION); return 1; }
19aaeb1998-05-25Fredrik Hübinette (Hubbe) struct program *string_assignment_program; #undef THIS #define THIS ((struct string_assignment_storage *)(fp->current_storage)) static void f_string_assignment_index(INT32 args) { INT32 i; 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) error("Index %d is out of range 0 - %d.\n", i, THIS->s->len-1); 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); } static void f_string_assignment_assign_index(INT32 args) { INT32 i,j; 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) error("String index out of range %ld\n",(long)i); 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++; if(sp[-1].type != T_STRING) error("string[]= failed.\n"); if(i<0) i+=sp[-1].u.string->len; if(i<0 || i>=sp[-1].u.string->len) error("String index out of range %ld\n",(long)i); 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) 
be478c1997-08-30Henrik Grubbström (Grubba) void init_operators(void)
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) {
9f68471997-03-08Fredrik Hübinette (Hubbe)  add_efun2("`[]",f_index,
0503c31998-05-25Henrik Grubbström (Grubba)  "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)",OPT_TRY_OPTIMIZE,0,0);
9f68471997-03-08Fredrik Hübinette (Hubbe)  add_efun2("`->",f_arrow,
0503c31998-05-25Henrik Grubbström (Grubba)  "function(array(object|mapping|multiset|array),string:array(mixed))|function(object|mapping|multiset|program,string:mixed)",OPT_TRY_OPTIMIZE,0,0);
9f68471997-03-08Fredrik Hübinette (Hubbe) 
e104411998-06-05Fredrik Hübinette (Hubbe)  add_efun2("`==",f_eq,"function(mixed...:int)",OPT_TRY_OPTIMIZE,optimize_eq,generate_comparison);
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  add_efun2("`!=",f_ne,"function(mixed...:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
e104411998-06-05Fredrik Hübinette (Hubbe)  add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,optimize_not,generate_not);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
5b4dd31998-02-23Fredrik Hübinette (Hubbe) #define CMP_TYPE "!function(!object...:mixed)&function(mixed...:int)|function(int|float...:int)|function(string...:int)"
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) 
9e52381998-03-01Fredrik Hübinette (Hubbe)  add_efun2("`+",f_add, "!function(!object...:mixed)&function(mixed...:mixed)|" "function(int...:int)|" "!function(int...:mixed)&function(int|float...:float)|" "!function(int|float...:mixed)&function(string|int|float...:string)|" "function(0=array...:0)|" "function(mapping(1=mixed:2=mixed)...:mapping(1:2))|" "function(3=multiset...:3)", OPT_TRY_OPTIMIZE,optimize_binary,generate_sum);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
1eaa381998-03-04Fredrik Hübinette (Hubbe)  add_efun2("`-",f_minus, "!function(!object...:mixed)&function(mixed...:mixed)|" "function(int:int)|" "function(float:float)|" "function(array(0=mixed),array:array(0))|" "function(mapping(1=mixed:2=mixed),mapping:mapping(1:2))|" "function(multiset(3=mixed),multiset:multiset(3))|" "function(float|int,float:float)|" "function(float,int:float)|" "function(int,int:int)|" "function(string,string:string)", OPT_TRY_OPTIMIZE,0,generate_minus);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
1eaa381998-03-04Fredrik Hübinette (Hubbe) #define LOG_TYPE "function(mixed,object...:mixed)|function(object,mixed...:mixed)|function(int...:int)|function(mapping(0=mixed:1=mixed)...:mapping(0:1))|function(multiset(2=mixed)...:multiset(2))|function(array(3=mixed)...:array(3))|function(string...:string)"
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  add_efun2("`&",f_and,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_and);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  add_efun2("`|",f_or,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_or);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  add_efun2("`^",f_xor,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_xor);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
1b89ad1997-10-10Fredrik Hübinette (Hubbe) #define SHIFT_TYPE "function(object,mixed:mixed)|function(mixed,object:mixed)|function(int,int:int)"
7bd0ea1996-02-19Fredrik Hübinette (Hubbe) 
07c0731996-06-21Fredrik Hübinette (Hubbe)  add_efun2("`<<",f_lsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_lsh); add_efun2("`>>",f_rsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_rsh);
1b61661998-02-19Fredrik Hübinette (Hubbe)  add_efun2("`*",f_multiply, "!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))|"
1b61661998-02-19Fredrik Hübinette (Hubbe)  "function(string,int:string)", OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); add_efun2("`/",f_divide,
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  "!function(!object...:mixed)&function(mixed...:mixed)|" "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)))|"
5b4dd31998-02-23Fredrik Hübinette (Hubbe)  "function(string,string|int|float...:array(string))",
1b61661998-02-19Fredrik Hübinette (Hubbe)  OPT_TRY_OPTIMIZE,0,generate_divide);
07c0731996-06-21Fredrik Hübinette (Hubbe) 
d429a71998-02-24Fredrik Hübinette (Hubbe)  add_efun2("`%",f_mod, "function(mixed,object:mixed)|" "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))|"
d429a71998-02-24Fredrik Hübinette (Hubbe)  "!function(int,int:mixed)&function(int|float,int|float:float)" ,OPT_TRY_OPTIMIZE,0,generate_mod);
07c0731996-06-21Fredrik Hübinette (Hubbe) 
fc0bb51997-02-13Niels Möller  add_efun2("`~",f_compl,"function(object:mixed)|function(int:int)|function(float:float)|function(string:string)",OPT_TRY_OPTIMIZE,0,generate_compl);
06983f1996-09-22Fredrik Hübinette (Hubbe)  add_efun2("sizeof", f_sizeof, "function(string|multiset|array|mapping|object:int)",0,0,generate_sizeof);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_efun2("`()",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function); /* This one should be removed */ add_efun2("call_function",f_call_function,"function(mixed,mixed ...:mixed)",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);
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  add_function("`[]",f_string_assignment_index,"function(int:int)",0); add_function("`[]=",f_string_assignment_assign_index,"function(int,int:int)",0); 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) }