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. \*/
b788cd1998-07-04Henrik Grubbström (Grubba) #include "global.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"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland) RCSID("$Id: opcodes.c,v 1.38 1999/06/19 09:55:58 mirar 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) { 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)
e747d81998-05-21Henrik Grubbström (Grubba)  error("Index %d is out of range 0 - %d.\n", i, what->u.string->len-1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  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;
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--;
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)  case T_MAPPING: switch(sp[-1].type) { case T_ARRAY: { f_transpose(1); sp--; 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); break; case T_STRING:
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); 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)  } sp[-1].type=T_INT; sp[-1].u.integer=i;
5267b71995-08-09Fredrik Hübinette (Hubbe)  break;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_FLOAT: { FLOAT_TYPE f; 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)  f=0.0; } 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: sp[-1].type = T_OBJECT; 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) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(run_time_type != sp[-1].type)
569c171998-02-27Fredrik Hübinette (Hubbe)  fatal("Internal error: Cast failed (run_time_type = %d, sp[-1].type = %d.)\n",run_time_type,sp[-1].type);
98f2b11998-02-19Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
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;
7ea3341998-05-16Fredrik Hübinette (Hubbe)  push_string(itype=index_type(type,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); push_string(vtype=index_type(type,0)); run_time_vtype=compile_type_to_runtime_type(vtype); if(run_time_itype != T_MIXED || run_time_vtype != T_MIXED) { struct mapping *m; struct mapping *tmp=sp[-3].u.mapping; 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 push_mapping(m=allocate_mapping(tmp->size)); 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--; }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* flags: * operators: %d %s %f %c %n %[ %% */
53842a1998-04-15Fredrik Hübinette (Hubbe) static int read_set(unsigned char *match,int cnt,char *set,int match_len)
5267b71995-08-09Fredrik Hübinette (Hubbe) { int init; int last=0; int e; if(cnt>=match_len) error("Error in sscanf format string.\n"); if(match[cnt]=='^') { for(e=0;e<256;e++) set[e]=1; init=0; cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); }else{ for(e=0;e<256;e++) set[e]=0; init=1; }
53842a1998-04-15Fredrik Hübinette (Hubbe)  if(match[cnt]==']' || match[cnt]=='-')
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
53842a1998-04-15Fredrik Hübinette (Hubbe)  set[last=match[cnt]]=init;
5267b71995-08-09Fredrik Hübinette (Hubbe)  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['-']=init; break; }
5c8e891995-10-29Fredrik Hübinette (Hubbe)  for(e=last;e<(int) EXTRACT_UCHAR(match+cnt);e++) set[e]=init;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } set[last=EXTRACT_UCHAR(match+cnt)]=init; } return cnt; }
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 */ /* Hmm... No idea how to generate NaN in a portable way. */ /* Let's turn it into a 0 for now... */ return (float)0.0; } else { /* +/- Infinity */ #ifdef HUGE_VAL return (float)(s? -HUGE_VAL:HUGE_VAL); #else /* This number is infinite enough... :) */ e = 1024; f = 1; extra_f = 0; #endif } r = (double)f; if(extra_f) r += ((double)extra_f)/4294967296.0; return (float)(s? -LDEXP(r, e):LDEXP(r, e)); } #endif
53842a1998-04-15Fredrik Hübinette (Hubbe) static INT32 really_low_sscanf(char *input, long input_len, char *match, long match_len, long *chars_matched, int *success)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct svalue sval;
2a50961995-08-23Fredrik Hübinette (Hubbe)  int e,cnt,matches,eye,arg;
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  int no_assign,field_length;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char set[256]; struct svalue *argp;
53842a1998-04-15Fredrik Hübinette (Hubbe)  success[0]=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  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])
53842a1998-04-15Fredrik Hübinette (Hubbe)  { chars_matched[0]=eye;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return matches;
53842a1998-04-15Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  eye++; }
53842a1998-04-15Fredrik Hübinette (Hubbe)  if(cnt>=match_len) { chars_matched[0]=eye; return matches; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(match[cnt]!='%' || match[cnt+1]=='%') { fatal("Error in sscanf.\n"); } #endif
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  no_assign=0; field_length=-1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n");
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  while(1)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  switch(match[cnt]) {
2b33e71999-06-19Mirar (Pontus Hagland)  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': { char *t; field_length=STRTOL(match+cnt,&t,10); cnt=t-match; continue; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
53842a1998-04-15Fredrik Hübinette (Hubbe)  case '{': { ONERROR err; long tmp; for(e=cnt+1,tmp=1;tmp;e++) { if(!match[e]) { 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);
2b33e71999-06-19Mirar (Pontus Hagland)  while(input_len-eye)
53842a1998-04-15Fredrik Hübinette (Hubbe)  { int yes; struct svalue *save_sp=sp; really_low_sscanf(input+eye, input_len-eye, match+cnt+1, e-cnt-2, &tmp, &yes); if(yes) { 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; }
2b33e71999-06-19Mirar (Pontus Hagland)  case 'c': if(field_length == -1) field_length = 1; if(eye+field_length > input_len) { chars_matched[0]=eye; return matches; } sval.type=T_INT; sval.subtype=NUMBER_NUMBER; sval.u.integer=0; while(--field_length >= 0) { sval.u.integer<<=8; sval.u.integer|=EXTRACT_UCHAR(input+eye); eye++; } break;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case 'd':
bf13151998-04-14Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  char * t;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  if(eye>=input_len) { chars_matched[0]=eye; return matches; } if(field_length != -1 && eye+field_length < input_len) { char save=input[eye+field_length]; input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,10); input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,10); if(input + eye == t) { chars_matched[0]=eye; return matches; } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; break;
53842a1998-04-15Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case 'x':
53842a1998-04-15Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  char * t;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  if(eye>=input_len) { chars_matched[0]=eye; return matches; } if(field_length != -1 && eye+field_length < input_len) { char save=input[eye+field_length]; input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,16); input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,16); if(input + eye == t) { chars_matched[0]=eye; return matches; } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; break;
53842a1998-04-15Fredrik Hübinette (Hubbe)  }
2b33e71999-06-19Mirar (Pontus Hagland)  case 'o':
53842a1998-04-15Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  char * t;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  if(eye>=input_len) { chars_matched[0]=eye; return matches; } if(field_length != -1 && eye+field_length < input_len) { char save=input[eye+field_length]; input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,8); input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,8); if(input + eye == t) { chars_matched[0]=eye; return matches; } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; break; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case 'D': case 'i':
53842a1998-04-15Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  char * t; if(eye>=input_len) { chars_matched[0]=eye; return matches; } if(field_length != -1 && eye+field_length < input_len) { char save=input[eye+field_length]; input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,0); input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,0); if(input + eye == t) { chars_matched[0]=eye; return matches; } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; break;
53842a1998-04-15Fredrik Hübinette (Hubbe)  }
2b33e71999-06-19Mirar (Pontus Hagland)  case 'f':
53842a1998-04-15Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  char * t; if(eye>=input_len) { chars_matched[0]=eye; return matches; } sval.u.float_number=STRTOD(input+eye,&t); if(input + eye == t) { chars_matched[0]=eye; return matches; } eye=t-input; sval.type=T_FLOAT;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
2b33e71999-06-19Mirar (Pontus Hagland)  break;
4bd22e1998-05-25Marcus Comstedt  }
2b33e71999-06-19Mirar (Pontus Hagland)  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;
4bd22e1998-05-25Marcus Comstedt #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
4bd22e1998-05-25Marcus Comstedt #endif
2b33e71999-06-19Mirar (Pontus Hagland)  switch(field_length) { case 4:
4bd22e1998-05-25Marcus Comstedt #ifdef FLOAT_IS_IEEE_BIG
2b33e71999-06-19Mirar (Pontus Hagland)  { float f; ((char *)&f)[0] = *(input+eye); ((char *)&f)[1] = *(input+eye+1); ((char *)&f)[2] = *(input+eye+2); ((char *)&f)[3] = *(input+eye+3); sval.u.float_number = f; }
4bd22e1998-05-25Marcus Comstedt #else #ifdef FLOAT_IS_IEEE_LITTLE
2b33e71999-06-19Mirar (Pontus Hagland)  { float f; ((char *)&f)[3] = *(input+eye); ((char *)&f)[2] = *(input+eye+1); ((char *)&f)[1] = *(input+eye+2); ((char *)&f)[0] = *(input+eye+3); sval.u.float_number = f; }
4bd22e1998-05-25Marcus Comstedt #else
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.float_number = low_parse_IEEE_float(input+eye, 4);
4bd22e1998-05-25Marcus Comstedt #endif #endif
2b33e71999-06-19Mirar (Pontus Hagland)  eye += 4; break; case 8:
4bd22e1998-05-25Marcus Comstedt #ifdef DOUBLE_IS_IEEE_BIG
2b33e71999-06-19Mirar (Pontus Hagland)  { double d; ((char *)&d)[0] = *(input+eye); ((char *)&d)[1] = *(input+eye+1); ((char *)&d)[2] = *(input+eye+2); ((char *)&d)[3] = *(input+eye+3); ((char *)&d)[4] = *(input+eye+4); ((char *)&d)[5] = *(input+eye+5); ((char *)&d)[6] = *(input+eye+6); ((char *)&d)[7] = *(input+eye+7); sval.u.float_number = (float)d; }
4bd22e1998-05-25Marcus Comstedt #else #ifdef DOUBLE_IS_IEEE_LITTLE
2b33e71999-06-19Mirar (Pontus Hagland)  { double d; ((char *)&d)[7] = *(input+eye); ((char *)&d)[6] = *(input+eye+1); ((char *)&d)[5] = *(input+eye+2); ((char *)&d)[4] = *(input+eye+3); ((char *)&d)[3] = *(input+eye+4); ((char *)&d)[2] = *(input+eye+5); ((char *)&d)[1] = *(input+eye+6); ((char *)&d)[0] = *(input+eye+7); sval.u.float_number = (float)d; }
4bd22e1998-05-25Marcus Comstedt #else
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.float_number = low_parse_IEEE_float(input+eye, 8);
4bd22e1998-05-25Marcus Comstedt #endif #endif
2b33e71999-06-19Mirar (Pontus Hagland)  eye += 8; break; }
4bd22e1998-05-25Marcus Comstedt  break;
2b33e71999-06-19Mirar (Pontus Hagland)  case 's': if(field_length != -1)
53842a1998-04-15Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  if(input_len - eye < field_length) { chars_matched[0]=eye; return matches; }
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  sval.type=T_STRING;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.string=make_shared_binary_string(input+eye,field_length); eye+=field_length; break; }
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  if(cnt+1>=match_len) { sval.type=T_STRING;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) #endif
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.string=make_shared_binary_string(input+eye,input_len-eye); eye=input_len; break; }else{ char *end_str_start; char *end_str_end; char *s=0; /* make gcc happy */ char *p=0; /* make gcc happy */ int start,contains_percent_percent, new_eye; start=eye; end_str_start=match+cnt+1;
3d2fb21996-08-06Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  s=match+cnt+1; test_again: if(*s=='%')
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  { s++;
2b33e71999-06-19Mirar (Pontus Hagland)  if(*s=='*') s++; switch(*s) { case 'n': s++; goto test_again;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case 's': error("Illegal to have two adjecent %%s.\n"); return 0; /* make gcc happy */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  /* sscanf("foo-bar","%s%d",a,b) might not work as expected */ case 'd': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; set['-']=0; goto match_set; case 'o': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='7';e++) set[e]=0; goto match_set; case 'x': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; for(e='a';e<='f';e++) set[e]=0; goto match_set; case 'D': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; set['-']=0; set['x']=0; goto match_set; case 'f': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; set['.']=set['-']=0; goto match_set; case '[': /* oh dear */ read_set((unsigned char *)match,s-match+1,set,match_len); for(e=0;e<256;e++) set[e]=!set[e]; goto match_set; }
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  contains_percent_percent=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  for(e=cnt;e<match_len;e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  if(match[e]=='%')
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  if(match[e+1]=='%') { contains_percent_percent=1; e++; }else{ break; }
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
2b33e71999-06-19Mirar (Pontus Hagland)  end_str_end=match+e;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  if(!contains_percent_percent)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  s=my_memmem(end_str_start, end_str_end-end_str_start, input+eye, input_len-eye); if(!s)
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  {
2b33e71999-06-19Mirar (Pontus Hagland)  chars_matched[0]=eye; return matches;
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  }
2b33e71999-06-19Mirar (Pontus Hagland)  eye=s-input; new_eye=eye+end_str_end-end_str_start; }else{ for(;eye<input_len;eye++) { p=input+eye; for(s=end_str_start;s<end_str_end;s++,p++) { if(*s!=*p) break; if(*s=='%') s++; } if(s==end_str_end) break; } if(eye==input_len) { chars_matched[0]=eye; return matches; } new_eye=p-input;
53842a1998-04-15Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  sval.type=T_STRING;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.string=make_shared_binary_string(input+start,eye-start);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  cnt=end_str_end-match-1; eye=new_eye; break; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case '[': cnt=read_set((unsigned char *)match,cnt+1,set,match_len);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  match_set: for(e=eye;eye<input_len && set[EXTRACT_UCHAR(input+eye)];eye++); sval.type=T_STRING;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef __CHECKER__
2b33e71999-06-19Mirar (Pontus Hagland)  sval.subtype=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
2b33e71999-06-19Mirar (Pontus Hagland)  sval.u.string=make_shared_binary_string(input+e,eye-e); break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  case 'n': sval.type=T_INT; sval.subtype=NUMBER_NUMBER; sval.u.integer=eye; break;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2b33e71999-06-19Mirar (Pontus Hagland)  default: error("Unknown sscanf token %%%c\n",match[cnt]);
3d2fb21996-08-06Fredrik Hübinette (Hubbe)  } break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } matches++;
53842a1998-04-15Fredrik Hübinette (Hubbe)  if(no_assign)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
53842a1998-04-15Fredrik Hübinette (Hubbe)  free_svalue(&sval); }else{ check_stack(1); *sp++=sval;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
53842a1998-04-15Fredrik Hübinette (Hubbe)  sval.type=99; #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
53842a1998-04-15Fredrik Hübinette (Hubbe)  chars_matched[0]=eye; success[0]=1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return matches; }
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"); i=really_low_sscanf(sp[-args].u.string->str, sp[-args].u.string->len, sp[1-args].u.string->str, sp[1-args].u.string->len, &matched_chars, &x); 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); i=really_low_sscanf(sp[-args].u.string->str, sp[-args].u.string->len, sp[1-args].u.string->str, sp[1-args].u.string->len, &matched_chars, &x); a=aggregate_array(sp-save_sp); pop_n_elems(args); push_array(a); }