e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
6d79ff2003-01-14Johan Sundström || $Id: opcodes.c,v 1.132 2003/01/14 11:54:06 jhs Exp $
e576bb2002-10-11Martin Nilsson */
aedfb12002-10-09Martin Nilsson 
b788cd1998-07-04Henrik Grubbström (Grubba) #include "global.h"
1b28b82001-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"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_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) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
6d79ff2003-01-14Johan Sundström RCSID("$Id: opcodes.c,v 1.132 2003/01/14 11:54:06 jhs 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))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Index permission denied.\n");
7e97c31999-01-21Fredrik Hübinette (Hubbe) #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) {
19ac6d2001-07-20Martin Stjernholm  if (ind->type == T_STRING) Pike_error("Indexing the integer %"PRINTPIKEINT"d " "with unknown method \"%s\".\n", val, ind->u.string->str); else Pike_error("Indexing the integer %"PRINTPIKEINT"d " "with an unknown method.\n", val);
635b9b2000-04-01Henrik Grubbström (Grubba)  } else {
1b99fb2000-11-12Andreas Sigfridsson  if(ind->type == T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Indexing the NULL value with \"%s\".\n", ind->u.string->str);
1b99fb2000-11-12Andreas Sigfridsson  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Indexing the NULL value.\n");
1b99fb2000-11-12Andreas Sigfridsson  }
635b9b2000-04-01Henrik Grubbström (Grubba)  } }
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)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Attempt to index the empty string with %d.\n", i);
f0e76d1999-08-22Fredrik Noring  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Index %d is out of string range 0 - %ld.\n",
6f95902000-08-17Henrik Grubbström (Grubba)  i, PTRDIFF_T_TO_LONG(what->u.string->len - 1));
f0e76d1999-08-22Fredrik Noring  } 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{
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Index is not an integer.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Indexing a basic type.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
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) }
c6f8f92002-12-07Henrik Grubbström (Grubba) /*! @class MasterObject */ /*! @decl object cast_to_object(string str, string|void current_file) *! *! Called by the Pike runtime to cast strings to objects. *! *! @param str *! String to cast to object. *! *! @param current_file *! Filename of the file that attempts to perform the cast. *! *! @returns *! Returns the resulting object. *! *! @seealso *! @[cast_to_program()] */ /*! @decl program cast_to_program(string str, string|void current_file) *! *! Called by the Pike runtime to cast strings to programs. *! *! @param str *! String to cast to object. *! *! @param current_file *! Filename of the file that attempts to perform the cast. *! *! @returns *! Returns the resulting program. *! *! @seealso *! @[cast_to_object()] */ /*! @endclass */
0232d22001-06-17Henrik Grubbström (Grubba) /* Special case for casting to int. */ void o_cast_to_int(void) { switch(sp[-1].type) { case T_OBJECT: { struct pike_string *s; MAKE_CONSTANT_SHARED_STRING(s, "int"); push_string(s); if(!sp[-2].u.object->prog) Pike_error("Cast called on destructed object.\n"); if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1) Pike_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--; dmalloc_touch_svalue(sp); }
7f94c22001-06-17Henrik Grubbström (Grubba)  if(sp[-1].type != PIKE_T_INT) { 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) { struct pike_string *s; MAKE_CONSTANT_SHARED_STRING(s, "int"); push_string(s); apply_low(sp[-2].u.object, f, 1);
9f516a2001-12-16Martin Stjernholm  f=!UNSAFE_IS_ZERO(sp-1);
7f94c22001-06-17Henrik Grubbström (Grubba)  pop_stack(); if(f) return; } } Pike_error("Cast failed, wanted int, got %s\n", get_name_of_type(sp[-1].type)); }
0232d22001-06-17Henrik Grubbström (Grubba)  break;
7f94c22001-06-17Henrik Grubbström (Grubba) 
0232d22001-06-17Henrik Grubbström (Grubba)  case T_FLOAT: { int i=DO_NOT_WARN((int)(sp[-1].u.float_number)); #ifdef AUTO_BIGNUM if((i < 0 ? -i : i) < floor(fabs(sp[-1].u.float_number))) { /* Note: This includes the case when i = 0x80000000, i.e. the absolute value is not computable. */ convert_stack_top_to_bignum(); return; /* FIXME: OK to return? Cast tests below indicates we have to do this, at least for now... /Noring */ /* Yes, it is ok to return, it is actually an optimization :) * /Hubbe */ } else #endif /* AUTO_BIGNUM */ { sp[-1].type=T_INT; sp[-1].u.integer=i; } } break; case T_STRING: /* 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 /* The generic function is rather slow, so I added this * code for benchmark purposes. :-) /per */ if( sp[-1].u.string->len < 10 && !sp[-1].u.string->size_shift ) { int i=atoi(sp[-1].u.string->str); free_string(sp[-1].u.string); sp[-1].type=T_INT; sp[-1].u.integer=i; } else 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 */ /* Yes, it is ok to return, it is actually an optimization :) * /Hubbe */ #else { int i=STRTOL(sp[-1].u.string->str,0,10); free_string(sp[-1].u.string); sp[-1].type=T_INT; sp[-1].u.integer=i; } #endif /* AUTO_BIGNUM */ break; case PIKE_T_INT: break; default: Pike_error("Cannot cast %s to int.\n", get_name_of_type(sp[-1].type)); } }
c6f8f92002-12-07Henrik Grubbström (Grubba) /* Special case for casting to string. */
7f94c22001-06-17Henrik Grubbström (Grubba) void o_cast_to_string(void) { char buf[200]; switch(sp[-1].type) { case PIKE_T_STRING: return; case T_OBJECT: { struct pike_string *s; MAKE_CONSTANT_SHARED_STRING(s, "string"); push_string(s); if(!sp[-2].u.object->prog) Pike_error("Cast called on destructed object.\n"); if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1) Pike_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--; dmalloc_touch_svalue(sp); } if(sp[-1].type != PIKE_T_STRING) { 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) { struct pike_string *s; MAKE_CONSTANT_SHARED_STRING(s, "string"); push_string(s); apply_low(sp[-2].u.object, f, 1);
9f516a2001-12-16Martin Stjernholm  f=!UNSAFE_IS_ZERO(sp-1);
7f94c22001-06-17Henrik Grubbström (Grubba)  pop_stack(); if(f) return; } } Pike_error("Cast failed, wanted string, got %s\n", get_name_of_type(sp[-1].type)); } return; case T_ARRAY: { int i; struct array *a = sp[-1].u.array; struct pike_string *s; int shift = 0; for(i = a->size; i--; ) { unsigned INT32 val; if (a->item[i].type != T_INT) { Pike_error("cast: Item %d is not an integer.\n", i); } val = (unsigned INT32)a->item[i].u.integer; if (val > 0xff) { shift = 1; if (val > 0xffff) { shift = 2; while(i--) if (a->item[i].type != T_INT) Pike_error("cast: Item %d is not an integer.\n", i); break; } while(i--) { if (a->item[i].type != T_INT) { Pike_error("cast: Item %d is not an integer.\n", i); } val = (unsigned INT32)a->item[i].u.integer; if (val > 0xffff) { shift = 2; while(i--) if (a->item[i].type != T_INT) Pike_error("cast: Item %d is not an integer.\n", i); break; } } break; } } 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));
5aad932002-08-15Marcus Comstedt  Pike_fatal("cast: Bad shift: %d.\n", shift);
7f94c22001-06-17Henrik Grubbström (Grubba)  break; } s = end_shared_string(s); pop_stack(); push_string(s); } return; 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; default: Pike_error("Cannot cast %s to string.\n", get_name_of_type(sp[-1].type)); } sp[-1].type = PIKE_T_STRING; sp[-1].u.string = make_shared_string(buf); }
d68a072001-02-20Henrik Grubbström (Grubba) void o_cast(struct pike_type *type, INT32 run_time_type)
5267b71995-08-09Fredrik 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)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast called on destructed object.\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No cast method in object.\n");
07c0731996-06-21Fredrik Hübinette (Hubbe)  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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot perform cast to that type.\n");
7e97c31999-01-21Fredrik Hübinette (Hubbe) 
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:
a96ce92000-04-19Fredrik Hübinette (Hubbe)  { extern void f_mkmultiset(INT32);
06f6112000-01-27Fredrik Hübinette (Hubbe)  f_mkmultiset(1); break;
a96ce92000-04-19Fredrik Hübinette (Hubbe)  }
06f6112000-01-27Fredrik Hübinette (Hubbe)  default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot cast %s to multiset.\n",get_name_of_type(sp[-1].type));
06f6112000-01-27Fredrik Hübinette (Hubbe)  } break;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  case T_MAPPING: switch(sp[-1].type) { case T_ARRAY: {
505aec2000-11-29Mirar (Pontus Hagland)  struct array *a=sp[-1].u.array; struct array *b; struct mapping *m; INT32 i; m=allocate_mapping(a->size); /* MAP_SLOTS(a->size) */ push_mapping(m); for (i=0; i<a->size; i++) { if (ITEM(a)[i].type!=T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast array to mapping: "
505aec2000-11-29Mirar (Pontus Hagland)  "element %d is not an array\n", i); b=ITEM(a)[i].u.array; if (b->size!=2)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast array to mapping: "
505aec2000-11-29Mirar (Pontus Hagland)  "element %d is not an array of size 2\n", i); mapping_insert(m,ITEM(b)+0,ITEM(b)+1); } stack_swap(); pop_n_elems(1); break;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  } default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot cast %s to mapping.\n",get_name_of_type(sp[-1].type));
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  } 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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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) 
0232d22001-06-17Henrik Grubbström (Grubba)  case T_INT: o_cast_to_int();
7f94c22001-06-17Henrik Grubbström (Grubba)  return;
98f2b11998-02-19Fredrik Hübinette (Hubbe) 
7f94c22001-06-17Henrik Grubbström (Grubba)  case T_STRING: o_cast_to_string(); return;
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:
a5cd6a2001-09-24Henrik Grubbström (Grubba)  f = (FLOAT_TYPE)STRTOD_PCHARP(MKPCHARP(sp[-1].u.string->str, sp[-1].u.string->size_shift), 0);
98f2b11998-02-19Fredrik Hübinette (Hubbe)  free_string(sp[-1].u.string); break; default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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_OBJECT: switch(sp[-1].type) {
807d072002-12-01Martin Stjernholm  case T_STRING: { struct pike_string *file; INT32 lineno; if(Pike_fp->pc && (file = low_get_line(Pike_fp->pc, Pike_fp->context.prog, &lineno))) { push_string(file);
98f2b11998-02-19Fredrik Hübinette (Hubbe)  }else{ push_int(0); }
c6f8f92002-12-07Henrik Grubbström (Grubba)  /* FIXME: Ought to allow compile_handler to override. */
98f2b11998-02-19Fredrik Hübinette (Hubbe)  APPLY_MASTER("cast_to_object",2); return;
807d072002-12-01Martin Stjernholm  }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  case T_FUNCTION:
a253f42001-03-31Henrik Grubbström (Grubba)  if (Pike_sp[-1].subtype == FUNCTION_BUILTIN) { Pike_error("Cannot cast builtin functions to object.\n"); } else {
e9ecc02001-03-31Henrik Grubbström (Grubba)  Pike_sp[-1].type = T_OBJECT;
a253f42001-03-31Henrik Grubbström (Grubba)  }
98f2b11998-02-19Fredrik Hübinette (Hubbe)  break;
569c171998-02-27Fredrik Hübinette (Hubbe)  default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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) {
807d072002-12-01Martin Stjernholm  case T_STRING: { struct pike_string *file; INT32 lineno; if(Pike_fp->pc && (file = low_get_line(Pike_fp->pc, Pike_fp->context.prog, &lineno))) { push_string(file);
0e70221998-04-05Fredrik Hübinette (Hubbe)  }else{ push_int(0); }
c6f8f92002-12-07Henrik Grubbström (Grubba)  /* FIXME: Ought to allow compile_handler to override. */
0e70221998-04-05Fredrik Hübinette (Hubbe)  APPLY_MASTER("cast_to_program",2); return;
807d072002-12-01Martin Stjernholm  }
0e70221998-04-05Fredrik Hübinette (Hubbe)  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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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);
9f516a2001-12-16Martin Stjernholm  f=!UNSAFE_IS_ZERO(sp-1);
110b3f1999-10-29Fredrik Hübinette (Hubbe)  pop_stack(); if(f) goto emulated_type_ok; } }
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast failed, wanted %s, got %s\n",
110b3f1999-10-29Fredrik Hübinette (Hubbe)  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)  {
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_type *itype;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  INT32 run_time_itype;
d68a072001-02-20Henrik Grubbström (Grubba)  push_type_value(itype = index_type(type, int_type_string, 0));
babd872001-02-23Henrik Grubbström (Grubba)  run_time_itype = compile_type_to_runtime_type(itype);
98f2b11998-02-19Fredrik Hübinette (Hubbe)  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{
a5cd6a2001-09-24Henrik Grubbström (Grubba)  INT32 e;
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("o_cast left stack droppings.\n");
7ea3341998-05-16Fredrik Hübinette (Hubbe) #endif
98f2b11998-02-19Fredrik Hübinette (Hubbe)  }
14bb592000-05-06Fredrik Hübinette (Hubbe)  END_CYCLIC();
98f2b11998-02-19Fredrik Hübinette (Hubbe)  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: {
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_type *itype;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  INT32 run_time_itype;
d68a072001-02-20Henrik Grubbström (Grubba)  push_type_value(itype = key_type(type, 0));
babd872001-02-23Henrik Grubbström (Grubba)  run_time_itype = compile_type_to_runtime_type(itype);
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  if(run_time_itype != T_MIXED) { struct multiset *m;
5b15bb2001-12-10Martin Stjernholm #ifdef PIKE_NEW_MULTISETS struct multiset *tmp=sp[-2].u.multiset; #else
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  struct array *tmp=sp[-2].u.multiset->ind;
5b15bb2001-12-10Martin Stjernholm #endif
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  DECLARE_CYCLIC(); if((m=(struct multiset *)BEGIN_CYCLIC(tmp,0))) { ref_push_multiset(m); }else{ #ifdef PIKE_DEBUG struct svalue *save_sp=sp+1; #endif
5b15bb2001-12-10Martin Stjernholm  #ifdef PIKE_NEW_MULTISETS ptrdiff_t nodepos; if (multiset_indval (tmp)) Pike_error ("FIXME: Casting not implemented for multisets with values.\n"); push_multiset (m = allocate_multiset (multiset_sizeof (tmp), multiset_get_flags (tmp), multiset_get_cmp_less (tmp))); SET_CYCLIC_RET(m); if ((nodepos = multiset_first (tmp)) >= 0) { ONERROR uwp; SET_ONERROR (uwp, do_sub_msnode_ref, tmp); do { push_multiset_index (tmp, nodepos); o_cast(itype, run_time_itype); multiset_insert_2 (m, sp - 1, NULL, 0); pop_stack(); } while ((nodepos = multiset_next (tmp, nodepos)) >= 0); UNSET_ONERROR (uwp); } #else /* PIKE_NEW_MULTISETS */ INT32 e; struct array *a;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  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(); }
5b15bb2001-12-10Martin Stjernholm  order_multiset(m); #endif
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(save_sp!=sp)
5aad932002-08-15Marcus Comstedt  Pike_fatal("o_cast left stack droppings.\n");
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) #endif }
14bb592000-05-06Fredrik Hübinette (Hubbe)  END_CYCLIC();
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  assign_svalue(sp-3,sp-1); pop_stack(); } pop_stack(); } break; case T_MAPPING: {
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_type *itype, *vtype;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  INT32 run_time_itype; INT32 run_time_vtype;
d68a072001-02-20Henrik Grubbström (Grubba)  push_type_value(itype = key_type(type, 0));
babd872001-02-23Henrik Grubbström (Grubba)  run_time_itype = compile_type_to_runtime_type(itype);
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) 
d68a072001-02-20Henrik Grubbström (Grubba)  push_type_value(vtype = index_type(type, mixed_type_string, 0));
babd872001-02-23Henrik Grubbström (Grubba)  run_time_vtype = compile_type_to_runtime_type(vtype);
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  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{
a5cd6a2001-09-24Henrik Grubbström (Grubba)  INT32 e;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("o_cast left stack droppings.\n");
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) #endif }
14bb592000-05-06Fredrik Hübinette (Hubbe)  END_CYCLIC();
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  assign_svalue(sp-4,sp-1); pop_stack(); } pop_n_elems(2); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_cast(void)
98f2b11998-02-19Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
98f2b11998-02-19Fredrik Hübinette (Hubbe)  struct svalue *save_sp=sp;
d68a072001-02-20Henrik Grubbström (Grubba)  if(sp[-2].type != T_TYPE)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Cast expression destroyed stack or left droppings! (Type:%d)\n",
b103b32001-02-20Henrik Grubbström (Grubba)  sp[-2].type);
98f2b11998-02-19Fredrik Hübinette (Hubbe) #endif
d68a072001-02-20Henrik Grubbström (Grubba)  o_cast(sp[-2].u.type,
07f5432001-02-21Henrik Grubbström (Grubba)  compile_type_to_runtime_type(sp[-2].u.type));
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
98f2b11998-02-19Fredrik Hübinette (Hubbe)  if(save_sp != sp)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Internal error: o_cast() left droppings on stack.\n");
98f2b11998-02-19Fredrik Hübinette (Hubbe) #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) \
b819352000-08-14Henrik Grubbström (Grubba) static ptrdiff_t PIKE_CONCAT(read_set,SIZE) ( \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  PIKE_CONCAT(p_wchar,SIZE) *match, \
b819352000-08-14Henrik Grubbström (Grubba)  ptrdiff_t cnt, \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  struct sscanf_set *set, \
b819352000-08-14Henrik Grubbström (Grubba)  ptrdiff_t match_len) \
e7a1721999-11-04Fredrik Hübinette (Hubbe) { \
b819352000-08-14Henrik Grubbström (Grubba)  size_t e, last = 0; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  CHAROPT( int set_size=0; ) \ \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ MEMSET(set->c, 0, sizeof(set->c)); \ set->a=0; \ \ if(match[cnt]=='^') \ { \ set->neg=1; \ cnt++; \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  }else{ \ set->neg=0; \ } \ \ if(match[cnt]==']' || match[cnt]=='-') \ { \ set->c[last=match[cnt]]=1; \ cnt++; \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \ \ for(;match[cnt]!=']';cnt++) \ { \ if(match[cnt]=='-') \ { \ cnt++; \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ if(match[cnt]==']') \ { \ set->c['-']=1; \ break; \ } \ \ if(last >= match[cnt]) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ CHAROPT( \
b819352000-08-14Henrik Grubbström (Grubba)  if(last < (size_t)sizeof(set->c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
b819352000-08-14Henrik Grubbström (Grubba)  if(match[cnt] < (size_t)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{ \
b819352000-08-14Henrik Grubbström (Grubba)  for(e=last;e<(size_t)sizeof(set->c);e++) \
2573d11999-12-22Henrik Grubbström (Grubba)  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]; \
b819352000-08-14Henrik Grubbström (Grubba)  if(last < (size_t)sizeof(set->c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  set->c[last]=1; \ CHAROPT( \ else{ \
2573d11999-12-22Henrik Grubbström (Grubba)  if(set_size && \
b819352000-08-14Henrik Grubbström (Grubba)  ((size_t)sp[-1].u.integer) == last-1) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ sp[-1].u.integer++; \ }else{ \ check_stack(2); \
8c37d12000-08-15Henrik Grubbström (Grubba)  push_int64(last); \ push_int64(last); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  set_size++; \ } \ } \ ) \ } \ \ CHAROPT( \ if(set_size) \ { \ INT32 *order; \ set->a=aggregate_array(set_size*2); \ order=get_switch_order(set->a); \
b819352000-08-14Henrik Grubbström (Grubba)  for(e=0;e<(size_t)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); \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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
65a5492000-08-10Per Hedbor static INLINE FLOAT_TYPE 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;
2ebc5a2001-07-31Marcus Comstedt  DECLARE_INF DECLARE_NAN
4bd22e1998-05-25Marcus Comstedt  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 */
2ebc5a2001-07-31Marcus Comstedt  return (FLOAT_TYPE)MAKE_NAN();
4bd22e1998-05-25Marcus Comstedt  } else { /* +/- Infinity */
2ebc5a2001-07-31Marcus Comstedt  return (FLOAT_TYPE)MAKE_INF(s? -1:1);
4bd22e1998-05-25Marcus Comstedt  } r = (double)f; if(extra_f) r += ((double)extra_f)/4294967296.0;
65a5492000-08-10Per Hedbor  return (FLOAT_TYPE)(s? -LDEXP(r, e):LDEXP(r, e));
4bd22e1998-05-25Marcus Comstedt } #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); \
b819352000-08-14Henrik Grubbström (Grubba)  (SVAL).u.float_number = (FLOAT_TYPE)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); \
b819352000-08-14Henrik Grubbström (Grubba)  (SVAL).u.float_number = (FLOAT_TYPE)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
8c37d12000-08-15Henrik Grubbström (Grubba) /* Avoid some warnings about loss of precision */ #ifdef __ECL
6b0d792000-08-15Henrik Grubbström (Grubba) static inline INT32 TO_INT32(ptrdiff_t x)
8c37d12000-08-15Henrik Grubbström (Grubba) {
6b0d792000-08-15Henrik Grubbström (Grubba)  return DO_NOT_WARN((INT32)x);
8c37d12000-08-15Henrik Grubbström (Grubba) } #else /* !__ECL */
1b1f8e2000-08-15Henrik Grubbström (Grubba) #define TO_INT32(x) ((INT32)(x))
8c37d12000-08-15Henrik Grubbström (Grubba) #endif /* __ECL */
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, \
a70bb42000-08-07Henrik Grubbström (Grubba)  ptrdiff_t input_len, \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  PIKE_CONCAT(p_wchar, MATCH_SHIFT) *match, \
a70bb42000-08-07Henrik Grubbström (Grubba)  ptrdiff_t match_len, \ ptrdiff_t *chars_matched, \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  int *success) \ { \ struct svalue sval; \
903b772000-08-09Henrik Grubbström (Grubba)  INT32 matches, arg; \
b819352000-08-14Henrik Grubbström (Grubba)  ptrdiff_t cnt, eye, e, field_length = 0; \ int no_assign = 0, minus_flag = 0; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  struct sscanf_set set; \ \ \
a70bb42000-08-07Henrik Grubbström (Grubba)  set.a = 0; \ success[0] = 0; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \
a70bb42000-08-07Henrik Grubbström (Grubba)  eye = arg = matches = 0; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ 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]=='%') \ { \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in sscanf.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \ ); \ \ no_assign=0; \ field_length=-1; \ minus_flag=0; \ \ cnt++; \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ while(1) \ { \ switch(match[cnt]) \ { \ case '*': \ no_assign=1; \ cnt++; \ if(cnt>=match_len) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Error in sscanf format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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; \
903b772000-08-09Henrik Grubbström (Grubba)  ptrdiff_t tmp; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  for(e=cnt+1,tmp=1;tmp;e++) \ { \
2b24591999-11-04Fredrik Hübinette (Hubbe)  if(e>=match_len) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Missing %%} in format string.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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) \ { \
8c37d12000-08-15Henrik Grubbström (Grubba)  f_aggregate(TO_INT32(sp-save_sp)); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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)  { \
a5cd6a2001-09-24Henrik Grubbström (Grubba) CHAROPT2( \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  int e; \
a5cd6a2001-09-24Henrik Grubbström (Grubba) ) \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  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) \ { \ 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; \ } \
a5cd6a2001-09-24Henrik Grubbström (Grubba)  sval.u.float_number = \ (FLOAT_TYPE)STRTOD_PCHARP(MKPCHARP(input+eye, \ INPUT_SHIFT),&t2); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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) \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid IEEE width %ld in sscanf format string.\n", \
6f95902000-08-17Henrik Grubbström (Grubba)  PTRDIFF_T_TO_LONG(field_length)); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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; \
a70bb42000-08-07Henrik Grubbström (Grubba)  int contains_percent_percent; \ ptrdiff_t start, new_eye; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \
89a2162001-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) \ { \
89a2162001-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++; \
89a2162001-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': \
89a2162001-01-15Henrik Grubbström (Grubba)  Pike_error("Illegal to have two adjecent %%s.\n"); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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; \ 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; \ \
89a2162001-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; \ \
89a2162001-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++) \ { \
f1caab2000-08-13Henrik Grubbström (Grubba) CHAROPT2( \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  if(input[eye]<sizeof(set.c)) \ { \ ) \ if(set.c[input[eye]] == set.neg) \ break; \
f1caab2000-08-13Henrik 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{ \
4bade72001-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; \
8c37d12000-08-15Henrik Grubbström (Grubba)  sval.u.integer=TO_INT32(eye); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  break; \ \ default: \
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Unknown sscanf token %%%c(0x%02x)\n", \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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 */
f1caab2000-08-13Henrik 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) #define CHAROPT(X)
f1caab2000-08-13Henrik Grubbström (Grubba) #define CHAROPT2(X)
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)
6d79ff2003-01-14Johan Sundström /*! @decl int sscanf(string data, string format, mixed ... lvalues) *! *! The purpose of sscanf is to match one string against a format string and *! place the matching results into a list of variables. The list of @[lvalues] *! are destructively modified (which is only possible because sscanf really is *! an opcode, rather than a pike function) with the values extracted from the *! @[data] according to the @[format] specification. Only the variables up to *! the last matching directive of the format string are touched. *! *! Refer to the @[chapter::sscanf] chapter for the complete list of directives *! sscanf understands. *! *! @returns *! The number of directives matched in the format string. Note that a string *! directive (%s or %[]) always counts as a match, even when matching the *! empty string. *! @seealso *! @[array_sscanf()], @[chapter::sscanf] */
53842a1998-04-15Fredrik Hübinette (Hubbe) void o_sscanf(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
89ee9e2002-10-28Martin Nilsson  INT32 i=0;
53842a1998-04-15Fredrik Hübinette (Hubbe)  int x;
080b1a2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t matched_chars;
53842a1998-04-15Fredrik Hübinette (Hubbe)  struct svalue *save_sp=sp; if(sp[-args].type != T_STRING)
d4ecd72003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("sscanf", 1, "string");
53842a1998-04-15Fredrik Hübinette (Hubbe)  if(sp[1-args].type != T_STRING)
d4ecd72003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("sscanf", 2, "string");
53842a1998-04-15Fredrik Hübinette (Hubbe) 
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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Unsupported shift-combination to sscanf(): %d:%d\n",
f556f11999-10-31Henrik Grubbström (Grubba)  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)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too few arguments for sscanf format.\n");
53842a1998-04-15Fredrik Hübinette (Hubbe)  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
97ebb32003-01-09Henrik Grubbström (Grubba)  if(Pike_interpreter.trace_level >2)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { 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) 
2f3bea2001-01-31Henrik Grubbström (Grubba) /*! @decl array array_sscanf(string data, string format) *! *! This function works just like @[sscanf()], but returns the matched *! results in an array instead of assigning them to lvalues. This is often *! useful for user-defined sscanf strings. *! *! @seealso *! @[sscanf()], @[`/()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_sscanf(INT32 args)
53842a1998-04-15Fredrik Hübinette (Hubbe) {
89ee9e2002-10-28Martin Nilsson  INT32 i;
53842a1998-04-15Fredrik Hübinette (Hubbe)  int x;
080b1a2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t matched_chars;
53842a1998-04-15Fredrik Hübinette (Hubbe)  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:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Unsupported shift-combination to sscanf(): %d:%d\n",
f556f11999-10-31Henrik Grubbström (Grubba)  sp[-args].u.string->size_shift, sp[1-args].u.string->size_shift); break; }
53842a1998-04-15Fredrik Hübinette (Hubbe) 
585bb72000-08-09Henrik Grubbström (Grubba)  a = aggregate_array(DO_NOT_WARN(sp - save_sp));
53842a1998-04-15Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_array(a); }
d49add2001-04-25Fredrik Hübinette (Hubbe)  void o_breakpoint(void) { /* Does nothing */ }