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. \*/
41e2cb1999-10-24Henrik Grubbström (Grubba) /**/
b788cd1998-07-04Henrik Grubbström (Grubba) #include "global.h"
ab74fc2001-05-28Marcus Comstedt #include <errno.h>
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <math.h> #include <ctype.h> #include "interpret.h" #include "svalue.h" #include "array.h" #include "stralloc.h" #include "mapping.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "opcodes.h" #include "object.h" #include "error.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "pike_types.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "fd_control.h"
98f2b11998-02-19Fredrik Hübinette (Hubbe) #include "cyclic.h" #include "builtin_functions.h"
53842a1998-04-15Fredrik Hübinette (Hubbe) #include "module_support.h"
7e97c31999-01-21Fredrik Hübinette (Hubbe) #include "security.h"
39ac731999-10-20Fredrik Noring #include "bignum.h"
22d95e1999-11-04Fredrik Hübinette (Hubbe) #include "operators.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ab74fc2001-05-28Marcus Comstedt RCSID("$Id: opcodes.c,v 1.79 2001/05/28 18:19:43 marcus Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe) void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { INT32 i;
7e97c31999-01-21Fredrik Hübinette (Hubbe)  #ifdef PIKE_SECURITY if(what->type <= MAX_COMPLEX) if(!CHECK_DATA_SECURITY(what->u.array, SECURITY_BIT_INDEX)) error("Index permission denied.\n"); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(what->type) {
39ac731999-10-20Fredrik Noring #ifdef AUTO_BIGNUM case T_INT:
635b9b2000-04-01Henrik Grubbström (Grubba)  { INT_TYPE val = what->u.integer; convert_svalue_to_bignum(what); index_no_free(to, what, ind); if(IS_UNDEFINED(to)) { if (val) { error("Indexing the integer %d with an unknown method.\n", val); } else { error("Indexing the NULL value.\n"); } } }
39ac731999-10-20Fredrik Noring  break; #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_ARRAY: simple_array_index_no_free(to,what->u.array,ind); break; case T_MAPPING: mapping_index_no_free(to,what->u.mapping,ind); break; case T_OBJECT: object_index_no_free(to, what->u.object, ind); break;
06983f1996-09-22Fredrik Hübinette (Hubbe)  case T_MULTISET: i=multiset_member(what->u.multiset, ind);
5267b71995-08-09Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=i ? NUMBER_UNDEFINED : 0; to->u.integer=i; break; case T_STRING: if(ind->type==T_INT) { i=ind->u.integer; if(i<0) i+=what->u.string->len; if(i<0 || i>=what->u.string->len)
f0e76d1999-08-22Fredrik Noring  { if(what->u.string->len == 0) error("Attempt to index the empty string with %d.\n", i); else error("Index %d is out of string range 0 - %d.\n", i, what->u.string->len-1); } else
db4a401998-10-09Fredrik Hübinette (Hubbe)  i=index_shared_string(what->u.string,i);
5267b71995-08-09Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=NUMBER_NUMBER; to->u.integer=i; break; }else{ error("Index is not an integer.\n"); }
3a1bef1998-06-07Henrik Grubbström (Grubba)  case T_PROGRAM: program_index_no_free(to, what->u.program, ind); break; case T_FUNCTION: { struct program *p = program_from_svalue(what); if (p) { program_index_no_free(to, p, ind); break; } } /* FALL THROUGH */
5267b71995-08-09Fredrik Hübinette (Hubbe)  default: error("Indexing a basic type.\n"); } }
be478c1997-08-30Henrik Grubbström (Grubba) void o_index(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
de2a581997-09-28Fredrik Hübinette (Hubbe)  struct svalue s; index_no_free(&s,sp-2,sp-1); pop_n_elems(2); *sp=s;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
5683de1995-11-06Fredrik Hübinette (Hubbe)  sp++;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
98f2b11998-02-19Fredrik Hübinette (Hubbe) void o_cast(struct pike_string *type, INT32 run_time_type)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 i;
07c0731996-06-21Fredrik Hübinette (Hubbe) 
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(run_time_type != sp[-1].type)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(run_time_type == T_MIXED)
07c0731996-06-21Fredrik Hübinette (Hubbe)  return;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(sp[-1].type == T_OBJECT)
07c0731996-06-21Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *s;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  s=describe_type(type);
07c0731996-06-21Fredrik Hübinette (Hubbe)  push_string(s); if(!sp[-2].u.object->prog) error("Cast called on destructed object.\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1)
07c0731996-06-21Fredrik Hübinette (Hubbe)  error("No cast method in object.\n"); apply_lfun(sp[-2].u.object, LFUN_CAST, 1); free_svalue(sp-2); sp[-2]=sp[-1]; sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  }else
07c0731996-06-21Fredrik Hübinette (Hubbe) 
98f2b11998-02-19Fredrik Hübinette (Hubbe)  switch(run_time_type)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
7e97c31999-01-21Fredrik Hübinette (Hubbe)  default: error("Cannot perform cast to that type.\n");
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_MIXED:
e97d731998-02-27Fredrik Hübinette (Hubbe)  return;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) 
06f6112000-01-27Fredrik Hübinette (Hubbe)  case T_MULTISET: switch(sp[-1].type) { case T_ARRAY: f_mkmultiset(1); break; default: error("Cannot cast %s to multiset.\n",get_name_of_type(sp[-1].type)); } break;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  case T_MAPPING: switch(sp[-1].type) { case T_ARRAY: { f_transpose(1); sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  push_array_items(sp->u.array); f_mkmapping(2); break; } default: error("Cannot cast %s to mapping.\n",get_name_of_type(sp[-1].type)); } break;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_ARRAY: switch(sp[-1].type) { case T_MAPPING: { struct array *a=mapping_to_array(sp[-1].u.mapping); pop_stack(); push_array(a); break; } case T_STRING: f_values(1); break; case T_MULTISET: f_indices(1); break; default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to array.\n",get_name_of_type(sp[-1].type));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
98f2b11998-02-19Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_INT:
98f2b11998-02-19Fredrik Hübinette (Hubbe)  switch(sp[-1].type) { case T_FLOAT: i=(int)(sp[-1].u.float_number);
39ac731999-10-20Fredrik Noring #ifdef AUTO_BIGNUM
c3732a1999-10-22Fredrik Noring  if((i < 0 ? -i : i) < floor(fabs(sp[-1].u.float_number)))
39ac731999-10-20Fredrik Noring  { /* Note: This includes the case when i = 0x80000000, i.e. the absolute value is not computable. */ convert_stack_top_to_bignum();
31ea271999-10-22Fredrik Noring  return; /* FIXME: OK to return? Cast tests below indicates we have to do this, at least for now... /Noring */
110b3f1999-10-29Fredrik Hübinette (Hubbe)  /* Yes, it is ok to return, it is actually an optimization :) * /Hubbe */
39ac731999-10-20Fredrik Noring  }
31ea271999-10-22Fredrik Noring  else
39ac731999-10-20Fredrik Noring #endif /* AUTO_BIGNUM */
31ea271999-10-22Fredrik Noring  { sp[-1].type=T_INT; sp[-1].u.integer=i; }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  break; case T_STRING:
31ea271999-10-22Fredrik Noring  /* This can be here independently of AUTO_BIGNUM. Besides, we really want to reduce the number of number parsers around here. :) /Noring */ #ifdef AUTO_BIGNUM convert_stack_top_string_to_inumber(10); return; /* FIXME: OK to return? Cast tests below indicates we have to do this, at least for now... /Noring */
110b3f1999-10-29Fredrik Hübinette (Hubbe)  /* Yes, it is ok to return, it is actually an optimization :) * /Hubbe */
31ea271999-10-22Fredrik Noring #else
7c89ac1998-12-31Fredrik Hübinette (Hubbe)  i=STRTOL(sp[-1].u.string->str,0,10);
98f2b11998-02-19Fredrik Hübinette (Hubbe)  free_string(sp[-1].u.string);
31ea271999-10-22Fredrik Noring  sp[-1].type=T_INT; sp[-1].u.integer=i; #endif /* AUTO_BIGNUM */
98f2b11998-02-19Fredrik Hübinette (Hubbe)  break; default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to int.\n",get_name_of_type(sp[-1].type));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_FLOAT: {
3ef2481999-10-22Fredrik Noring  FLOAT_TYPE f = 0.0;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  switch(sp[-1].type) { case T_INT: f=(FLOAT_TYPE)(sp[-1].u.integer); break; case T_STRING: f=STRTOD(sp[-1].u.string->str,0); free_string(sp[-1].u.string); break; default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to float.\n",get_name_of_type(sp[-1].type));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  } sp[-1].type=T_FLOAT; sp[-1].u.float_number=f;
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_STRING:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
98f2b11998-02-19Fredrik Hübinette (Hubbe)  char buf[200]; switch(sp[-1].type) { case T_INT: sprintf(buf,"%ld",(long)sp[-1].u.integer); break; case T_FLOAT: sprintf(buf,"%f",(double)sp[-1].u.float_number); break;
0707481998-05-06Henrik Grubbström (Grubba)  case T_ARRAY: { int i; struct array *a = sp[-1].u.array; struct pike_string *s;
a294ff1998-10-10Henrik Grubbström (Grubba)  int shift = 0;
0707481998-05-06Henrik Grubbström (Grubba)  for(i = a->size; i--; ) {
a294ff1998-10-10Henrik Grubbström (Grubba)  unsigned INT32 val;
0707481998-05-06Henrik Grubbström (Grubba)  if (a->item[i].type != T_INT) { error("cast: Item %d is not an integer.\n", i); }
a294ff1998-10-10Henrik Grubbström (Grubba)  val = (unsigned INT32)a->item[i].u.integer; if (val > 0xff) { shift = 1; if (val > 0xffff) { shift = 2; break; } while(i--) { if (a->item[i].type != T_INT) { error("cast: Item %d is not an integer.\n", i); } val = (unsigned INT32)a->item[i].u.integer; if (val > 0xffff) { shift = 2; break; } } break;
0707481998-05-06Henrik Grubbström (Grubba)  } }
a294ff1998-10-10Henrik Grubbström (Grubba)  s = begin_wide_shared_string(a->size, shift); switch(shift) { case 0: for(i = a->size; i--; ) { s->str[i] = a->item[i].u.integer; } break; case 1: { p_wchar1 *str1 = STR1(s); for(i = a->size; i--; ) { str1[i] = a->item[i].u.integer; } } break; case 2: { p_wchar2 *str2 = STR2(s); for(i = a->size; i--; ) { str2[i] = a->item[i].u.integer; } } break; default: free_string(end_shared_string(s)); fatal("cast: Bad shift: %d.\n", shift); break;
0707481998-05-06Henrik Grubbström (Grubba)  } s = end_shared_string(s); pop_stack(); push_string(s); return; } break;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to string.\n",get_name_of_type(sp[-1].type));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  } sp[-1].type=T_STRING; sp[-1].u.string=make_shared_string(buf);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_OBJECT: switch(sp[-1].type) { case T_STRING: if(fp->pc) { INT32 lineno; push_text(get_line(fp->pc, fp->context.prog, &lineno)); }else{ push_int(0); } APPLY_MASTER("cast_to_object",2); return; case T_FUNCTION:
83ca5a2001-03-31Henrik Grubbström (Grubba)  if (sp[-1].subtype == FUNCTION_BUILTIN) {
afc85c2001-03-31Henrik Grubbström (Grubba)  error("Cannot cast builtin functions to object.\n");
83ca5a2001-03-31Henrik Grubbström (Grubba)  } else { sp[-1].type = T_OBJECT; }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  break;
569c171998-02-27Fredrik Hübinette (Hubbe)  default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to object.\n",get_name_of_type(sp[-1].type));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  } break; case T_PROGRAM:
0e70221998-04-05Fredrik Hübinette (Hubbe)  switch(sp[-1].type) { case T_STRING: if(fp->pc) { INT32 lineno; push_text(get_line(fp->pc, fp->context.prog, &lineno)); }else{ push_int(0); } APPLY_MASTER("cast_to_program",2); return; case T_FUNCTION:
0a9e131997-02-16Fredrik Hübinette (Hubbe)  {
0e70221998-04-05Fredrik Hübinette (Hubbe)  struct program *p=program_from_function(sp-1); if(p) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(p);
0e70221998-04-05Fredrik Hübinette (Hubbe)  pop_stack(); push_program(p); }else{ pop_stack(); push_int(0); }
0a9e131997-02-16Fredrik Hübinette (Hubbe)  }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  return;
0e70221998-04-05Fredrik Hübinette (Hubbe)  default:
f7f8a61998-05-14Fredrik Hübinette (Hubbe)  error("Cannot cast %s to a program.\n",get_name_of_type(sp[-1].type));
0e70221998-04-05Fredrik Hübinette (Hubbe)  }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(run_time_type != sp[-1].type)
110b3f1999-10-29Fredrik Hübinette (Hubbe)  { if(sp[-1].type == T_OBJECT && sp[-1].u.object->prog) { int f=FIND_LFUN(sp[-1].u.object->prog, LFUN__IS_TYPE); if( f != -1) { push_text(get_name_of_type(run_time_type)); apply_low(sp[-2].u.object, f, 1); f=!IS_ZERO(sp-1); pop_stack(); if(f) goto emulated_type_ok; } } error("Cast failed, wanted %s, got %s\n", get_name_of_type(run_time_type), get_name_of_type(sp[-1].type)); } emulated_type_ok:
5267b71995-08-09Fredrik Hübinette (Hubbe) 
0252201999-07-27Mirar (Pontus Hagland)  if (!type) return;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  switch(run_time_type) { case T_ARRAY:
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
98f2b11998-02-19Fredrik Hübinette (Hubbe)  struct pike_string *itype; INT32 run_time_itype;
5f9ca22000-03-10Henrik Grubbström (Grubba)  push_string(itype=index_type(type,int_type_string,0));
98f2b11998-02-19Fredrik Hübinette (Hubbe)  run_time_itype=compile_type_to_runtime_type(itype); if(run_time_itype != T_MIXED)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
98f2b11998-02-19Fredrik Hübinette (Hubbe)  struct array *a; struct array *tmp=sp[-2].u.array; DECLARE_CYCLIC(); if((a=(struct array *)BEGIN_CYCLIC(tmp,0))) { ref_push_array(a); }else{ INT32 e,i;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
7ea3341998-05-16Fredrik Hübinette (Hubbe)  struct svalue *save_sp=sp+1; #endif
98f2b11998-02-19Fredrik Hübinette (Hubbe)  push_array(a=allocate_array(tmp->size)); SET_CYCLIC_RET(a); for(e=0;e<a->size;e++) { push_svalue(tmp->item+e); o_cast(itype, run_time_itype); array_set_index(a,e,sp-1); pop_stack(); }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
7ea3341998-05-16Fredrik Hübinette (Hubbe)  if(save_sp!=sp) fatal("o_cast left stack droppings.\n"); #endif
98f2b11998-02-19Fredrik Hübinette (Hubbe)  END_CYCLIC(); } assign_svalue(sp-3,sp-1); pop_stack();
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  pop_stack();
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  break; case T_MULTISET: { struct pike_string *itype; INT32 run_time_itype; push_string(itype=key_type(type,0)); run_time_itype=compile_type_to_runtime_type(itype); if(run_time_itype != T_MIXED) { struct multiset *m; struct array *tmp=sp[-2].u.multiset->ind; DECLARE_CYCLIC(); if((m=(struct multiset *)BEGIN_CYCLIC(tmp,0))) { ref_push_multiset(m); }else{ INT32 e,i; struct array *a; #ifdef PIKE_DEBUG struct svalue *save_sp=sp+1; #endif push_multiset(m=allocate_multiset(a=allocate_array(tmp->size))); SET_CYCLIC_RET(m); for(e=0;e<a->size;e++) { push_svalue(tmp->item+e); o_cast(itype, run_time_itype); array_set_index(a,e,sp-1); pop_stack(); } #ifdef PIKE_DEBUG if(save_sp!=sp) fatal("o_cast left stack droppings.\n"); #endif order_multiset(m); END_CYCLIC(); } assign_svalue(sp-3,sp-1); pop_stack(); } pop_stack(); } break; case T_MAPPING: { struct pike_string *itype,*vtype; INT32 run_time_itype; INT32 run_time_vtype; push_string(itype=key_type(type,0)); run_time_itype=compile_type_to_runtime_type(itype);
4d7b181999-12-07Fredrik Hübinette (Hubbe)  push_string(vtype=index_type(type,mixed_type_string,0));
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  run_time_vtype=compile_type_to_runtime_type(vtype); if(run_time_itype != T_MIXED || run_time_vtype != T_MIXED) { struct mapping *m; struct mapping *tmp=sp[-3].u.mapping; DECLARE_CYCLIC(); if((m=(struct mapping *)BEGIN_CYCLIC(tmp,0))) { ref_push_mapping(m); }else{ INT32 e,i; struct keypair *k; #ifdef PIKE_DEBUG struct svalue *save_sp=sp+1; #endif
06f6112000-01-27Fredrik Hübinette (Hubbe)  push_mapping(m=allocate_mapping(m_sizeof(tmp)));
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  SET_CYCLIC_RET(m); MAPPING_LOOP(tmp) { push_svalue(& k->ind); o_cast(itype, run_time_itype); push_svalue(& k->val); o_cast(vtype, run_time_vtype); mapping_insert(m,sp-2,sp-1); pop_n_elems(2); } #ifdef PIKE_DEBUG if(save_sp!=sp) fatal("o_cast left stack droppings.\n"); #endif END_CYCLIC(); } assign_svalue(sp-4,sp-1); pop_stack(); } pop_n_elems(2); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
98f2b11998-02-19Fredrik Hübinette (Hubbe) void f_cast(void) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
98f2b11998-02-19Fredrik Hübinette (Hubbe)  struct svalue *save_sp=sp;
044c621999-04-14Fredrik Hübinette (Hubbe)  if(sp[-2].type != T_STRING) fatal("Cast expression destroyed stack or left droppings!\n");
98f2b11998-02-19Fredrik Hübinette (Hubbe) #endif o_cast(sp[-2].u.string, compile_type_to_runtime_type(sp[-2].u.string));
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(save_sp != sp) fatal("Internal error: o_cast() left droppings on stack.\n"); #endif free_svalue(sp-2); sp[-2]=sp[-1]; sp--;
41e2cb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
98f2b11998-02-19Fredrik Hübinette (Hubbe) }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* flags: * operators: %d %s %f %c %n %[ %% */
e7a1721999-11-04Fredrik Hübinette (Hubbe) struct sscanf_set { int neg; char c[256]; struct array *a; }; /* FIXME: * This implementation will break in certain cases, especially cases * like this [\1000-\1002\1001] (ie, there is a single character which * is also a part of a range * /Hubbe */ #define MKREADSET(SIZE) \ static int PIKE_CONCAT(read_set,SIZE) ( \ PIKE_CONCAT(p_wchar,SIZE) *match, \ int cnt, \ struct sscanf_set *set, \ int match_len) \ { \ unsigned long e,last=0; \ CHAROPT( int set_size=0; ) \ \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ \ MEMSET(set->c, 0, sizeof(set->c)); \ set->a=0; \ \ if(match[cnt]=='^') \ { \ set->neg=1; \ cnt++; \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ }else{ \ set->neg=0; \ } \ \ if(match[cnt]==']' || match[cnt]=='-') \ { \ set->c[last=match[cnt]]=1; \ cnt++; \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ } \ \ for(;match[cnt]!=']';cnt++) \ { \ if(match[cnt]=='-') \ { \ cnt++; \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ \ if(match[cnt]==']') \ { \ set->c['-']=1; \ break; \ } \ \ if(last >= match[cnt]) \ error("Error in sscanf format string.\n"); \ \ CHAROPT( \
2573d11999-12-22Henrik Grubbström (Grubba)  if(last < (unsigned long)sizeof(set->c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
2573d11999-12-22Henrik Grubbström (Grubba)  if(match[cnt] < (unsigned long)sizeof(set->c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ ) \
76393d1999-11-08Fredrik Hübinette (Hubbe)  for(e=last;e<=match[cnt];e++) set->c[e]=1; \
e7a1721999-11-04Fredrik Hübinette (Hubbe) CHAROPT( \ }else{ \
2573d11999-12-22Henrik Grubbström (Grubba)  for(e=last;e<(unsigned long)sizeof(set->c);e++) \ set->c[e]=1; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ check_stack(2); \ push_int(256); \ push_int(match[cnt]); \ set_size++; \ } \ } \ else \ { \ sp[-1].u.integer=match[cnt]; \ } \ ) \ continue; \ } \ last=match[cnt]; \
2573d11999-12-22Henrik Grubbström (Grubba)  if(last < (unsigned long)sizeof(set->c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  set->c[last]=1; \ CHAROPT( \ else{ \
2573d11999-12-22Henrik Grubbström (Grubba)  if(set_size && \ ((unsigned long)sp[-1].u.integer) == last-1) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ sp[-1].u.integer++; \ }else{ \ check_stack(2); \ push_int(last); \ push_int(last); \ set_size++; \ } \ } \ ) \ } \ \ CHAROPT( \ if(set_size) \ { \ INT32 *order; \ set->a=aggregate_array(set_size*2); \ order=get_switch_order(set->a); \
2573d11999-12-22Henrik Grubbström (Grubba)  for(e=0;e<(unsigned long)set->a->size;e+=2) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ if(order[e]+1 != order[e+1]) \ { \ free_array(set->a); \ set->a=0; \ free((char *)order); \ error("Overlapping ranges in sscanf not supported.\n"); \
2573d11999-12-22Henrik Grubbström (Grubba)  } \ } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ order_array(set->a,order); \ free((char *)order); \ } \ ) \ return cnt; \
5267b71995-08-09Fredrik Hübinette (Hubbe) }
53842a1998-04-15Fredrik Hübinette (Hubbe) 
4bd22e1998-05-25Marcus Comstedt  /* Parse binary IEEE strings on a machine which uses a different kind of floating point internally */ #ifndef FLOAT_IS_IEEE_BIG #ifndef FLOAT_IS_IEEE_LITTLE #define NEED_CUSTOM_IEEE #endif #endif #ifndef NEED_CUSTOM_IEEE #ifndef DOUBLE_IS_IEEE_BIG #ifndef DOUBLE_IS_IEEE_LITTLE #define NEED_CUSTOM_IEEE #endif #endif #endif #ifdef NEED_CUSTOM_IEEE #if HAVE_LDEXP #define LDEXP ldexp #else extern double LDEXP(double x, int exp); /* defined in encode.c */ #endif
c72a4e1998-12-15Fredrik Hübinette (Hubbe) static INLINE float low_parse_IEEE_float(char *b, int sz)
4bd22e1998-05-25Marcus Comstedt { unsigned INT32 f, extra_f; int s, e; unsigned char x[4]; double r; x[0] = EXTRACT_UCHAR(b); x[1] = EXTRACT_UCHAR(b+1); x[2] = EXTRACT_UCHAR(b+2); x[3] = EXTRACT_UCHAR(b+3); s = ((x[0]&0x80)? 1 : 0); if(sz==4) { e = (((int)(x[0]&0x7f))<<1)|((x[1]&0x80)>>7); f = (((unsigned INT32)(x[1]&0x7f))<<16)|(((unsigned INT32)x[2])<<8)|x[3]; extra_f = 0; if(e==255) e = 9999; else if(e>0) { f |= 0x00800000; e -= 127+23; } else e -= 126+23; } else { e = (((int)(x[0]&0x7f))<<4)|((x[1]&0xf0)>>4); f = (((unsigned INT32)(x[1]&0x0f))<<16)|(((unsigned INT32)x[2])<<8)|x[3]; extra_f = (((unsigned INT32)EXTRACT_UCHAR(b+4))<<24)| (((unsigned INT32)EXTRACT_UCHAR(b+5))<<16)| (((unsigned INT32)EXTRACT_UCHAR(b+6))<<8)| ((unsigned INT32)EXTRACT_UCHAR(b+7)); if(e==2047) e = 9999; else if(e>0) { f |= 0x00100000; e -= 1023+20; } else e -= 1022+20; } if(e>=9999) if(f||extra_f) { /* NAN */
ab74fc2001-05-28Marcus Comstedt #ifdef HAVE_INFNAN return (float)infnan(EDOM); #else #ifdef HAVE_NAN /* C99 provides a portable way of generating NaN */ return (float)nan(""); #else
4bd22e1998-05-25Marcus Comstedt  return (float)0.0;
ab74fc2001-05-28Marcus Comstedt #endif /* HAVE_NAN */ #endif /* HAVE_INFNAN */
4bd22e1998-05-25Marcus Comstedt  } else { /* +/- Infinity */
ab74fc2001-05-28Marcus Comstedt #ifdef HAVE_INFNAN return (float)infnan(s? -ERANGE:ERANGE); #else
4bd22e1998-05-25Marcus Comstedt #ifdef HUGE_VAL return (float)(s? -HUGE_VAL:HUGE_VAL); #else /* This number is infinite enough... :) */ e = 1024; f = 1; extra_f = 0;
ab74fc2001-05-28Marcus Comstedt #endif /* HUGE_VAL */ #endif /* HAVE_INFNAN */
4bd22e1998-05-25Marcus Comstedt  } r = (double)f; if(extra_f) r += ((double)extra_f)/4294967296.0; return (float)(s? -LDEXP(r, e):LDEXP(r, e)); } #endif
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
f556f11999-10-31Henrik Grubbström (Grubba) #define DO_IF_DEBUG(X) X #else /* !PIKE_DEBUG */ #define DO_IF_DEBUG(X) #endif /* PIKE_DEBUG */
53842a1998-04-15Fredrik Hübinette (Hubbe) 
eccd0a1999-10-29Fredrik Noring #ifdef AUTO_BIGNUM
f556f11999-10-31Henrik Grubbström (Grubba) #define DO_IF_BIGNUM(X) X #else /* !AUTO_BIGNUM */ #define DO_IF_BIGNUM(X)
eccd0a1999-10-29Fredrik Noring #endif /* AUTO_BIGNUM */
2b33e71999-06-19Mirar (Pontus Hagland) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
f556f11999-10-31Henrik Grubbström (Grubba) #define DO_IF_CHECKER(X) X #else /* !__CHECKER__ */ #define DO_IF_CHECKER(X) #endif /* __CHECKER__ */
2b33e71999-06-19Mirar (Pontus Hagland) 
4bd22e1998-05-25Marcus Comstedt #ifdef FLOAT_IS_IEEE_BIG
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \
6473361999-10-31Henrik Grubbström (Grubba)  do { \
f556f11999-10-31Henrik Grubbström (Grubba)  float f; \ ((char *)&f)[0] = *((INPUT)); \ ((char *)&f)[1] = *((INPUT)+1); \ ((char *)&f)[2] = *((INPUT)+2); \ ((char *)&f)[3] = *((INPUT)+3); \ (SVAL).u.float_number = f; \
6473361999-10-31Henrik Grubbström (Grubba)  } while(0)
4bd22e1998-05-25Marcus Comstedt #else #ifdef FLOAT_IS_IEEE_LITTLE
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \
6473361999-10-31Henrik Grubbström (Grubba)  do { \
f556f11999-10-31Henrik Grubbström (Grubba)  float f; \ ((char *)&f)[3] = *((INPUT)); \ ((char *)&f)[2] = *((INPUT)+1); \ ((char *)&f)[1] = *((INPUT)+2); \ ((char *)&f)[0] = *((INPUT)+3); \ (SVAL).u.float_number = f; \
6473361999-10-31Henrik Grubbström (Grubba)  } while(0)
4bd22e1998-05-25Marcus Comstedt #else
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \
85892f1999-10-31Henrik Grubbström (Grubba)  do { \ char x[4]; \ x[0] = (INPUT)[0]; \ x[1] = (INPUT)[1]; \ x[2] = (INPUT)[2]; \ x[3] = (INPUT)[3]; \ (SVAL).u.float_number = low_parse_IEEE_float(x, 4); \ } while(0)
4bd22e1998-05-25Marcus Comstedt #endif #endif
f556f11999-10-31Henrik Grubbström (Grubba) 
4bd22e1998-05-25Marcus Comstedt #ifdef DOUBLE_IS_IEEE_BIG
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \
6473361999-10-31Henrik Grubbström (Grubba)  do { \
f556f11999-10-31Henrik Grubbström (Grubba)  double d; \ ((char *)&d)[0] = *((INPUT)); \ ((char *)&d)[1] = *((INPUT)+1); \ ((char *)&d)[2] = *((INPUT)+2); \ ((char *)&d)[3] = *((INPUT)+3); \ ((char *)&d)[4] = *((INPUT)+4); \ ((char *)&d)[5] = *((INPUT)+5); \ ((char *)&d)[6] = *((INPUT)+6); \ ((char *)&d)[7] = *((INPUT)+7); \ (SVAL).u.float_number = (float)d; \
6473361999-10-31Henrik Grubbström (Grubba)  } while(0)
4bd22e1998-05-25Marcus Comstedt #else #ifdef DOUBLE_IS_IEEE_LITTLE
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \
6473361999-10-31Henrik Grubbström (Grubba)  do { \
f556f11999-10-31Henrik Grubbström (Grubba)  double d; \ ((char *)&d)[7] = *((INPUT)); \ ((char *)&d)[6] = *((INPUT)+1); \ ((char *)&d)[5] = *((INPUT)+2); \ ((char *)&d)[4] = *((INPUT)+3); \ ((char *)&d)[3] = *((INPUT)+4); \ ((char *)&d)[2] = *((INPUT)+5); \ ((char *)&d)[1] = *((INPUT)+6); \ ((char *)&d)[0] = *((INPUT)+7); \ (SVAL).u.float_number = (float)d; \
6473361999-10-31Henrik Grubbström (Grubba)  } while(0)
4bd22e1998-05-25Marcus Comstedt #else
f556f11999-10-31Henrik Grubbström (Grubba) #define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \
85892f1999-10-31Henrik Grubbström (Grubba)  do { \ char x[8]; \ x[0] = (INPUT)[0]; \ x[1] = (INPUT)[1]; \ x[2] = (INPUT)[2]; \ x[3] = (INPUT)[3]; \ x[4] = (INPUT)[4]; \ x[5] = (INPUT)[5]; \ x[6] = (INPUT)[6]; \ x[7] = (INPUT)[7]; \ (SVAL).u.float_number = low_parse_IEEE_float(x, 8); \ } while(0)
4bd22e1998-05-25Marcus Comstedt #endif #endif
e7a1721999-11-04Fredrik Hübinette (Hubbe) #define MK_VERY_LOW_SSCANF(INPUT_SHIFT, MATCH_SHIFT) \ static INT32 PIKE_CONCAT4(very_low_sscanf_,INPUT_SHIFT,_,MATCH_SHIFT)( \ PIKE_CONCAT(p_wchar, INPUT_SHIFT) *input, \ long input_len, \ PIKE_CONCAT(p_wchar, MATCH_SHIFT) *match, \ long match_len, \ long *chars_matched, \ int *success) \ { \ struct svalue sval; \ int e,cnt,matches,eye,arg; \ int no_assign = 0, field_length = 0, minus_flag = 0; \ struct sscanf_set set; \ struct svalue *argp; \ \ \ set.a=0; \ success[0]=0; \ \ arg=eye=matches=0; \ \ for(cnt = 0; cnt < match_len; cnt++) \ { \ for(;cnt<match_len;cnt++) \ { \ if(match[cnt]=='%') \ { \ if(match[cnt+1]=='%') \ { \ cnt++; \ }else{ \ break; \ } \ } \ if(eye>=input_len || input[eye]!=match[cnt]) \ { \ chars_matched[0]=eye; \ return matches; \ } \ eye++; \ } \ if(cnt>=match_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ \ DO_IF_DEBUG( \ if(match[cnt]!='%' || match[cnt+1]=='%') \ { \ fatal("Error in sscanf.\n"); \ } \ ); \ \ no_assign=0; \ field_length=-1; \ minus_flag=0; \ \ cnt++; \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ \ while(1) \ { \ switch(match[cnt]) \ { \ case '*': \ no_assign=1; \ cnt++; \ if(cnt>=match_len) \ error("Error in sscanf format string.\n"); \ continue; \ \ case '0': case '1': case '2': case '3': case '4': \ case '5': case '6': case '7': case '8': case '9': \ { \ PCHARP t; \ field_length = STRTOL_PCHARP(MKPCHARP(match+cnt, MATCH_SHIFT), \ &t,10); \ cnt = SUBTRACT_PCHARP(t, MKPCHARP(match, MATCH_SHIFT)); \ continue; \ } \ \ case '-': \ minus_flag=1; \ cnt++; \ continue; \ \ case '{': \ { \ ONERROR err; \ long tmp; \ for(e=cnt+1,tmp=1;tmp;e++) \ { \
2b24591999-11-04Fredrik Hübinette (Hubbe)  if(e>=match_len) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ error("Missing %%} in format string.\n"); \ break; /* UNREACHED */ \ } \ if(match[e]=='%') \ { \ switch(match[e+1]) \ { \ case '%': e++; break; \ case '}': tmp--; break; \ case '{': tmp++; break; \ } \ } \ } \ sval.type=T_ARRAY; \ sval.u.array=allocate_array(0); \ SET_ONERROR(err, do_free_array, sval.u.array); \ \ while(input_len-eye) \ { \ int yes; \ struct svalue *save_sp=sp; \ PIKE_CONCAT4(very_low_sscanf_, INPUT_SHIFT, _, MATCH_SHIFT)( \ input+eye, \ input_len-eye, \ match+cnt+1, \ e-cnt-2, \ &tmp, \ &yes); \ if(yes && tmp) \ { \ f_aggregate(sp-save_sp); \ sval.u.array=append_array(sval.u.array,sp-1); \ pop_stack(); \ eye+=tmp; \ }else{ \ pop_n_elems(sp-save_sp); \ break; \ } \ } \ cnt=e; \ UNSET_ONERROR(err); \ break; \ } \ \ case 'c': \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  { \ int e; \ sval.type=T_INT; \ sval.subtype=NUMBER_NUMBER; \ if(field_length == -1) \ { \ if(eye+1 > input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ sval.u.integer=input[eye]; \ eye++; \ break; \ } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  if(eye+field_length > input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \
22d95e1999-11-04Fredrik Hübinette (Hubbe) CHAROPT2( \ for(e=0;e<field_length;e++) \ { \ if(input[eye+e]>255) \ { \ chars_matched[0]=eye; \ return matches; \ } \ } \ ) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  sval.u.integer=0; \ if (minus_flag) \ { \ int x, pos=0; \ \ while(--field_length >= 0) \ { \ int lshfun, orfun; \ x = input[eye]; \ \ DO_IF_BIGNUM( \ if(INT_TYPE_LSH_OVERFLOW(x, pos)) \ { \ push_int(sval.u.integer); \ convert_stack_top_to_bignum(); \ \ while(field_length-- >= 0) \ { \ push_int(input[eye]); \ convert_stack_top_to_bignum(); \ push_int(pos); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  o_lsh(); \ o_or(); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  pos+=8; \ eye++; \ } \ sval=*--sp; \ break; \ } \ ); \ sval.u.integer|=x<<pos; \ \ pos+=8; \ eye++; \ } \ } \ else \ while(--field_length >= 0) \ { \ DO_IF_BIGNUM( \ if(INT_TYPE_LSH_OVERFLOW(sval.u.integer, 8)) \ { \ push_int(sval.u.integer); \ convert_stack_top_to_bignum(); \ \ while(field_length-- >= 0) \ { \ push_int(8); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  o_lsh(); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  push_int(input[eye]); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  o_or(); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  eye++; \ } \ sval=*--sp; \ break; \ } \ ); \ sval.u.integer<<=8; \ sval.u.integer |= input[eye]; \ eye++; \ } \ break; \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ case 'b': \ case 'o': \ case 'd': \ case 'x': \ case 'D': \ case 'i': \ { \ int base = 0; \ PIKE_CONCAT(p_wchar, INPUT_SHIFT) *t; \ \ if(eye>=input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ \ switch(match[cnt]) \ { \ case 'b': base = 2; break; \ case 'o': base = 8; break; \ case 'd': base = 10; break; \ case 'x': base = 16; break; \ } \ \ wide_string_to_svalue_inumber(&sval, input+eye, (void **)&t, \ base, field_length, \ INPUT_SHIFT); \ \ if(input + eye == t) \ { \ chars_matched[0]=eye; \ return matches; \ } \ eye=t-input; \ break; \ } \ \ case 'f': \ { \ PIKE_CONCAT(p_wchar, INPUT_SHIFT) *t; \ PCHARP t2; \ \ if(eye>=input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ sval.u.float_number=STRTOD_PCHARP(MKPCHARP(input+eye, \ INPUT_SHIFT),&t2); \ t = (PIKE_CONCAT(p_wchar, INPUT_SHIFT) *)(t2.ptr); \ if(input + eye == t) \ { \ chars_matched[0]=eye; \ return matches; \ } \ eye=t-input; \ sval.type=T_FLOAT; \ DO_IF_CHECKER(sval.subtype=0); \ break; \ } \ \ case 'F': \ if(field_length == -1) field_length = 4; \ if(field_length != 4 && field_length != 8) \ error("Invalid IEEE width %d in sscanf format string.\n", \ field_length); \ if(eye+field_length > input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ sval.type=T_FLOAT; \ DO_IF_CHECKER(sval.subtype=0); \ switch(field_length) { \ case 4: \ EXTRACT_FLOAT(sval, input+eye, INPUT_SHIFT); \ eye += 4; \ break; \ case 8: \ EXTRACT_DOUBLE(sval, input+eye, INPUT_SHIFT); \ eye += 8; \ break; \ } \ break; \ \ case 's': \ if(field_length != -1) \ { \ if(input_len - eye < field_length) \ { \ chars_matched[0]=eye; \ return matches; \ } \ \ sval.type=T_STRING; \ DO_IF_CHECKER(sval.subtype=0); \ sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ INPUT_SHIFT)(input+eye, \ field_length); \ eye+=field_length; \ break; \ } \ \ if(cnt+1>=match_len) \ { \ sval.type=T_STRING; \ DO_IF_CHECKER(sval.subtype=0); \ sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ INPUT_SHIFT)(input+eye, \ input_len-eye); \ eye=input_len; \ break; \ }else{ \ PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_start; \ PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_end; \ PIKE_CONCAT(p_wchar, MATCH_SHIFT) *s=0; \ PIKE_CONCAT(p_wchar, MATCH_SHIFT) *p=0; \ int start,contains_percent_percent, new_eye; \ \
35eaff2001-01-15Henrik Grubbström (Grubba)  e = cnt; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  start=eye; \ end_str_start=match+cnt+1; \ \ s=match+cnt+1; \ test_again: \ if(*s=='%') \ { \ s++; \ if(*s=='*') s++; \ set.neg=0; \ switch(*s) \ { \
35eaff2001-01-15Henrik Grubbström (Grubba)  case 0: \ /* FIXME: Should really look at the match len */ \ Pike_error("%% without conversion specifier.\n"); \ break; \ \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  case 'n': \ s++; \
35eaff2001-01-15Henrik Grubbström (Grubba)  /* Advance the end string start pointer */ \ end_str_start = s; \ e = s - match; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  goto test_again; \ \ case 's': \ error("Illegal to have two adjecent %%s.\n"); \ return 0; /* make gcc happy */ \ \ /* sscanf("foo-bar","%s%d",a,b) might not work as expected */ \ case 'd': \ MEMSET(set.c, 1, sizeof(set.c)); \ for(e='0';e<='9';e++) set.c[e]=0; \ set.c['-']=0; \ goto match_set; \ \ case 'o': \ MEMSET(set.c, 1, sizeof(set.c)); \ for(e='0';e<='7';e++) set.c[e]=0; \ goto match_set; \ \ case 'x': \ MEMSET(set.c, 1, sizeof(set.c)); \ for(e='0';e<='9';e++) set.c[e]=0; \ for(e='a';e<='f';e++) set.c[e]=0; \ goto match_set; \ \ case 'D': \ MEMSET(set.c, 1, sizeof(set.c)); \ for(e='0';e<='9';e++) set.c[e]=0; \ set.c['-']=0; \ set.c['x']=0; \ goto match_set; \ \ case 'f': \ MEMSET(set.c, 1, sizeof(set.c)); \ for(e='0';e<='9';e++) set.c[e]=0; \ set.c['.']=set.c['-']=0; \ goto match_set; \ \ case '[': /* oh dear */ \ PIKE_CONCAT(read_set,MATCH_SHIFT)(match, \ s-match+1, \ &set, \ match_len); \ set.neg=!set.neg; \ goto match_set; \ } \ } \ \ contains_percent_percent=0; \ \
35eaff2001-01-15Henrik Grubbström (Grubba)  for(;e<match_len;e++) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ if(match[e]=='%') \ { \ if(match[e+1]=='%') \ { \ contains_percent_percent=1; \ e++; \ }else{ \ break; \ } \ } \ } \ \ end_str_end=match+e; \ \
35eaff2001-01-15Henrik Grubbström (Grubba)  if (end_str_end == end_str_start) { \ sval.type=T_STRING; \ DO_IF_CHECKER(sval.subtype=0); \ sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ INPUT_SHIFT)(input+eye, \ input_len-eye); \ eye=input_len; \ break; \ } else if(!contains_percent_percent) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ struct generic_mem_searcher searcher; \ PIKE_CONCAT(p_wchar, INPUT_SHIFT) *s2; \ init_generic_memsearcher(&searcher, end_str_start, \ end_str_end - end_str_start, \ MATCH_SHIFT, input_len - eye, \ INPUT_SHIFT); \ s2 = generic_memory_search(&searcher, input+eye, \ input_len - eye, INPUT_SHIFT); \ if(!s2) \ { \ chars_matched[0]=eye; \ return matches; \ } \ eye=s2-input; \ new_eye=eye+end_str_end-end_str_start; \ }else{ \ PIKE_CONCAT(p_wchar, INPUT_SHIFT) *p2 = NULL; \ for(;eye<input_len;eye++) \ { \ p2=input+eye; \ for(s=end_str_start;s<end_str_end;s++,p2++) \ { \ if(*s!=*p2) break; \ if(*s=='%') s++; \ } \ if(s==end_str_end) \ break; \ } \ if(eye==input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ new_eye=p2-input; \ } \ \ sval.type=T_STRING; \ DO_IF_CHECKER(sval.subtype=0); \ sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ INPUT_SHIFT)(input+start, \ eye-start); \ \ cnt=end_str_end-match-1; \ eye=new_eye; \ break; \ } \ \ case '[': \ cnt=PIKE_CONCAT(read_set,MATCH_SHIFT)(match,cnt+1, \ &set,match_len); \ \ match_set: \ for(e=eye;eye<input_len;eye++) \ { \
74d9382000-08-14Henrik Grubbström (Grubba) CHAROPT2( \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  if(input[eye]<sizeof(set.c)) \ { \ ) \ if(set.c[input[eye]] == set.neg) \ break; \
74d9382000-08-14Henrik Grubbström (Grubba) CHAROPT2( \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  }else{ \ if(set.a) \ { \ INT32 x; \ struct svalue tmp; \ tmp.type=T_INT; \ tmp.u.integer=input[eye]; \ x=switch_lookup(set.a, &tmp); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  if( set.neg != (x<0 && (x&1)) ) break; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  }else{ \
ded7032001-05-14Fredrik Hübinette (Hubbe)  if(!set.neg) break; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \ } \ ) \ } \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  if(set.a) { free_array(set.a); set.a=0; } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  sval.type=T_STRING; \ DO_IF_CHECKER(sval.subtype=0); \ sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ INPUT_SHIFT)(input+e,eye-e); \ break; \ \ case 'n': \ sval.type=T_INT; \ sval.subtype=NUMBER_NUMBER; \ sval.u.integer=eye; \ break; \ \ default: \ error("Unknown sscanf token %%%c(0x%02x)\n", \ match[cnt], match[cnt]); \ } \ break; \ } \ matches++; \ \ if(no_assign) \ { \ free_svalue(&sval); \ }else{ \ check_stack(1); \ *sp++=sval; \ DO_IF_DEBUG(sval.type=99); \ } \ } \ chars_matched[0]=eye; \ success[0]=1; \ return matches; \
5267b71995-08-09Fredrik Hübinette (Hubbe) }
22d95e1999-11-04Fredrik Hübinette (Hubbe)  /* Confusing? Yes - Hubbe */
e7a1721999-11-04Fredrik Hübinette (Hubbe) #define CHAROPT(X)
74d9382000-08-14Henrik Grubbström (Grubba) #define CHAROPT2(X)
e7a1721999-11-04Fredrik Hübinette (Hubbe) 
74d9382000-08-14Henrik Grubbström (Grubba) /* CHAROPT(X) is X if the match set is wide. * CHAROPT2(X) is X if the input is wide. */
e7a1721999-11-04Fredrik Hübinette (Hubbe) MKREADSET(0)
f556f11999-10-31Henrik Grubbström (Grubba) MK_VERY_LOW_SSCANF(0,0)
22d95e1999-11-04Fredrik Hübinette (Hubbe)  #undef CHAROPT2 #define CHAROPT2(X) X
f556f11999-10-31Henrik Grubbström (Grubba) MK_VERY_LOW_SSCANF(1,0) MK_VERY_LOW_SSCANF(2,0)
e7a1721999-11-04Fredrik Hübinette (Hubbe)  #undef CHAROPT #define CHAROPT(X) X
22d95e1999-11-04Fredrik Hübinette (Hubbe) 
e7a1721999-11-04Fredrik Hübinette (Hubbe) MKREADSET(1) MKREADSET(2)
22d95e1999-11-04Fredrik Hübinette (Hubbe) #undef CHAROPT2 #define CHAROPT2(X)
e7a1721999-11-04Fredrik Hübinette (Hubbe)  MK_VERY_LOW_SSCANF(0,1)
22d95e1999-11-04Fredrik Hübinette (Hubbe) MK_VERY_LOW_SSCANF(0,2) #undef CHAROPT2 #define CHAROPT2(X) X
e7a1721999-11-04Fredrik Hübinette (Hubbe) MK_VERY_LOW_SSCANF(1,1)
f556f11999-10-31Henrik Grubbström (Grubba) MK_VERY_LOW_SSCANF(2,1)
e7a1721999-11-04Fredrik Hübinette (Hubbe) MK_VERY_LOW_SSCANF(1,2)
f556f11999-10-31Henrik Grubbström (Grubba) MK_VERY_LOW_SSCANF(2,2)
53842a1998-04-15Fredrik Hübinette (Hubbe) void o_sscanf(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  extern int t_flag; #endif
53842a1998-04-15Fredrik Hübinette (Hubbe)  INT32 e,i; int x; long matched_chars; struct svalue *save_sp=sp; if(sp[-args].type != T_STRING) error("Bad argument 1 to sscanf().\n"); if(sp[1-args].type != T_STRING) error("Bad argument 1 to sscanf().\n");
f556f11999-10-31Henrik Grubbström (Grubba)  switch(sp[-args].u.string->size_shift*3 + sp[1-args].u.string->size_shift) { /* input_shift : match_shift */ case 0: /* 0 : 0 */ i=very_low_sscanf_0_0(STR0(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 1: /* 0 : 1 */ i=very_low_sscanf_0_1(STR0(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 2: /* 0 : 2 */ i=very_low_sscanf_0_2(STR0(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 3: /* 1 : 0 */ i=very_low_sscanf_1_0(STR1(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 4: /* 1 : 1 */ i=very_low_sscanf_1_1(STR1(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 5: /* 1 : 2 */ i=very_low_sscanf_1_2(STR1(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 6: /* 2 : 0 */ i=very_low_sscanf_2_0(STR2(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 7: /* 2 : 1 */ i=very_low_sscanf_2_1(STR2(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 8: /* 2 : 2 */ i=very_low_sscanf_2_2(STR2(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; default: error("Unsupported shift-combination to sscanf(): %d:%d\n", sp[-args].u.string->size_shift, sp[1-args].u.string->size_shift); break; }
53842a1998-04-15Fredrik Hübinette (Hubbe)  if(sp-save_sp > args/2-1) error("Too few arguments for sscanf format.\n"); for(x=0;x<sp-save_sp;x++) assign_lvalue(save_sp-args+2+x*2,save_sp+x); pop_n_elems(sp-save_sp +args);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(t_flag >2) { int nonblock; if((nonblock=query_nonblocking(2))) set_nonblocking(2,0);
f90e541995-08-17Fredrik Hübinette (Hubbe)  fprintf(stderr,"- Matches: %ld\n",(long)i);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(nonblock) set_nonblocking(2,1); }
53842a1998-04-15Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_int(i); }
53842a1998-04-15Fredrik Hübinette (Hubbe)  void f_sscanf(INT32 args) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
53842a1998-04-15Fredrik Hübinette (Hubbe)  extern int t_flag; #endif INT32 e,i; int x; long matched_chars; struct svalue *save_sp=sp; struct array *a; check_all_args("array_sscanf",args,BIT_STRING, BIT_STRING,0);
f556f11999-10-31Henrik Grubbström (Grubba)  switch(sp[-args].u.string->size_shift*3 + sp[1-args].u.string->size_shift) { /* input_shift : match_shift */ case 0: /* 0 : 0 */ i=very_low_sscanf_0_0(STR0(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 1: /* 0 : 1 */ i=very_low_sscanf_0_1(STR0(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 2: /* 0 : 2 */ i=very_low_sscanf_0_2(STR0(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 3: /* 1 : 0 */ i=very_low_sscanf_1_0(STR1(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 4: /* 1 : 1 */ i=very_low_sscanf_1_1(STR1(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 5: /* 1 : 2 */ i=very_low_sscanf_1_2(STR1(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 6: /* 2 : 0 */ i=very_low_sscanf_2_0(STR2(sp[-args].u.string), sp[-args].u.string->len, STR0(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 7: /* 2 : 1 */ i=very_low_sscanf_2_1(STR2(sp[-args].u.string), sp[-args].u.string->len, STR1(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; case 8: /* 2 : 2 */ i=very_low_sscanf_2_2(STR2(sp[-args].u.string), sp[-args].u.string->len, STR2(sp[1-args].u.string), sp[1-args].u.string->len, &matched_chars, &x); break; default: error("Unsupported shift-combination to sscanf(): %d:%d\n", sp[-args].u.string->size_shift, sp[1-args].u.string->size_shift); break; }
53842a1998-04-15Fredrik Hübinette (Hubbe)  a=aggregate_array(sp-save_sp); pop_n_elems(args); push_array(a); }