c6c01a | 2003-11-14 | Martin Stjernholm | |
#include "global.h"
#include "interpret.h"
#include "array.h"
|
38392e | 2015-09-06 | Per Hedbor | | #include "mapping.h"
#include "multiset.h"
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #include "stralloc.h"
#include "pike_error.h"
#include "fd_control.h"
#include "builtin_functions.h"
#include "module_support.h"
#include "operators.h"
|
0ba1be | 2004-03-06 | Martin Nilsson | | #include "bignum.h"
|
f36a62 | 2017-02-09 | Henrik Grubbström (Grubba) | | #include "pike_compiler.h"
|
b0ca93 | 2004-06-01 | Martin Nilsson | | #include "pike_float.h"
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | #include "pike_types.h"
|
37e413 | 2008-05-17 | Marcus Comstedt | | #include "sscanf.h"
|
a2133d | 2014-04-17 | Arne Goedeke | | #include "bitvector.h"
|
e0ac35 | 2018-01-18 | Martin Nilsson | | #include "pike_search.h"
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
e4e5a3 | 2004-09-18 | Martin Nilsson | | |
c6c01a | 2003-11-14 | Martin Stjernholm | | * helper functions for sscanf %O
*/
|
38392e | 2015-09-06 | Per Hedbor | | * res: svalue to fill in.
|
c6c01a | 2003-11-14 | Martin Stjernholm | | * str: string to parse.
* len: length of the string.
*
* Returns:
* NULL on failure.
* continuation point in str on success.
*/
|
38392e | 2015-09-06 | Per Hedbor | |
#define CONSUME(X) do{if(*len>=X){INC_PCHARP(*str,X);*len-=X;}}while(0)
static p_wchar2 next_char( PCHARP *str, ptrdiff_t *len )
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | p_wchar2 res = *len ? EXTRACT_PCHARP(*str) : 0;
CONSUME(1);
return res;
}
#define READ() next_char(str,len)
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS
#define NOINLINE_UNALIGNED
#else
#define NOINLINE_UNALIGNED ATTRIBUTE((noinline)) DECLSPEC((noinline))
#endif
|
9e10fe | 2020-06-06 | Marcus Comstedt | | #if SIZEOF_FLOAT_TYPE > SIZEOF_DOUBLE
#define STRTOFLOAT_PCHARP STRTOLD_PCHARP
#else
#define STRTOFLOAT_PCHARP STRTOD_PCHARP
#endif
|
38392e | 2015-09-06 | Per Hedbor | | static void skip_comment( PCHARP *str, ptrdiff_t *len )
{
CONSUME(1);
switch(READ())
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | case '*':
while(*len)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | while( READ() != '*' )
;
if( READ() == '/' )
return;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
break;
|
38392e | 2015-09-06 | Per Hedbor | | case '/':
while( *len && READ()!= '\n' )
;
}
}
static void skip_to_token( PCHARP *str, ptrdiff_t *len )
{
int worked;
do
{
worked=0;
|
aa7dd0 | 2016-12-17 | Martin Nilsson | | while(*len && wide_isspace(EXTRACT_PCHARP(*str)))
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
aa7dd0 | 2016-12-17 | Martin Nilsson | | worked = 1;
CONSUME(1);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
|
38392e | 2015-09-06 | Per Hedbor | | if( EXTRACT_PCHARP(*str) == '/' )
{
skip_comment(str,len);
worked=1;
}
}while(worked);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
|
38392e | 2015-09-06 | Per Hedbor | |
static int pcharp_to_svalue_rec(PCHARP *str,
ptrdiff_t *len)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | extern int parse_esc_seq_pcharp (PCHARP buf, p_wchar2 *chr, ptrdiff_t *len);
struct svalue *begin = Pike_sp;
PCHARP start = *str;
check_stack(100);
|
358e94 | 2015-09-07 | Tobias S. Josefowitz | | check_c_stack(1000);
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | while(1)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | skip_to_token(str,len);
switch( READ() )
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | default: goto fail;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | int base = 10;
CONSUME(-1);
goto read_number;
case '0':
switch( EXTRACT_PCHARP(*str) )
{
case 'x':case 'X': base = 16; CONSUME(1); break;
case 'b':case 'B': base = 2; CONSUME(1); break;
case '.':
CONSUME(-1);
goto read_float;
case 'e':case 'E':
CONSUME(-1);
push_float(0.0);
return 1;
default:
base = 8;
CONSUME(-1);
break;
}
read_number:
push_int(0);
if( pcharp_to_svalue_inumber(Pike_sp-1,*str,str,base,*len) )
{
if( (EXTRACT_PCHARP(*str) == '.' || EXTRACT_PCHARP(*str)=='e'|| EXTRACT_PCHARP(*str)=='E') )
{
read_float:
{
void *integer_parse = str->ptr;
|
9e10fe | 2020-06-06 | Marcus Comstedt | | FLOAT_TYPE res;
res = STRTOFLOAT_PCHARP(start,str);
|
38392e | 2015-09-06 | Per Hedbor | | if( integer_parse < str->ptr )
{
pop_stack();
push_float(res);
}
}
*len -= SUBTRACT_PCHARP(*str,start);
if( *len < 0 )
goto fail;
}
return 1;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
}
|
38392e | 2015-09-06 | Per Hedbor | | goto fail;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | case '\'':
{
unsigned int l = 0;
struct svalue res = svalue_int_zero;
ptrdiff_t used;
MP_INT bigint;
while(1)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | p_wchar2 tmp;
switch( (tmp=READ()) )
{
case 0:
goto fail;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | case '\\':
if( parse_esc_seq_pcharp(*str,&tmp,&used) )
return 0;
CONSUME(used);
default:
l++;
if( l == sizeof(INT_TYPE)-1 )
{
mpz_init(&bigint);
mpz_set_ui(&bigint,res.u.integer);
TYPEOF(res) = PIKE_T_OBJECT;
}
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | if( l >= sizeof(INT_TYPE)-1 )
{
mpz_mul_2exp(&bigint,&bigint,8);
mpz_add_ui(&bigint,&bigint,tmp);
}
else
{
res.u.integer <<= 8;
res.u.integer |= tmp;
}
break;
case '\'':
if( TYPEOF(res) == PIKE_T_OBJECT )
{
push_bignum( &bigint );
mpz_clear(&bigint);
reduce_stack_top_bignum();
return 1;
}
*Pike_sp++ = res;
return 1;
}
}
}
case '"':
{
struct string_builder tmp;
PCHARP start;
int cnt;
init_string_builder(&tmp,0);
start = *str;
cnt = 0;
for (;*len;)
{
switch(READ())
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
case '\"':
if (cnt) string_builder_append(&tmp, start, cnt);
|
38392e | 2015-09-06 | Per Hedbor | | push_string(finish_string_builder(&tmp));
return 1;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
case '\\':
|
38392e | 2015-09-06 | Per Hedbor | | {
p_wchar2 val=0;
ptrdiff_t consumed;
if( !parse_esc_seq_pcharp(*str,&val,&consumed) )
CONSUME(consumed);
if (cnt) string_builder_append(&tmp, start, cnt);
string_builder_putchar(&tmp, val);
*str=start;
}
continue;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
case '\n':
|
38392e | 2015-09-06 | Per Hedbor | | free_string_builder(&tmp);
goto fail;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
default:
cnt++;
continue;
}
}
|
38392e | 2015-09-06 | Per Hedbor | |
free_string_builder(&tmp);
goto fail;
}
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | case '(':
{
int num=0;
p_wchar2 tmp;
#define CHECK_STACK_ADD(ADD) do{ \
if(Pike_sp-begin > 100 ) { \
ADD(Pike_sp-begin); \
begin= Pike_sp; \
num++; \
} \
}while(0)
#define FINISH(ADD) do { \
num++; \
ADD(Pike_sp-begin); \
goto container_finished; \
} while(0)
switch( READ() )
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
|
38392e | 2015-09-06 | Per Hedbor | | case '[':
while(1)
{
skip_to_token(str,len);
if(EXTRACT_PCHARP(*str) == ']' )
{
CONSUME(1);
FINISH(f_aggregate_mapping);
}
if( !pcharp_to_svalue_rec(str,len) )
goto fail;
skip_to_token(str,len);
if( READ() != ':' )
goto fail;
if(!pcharp_to_svalue_rec(str,len))
goto fail;
skip_to_token(str,len);
tmp = READ();
if( tmp == ']' )
FINISH(f_aggregate_mapping);
if( tmp != ',' )
goto fail;
CHECK_STACK_ADD(f_aggregate_mapping);
}
break;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | case '{':
while(1)
{
skip_to_token(str,len);
if(EXTRACT_PCHARP(*str)=='}' )
{
CONSUME(1);
FINISH(f_aggregate);
}
if( !pcharp_to_svalue_rec(str,len) )
goto fail;
skip_to_token(str,len);
tmp=READ();
if(tmp == '}' )
FINISH(f_aggregate);
if( tmp != ',' )
goto fail;
CHECK_STACK_ADD(f_aggregate);
}
break;
case '<':
while(1)
{
skip_to_token(str,len);
if(EXTRACT_PCHARP(*str)=='>' )
{
CONSUME(1);
FINISH(f_aggregate_multiset);
}
|
f31675 | 2016-12-17 | Martin Nilsson | | if( !pcharp_to_svalue_rec(str,len) )
goto fail;
|
38392e | 2015-09-06 | Per Hedbor | | skip_to_token(str,len);
tmp=READ();
if(tmp == '>' )
FINISH(f_aggregate_multiset);
if( tmp != ',' )
goto fail;
CHECK_STACK_ADD(f_aggregate_multiset);
}
break;
default:
goto fail;
}
#undef FINISH
#undef CHECK_STACK_ADD
container_finished:
if( READ() != ')' )
goto fail;
if(num > 1 )
f_add(num);
return 1;
}
}
}
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
38392e | 2015-09-06 | Per Hedbor | | fail:
pop_n_elems(Pike_sp-begin);
return 0;
}
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
13670c | 2015-05-25 | Martin Nilsson | |
|
38392e | 2015-09-06 | Per Hedbor | | static void *pcharp_to_svalue_percent_o(struct svalue *res,
PCHARP str,
ptrdiff_t len)
{
SET_SVAL(*res, T_INT, NUMBER_UNDEFINED, integer, 0);
if( pcharp_to_svalue_rec( &str, &len ) )
{
*res = *--Pike_sp;
return str.ptr;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
return NULL;
}
|
eb081d | 2007-04-28 | Per Hedbor | | %H
|
c6c01a | 2003-11-14 | Martin Stjernholm | | %s
%f
%c
%n
%[
%%
%O
*/
struct sscanf_set
{
int neg;
char c[256];
struct array *a;
};
#define MKREADSET(SIZE) \
static ptrdiff_t PIKE_CONCAT(read_set,SIZE) ( \
PIKE_CONCAT(p_wchar,SIZE) *match, \
ptrdiff_t cnt, \
struct sscanf_set *set, \
|
558e91 | 2014-10-05 | Martin Nilsson | | ptrdiff_t match_len) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
|
917681 | 2008-07-01 | Marcus Comstedt | | p_wchar2 e, last = 0; \
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( int set_size=0; ) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Unterminated sscanf set.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set->c, 0, sizeof(set->c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | set->a=0; \
\
|
dc8c3e | 2008-05-14 | Marcus Comstedt | | if(match[cnt]=='^' && \
(cnt+2>=match_len || match[cnt+1]!='-' || \
|
c9562b | 2014-10-05 | Martin Nilsson | | match[cnt+2]==']')) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
set->neg=1; \
cnt++; \
if(cnt>=match_len) \
|
19961b | 2017-04-08 | Martin Nilsson | | Pike_error("Unterminated negated sscanf set.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }else{ \
set->neg=0; \
} \
\
if(match[cnt]==']' || match[cnt]=='-') \
{ \
set->c[last=match[cnt]]=1; \
cnt++; \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Empty sscanf range.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
\
|
0b5539 | 2008-05-15 | Marcus Comstedt | | for(;match[cnt]!=']';) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
if(match[cnt]=='-') \
{ \
cnt++; \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Unterminated sscanf range.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
if(match[cnt]==']') \
{ \
set->c['-']=1; \
break; \
} \
\
|
dc8c3e | 2008-05-14 | Marcus Comstedt | | if(last > match[cnt]) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Inverted sscanf range [%c-%c].\n", \
last, match[cnt]); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( \
|
917681 | 2008-07-01 | Marcus Comstedt | | if(last < (p_wchar2)sizeof(set->c) && last >= 0) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
|
917681 | 2008-07-01 | Marcus Comstedt | | if(match[cnt] < (p_wchar2)sizeof(set->c)) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
) \
for(e=last;e<=match[cnt];e++) set->c[e]=1; \
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }else{ \
|
917681 | 2008-07-01 | Marcus Comstedt | | for(e=last;e<(p_wchar2)sizeof(set->c);e++) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | set->c[e]=1; \
\
check_stack(2); \
push_int(256); \
push_int(match[cnt]); \
set_size++; \
} \
} \
else \
{ \
|
19961b | 2017-04-08 | Martin Nilsson | | Pike_sp[-1].u.integer=match[cnt]; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
) \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | } else { \
last=match[cnt]; \
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( \
|
917681 | 2008-07-01 | Marcus Comstedt | | if(last < (p_wchar2)sizeof(set->c) && last >= 0) \
) \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | set->c[last]=1; \
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | else{ \
if(set_size && \
|
19961b | 2017-04-08 | Martin Nilsson | | ((p_wchar2)Pike_sp[-1].u.integer) == last-1) \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | { \
|
19961b | 2017-04-08 | Martin Nilsson | | Pike_sp[-1].u.integer++; \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | }else{ \
check_stack(2); \
|
917681 | 2008-07-01 | Marcus Comstedt | | push_int(last); \
push_int(last); \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | set_size++; \
} \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | ) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
|
0b5539 | 2008-05-15 | Marcus Comstedt | | cnt++; \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Unterminated sscanf set.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
\
|
d68959 | 2008-07-09 | Martin Stjernholm | | MATCH_IS_WIDE( \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(set_size) \
{ \
INT32 *order; \
set->a=aggregate_array(set_size*2); \
order=get_switch_order(set->a); \
|
917681 | 2008-07-01 | Marcus Comstedt | | for(e=0;e<(p_wchar2)set->a->size;e+=2) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
if(order[e]+1 != order[e+1] && \
order[e+1]+1 != order[e]) { \
free_array(set->a); \
set->a=0; \
|
0ec752 | 2014-04-27 | Martin Nilsson | | free(order); \
|
d68959 | 2008-07-09 | Martin Stjernholm | | Pike_error("Overlapping ranges in sscanf not supported.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
} \
\
order_array(set->a,order); \
|
0ec752 | 2014-04-27 | Martin Nilsson | | free(order); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
) \
return cnt; \
}
#ifdef NEED_CUSTOM_IEEE
|
d30673 | 2017-07-16 | Martin Nilsson | | static inline FLOAT_TYPE low_parse_IEEE_float(const char *b, int sz)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
unsigned INT32 f, extra_f;
int s, e;
unsigned char x[4];
double r;
|
86d824 | 2017-07-17 | Marcus Comstedt | | if (sz < 0) {
x[0] = EXTRACT_UCHAR(b-sz-1);
x[1] = EXTRACT_UCHAR(b-sz-2);
x[2] = EXTRACT_UCHAR(b-sz-3);
x[3] = EXTRACT_UCHAR(b-sz-4);
} else {
x[0] = EXTRACT_UCHAR(b);
x[1] = EXTRACT_UCHAR(b+1);
x[2] = EXTRACT_UCHAR(b+2);
x[3] = EXTRACT_UCHAR(b+3);
}
|
c6c01a | 2003-11-14 | Martin Stjernholm | | s = ((x[0]&0x80)? 1 : 0);
|
86d824 | 2017-07-17 | Marcus Comstedt | | if(sz==4 || sz==-4) {
|
c6c01a | 2003-11-14 | Martin Stjernholm | | 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];
|
86d824 | 2017-07-17 | Marcus Comstedt | | if (sz < 0)
extra_f = (((unsigned INT32)EXTRACT_UCHAR(b+3))<<24)|
(((unsigned INT32)EXTRACT_UCHAR(b+2))<<16)|
(((unsigned INT32)EXTRACT_UCHAR(b+1))<<8)|
((unsigned INT32)EXTRACT_UCHAR(b));
else
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));
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(e==2047)
e = 9999;
else if(e>0) {
f |= 0x00100000;
e -= 1023+20;
} else
e -= 1022+20;
}
|
d30673 | 2017-07-16 | Martin Nilsson | |
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(e>=9999)
|
d30673 | 2017-07-16 | Martin Nilsson | | {
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(f||extra_f) {
return (FLOAT_TYPE)MAKE_NAN();
} else {
|
d30673 | 2017-07-16 | Martin Nilsson | | return (FLOAT_TYPE)MAKE_INF() * (s? -1:1);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
|
d30673 | 2017-07-16 | Martin Nilsson | | }
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
r = (double)f;
if(extra_f)
r += ((double)extra_f)/4294967296.0;
|
159a2b | 2014-09-03 | Martin Nilsson | | return (FLOAT_TYPE)(s? -ldexp(r, e):ldexp(r, e));
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
#endif
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | static FLOAT_TYPE NOINLINE_UNALIGNED extract_float_be(const char * x) {
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #ifdef FLOAT_IS_IEEE_BIG
|
86d824 | 2017-07-17 | Marcus Comstedt | | float f;
|
a2133d | 2014-04-17 | Arne Goedeke | | memcpy(&f, x, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
a2133d | 2014-04-17 | Arne Goedeke | | #elif FLOAT_IS_IEEE_LITTLE
|
86d824 | 2017-07-17 | Marcus Comstedt | | float f;
|
a2133d | 2014-04-17 | Arne Goedeke | | unsigned INT32 tmp = get_unaligned32(x);
tmp = bswap32(tmp);
memcpy(&f, &tmp, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #else
|
86d824 | 2017-07-17 | Marcus Comstedt | | return low_parse_IEEE_float(x, 4);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #endif
|
a2133d | 2014-04-17 | Arne Goedeke | | }
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | static FLOAT_TYPE NOINLINE_UNALIGNED extract_double_be(const char * x) {
|
d99380 | 2017-07-17 | Martin Nilsson | | #ifdef DOUBLE_IS_IEEE_BIG
|
86d824 | 2017-07-17 | Marcus Comstedt | | double f;
|
a2133d | 2014-04-17 | Arne Goedeke | | memcpy(&f, x, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
d99380 | 2017-07-17 | Martin Nilsson | | #elif DOUBLE_IS_IEEE_LITTLE
|
86d824 | 2017-07-17 | Marcus Comstedt | | double f;
#ifdef UINT64
|
30f5b2 | 2016-04-09 | Martin Nilsson | | UINT64 tmp = get_unaligned64(x);
|
a2133d | 2014-04-17 | Arne Goedeke | | tmp = bswap64(tmp);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #else
|
86d824 | 2017-07-17 | Marcus Comstedt | | char tmp[8];
tmp[7] = x[0];
tmp[6] = x[1];
tmp[5] = x[2];
tmp[4] = x[3];
tmp[3] = x[4];
tmp[2] = x[5];
tmp[1] = x[6];
tmp[0] = x[7];
|
a2133d | 2014-04-17 | Arne Goedeke | | #endif
|
86d824 | 2017-07-17 | Marcus Comstedt | | memcpy(&f, &tmp, sizeof(f));
|
a2133d | 2014-04-17 | Arne Goedeke | | return f;
|
86d824 | 2017-07-17 | Marcus Comstedt | | #else
return low_parse_IEEE_float(x, 8);
#endif
|
a2133d | 2014-04-17 | Arne Goedeke | | }
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | static FLOAT_TYPE NOINLINE_UNALIGNED extract_float_le(const char * x) {
|
a2133d | 2014-04-17 | Arne Goedeke | | #ifdef FLOAT_IS_IEEE_LITTLE
|
86d824 | 2017-07-17 | Marcus Comstedt | | float f;
|
a2133d | 2014-04-17 | Arne Goedeke | | memcpy(&f, x, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
a2133d | 2014-04-17 | Arne Goedeke | | #elif FLOAT_IS_IEEE_BIG
|
86d824 | 2017-07-17 | Marcus Comstedt | | float f;
|
a2133d | 2014-04-17 | Arne Goedeke | | unsigned INT32 tmp = get_unaligned32(x);
tmp = bswap32(tmp);
memcpy(&f, &tmp, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #else
|
86d824 | 2017-07-17 | Marcus Comstedt | | return low_parse_IEEE_float(x, -4);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #endif
|
a2133d | 2014-04-17 | Arne Goedeke | | }
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | static FLOAT_TYPE NOINLINE_UNALIGNED extract_double_le(const char * x) {
|
d99380 | 2017-07-17 | Martin Nilsson | | #ifdef DOUBLE_IS_IEEE_LITTLE
|
86d824 | 2017-07-17 | Marcus Comstedt | | double f;
|
a2133d | 2014-04-17 | Arne Goedeke | | memcpy(&f, x, sizeof(f));
|
86d824 | 2017-07-17 | Marcus Comstedt | | return f;
|
d99380 | 2017-07-17 | Martin Nilsson | | #elif DOUBLE_IS_IEEE_BIG
|
86d824 | 2017-07-17 | Marcus Comstedt | | double f;
#ifdef UINT64
|
30f5b2 | 2016-04-09 | Martin Nilsson | | UINT64 tmp = get_unaligned64(x);
|
a2133d | 2014-04-17 | Arne Goedeke | | tmp = bswap64(tmp);
#else
|
86d824 | 2017-07-17 | Marcus Comstedt | | char tmp[8];
tmp[7] = x[0];
tmp[6] = x[1];
tmp[5] = x[2];
tmp[4] = x[3];
tmp[3] = x[4];
tmp[2] = x[5];
tmp[1] = x[6];
tmp[0] = x[7];
|
c6c01a | 2003-11-14 | Martin Stjernholm | | #endif
|
86d824 | 2017-07-17 | Marcus Comstedt | | memcpy(&f, &tmp, sizeof(f));
|
a2133d | 2014-04-17 | Arne Goedeke | | return f;
|
86d824 | 2017-07-17 | Marcus Comstedt | | #else
return low_parse_IEEE_float(x, -8);
#endif
|
a2133d | 2014-04-17 | Arne Goedeke | | }
#define EXTRACT_FLOAT(SVAL, input, shift, fun) do { \
char x[4]; \
if (shift == 0) { \
memcpy(x, input, sizeof(x)); \
} else { \
PCHARP tmp = MKPCHARP(input, shift); \
size_t i; \
for (i = 0; i < sizeof(x); INC_PCHARP(tmp, 1), i++) \
x[i] = EXTRACT_PCHARP(tmp); \
} \
(SVAL).u.float_number = fun(x); \
} while (0)
#define EXTRACT_DOUBLE(SVAL, input, shift, fun) do { \
char x[8]; \
if (shift == 0) { \
memcpy(x, input, sizeof(x)); \
} else { \
PCHARP tmp = MKPCHARP(input, shift); \
size_t i; \
for (i = 0; i < sizeof(x); INC_PCHARP(tmp, 1), i++) \
x[i] = EXTRACT_PCHARP(tmp); \
} \
(SVAL).u.float_number = fun(x); \
} while (0)
|
d0233c | 2018-07-05 | Henrik Grubbström (Grubba) | | static struct pike_string * NOINLINE_UNALIGNED
get_string_slice( void *input, int shift,
ptrdiff_t offset, ptrdiff_t len,
struct pike_string *str )
|
11ff45 | 2015-08-24 | Per Hedbor | | {
|
db40b0 | 2015-09-01 | Per Hedbor | | if( !shift && str )
|
11ff45 | 2015-08-24 | Per Hedbor | | return string_slice( str, offset, len );
|
db40b0 | 2015-09-01 | Per Hedbor | | return make_shared_binary_pcharp(MKPCHARP(((char *)input)+(offset<<shift),shift),
len);
|
11ff45 | 2015-08-24 | Per Hedbor | | }
|
c6c01a | 2003-11-14 | Martin Stjernholm | | |
9a2ff0 | 2014-08-28 | Per Hedbor | | * FIXME: success is only used internally, and should probably be
* gotten rid of.
|
c6c01a | 2003-11-14 | Martin Stjernholm | | */
#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, \
ptrdiff_t input_len, \
PIKE_CONCAT(p_wchar, MATCH_SHIFT) *match, \
ptrdiff_t match_len, \
ptrdiff_t *chars_matched, \
|
11ff45 | 2015-08-24 | Per Hedbor | | int *success, \
struct pike_string *pstr) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
struct svalue sval; \
INT32 matches, arg; \
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | ptrdiff_t cnt, eye, start_eye, e, field_length = 0, truncated = 0; \
int no_assign = 0, minus_flag = 0, plus_flag = 0, truncate = 0; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | struct sscanf_set set; \
\
\
set.a = 0; \
success[0] = 0; \
\
eye = arg = matches = 0; \
\
for(cnt = 0; cnt < match_len; cnt++) \
{ \
for(;cnt<match_len;cnt++) \
{ \
if(match[cnt]=='%') \
{ \
if(match[cnt+1]=='%') \
{ \
cnt++; \
}else{ \
break; \
} \
} \
if(eye>=input_len || input[eye]!=match[cnt]) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
eye++; \
} \
if(cnt>=match_len) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
\
DO_IF_DEBUG( \
if(match[cnt]!='%' || match[cnt+1]=='%') \
{ \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_fatal("Failed to escape in sscanf.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
); \
\
no_assign=0; \
field_length=-1; \
minus_flag=0; \
plus_flag=0; \
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | truncate=0; \
start_eye = eye; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
cnt++; \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Missing format specifier in sscanf format string.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
while(1) \
{ \
switch(match[cnt]) \
{ \
case '*': \
no_assign=1; \
cnt++; \
if(cnt>=match_len) \
|
b8b8af | 2014-08-27 | Henrik Grubbström (Grubba) | | Pike_error("Missing format specifier in ignored sscanf " \
"format string.\n"); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | 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 '+': \
plus_flag=1; \
cnt++; \
continue; \
\
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | case '!': \
truncate=1; \
cnt++; \
continue; \
\
|
c6c01a | 2003-11-14 | Martin Stjernholm | | case '{': \
{ \
ONERROR err; \
ptrdiff_t tmp; \
for(e=cnt+1,tmp=1;tmp;e++) \
{ \
if(e>=match_len) \
{ \
Pike_error("Missing %%} in format string.\n"); \
|
9282fd | 2015-09-27 | Martin Nilsson | | UNREACHABLE(break); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
if(match[e]=='%') \
{ \
switch(match[e+1]) \
{ \
case '%': e++; break; \
case '}': tmp--; break; \
case '{': tmp++; break; \
} \
} \
} \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(sval, T_ARRAY, 0, array, allocate_array(0)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | SET_ONERROR(err, do_free_array, sval.u.array); \
\
while(input_len-eye) \
|
19961b | 2017-04-08 | Martin Nilsson | | { \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | int yes; \
|
19961b | 2017-04-08 | Martin Nilsson | | struct svalue *save_sp=Pike_sp; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | PIKE_CONCAT4(very_low_sscanf_, INPUT_SHIFT, _, MATCH_SHIFT)( \
input+eye, \
input_len-eye, \
match+cnt+1, \
e-cnt-2, \
&tmp, \
|
11ff45 | 2015-08-24 | Per Hedbor | | &yes,0); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(yes && tmp) \
{ \
|
19961b | 2017-04-08 | Martin Nilsson | | f_aggregate((INT32)(Pike_sp-save_sp)); \
sval.u.array=append_array(sval.u.array,Pike_sp-1); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | pop_stack(); \
eye+=tmp; \
}else{ \
|
19961b | 2017-04-08 | Martin Nilsson | | pop_n_elems(Pike_sp-save_sp); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
} \
} \
cnt=e; \
UNSET_ONERROR(err); \
break; \
} \
\
case 'c': \
{ \
|
d68959 | 2008-07-09 | Martin Stjernholm | | INPUT_IS_WIDE( \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | int e; \
) \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(sval, T_INT, NUMBER_NUMBER, integer, 0); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if(field_length == -1) \
{ \
if(eye+1 > input_len) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
sval.u.integer=input[eye]; \
eye++; \
break; \
} \
if(eye+field_length > input_len) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
|
d68959 | 2008-07-09 | Martin Stjernholm | | INPUT_IS_WIDE( \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | for(e=0;e<field_length;e++) \
{ \
|
19961b | 2017-04-08 | Martin Nilsson | | if((unsigned INT32) input[eye+e] > 255) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
chars_matched[0]=eye; \
return matches; \
} \
} \
) \
sval.u.integer=0; \
if (minus_flag) \
{ \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | int pos=0; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | if (field_length >= 0) { \
pos = (eye += field_length); \
} \
if (plus_flag && (--field_length >= 0)) { \
sval.u.integer = (signed char)input[--pos]; \
} \
while(--field_length >= 0) \
{ \
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); \
o_lsh(); \
push_int(input[--pos]); \
o_or(); \
} \
dmalloc_touch_svalue(Pike_sp-1); \
|
19961b | 2017-04-08 | Martin Nilsson | | sval=*--Pike_sp; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
} \
sval.u.integer<<=8; \
sval.u.integer |= input[--pos]; \
} \
} else { \
if (plus_flag && (--field_length >= 0)) { \
sval.u.integer = (signed char)input[eye++]; \
} \
while(--field_length >= 0) \
{ \
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); \
o_lsh(); \
push_int(input[eye]); \
o_or(); \
eye++; \
} \
dmalloc_touch_svalue(Pike_sp-1); \
|
19961b | 2017-04-08 | Martin Nilsson | | sval=*--Pike_sp; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
} \
sval.u.integer<<=8; \
sval.u.integer |= input[eye]; \
eye++; \
} \
} \
break; \
} \
|
eb081d | 2007-04-28 | Per Hedbor | | \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | case 'H': \
{ \
|
659474 | 2012-04-17 | Per Hedbor | | unsigned long len=0; \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | if(field_length == -1) \
field_length=1; \
if(field_length == 0) \
Pike_error("%%H size field is 0.\n"); \
if(eye+field_length > input_len) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
INPUT_IS_WIDE ( \
for(e=0;e<field_length;e++) \
{ \
if((unsigned INT32) input[eye+e] > 255) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
} \
); \
if (minus_flag) \
{ \
int pos=0; \
pos = (eye += field_length); \
while(--field_length >= 0) \
{ \
len<<=8; \
len |= input[--pos]; \
} \
} else { \
while(--field_length >= 0) \
{ \
len<<=8; \
len |= input[eye]; \
eye++; \
} \
} \
if(len > (unsigned long)(input_len-eye)) \
{ \
chars_matched[0]=eye-field_length; \
return matches; \
} \
if (no_assign) { \
no_assign = 2; \
} else { \
SET_SVAL(sval, T_STRING, 0, string, \
PIKE_CONCAT(make_shared_binary_string, \
INPUT_SHIFT)(input+eye, len)); \
} \
eye+=len; \
break; \
} \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
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, &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; \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | FLOAT_TYPE f; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
if(eye>=input_len) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
|
9e10fe | 2020-06-06 | Marcus Comstedt | | f = (FLOAT_TYPE)STRTOFLOAT_PCHARP(MKPCHARP(input+eye, \
INPUT_SHIFT),&t2); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | t = (PIKE_CONCAT(p_wchar, INPUT_SHIFT) *)(t2.ptr); \
if(input + eye == t) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
eye=t-input; \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(sval, T_FLOAT, 0, float_number, f); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
} \
\
case 'F': \
if(field_length == -1) field_length = 4; \
if(field_length != 4 && field_length != 8) \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | Pike_error("Invalid IEEE width %ld in sscanf format string.\n", \
(long)field_length); \
if(eye+field_length > input_len) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
chars_matched[0]=eye; \
return matches; \
} \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(sval, T_FLOAT, 0, float_number, 0.0); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | switch(field_length) { \
case 4: \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | if (minus_flag) \
EXTRACT_FLOAT(sval, input+eye, INPUT_SHIFT, extract_float_le); \
else \
EXTRACT_FLOAT(sval, input+eye, INPUT_SHIFT, extract_float_be); \
eye += 4; \
break; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | case 8: \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | if (minus_flag) \
EXTRACT_DOUBLE(sval, input+eye, INPUT_SHIFT, extract_double_le); \
else \
EXTRACT_DOUBLE(sval, input+eye, INPUT_SHIFT, extract_double_be); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | eye += 8; \
break; \
} \
break; \
\
case 's': \
if(field_length != -1) \
{ \
if(input_len - eye < field_length) \
{ \
chars_matched[0]=eye; \
return matches; \
} \
\
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign) { \
no_assign = 2; \
} else { \
|
11ff45 | 2015-08-24 | Per Hedbor | | SET_SVAL(sval, T_STRING, 0, string, \
get_string_slice(input,INPUT_SHIFT,eye, \
field_length,pstr)); \
|
4e6246 | 2005-07-31 | Jonas Wallden | | } \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | eye+=field_length; \
break; \
} \
\
if(cnt+1>=match_len) \
{ \
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign) { \
no_assign = 2; \
} else { \
|
11ff45 | 2015-08-24 | Per Hedbor | | SET_SVAL(sval, T_STRING, 0, string, \
get_string_slice(input,INPUT_SHIFT,eye, \
input_len-eye,pstr)); \
|
4e6246 | 2005-07-31 | Jonas Wallden | | } \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | eye=input_len; \
break; \
}else{ \
PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_start; \
PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_end; \
PIKE_CONCAT(p_wchar, MATCH_SHIFT) *s=0; \
PIKE_CONCAT(p_wchar, MATCH_SHIFT) *p=0; \
int contains_percent_percent; \
ptrdiff_t start, new_eye; \
\
e = cnt; \
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) \
{ \
case 0: \
/* FIXME: Should really look at the match len */ \
Pike_error("%% without conversion specifier.\n"); \
break; \
\
case 'n': \
s++; \
/* Advance the end string start pointer */ \
end_str_start = s; \
e = s - match; \
goto test_again; \
\
case 's': \
Pike_error("Illegal to have two adjecent %%s.\n"); \
|
9282fd | 2015-09-27 | Martin Nilsson | | UNREACHABLE(return 0); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
/* sscanf("foo-bar","%s%d",a,b) might not work as expected */ \
case 'd': \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set.c, 1, sizeof(set.c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | for(e='0';e<='9';e++) set.c[e]=0; \
set.c['-']=0; \
goto match_set; \
\
case 'o': \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set.c, 1, sizeof(set.c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | for(e='0';e<='7';e++) set.c[e]=0; \
goto match_set; \
\
case 'x': \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set.c, 1, sizeof(set.c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | 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': \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set.c, 1, sizeof(set.c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | for(e='0';e<='9';e++) set.c[e]=0; \
set.c['-']=0; \
goto match_set; \
\
case 'f': \
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(set.c, 1, sizeof(set.c)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | 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, \
|
f7ce89 | 2017-04-08 | Martin Nilsson | | match_len); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | set.neg=!set.neg; \
goto match_set; \
} \
} \
\
contains_percent_percent=0; \
\
for(;e<match_len;e++) \
{ \
if(match[e]=='%') \
{ \
if(match[e+1]=='%') \
{ \
contains_percent_percent=1; \
e++; \
}else{ \
break; \
} \
} \
} \
\
end_str_end=match+e; \
\
if (end_str_end == end_str_start) { \
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign) { \
no_assign = 2; \
} else { \
|
11ff45 | 2015-08-24 | Per Hedbor | | SET_SVAL(sval, T_STRING, 0, string, \
get_string_slice(input,INPUT_SHIFT,eye, \
input_len-eye,pstr)); \
|
4e6246 | 2005-07-31 | Jonas Wallden | | } \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | eye=input_len; \
break; \
} else if(!contains_percent_percent) \
{ \
|
2934f4 | 2004-03-07 | Martin Nilsson | | struct pike_mem_searcher searcher; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | PIKE_CONCAT(p_wchar, INPUT_SHIFT) *s2; \
|
2934f4 | 2004-03-07 | Martin Nilsson | | pike_init_memsearch(&searcher, \
MKPCHARP(end_str_start, MATCH_SHIFT), \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | end_str_end - end_str_start, \
|
2934f4 | 2004-03-07 | Martin Nilsson | | input_len - eye); \
|
380db7 | 2004-03-07 | Martin Nilsson | | s2 = searcher.mojt.vtab-> PIKE_CONCAT(func,INPUT_SHIFT) \
(searcher.mojt.data, input+eye, input_len-eye); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | 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; \
} \
\
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign) { \
no_assign = 2; \
} else { \
|
11ff45 | 2015-08-24 | Per Hedbor | | SET_SVAL(sval, T_STRING, 0, string, \
get_string_slice(input,INPUT_SHIFT,start, \
eye-start,pstr)); \
|
4e6246 | 2005-07-31 | Jonas Wallden | | } \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
cnt=end_str_end-match-1; \
eye=new_eye; \
break; \
} \
\
case '[': \
cnt=PIKE_CONCAT(read_set,MATCH_SHIFT)(match,cnt+1, \
|
558e91 | 2014-10-05 | Martin Nilsson | | &set,match_len); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
match_set: \
{ \
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++) \
{ \
|
d68959 | 2008-07-09 | Martin Stjernholm | | INPUT_IS_WIDE( \
|
558e91 | 2014-10-05 | Martin Nilsson | | if((unsigned INT32) input[eye] < sizeof(set.c)) \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | { \
) \
if(set.c[input[eye]] == set.neg) \
break; \
|
d68959 | 2008-07-09 | Martin Stjernholm | | INPUT_IS_WIDE( \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }else{ \
if(set.a) \
{ \
INT32 x; \
struct svalue tmp; \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(tmp, T_INT, NUMBER_NUMBER, \
integer, input[eye]); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | x=switch_lookup(set.a, &tmp); \
if( set.neg != (x<0 && (x&1)) ) break; \
}else{ \
if(!set.neg) break; \
} \
} \
) \
} \
if ((field_length != -1) && (eye != len)) { \
/* Couldn't read the entire field. Fail. */ \
chars_matched[0]=e; \
return matches; \
} \
} \
if(set.a) { free_array(set.a); set.a=0; } \
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign) { \
no_assign = 2; \
} else { \
|
11ff45 | 2015-08-24 | Per Hedbor | | SET_SVAL(sval, T_STRING, 0, string, \
get_string_slice(input,INPUT_SHIFT,e, \
eye-e,pstr)); \
|
4e6246 | 2005-07-31 | Jonas Wallden | | } \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
\
case 'O': \
{ \
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; \
\
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; \
\
break; \
} \
\
case 'n': \
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(sval, T_INT, NUMBER_NUMBER, integer, \
|
e9e703 | 2016-02-12 | Martin Nilsson | | (INT32)(eye - truncated)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break; \
\
default: \
Pike_error("Unknown sscanf token %%%c(0x%02x)\n", \
match[cnt], match[cnt]); \
} \
break; \
} \
matches++; \
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | if (truncate) { \
truncated += eye - start_eye; \
} \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | \
if(no_assign) \
{ \
|
4e6246 | 2005-07-31 | Jonas Wallden | | if (no_assign == 1) \
free_svalue(&sval); \
} else { \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | check_stack(1); \
|
19961b | 2017-04-08 | Martin Nilsson | | *Pike_sp++=sval; \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | dmalloc_touch_svalue(Pike_sp-1); \
|
1f4d70 | 2011-10-28 | Henrik Grubbström (Grubba) | | DO_IF_DEBUG(INVALIDATE_SVAL(sval)); \
|
c6c01a | 2003-11-14 | Martin Stjernholm | | } \
} \
chars_matched[0]=eye; \
success[0]=1; \
return matches; \
}
|
d68959 | 2008-07-09 | Martin Stjernholm | |
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
d68959 | 2008-07-09 | Martin Stjernholm | | |
c6c01a | 2003-11-14 | Martin Stjernholm | | */
|
d68959 | 2008-07-09 | Martin Stjernholm | | #define MATCH_IS_WIDE(X)
#define INPUT_IS_WIDE(X)
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
MKREADSET(0)
MK_VERY_LOW_SSCANF(0,0)
|
d68959 | 2008-07-09 | Martin Stjernholm | | #undef INPUT_IS_WIDE
#define INPUT_IS_WIDE(X) X
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
MK_VERY_LOW_SSCANF(1,0)
MK_VERY_LOW_SSCANF(2,0)
|
d68959 | 2008-07-09 | Martin Stjernholm | | #undef MATCH_IS_WIDE
#define MATCH_IS_WIDE(X) X
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
MKREADSET(1)
MKREADSET(2)
|
d68959 | 2008-07-09 | Martin Stjernholm | | #undef INPUT_IS_WIDE
#define INPUT_IS_WIDE(X)
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
MK_VERY_LOW_SSCANF(0,1)
MK_VERY_LOW_SSCANF(0,2)
|
d68959 | 2008-07-09 | Martin Stjernholm | | #undef INPUT_IS_WIDE
#define INPUT_IS_WIDE(X) X
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
MK_VERY_LOW_SSCANF(1,1)
MK_VERY_LOW_SSCANF(2,1)
MK_VERY_LOW_SSCANF(1,2)
MK_VERY_LOW_SSCANF(2,2)
|
9a2ff0 | 2014-08-28 | Per Hedbor | |
INT32 low_sscanf_pcharp(PCHARP input, ptrdiff_t len,
PCHARP format, ptrdiff_t format_len,
|
558e91 | 2014-10-05 | Martin Nilsson | | ptrdiff_t *chars_matched)
|
9a2ff0 | 2014-08-28 | Per Hedbor | | {
int ok;
check_c_stack(sizeof(struct sscanf_set)*2 + 512);
switch( input.shift*3 + format.shift )
{
case 0:
return very_low_sscanf_0_0(input.ptr, len,format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 1:
return very_low_sscanf_0_1(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 2:
return very_low_sscanf_0_2(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 3:
return very_low_sscanf_1_0(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 4:
return very_low_sscanf_1_1(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 5:
return very_low_sscanf_1_2(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 6:
return very_low_sscanf_2_0(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 7:
return very_low_sscanf_2_1(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | case 8:
return very_low_sscanf_2_2(input.ptr, len, format.ptr, format_len,
|
11ff45 | 2015-08-24 | Per Hedbor | | chars_matched, &ok,0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | }
|
5ee9e3 | 2018-12-26 | Henrik Grubbström (Grubba) | | UNREACHABLE(return 0);
|
9a2ff0 | 2014-08-28 | Per Hedbor | | }
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
558e91 | 2014-10-05 | Martin Nilsson | | INT32 low_sscanf(struct pike_string *data, struct pike_string *format)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
ptrdiff_t matched_chars;
int x;
check_c_stack(sizeof(struct sscanf_set)*2 + 512);
switch(data->size_shift*3 + format->size_shift) {
case 0:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_0_0(STR0(data), data->len,
STR0(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 1:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_0_1(STR0(data), data->len,
STR1(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 2:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_0_2(STR0(data), data->len,
STR2(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 3:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_1_0(STR1(data), data->len,
STR0(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 4:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_1_1(STR1(data), data->len,
STR1(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 5:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_1_2(STR1(data), data->len,
STR2(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 6:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_2_0(STR2(data), data->len,
STR0(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 7:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_2_1(STR2(data), data->len,
STR1(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
case 8:
|
759c42 | 2015-10-17 | Martin Nilsson | | return very_low_sscanf_2_2(STR2(data), data->len,
STR2(format), format->len,
&matched_chars, &x,data);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | break;
}
|
759c42 | 2015-10-17 | Martin Nilsson | |
|
5ee9e3 | 2018-12-26 | Henrik Grubbström (Grubba) | | UNREACHABLE(return 0);
|
c6c01a | 2003-11-14 | Martin Stjernholm | | }
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! sscanf really is a special form, rather than a pike function) with the values
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! extracted from the @[data] according to the @[format] specification. Only
*! the variables up to the last matching directive of the format string are
*! touched.
*!
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! The @[format] string may contain strings separated by special matching
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! directives like @tt{%d@}, @tt{%s@} @tt{%c@} and @tt{%f@}. Every such
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! directive corresponds to one of the @[lvalues], in the order they are listed.
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! An lvalue is the name of a variable, a name of a local variable, an index
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! into an array, mapping or object. It is because of these lvalues that sscanf
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! can not be implemented as a normal function.
*!
*! Whenever a percent character is found in the format string, a match is
*! performed, according to which operator and modifiers follow it:
*!
*! @string
*! @value "%b"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Reads a binary integer (@expr{"0101"@} makes @expr{5@})
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%d"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Reads a decimal integer (@expr{"0101"@} makes @expr{101@}).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%o"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Reads an octal integer (@expr{"0101"@} makes @expr{65@}).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%x"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Reads a hexadecimal integer (@expr{"0101"@} makes @expr{257@}).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%D"
*! Reads an integer that is either octal (leading zero),
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! hexadecimal (leading @expr{0x@}) or decimal. (@expr{"0101"@} makes
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! @expr{65@}).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%c"
*! Reads one character and returns it as an integer
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! (@expr{"0101"@} makes @expr{48@}, or @expr{'0'@}, leaving
*! @expr{"101"@} for later directives). Using the field width and
*! endianness modifiers, you can decode integers of any size and
*! endianness. For example @expr{"%-2c"@} decodes @expr{"0101"@}
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! into @expr{12592@}, leaving @expr{"01"@} for later directives.
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! The sign modifiers can be used to modify the signature of the
*! data, making @expr{"%+1c"@} decode @expr{"ä"@} into
*! @expr{-28@}.
|
a1c9d7 | 2010-11-19 | Henrik Grubbström (Grubba) | | *! @value "%n"
*! Returns the current character offset in @[data].
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | *! Note that any characters matching fields scanned with the
*! @expr{"!"@}-modifier are removed from the count (see below).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%f"
*! Reads a float ("0101" makes 101.0).
*! @value "%F"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Reads a float encoded according to the IEEE single precision
*! binary format (@expr{"0101"@} makes @expr{6.45e-10@},
*! approximately). Given a field width modifier of 8 (4 is the
*! default), the data will be decoded according to the IEEE
*! double precision binary format instead. (You will however
*! still get a float, unless your pike was compiled with the
*! configure argument @tt{--with-double-precision@}.)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%s"
*! Reads a string. If followed by %d, %s will only read non-numerical
*! characters. If followed by a %[], %s will only read characters not
*! present in the set. If followed by normal text, %s will match all
*! characters up to but not including the first occurrence of that text.
|
e37f18 | 2007-04-29 | Martin Nilsson | | *! @value "%H"
|
f42497 | 2007-04-30 | Henrik Grubbström (Grubba) | | *! Reads a Hollerith-encoded string, i.e. first reads the length
|
e37f18 | 2007-04-29 | Martin Nilsson | | *! of the string and then that number of characters. The size and
*! byte order of the length descriptor can be modified in the
*! same way as @tt{%c@}. As an example @expr{"%2H"@} first reads
*! @expr{"%2c"@} and then the resulting number of characters.
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%[set]"
*! Matches a string containing a given set of characters (those given
|
dc8c3e | 2008-05-14 | Marcus Comstedt | | *! inside the brackets). Ranges of characters can be defined by using
*! a minus character between the first and the last character to be
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! included in the range. Example: @expr{%[0-9H]@} means any number or 'H'.
|
dc8c3e | 2008-05-14 | Marcus Comstedt | | *! Note that sets that includes the character '-' must have it first
*! (not possible in complemented sets, see below) or last in the brackets
*! to avoid having a range defined. Sets including the character ']' must
|
65493f | 2005-09-01 | Martin Stjernholm | | *! list this first too. If both '-' and ']' should be included
|
dc8c3e | 2008-05-14 | Marcus Comstedt | | *! then put ']' first and '-' last. It is not possible to make a range
*! that ends with ']'; make the range end with '\' instead and put ']'
*! at the beginning of the set. Likewise it is generally not possible
*! to have a range start with '-'; make the range start with '.' instead
*! and put '-' at the end of the set. If the first character after the
*! [ bracket is '^' (%[^set]), and this character does not begin a
*! range, it means that the set is complemented, which is to say that
*! any character except those inside brackets is matched. To include '-'
*! in a complemented set, it must be put last, not first. To include '^'
*! in a non-complemented set, it can be put anywhere but first, or be
*! specified as a range ("^-^").
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "%{format%}"
*! Repeatedly matches 'format' as many times as possible and assigns an
*! array of arrays with the results to the lvalue.
*! @value "%O"
*! Match a Pike constant, such as string or integer (currently only
*! integer, string and character constants are functional).
*! @value "%%"
*! Match a single percent character (hence this is how you quote the %
*! character to just match, and not start an lvalue matcher directive).
*! @endstring
*!
*! Similar to @[sprintf], you may supply modifiers between the % character
*! and the operator, to slightly change its behaviour from the default:
*!
*! @string
*! @value "*"
*! The operator will only match its argument, without assigning any
*! variable.
*! @value number
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! You may define a field width by supplying a numeric modifier.
*! This means that the format should match that number of
*! characters in the input data; be it a @i{number@} characters
*! long string, integer or otherwise (@expr{"0101"@} using the
*! format %2c would read an unsigned short @expr{12337@}, leaving
*! the final @expr{"01"@} for later operators, for instance).
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @value "-"
*! Supplying a minus sign toggles the decoding to read the data encoded
*! in little-endian byte order, rather than the default network
*! (big-endian) byte order.
*! @value "+"
|
68ab58 | 2004-03-23 | Martin Nilsson | | *! Interpret the data as a signed entity. In other words,
*! @expr{"%+1c"@} will read @expr{"\xFF"@} as @expr{-1@} instead
*! of @expr{255@}, as @expr{"%1c"@} would have.
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | *! @value "!"
*! Ignore the matched characters with respect to any following
*! @expr{"%n"@}.
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! @endstring
*!
*! @note
*! Sscanf does not use backtracking. Sscanf simply looks at the format string
*! up to the next % and tries to match that with the string. It then proceeds
*! to look at the next part. If a part does not match, sscanf immediately
*! returns how many % were matched. If this happens, the lvalues for % that
*! were not matched will not be changed.
*!
*! @example
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! @code
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *! // a will be assigned "oo" and 1 will be returned
*! sscanf("foo", "f%s", a);
*!
*! // a will be 4711 and b will be "bar", 2 will be returned
*! sscanf("4711bar", "%d%s", a, b);
*!
*! // a will be 4711, 2 will be returned
*! sscanf("bar4711foo", "%*s%d", a);
*!
*! // a will become "test", 2 will be returned
*! sscanf(" \t test", "%*[ \t]%s", a);
*!
*! // Remove "the " from the beginning of a string
*! // If 'str' does not begin with "the " it will not be changed
*! sscanf(str, "the %s", str);
*!
*! // It is also possible to declare a variable directly in the sscanf call;
*! // another reason for sscanf not to be an ordinary function:
*!
*! sscanf("abc def", "%s %s", string a, string b);
|
486947 | 2016-11-17 | Henrik Grubbström (Grubba) | | *! @endcode
|
c6c01a | 2003-11-14 | Martin Stjernholm | | *!
*! @returns
*! The number of directives matched in the format string. Note that a string
*! directive (%s or %[]) counts as a match even when matching just the empty
*! string (which either may do).
*! @seealso
*! @[sprintf], @[array_sscanf]
* @[parse_format]
*/
|
fffdad | 2014-10-13 | Martin Nilsson | | void o_sscanf(INT32 args)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | {
INT32 i=0;
int x;
|
19961b | 2017-04-08 | Martin Nilsson | | struct svalue *save_sp=Pike_sp;
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
19961b | 2017-04-08 | Martin Nilsson | | if(TYPEOF(Pike_sp[-args]) != T_STRING)
|
f98274 | 2016-01-26 | Martin Nilsson | | SIMPLE_ARG_TYPE_ERROR("sscanf", 1, "string");
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
19961b | 2017-04-08 | Martin Nilsson | | if(TYPEOF(Pike_sp[1-args]) != T_STRING)
|
f98274 | 2016-01-26 | Martin Nilsson | | SIMPLE_ARG_TYPE_ERROR("sscanf", 2, "string");
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
19961b | 2017-04-08 | Martin Nilsson | | i = low_sscanf(Pike_sp[-args].u.string, Pike_sp[1-args].u.string);
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
|
19961b | 2017-04-08 | Martin Nilsson | | if(Pike_sp-save_sp > args/2-1)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | Pike_error("Too few arguments for sscanf format.\n");
|
19961b | 2017-04-08 | Martin Nilsson | | for(x=0;x<Pike_sp-save_sp;x++)
|
c6c01a | 2003-11-14 | Martin Stjernholm | | assign_lvalue(save_sp-args+2+x*2,save_sp+x);
|
19961b | 2017-04-08 | Martin Nilsson | | pop_n_elems(Pike_sp-save_sp +args);
|
c6c01a | 2003-11-14 | Martin Stjernholm | |
#ifdef PIKE_DEBUG
if(Pike_interpreter.trace_level >2)
{
int nonblock;
if((nonblock=query_nonblocking(2)))
set_nonblocking(2,0);
fprintf(stderr,"- Matches: %ld\n",(long)i);
if(nonblock)
set_nonblocking(2,1);
}
#endif
push_int(i);
}
PMOD_EXPORT void f_sscanf(INT32 args)
{
INT32 i;
|
19961b | 2017-04-08 | Martin Nilsson | | struct svalue *save_sp=Pike_sp;
|
c6c01a | 2003-11-14 | Martin Stjernholm | | struct array *a;
check_all_args("array_sscanf",args,BIT_STRING, BIT_STRING,0);
|
19961b | 2017-04-08 | Martin Nilsson | | i = low_sscanf(Pike_sp[-args].u.string, Pike_sp[1-args].u.string);
|
37e413 | 2008-05-17 | Marcus Comstedt | |
|
19961b | 2017-04-08 | Martin Nilsson | | a = aggregate_array(Pike_sp - save_sp);
|
37e413 | 2008-05-17 | Marcus Comstedt | | pop_n_elems(args);
push_array(a);
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
|
558e91 | 2014-10-05 | Martin Nilsson | | int cnt)
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | {
for(; cnt < format_len; cnt++)
{
int no_assign=0;
while((cnt<format_len) && (INDEX_PCHARP(format, cnt) != '%'))
cnt++;
cnt++;
if (cnt >= format_len) break;
while(1)
{
switch(INDEX_PCHARP(format, cnt))
{
case '%':
break;
case '*':
no_assign=1;
|
5f5084 | 2018-02-12 | Marcus Comstedt | |
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | |
case '-':
case '+':
|
e02b4f | 2010-11-21 | Henrik Grubbström (Grubba) | | case '!':
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
cnt++;
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if(cnt>=format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | continue;
case '{':
{
int e;
int depth = 1;
for(e=cnt+1;depth;e++)
{
if(e>=format_len)
{
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Missing %%} in format string.");
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
if(INDEX_PCHARP(format, e)=='%')
{
switch(INDEX_PCHARP(format, e+1))
{
case '%': e++; break;
case '}': depth--; break;
case '{': depth++; break;
}
}
}
if (!no_assign) {
type_stack_mark();
|
558e91 | 2014-10-05 | Martin Nilsson | | push_sscanf_argument_types(format, e, cnt+1);
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if (!(depth = pop_stack_mark())) {
push_type(PIKE_T_ZERO);
} else {
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | while (depth > 1) {
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | push_type(T_OR);
depth--;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
|
04017d | 2020-01-02 | Henrik Grubbström (Grubba) | | push_unlimited_array_type(PIKE_T_ARRAY);
push_unlimited_array_type(PIKE_T_ARRAY);
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
|
d81c31 | 2008-05-18 | Henrik Grubbström (Grubba) | | cnt = e;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
120fff | 2020-08-07 | Henrik Grubbström (Grubba) | | case 'n':
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | case 'b':
case 'o':
case 'd':
case 'x':
case 'D':
case 'i':
|
120fff | 2020-08-07 | Henrik Grubbström (Grubba) | | case 'c':
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | if (!no_assign)
push_finished_type(int_type_string);
break;
case '[':
{
int ch;
cnt++;
if (cnt >= format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
if((INDEX_PCHARP(format, cnt)=='^') &&
(cnt+2>=format_len ||
(INDEX_PCHARP(format, cnt+1)!='-') ||
|
c9562b | 2014-10-05 | Martin Nilsson | | (INDEX_PCHARP(format, cnt+2)==']') ))
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | {
cnt++;
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if(cnt >= format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
if(((ch = INDEX_PCHARP(format, cnt))==']') || (ch=='-'))
{
cnt++;
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if(cnt >= format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | ch = INDEX_PCHARP(format, cnt);
}
while(ch != ']')
{
if(ch == '-')
{
cnt++;
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if(cnt >= format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | |
if(INDEX_PCHARP(format, cnt)==']')
{
break;
}
}
cnt++;
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if(cnt>=format_len) {
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Error in sscanf format string.");
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | ch = INDEX_PCHARP(format, cnt);
}
}
|
5f5084 | 2018-02-12 | Marcus Comstedt | |
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | case 's':
case 'H':
|
120fff | 2020-08-07 | Henrik Grubbström (Grubba) | | if (!no_assign) {
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | push_finished_type(string_type_string);
|
120fff | 2020-08-07 | Henrik Grubbström (Grubba) | | }
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
case 'F':
case 'f':
if (!no_assign)
push_finished_type(float_type_string);
break;
break;
case 'O':
if (!no_assign)
push_finished_type(mixed_type_string);
break;
default:
|
94d66b | 2008-05-24 | Henrik Grubbström (Grubba) | | yyreport(REPORT_ERROR, type_check_system_string,
0, "Unknown sscanf token %%%c(0x%02x) at offset %d.",
|
2ffe97 | 2008-05-21 | Henrik Grubbström (Grubba) | | INDEX_PCHARP(format, cnt), INDEX_PCHARP(format, cnt),
cnt-1);
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | break;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
break;
}
}
}
void f___handle_sscanf_format(INT32 args)
{
struct pike_type *res;
struct pike_type *tmp;
struct pike_string *attr;
struct pike_string *fmt;
struct pike_string *sscanf_format_string;
struct pike_string *sscanf_76_format_string;
int found = 0;
int fmt_count;
|
2ffe97 | 2008-05-21 | Henrik Grubbström (Grubba) | |
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | #if 0
|
120fff | 2020-08-07 | Henrik Grubbström (Grubba) | | fprintf(stderr, "__handle_sscanf_format()\n");
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | #endif /* 0 */
if (args != 4)
SIMPLE_WRONG_NUM_ARGS_ERROR("__handle_sscanf_format", 4);
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-4]) != PIKE_T_STRING)
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | SIMPLE_ARG_TYPE_ERROR("__handle_sscanf_format", 1, "string");
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-3]) != PIKE_T_STRING)
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | SIMPLE_ARG_TYPE_ERROR("__handle_sscanf_format", 2, "string");
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-2]) != PIKE_T_TYPE)
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | SIMPLE_ARG_TYPE_ERROR("__handle_sscanf_format", 3, "type");
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-1]) != PIKE_T_TYPE)
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | SIMPLE_ARG_TYPE_ERROR("__handle_sscanf_format", 4, "type");
tmp = Pike_sp[-1].u.type;
if ((tmp->type != PIKE_T_FUNCTION) && (tmp->type != T_MANY)) {
SIMPLE_ARG_TYPE_ERROR("__handle_sscanf_format", 4, "type(function)");
}
|
13670c | 2015-05-25 | Martin Nilsson | | MAKE_CONST_STRING(sscanf_format_string, "sscanf_format");
MAKE_CONST_STRING(sscanf_76_format_string, "sscanf_76_format");
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | |
if (Pike_sp[-4].u.string != sscanf_format_string) {
if (Pike_sp[-4].u.string != sscanf_76_format_string) {
pop_n_elems(args);
push_undefined();
return;
}
}
fmt = Pike_sp[-3].u.string;
|
13670c | 2015-05-25 | Martin Nilsson | | MAKE_CONST_STRING(attr, "sscanf_args");
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | |
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | #if 0
fprintf(stderr, "Checking sscanf format: \"%s\": ", fmt->str);
simple_describe_type(Pike_sp[-1].u.type);
fprintf(stderr, "\n");
#endif /* 0 */
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | type_stack_mark();
type_stack_mark();
for (; tmp; tmp = tmp->cdr) {
struct pike_type *arg = tmp->car;
int array_cnt = 0;
while(arg) {
switch(arg->type) {
case PIKE_T_ATTRIBUTE:
if (arg->car == (struct pike_type *)attr)
break;
|
5f5084 | 2018-02-12 | Marcus Comstedt | |
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | case PIKE_T_NAME:
arg = arg->cdr;
continue;
case PIKE_T_ARRAY:
array_cnt++;
|
297866 | 2019-12-17 | Henrik Grubbström (Grubba) | | arg = arg->cdr;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | continue;
default:
arg = NULL;
break;
}
break;
}
if (arg) {
type_stack_mark();
push_sscanf_argument_types(MKPCHARP(fmt->str, fmt->size_shift),
|
558e91 | 2014-10-05 | Martin Nilsson | | fmt->len, 0);
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | if (!array_cnt) {
pop_stack_mark();
push_type(T_VOID);
while (tmp->type == PIKE_T_FUNCTION) {
tmp = tmp->cdr;
}
push_finished_type(tmp->cdr);
push_reverse_type(T_MANY);
fmt_count = pop_stack_mark();
while (fmt_count > 1) {
push_reverse_type(T_FUNCTION);
fmt_count--;
}
res = pop_unfinished_type();
pop_n_elems(args);
push_type_value(res);
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | #if 0
fprintf(stderr, " ==> ");
simple_describe_type(res);
fprintf(stderr, "\n");
#endif /* 0 */
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | return;
} else {
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | if (!(fmt_count = pop_stack_mark())) {
push_type(PIKE_T_ZERO);
} else {
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | while (fmt_count > 1) {
|
39ff2d | 2008-05-18 | Henrik Grubbström (Grubba) | | push_type(T_OR);
fmt_count--;
}
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
while (array_cnt--) {
|
04017d | 2020-01-02 | Henrik Grubbström (Grubba) | | push_unlimited_array_type(PIKE_T_ARRAY);
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
found = 1;
}
} else {
push_finished_type(tmp->car);
}
if (tmp->type == T_MANY) {
tmp = tmp->cdr;
break;
}
}
if (found) {
push_finished_type(tmp);
push_reverse_type(T_MANY);
fmt_count = pop_stack_mark();
while (fmt_count > 1) {
push_reverse_type(T_FUNCTION);
fmt_count--;
}
res = pop_unfinished_type();
pop_n_elems(args);
push_type_value(res);
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | #if 0
fprintf(stderr, " ==> ");
simple_describe_type(res);
fprintf(stderr, "\n");
#endif /* 0 */
|
2ffe97 | 2008-05-21 | Henrik Grubbström (Grubba) | | return;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | } else if (tmp) {
struct pike_type *arg = tmp;
int array_cnt = 0;
while(arg) {
switch(arg->type) {
case PIKE_T_ATTRIBUTE:
if (arg->car == (struct pike_type *)attr)
break;
|
5f5084 | 2018-02-12 | Marcus Comstedt | |
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | case PIKE_T_NAME:
arg = arg->cdr;
continue;
case PIKE_T_ARRAY:
array_cnt++;
|
297866 | 2019-12-17 | Henrik Grubbström (Grubba) | | arg = arg->cdr;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | continue;
default:
arg = NULL;
break;
}
break;
}
if (arg) {
type_stack_mark();
push_sscanf_argument_types(MKPCHARP(fmt->str, fmt->size_shift),
|
558e91 | 2014-10-05 | Martin Nilsson | | fmt->len, 0);
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | |
|
317759 | 2008-05-19 | Henrik Grubbström (Grubba) | | if (!(fmt_count = pop_stack_mark())) {
push_type(PIKE_T_ZERO);
} else while (fmt_count > 2) {
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | push_type(T_OR);
|
317759 | 2008-05-19 | Henrik Grubbström (Grubba) | | fmt_count--;
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
while (array_cnt--) {
|
04017d | 2020-01-02 | Henrik Grubbström (Grubba) | | push_unlimited_array_type(PIKE_T_ARRAY);
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | }
push_reverse_type(T_MANY);
fmt_count = pop_stack_mark();
while (fmt_count > 1) {
push_reverse_type(T_FUNCTION);
fmt_count--;
}
res = pop_unfinished_type();
pop_n_elems(args);
push_type_value(res);
|
487286 | 2008-06-18 | Henrik Grubbström (Grubba) | | #if 0
fprintf(stderr, " ==> ");
simple_describe_type(res);
fprintf(stderr, "\n");
#endif /* 0 */
|
6f16cb | 2008-05-18 | Henrik Grubbström (Grubba) | | return;
}
}
#if 0
fprintf(stderr, " ==> No marker found.\n");
#endif /* 0 */
pop_stack_mark();
type_stack_pop_to_mark();
pop_n_elems(args);
push_undefined();
}
|