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.
fd82ac2003-09-10Henrik Grubbström (Grubba) || $Id: opcodes.c,v 1.152 2003/09/10 09:42:05 grubba 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
fd82ac2003-09-10Henrik Grubbström (Grubba) RCSID("$Id: opcodes.c,v 1.152 2003/09/10 09:42:05 grubba 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) {
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) { 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;
e3f1e82003-04-28Martin Stjernholm  case T_MULTISET: { int i=multiset_member(what->u.multiset, ind);
5267b71995-08-09Fredrik Hübinette (Hubbe)  to->type=T_INT;
2843b82003-08-05Martin Stjernholm  to->subtype=i ? 0 : NUMBER_UNDEFINED;
5267b71995-08-09Fredrik Hübinette (Hubbe)  to->u.integer=i; break;
e3f1e82003-04-28Martin Stjernholm  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  case T_STRING: if(ind->type==T_INT) {
b99d882003-05-15Martin Stjernholm  ptrdiff_t len = what->u.string->len; INT_TYPE p = ind->u.integer; INT_TYPE i = p < 0 ? p + len : p; if(i<0 || i>=len)
f0e76d1999-08-22Fredrik Noring  {
b99d882003-05-15Martin Stjernholm  if(len == 0)
e3f1e82003-04-28Martin Stjernholm  Pike_error("Attempt to index the empty string with %"PRINTPIKEINT"d.\n", i);
f0e76d1999-08-22Fredrik Noring  else
e3f1e82003-04-28Martin Stjernholm  Pike_error("Index %"PRINTPIKEINT"d is out of string range "
b99d882003-05-15Martin Stjernholm  "%"PRINTPTRDIFFT"d..%"PRINTPTRDIFFT"d.\n", i, -len, 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{
e3f1e82003-04-28Martin Stjernholm  if (ind->type == T_STRING && !ind->u.string->size_shift) Pike_error ("Expected integer as string index, got \"%s\".\n", ind->u.string->str); else Pike_error ("Expected integer as string index, got %s.\n", get_name_of_type (ind->type));
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 */
136bad2003-08-13Henrik Grubbström (Grubba) #ifdef AUTO_BIGNUM case T_INT: if (ind->type == T_STRING) { INT_TYPE val = what->u.integer; convert_svalue_to_bignum(what); index_no_free(to, what, ind); if(IS_UNDEFINED(to)) { if (val) { if (!ind->u.string->size_shift) 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 a wide string.\n", val); } else { if(!ind->u.string->size_shift) Pike_error("Indexing the NULL value with \"%s\".\n", ind->u.string->str); else Pike_error("Indexing the NULL value with a wide string.\n"); } } break; } /* FALL_THROUGH */ #endif /* AUTO_BIGNUM */
5267b71995-08-09Fredrik Hübinette (Hubbe)  default:
e3f1e82003-04-28Martin Stjernholm  if (ind->type == T_INT) Pike_error ("Cannot index %s with %"PRINTPIKEINT"d.\n",
136bad2003-08-13Henrik Grubbström (Grubba)  (what->type == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(what->type), ind->u.integer);
e3f1e82003-04-28Martin Stjernholm  else if (ind->type == T_FLOAT) Pike_error ("Cannot index %s with %"PRINTPIKEFLOAT"g.\n",
136bad2003-08-13Henrik Grubbström (Grubba)  (what->type == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(what->type), ind->u.float_number);
e3f1e82003-04-28Martin Stjernholm  else if (ind->type == T_STRING && !ind->u.string->size_shift)
136bad2003-08-13Henrik Grubbström (Grubba)  Pike_error ("Cannot index %s with \"%s\".\n", (what->type == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(what->type),
e3f1e82003-04-28Martin Stjernholm  ind->u.string->str); else
136bad2003-08-13Henrik Grubbström (Grubba)  Pike_error ("Cannot index %s with %s.\n", (what->type == T_INT && !what->u.integer)? "the NULL value":get_name_of_type(what->type),
e3f1e82003-04-28Martin Stjernholm  get_name_of_type (ind->type));
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++;
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp-1);
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;
de56ec2003-02-08Martin Stjernholm  REF_MAKE_CONST_STRING(s, "int");
0232d22001-06-17Henrik Grubbström (Grubba)  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;
de56ec2003-02-08Martin Stjernholm  REF_MAKE_CONST_STRING(s, "int");
7f94c22001-06-17Henrik Grubbström (Grubba)  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;
de56ec2003-02-08Martin Stjernholm  REF_MAKE_CONST_STRING(s, "string");
7f94c22001-06-17Henrik Grubbström (Grubba)  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;
de56ec2003-02-08Martin Stjernholm  REF_MAKE_CONST_STRING(s, "string");
7f94c22001-06-17Henrik Grubbström (Grubba)  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:
de4b122003-01-26Mirar (Pontus Hagland)  sprintf(buf, "%"PRINTPIKEINT"d", sp[-1].u.integer);
7f94c22001-06-17Henrik Grubbström (Grubba)  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");
493b222003-01-15Henrik Grubbström (Grubba)  } else if (Pike_sp[-1].u.object->prog == pike_trampoline_program) { ref_push_object(((struct pike_trampoline *) (Pike_sp[-1].u.object->storage))-> frame->current_object);
0d0bab2003-04-27Martin Stjernholm  stack_pop_keep_top();
a253f42001-03-31Henrik Grubbström (Grubba)  } 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;
2523ce2003-04-28Martin Stjernholm  TYPE_FIELD types = 0;
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);
2523ce2003-04-28Martin Stjernholm  stack_pop_to_no_free (ITEM(a) + e); types |= 1 << ITEM(a)[e].type;
98f2b11998-02-19Fredrik Hübinette (Hubbe)  }
2523ce2003-04-28Martin Stjernholm  a->type_field = types;
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);
cf626e2003-08-26Henrik Grubbström (Grubba)  sub_msnode_ref (tmp);
5b15bb2001-12-10Martin Stjernholm  } #else /* PIKE_NEW_MULTISETS */ INT32 e; struct array *a;
2523ce2003-04-28Martin Stjernholm  TYPE_FIELD types = 0;
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);
2523ce2003-04-28Martin Stjernholm  stack_pop_to_no_free (ITEM(a) + e); types |= 1 << ITEM(a)[e].type;
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  }
2523ce2003-04-28Martin Stjernholm  a->type_field = types;
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) }
1bd41b2003-02-11Mirar (Pontus Hagland) /* * helper functions for sscanf %O */
56ed392003-02-13Henrik Grubbström (Grubba) /* Calling convention: * val: Integer to fill in. * str: string to parse. * len: length of the string. * * Returns: * NULL on failure. * continuation point in str on success. */ static void *pcharp_extract_char_const(INT_TYPE *val, PCHARP str, ptrdiff_t len)
1bd41b2003-02-11Mirar (Pontus Hagland) {
56ed392003-02-13Henrik Grubbström (Grubba)  int c;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  /* use of macros to keep similar to lexer.h: char_const */ #define LOOK() (len>0?EXTRACT_PCHARP(str):0) #define GETC() ((len > 0)?(INC_PCHARP(str, 1), len--, INDEX_PCHARP(str, -1)):0)
7965e12003-02-11Henrik Grubbström (Grubba) 
56ed392003-02-13Henrik Grubbström (Grubba)  switch (c=GETC()) { case 0: return NULL;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case '\n': return NULL; /* Newline in character constant. */
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case 'a': c = 7; break; /* BEL */ case 'b': c = 8; break; /* BS */ case 't': c = 9; break; /* HT */ case 'n': c = 10; break; /* LF */ case 'v': c = 11; break; /* VT */ case 'f': c = 12; break; /* FF */ case 'r': c = 13; break; /* CR */ case 'e': c = 27; break; /* ESC */
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal escape. */ c-='0'; while(LOOK()>='0' && LOOK()<='8') c=c*8+(GETC()-'0'); break;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case 'x': /* Hexadecimal escape. */ c=0; while(1) { switch(LOOK()) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c=c*16+GETC()-'0'; continue;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c=c*16+GETC()-'a'+10; continue;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c=c*16+GETC()-'A'+10; continue; } break; } break; case 'd': /* Decimal escape. */ c=0; while(1) { switch(LOOK()) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c=c*10+GETC()-'0'; continue; } break; } break;
1bd41b2003-02-11Mirar (Pontus Hagland) #undef LOOK #undef GETC
56ed392003-02-13Henrik Grubbström (Grubba)  } *val = c; return str.ptr;
1bd41b2003-02-11Mirar (Pontus Hagland) }
56ed392003-02-13Henrik Grubbström (Grubba) /* Calling convention: * res: svalue to fill in. * str: string to parse. * len: length of the string. * * Returns: * NULL on failure. * continuation point in str on success. */ static void *pcharp_to_svalue_percent_o(struct svalue *res, PCHARP str, ptrdiff_t len)
1bd41b2003-02-11Mirar (Pontus Hagland) {
56ed392003-02-13Henrik Grubbström (Grubba)  res->type = T_INT; res->subtype = NUMBER_UNDEFINED; res->u.integer = 0; for (;len>0; INC_PCHARP(str, 1), len--) { switch (EXTRACT_PCHARP(str)) { case ' ': /* whitespace */ case '\t': case '\n': case '\r': break;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* fixme: grok floats */ if (!pcharp_to_svalue_inumber(res, str, &str, 0, len)) { return NULL; } return str.ptr; }
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case '\"':
1bd41b2003-02-11Mirar (Pontus Hagland)  {
56ed392003-02-13Henrik Grubbström (Grubba)  struct string_builder tmp; PCHARP start; int cnt; init_string_builder(&tmp,0); INC_PCHARP(str, 1); /* Skip the quote. */ len--;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  start = str; cnt = 0; for (;len;) { switch(EXTRACT_PCHARP(str)) { case '\"': /* End of string -- done. */ INC_PCHARP(str, 1); /* Skip the quote. */
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  if (cnt) string_builder_append(&tmp, start, cnt); res->type=T_STRING; res->subtype=0; res->u.string=finish_string_builder(&tmp); return str.ptr; case '\\':
1bd41b2003-02-11Mirar (Pontus Hagland)  {
56ed392003-02-13Henrik Grubbström (Grubba)  /* Escaped character */ INT_TYPE val; if (cnt) string_builder_append(&tmp, start, cnt); INC_PCHARP(str, 1); len--; start.ptr = pcharp_extract_char_const(&val, str, len); if (!start.ptr) break; string_builder_putchar(&tmp, val); /* Continue parsing after the escaped character. */ len -= LOW_SUBTRACT_PCHARP(start, str); cnt = 0; str = start;
1bd41b2003-02-11Mirar (Pontus Hagland)  }
56ed392003-02-13Henrik Grubbström (Grubba)  continue;
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  case '\n': /* Newline in string -- fail. */ break; default: len--; cnt++; INC_PCHARP(str, 1); continue; } break; } /* Unterminated string -- fail. */ free_string_builder(&tmp); return NULL; /* end of data */ } case '\'': if (len>2) { INC_PCHARP(str, 1); /* Skip the quote. */ res->subtype=0; res->type=T_INT; res->u.integer = EXTRACT_PCHARP(str); INC_PCHARP(str, 1);
1bd41b2003-02-11Mirar (Pontus Hagland) 
56ed392003-02-13Henrik Grubbström (Grubba)  len -= 2; if (res->u.integer == '\\') { PCHARP tmp; tmp.ptr = pcharp_extract_char_const(&res->u.integer, str, len); if (!tmp.ptr) return NULL; tmp.shift = str.shift; len -= LOW_SUBTRACT_PCHARP(tmp, str); str.ptr = tmp.ptr; } if (!len || (EXTRACT_PCHARP(str) != '\'')) return NULL; INC_PCHARP(str, 1); /* Skip the ending quote. */ return str.ptr;
1bd41b2003-02-11Mirar (Pontus Hagland)  }
56ed392003-02-13Henrik Grubbström (Grubba)  return NULL; /* fixme: arrays, multisets, mappings */ } } return NULL;
1bd41b2003-02-11Mirar (Pontus Hagland) }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* flags: * operators: %d %s %f %c %n %[ %%
1bd41b2003-02-11Mirar (Pontus Hagland)  %O
5267b71995-08-09Fredrik Hübinette (Hubbe) */
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)  { \
fa76612003-02-19Marcus Comstedt  if(order[e]+1 != order[e+1] && \
5ec12c2003-02-19Marcus Comstedt  order[e+1]+1 != order[e]) { \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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 */
247e122003-03-06Henrik Grubbström (Grubba) /* INT32 very_low_sscanf_{0,1,2}_{0,1,2}(p_wchar *input, ptrdiff_t input_len, * p_wchar *match, ptrdiff_t match_len, * ptrdiff_t *chars_matched, * int *success) * * Perform the actual parsing. * * Arguments: * input, input_len Input data to parse. * match, match_len Format string. * chars_matched Gets set to the number of characters * in the input that were advanced. * success Gets set to 1 on success. * * Returns: * Returns the number of %-directives that were successfully matched. * Pushes non-ignored matches on the Pike stack in the order they * were matched. * * FIXME: chars_matched and success are only used internally, and * should probably be gotten rid of. */
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; \
fd82ac2003-09-10Henrik Grubbström (Grubba)  int no_assign = 0, minus_flag = 0, plus_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; \
fd82ac2003-09-10Henrik Grubbström (Grubba)  plus_flag=0; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  \ 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) \
fd46e42003-02-10Henrik Grubbström (Grubba)  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; \ \
fd82ac2003-09-10Henrik Grubbström (Grubba)  case '+': \ plus_flag=1; \ cnt++; \ continue; \ \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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)  { \
fd46e42003-02-10Henrik Grubbström (Grubba)  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; \
fd82ac2003-09-10Henrik Grubbström (Grubba)  if (field_length >= 0) { \ pos = (eye += field_length); \ } \ if (plus_flag && (--field_length >= 0)) { \ sval.u.integer = (signed char)input[--pos]; \ } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  while(--field_length >= 0) \ { \ DO_IF_BIGNUM( \
fd82ac2003-09-10Henrik Grubbström (Grubba)  if(INT_TYPE_LSH_OVERFLOW(sval.u.integer, 8)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \ push_int(sval.u.integer); \ convert_stack_top_to_bignum(); \ \ while(field_length-- >= 0) \ { \
fd82ac2003-09-10Henrik Grubbström (Grubba)  push_int(8); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  o_lsh(); \
fd82ac2003-09-10Henrik Grubbström (Grubba)  push_int(input[--pos]); \
22d95e1999-11-04Fredrik Hübinette (Hubbe)  o_or(); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp-1); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  sval=*--sp; \ break; \ } \
fd82ac2003-09-10Henrik Grubbström (Grubba)  ); \ sval.u.integer<<=8; \ sval.u.integer |= input[--pos]; \ } \ } else { \ if (plus_flag && (--field_length >= 0)) { \ sval.u.integer = (signed char)input[eye++]; \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \ 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++; \ } \
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp-1); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  sval=*--sp; \ break; \ } \ ); \ sval.u.integer<<=8; \ sval.u.integer |= input[eye]; \ eye++; \ } \
fd82ac2003-09-10Henrik Grubbström (Grubba)  } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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; \ } \ \
fe5d952003-07-30Martin Stjernholm  wide_string_to_svalue_inumber(&sval, input+eye, &t, \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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); \ \
fd46e42003-02-10Henrik Grubbström (Grubba)  match_set: \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
fd46e42003-02-10Henrik Grubbström (Grubba)  int len = input_len; \ if (field_length != -1) { \ len = eye + field_length; \ if (len > input_len) { \ /* Mismatch -- too little data */ \ chars_matched[0]=eye; \ return matches; \ } \ } \ for(e=eye;eye<len;eye++) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
f1caab2000-08-13Henrik Grubbström (Grubba) CHAROPT2( \
fd46e42003-02-10Henrik Grubbström (Grubba)  if(input[eye]<sizeof(set.c)) \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  { \
fd46e42003-02-10Henrik Grubbström (Grubba) ) \ if(set.c[input[eye]] == set.neg) \ break; \ CHAROPT2( \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  }else{ \
fd46e42003-02-10Henrik Grubbström (Grubba)  if(set.a) \ { \ INT32 x; \ struct svalue tmp; \ tmp.type=T_INT; \ tmp.u.integer=input[eye]; \ x=switch_lookup(set.a, &tmp); \ if( set.neg != (x<0 && (x&1)) ) break; \ }else{ \ if(!set.neg) break; \ } \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  } \ ) \
fd46e42003-02-10Henrik Grubbström (Grubba)  } \ if ((field_length != -1) && (eye != len)) { \ /* Couldn't read the entire field. Fail. */ \ chars_matched[0]=e; \ return matches; \ } \
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; \ \
7965e12003-02-11Henrik Grubbström (Grubba)  case 'O': \ { \
56ed392003-02-13Henrik Grubbström (Grubba)  PIKE_CONCAT(p_wchar, INPUT_SHIFT) *cont; \ if(eye>=input_len) \ { \ chars_matched[0]=eye; \ return matches; \ } \ if ((field_length == -1) || \ ((input_len - eye) < field_length)) \ field_length = input_len - eye; \
7965e12003-02-11Henrik Grubbström (Grubba)  \
56ed392003-02-13Henrik Grubbström (Grubba)  cont = \ pcharp_to_svalue_percent_o(&sval, \ MKPCHARP(input+eye, INPUT_SHIFT), \ field_length); \ if(!cont) \ { \ chars_matched[0]=eye; \ return matches; \ } \ eye = cont-input; \
7965e12003-02-11Henrik Grubbström (Grubba)  \
56ed392003-02-13Henrik Grubbström (Grubba)  break; \
7965e12003-02-11Henrik Grubbström (Grubba)  } \ \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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: \
fd46e42003-02-10Henrik Grubbström (Grubba)  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; \
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp-1); \
e7a1721999-11-04Fredrik Hübinette (Hubbe)  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)
247e122003-03-06Henrik Grubbström (Grubba) /* Simplified interface to very_low_sscanf_{0,1,2}_{0,1,2}(). */ static INT32 low_sscanf(struct pike_string *data, struct pike_string *format)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
080b1a2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t matched_chars;
247e122003-03-06Henrik Grubbström (Grubba)  int x; INT32 i;
136bad2003-08-13Henrik Grubbström (Grubba)  check_c_stack(sizeof(struct sscanf_set)*2 + 512);
247e122003-03-06Henrik Grubbström (Grubba)  switch(data->size_shift*3 + format->size_shift) {
f556f11999-10-31Henrik Grubbström (Grubba)  /* input_shift : match_shift */ case 0: /* 0 : 0 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_0_0(STR0(data), data->len, STR0(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 1: /* 0 : 1 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_0_1(STR0(data), data->len, STR1(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 2: /* 0 : 2 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_0_2(STR0(data), data->len, STR2(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 3: /* 1 : 0 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_1_0(STR1(data), data->len, STR0(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 4: /* 1 : 1 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_1_1(STR1(data), data->len, STR1(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 5: /* 1 : 2 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_1_2(STR1(data), data->len, STR2(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 6: /* 2 : 0 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_2_0(STR2(data), data->len, STR0(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 7: /* 2 : 1 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_2_1(STR2(data), data->len, STR1(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; case 8: /* 2 : 2 */
247e122003-03-06Henrik Grubbström (Grubba)  i = very_low_sscanf_2_2(STR2(data), data->len, STR2(format), format->len, &matched_chars, &x);
f556f11999-10-31Henrik Grubbström (Grubba)  break; default:
247e122003-03-06Henrik Grubbström (Grubba)  Pike_fatal("Unsupported shift-combination to low_sscanf(): %d:%d\n", data->size_shift, format->size_shift);
f556f11999-10-31Henrik Grubbström (Grubba)  break; }
247e122003-03-06Henrik Grubbström (Grubba)  return i; } /*! @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] */ void o_sscanf(INT32 args) { INT32 i=0; int x; struct svalue *save_sp=sp; if(sp[-args].type != T_STRING) SIMPLE_BAD_ARG_ERROR("sscanf", 1, "string"); if(sp[1-args].type != T_STRING) SIMPLE_BAD_ARG_ERROR("sscanf", 2, "string"); i = low_sscanf(sp[-args].u.string, sp[1-args].u.string);
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)  struct svalue *save_sp=sp; struct array *a; check_all_args("array_sscanf",args,BIT_STRING, BIT_STRING,0);
247e122003-03-06Henrik Grubbström (Grubba)  i = low_sscanf(sp[-args].u.string, sp[1-args].u.string);
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 */ }