pike.git
/
src
/
builtin.cmod
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/builtin.cmod:21:
#include "threads.h" #include "module_support.h" #include "cyclic.h" #include "bignum.h" #include "main.h" #include "operators.h" #include "builtin_functions.h" #include "fsort.h" #include "port.h" #include "gc.h"
-
#include "block_
alloc
.h"
+
#include "block_
allocator
.h"
#include "pikecode.h" #include "opcodes.h" #include <ctype.h> #include <errno.h> #include <math.h> DECLARATIONS
-
+
+
/*! @module System
+
*/
+
+
#if defined(HAVE_MKTIME) && defined(HAVE_GMTIME) && defined(HAVE_LOCALTIME)
+
PIKECLASS TM
+
/*! @class TM
+
*! A wrapper for the system struct tm time keeping structure.
+
*! This can be used as a (very) lightweight alternative to Calendar.
+
*/
+
{
+
CVAR struct tm t;
+
CVAR time_t unix_time;
+
CVAR int modified;
+
CVAR struct pike_string *set_zone;
+
+
#ifdef STRUCT_TM_HAS___TM_GMTOFF
+
#define tm_zone __tm_zone
+
#define tm_gmtoff __tm_gmtoff
+
#endif
+
+
#if 0
+
/* This is supposed to make any timezone work.
+
* However: It does not really work. And makes things even slower than
+
* the calendar module.
+
*/
+
#ifndef HAVE_EXTERNAL_TIMEZONE
+
#define timezone 0
+
#endif
+
#define WITH_ZONE(RETURNTYPE, FUNCTION, ARGUMENTS, CALL ) \
+
static RETURNTYPE FUNCTION##_zone ARGUMENTS \
+
{ \
+
RETURNTYPE res; \
+
int reset = 0; \
+
char *old_zone = NULL; \
+
if( x->tm_zone ) \
+
{ \
+
reset = 1; \
+
old_zone = getenv("TZ"); \
+
setenv("TZ", x->tm_zone, 1 ); \
+
tzset(); \
+
x->tm_gmtoff = timezone; \
+
} \
+
\
+
res = FUNCTION CALL; \
+
\
+
if( reset ) \
+
{ \
+
if( old_zone ) \
+
setenv("TZ", old_zone, 1 ); \
+
else \
+
unsetenv( "TZ" ); \
+
tzset(); \
+
} \
+
return res; \
+
}
+
+
WITH_ZONE(time_t,mktime,( struct tm *x ),(x));
+
WITH_ZONE(struct tm*,localtime,( time_t *t, struct tm *x ),(t));
+
WITH_ZONE(char *,asctime,( struct tm *x ),(x));
+
WITH_ZONE(int,strftime,( char *buffer, size_t max_len, char *format, struct tm *x ),(buffer,max_len,format,x));
+
#ifdef HAVE_STRPTIME
+
WITH_ZONE(char *,strptime,( const char *str, const char *format, struct tm *x ),(str,format,x));
+
#endif
+
#else
+
#define strftime_zone strftime
+
#define mktime_zone mktime
+
#define strptime_zone strptime
+
#define asctime_zone asctime
+
#define localtime_zone(X,Y) localtime(X)
+
#endif
+
#ifndef HAVE_EXTERNAL_TIMEZONE
+
#undef timezone
+
#endif
+
+
#define MODIFY(X) do{ THIS->modified = 1;THIS->t.X; }while(0)
+
#define FIX_THIS() do { \
+
if(THIS->modified){ \
+
THIS->unix_time = mktime_zone( &THIS->t ); \
+
THIS->modified = 0; \
+
} \
+
} while(0)
+
+
#ifdef HAVE_STRPTIME
+
/*
+
*! @decl int(0..1) strptime( string(1..255) format, string(1..255) data )
+
*!
+
*! Parse the given @[data] using the format in @[format] as a date.
+
*!
+
*! %% The % character.
+
*!
+
*! %a or %A
+
*! The weekday name according to the C locale, in abbreviated
+
*! form or the full name.
+
*!
+
*! %b or %B or %h
+
*! The month name according to the C locale, in abbreviated form
+
*! or the full name.
+
*!
+
*! %c The date and time representation for the C locale.
+
*!
+
*! %C The century number (0-99).
+
*!
+
*! %d or %e
+
*! The day of month (1-31).
+
*!
+
*! %D Equivalent to %m/%d/%y.
+
*!
+
*! %H The hour (0-23).
+
*!
+
*! %I The hour on a 12-hour clock (1-12).
+
*!
+
*! %j The day number in the year (1-366).
+
*!
+
*! %m The month number (1-12).
+
*!
+
*! %M The minute (0-59).
+
*!
+
*! %n Arbitrary whitespace.
+
*!
+
*! %p The C locale's equivalent of AM or PM.
+
*!
+
*! %R Equivalent to %H:%M.
+
*!
+
*! %S The second (0-60; 60 may occur for leap seconds; earlier also 61 was allowed).
+
*!
+
*! %t Arbitrary whitespace.
+
*!
+
*! %T Equivalent to %H:%M:%S.
+
*!
+
*! %U The week number with Sunday the first day of the week (0-53).
+
*!
+
*! %w The weekday number (0-6) with Sunday = 0.
+
*!
+
*! %W The week number with Monday the first day of the week (0-53).
+
*!
+
*! %x The date, using the C locale's date format.
+
*!
+
*! %X The time, using the C locale's time format.
+
*!
+
*! %y
+
*! The year within century (0-99). When a century is not
+
*! otherwise specified, values in the range 69-99 refer to years
+
*! in the twentieth century (1969-1999); values in the range
+
*! 00-68 refer to years in the twenty-first century (2000-2068).
+
*!
+
*! %Y The year, including century (for example, 1991).
+
*!
+
*/
+
PIKEFUN int(0..1) strptime( string(1..255) format, string(1..255) data )
+
{
+
if( format->size_shift || data->size_shift )
+
Pike_error("Only 8bit strings are supported\n");
+
THIS->modified = 1;
+
if( strptime_zone( data->str, format->str, &THIS->t ) == NULL )
+
RETURN 0;
+
RETURN 1;
+
}
+
#endif
+
/*! @decl string(1..255) strftime( string(1..255) format )
+
*! See also @[Gettext.setlocale]
+
*!
+
*! Convert the structure to a string.
+
*!
+
*! %a The abbreviated weekday name according to the current locale
+
*!
+
*! %A The full weekday name according to the current locale.
+
*!
+
*! %b The abbreviated month name according to the current locale.
+
*!
+
*! %B The full month name according to the current locale.
+
*!
+
*! %c The preferred date and time representation for the current locale.
+
*!
+
*! %C The century number (year/100) as a 2-digit integer.
+
*!
+
*! %d The day of the month as a decimal number (range 01 to 31).
+
*!
+
*! %D Equivalent to %m/%d/%y. (for Americans only. Americans should note that in other countries %d/%m/%y is rather common. This means that in international context this format is ambiguous and should not be used.)
+
*!
+
*! %e Like %d, the day of the month as a decimal number, but a leading zero is replaced by a space.
+
*!
+
*! %E Modifier: use alternative format, see below.
+
*!
+
*! %F Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)
+
*!
+
*! %G The ISO 8601 week-based year (see NOTES) with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V). This has the same format and value as %Y, except that if the ISO week number belongs to the previous or next year, that year is used instead.
+
*!
+
*! %g Like %G, but without century, that is, with a 2-digit year (00-99). (TZ)
+
*!
+
*! %h Equivalent to %b.
+
*!
+
*! %H The hour as a decimal number using a 24-hour clock (range 00 to 23).
+
*!
+
*! %I The hour as a decimal number using a 12-hour clock (range 01 to 12).
+
*!
+
*! %j The day of the year as a decimal number (range 001 to 366).
+
*!
+
*! %k The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded by a blank. (See also %H.)
+
*!
+
*! %l The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded by a blank. (See also %I.)
+
*!
+
*! %m The month as a decimal number (range 01 to 12).
+
*!
+
*! %M The minute as a decimal number (range 00 to 59).
+
*!
+
*! %n A newline character. (SU)
+
*!
+
*! %O Modifier: use alternative format, see below. (SU)
+
*!
+
*! %p Either "AM" or "PM" according to the given time value, or the corresponding strings for the current locale. Noon is treated as "PM" and midnight as "AM".
+
*!
+
*! %P Like %p but in lowercase: "am" or "pm" or a corresponding string for the current locale.
+
*!
+
*! %r The time in a.m. or p.m. notation. In the POSIX locale this is equivalent to %I:%M:%S %p.
+
*!
+
*! %R The time in 24-hour notation (%H:%M). (SU) For a version including the seconds, see %T below.
+
*!
+
*! %s The number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). (TZ)
+
*!
+
*! %S The second as a decimal number (range 00 to 60). (The range is up to 60 to allow for occasional leap seconds.)
+
*!
+
*! %t A tab character. (SU)
+
*!
+
*! %T The time in 24-hour notation (%H:%M:%S). (SU)
+
*!
+
*! %u The day of the week as a decimal, range 1 to 7, Monday being 1. See also %w. (SU)
+
*!
+
*! %U The week number of the current year as a decimal number, range 00 to 53, starting with the first Sunday as the first day of week 01. See also %V and %W.
+
*!
+
*! %V The ISO 8601 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the new year. See also %U and %W.
+
*!
+
*! %w The day of the week as a decimal, range 0 to 6, Sunday being 0. See also %u.
+
*/
+
PIKEFUN string strftime(string(1..255) format)
+
{
+
char *buffer = xalloc( 8192 );
+
buffer[0] = 0;
+
strftime_zone( buffer, 8192, format->str, &THIS->t );
+
push_text( buffer );
+
}
+
+
/*
+
*! @decl int(0..60) sec;
+
*! @decl int(0..59) min;
+
*! @decl int(0..59) hour;
+
*! @decl int(1..31) mday;
+
*! @decl int(0..11) mon;
+
*! @decl int year;
+
*!
+
*! The various fields in the structure. Note that setting these
+
*! might cause other fields to be recalculated, as an example,
+
*! adding 1000 to the hour field would advance the 'mday', 'mon'
+
*! and possibly 'year' fields.
+
*!
+
*! When read the fields are always normalized.
+
*!
+
*! Unlike the system struct tm the 'year' field is not year-1900,
+
*! instead it is the actual year.
+
*/
+
PIKEFUN int(0..60) `sec() { FIX_THIS();RETURN THIS->t.tm_sec; }
+
PIKEFUN int(0..59) `min() { FIX_THIS();RETURN THIS->t.tm_min; }
+
PIKEFUN int(0..23) `hour() { FIX_THIS();RETURN THIS->t.tm_hour; }
+
PIKEFUN int(1..31) `mday() { FIX_THIS();RETURN THIS->t.tm_mday; }
+
PIKEFUN int(0..11) `mon() { FIX_THIS();RETURN THIS->t.tm_mon; }
+
PIKEFUN int `year() { FIX_THIS();RETURN THIS->t.tm_year+1900; }
+
+
PIKEFUN int `sec=(int a) { MODIFY(tm_sec=a); }
+
PIKEFUN int `min=(int a) { MODIFY(tm_min=a); }
+
PIKEFUN int `hour=(int a){ MODIFY(tm_hour=a); }
+
PIKEFUN int `mday=(int a){ MODIFY(tm_mday=a); }
+
PIKEFUN int `year=(int a){ MODIFY(tm_year=a-1900); }
+
PIKEFUN int `mon=(int a){ MODIFY(tm_mon=a); }
+
+
/*! @decl int isdst
+
*!
+
*! True if daylight savings are in effect. If this field is -1
+
*! (the default) it (and the timezone info) will be updated
+
*! automatically using the timezone rules.
+
*/
+
PIKEFUN int(-1..1) `isdst() {
+
FIX_THIS();
+
RETURN THIS->t.tm_isdst;
+
}
+
+
/*! @decl int wday
+
*! The day of the week, sunday is 0, saturday is 6.
+
*! This is calculated from the other fields and can not be changed directly.
+
*/
+
PIKEFUN int(0..6) `wday() { FIX_THIS(); RETURN THIS->t.tm_wday; }
+
+
/*! @decl int yday
+
*! The day of the year, from 0 (the first day) to 365
+
*! This is calculated from the other fields and can not be changed directly.
+
*/
+
PIKEFUN int(0..365) `yday() { FIX_THIS(); RETURN THIS->t.tm_yday; }
+
+
/*! @decl int unix_time()
+
*! Return the unix time corresponding to this time_t. If no time
+
*! can be parsed from the structure -1 is returned.
+
*/
+
PIKEFUN int unix_time()
+
{
+
FIX_THIS();
+
RETURN THIS->unix_time;
+
}
+
+
/*! @decl string asctime()
+
*! Return a string representing the time. Mostly useful for debug
+
*! purposes, the exact format is very locale (see
+
*! @[Gettext.setlocale]) and OS dependent.
+
*/
+
PIKEFUN string asctime()
+
{
+
FIX_THIS();
+
{
+
char *tval = asctime_zone( &THIS->t );
+
if( tval )
+
push_text( tval );
+
else
+
push_text( 0 );
+
}
+
}
+
+
PIKEFUN void _sprintf( int flag, mapping options )
+
{
+
int post_sum = 1;
+
switch( flag )
+
{
+
case 'O':
+
push_text("System.TM(");
+
post_sum = 1;
+
/* fallthrough */
+
case 's':
+
f_TM_asctime(0);
+
push_text("\n");
+
if( THIS->t.tm_zone )
+
{
+
push_text(" ");
+
push_text( THIS->t.tm_zone );
+
f_add( 2 );
+
}
+
else
+
push_text("");
+
f_replace( 3 );
+
break;
+
case 'd':
+
f_TM_unix_time(0);
+
break;
+
default:
+
Pike_error("Can not format as %c", flag );
+
}
+
if( post_sum )
+
{
+
push_text(")");
+
f_add(3);
+
}
+
+
}
+
+
PIKEFUN mixed cast( string to )
+
{
+
struct pike_string *s_string, *s_int;
+
MAKE_CONST_STRING(s_int, "int");
+
MAKE_CONST_STRING(s_string, "string");
+
if( to == s_int )
+
{
+
f_TM_unix_time(0);
+
return;
+
}
+
if( to == s_string )
+
{
+
f_TM_asctime(0);
+
return;
+
}
+
Pike_error("Does not know how to cast to %s\n", to->str );
+
}
+
+
/*! @decl string zone
+
*!
+
*! The timezone of this structure
+
*/
+
PIKEFUN string `zone() {
+
FIX_THIS();
+
if( THIS->t.tm_zone )
+
push_text( THIS->t.tm_zone );
+
else
+
push_undefined();
+
}
+
+
/*! @decl int gmtoff
+
*! The offset from GMT for the time in this tm-struct
+
*/
+
PIKEFUN int `gmtoff() {
+
FIX_THIS();
+
push_int( THIS->t.tm_gmtoff );
+
}
+
+
/* Setting the zone does not work, so.. */
+
+
/* PIKEFUN string `zone=(string x) { */
+
/* if( THIS->set_zone ) */
+
/* free_string( THIS->set_zone ); */
+
/* THIS->set_zone = x; */
+
/* MODIFY( tm_zone = x->str ); */
+
/* x->refs++; */
+
/* } */
+
+
/*! @decl int(0..1) localtime( int time )
+
*! Initialize the struct tm to the local time for the specified
+
*! unix time_t.
+
*/
+
PIKEFUN int(0..1) localtime( int _t )
+
{
+
time_t t = _t;
+
struct tm *res = localtime_zone( &t, &THIS->t );
+
+
/* These are supposedly correctly by localtime_zone. */
+
res->tm_gmtoff = THIS->t.tm_gmtoff;
+
res->tm_zone = THIS->t.tm_zone;
+
+
if( !res )
+
RETURN 0;
+
THIS->t = *res;
+
THIS->modified = 1;
+
RETURN 1;
+
}
+
+
+
/*! @decl int(0..1) gmtime( int time )
+
*! Initialize the struct tm to the UTC time for the specified
+
*! unix time_t.
+
*/
+
PIKEFUN int(0..1) gmtime( int _t )
+
{
+
time_t t = _t;
+
struct tm *res = gmtime( &t );
+
+
if( !res )
+
RETURN 0;
+
+
THIS->t = *res;
+
THIS->modified = 1;
+
RETURN 1;
+
}
+
+
/*! @decl void create(int t)
+
*! Create a new @[TM] initialized from a unix time_t.
+
*! The timezone will always be UTC when using this function.
+
*/
+
PIKEFUN void create( int _t )
+
{
+
f_TM_gmtime( 1 );
+
if( Pike_sp[-1].u.integer == 0 )
+
Pike_error("time out of range\n");
+
}
+
+
/*! @decl void create()
+
*! Construct a new TM, all fields will be set to 0.
+
*/
+
PIKEFUN void create( )
+
{
+
memset( &THIS->t, 0, sizeof( struct tm ) );
+
THIS->t.tm_isdst = -1;
+
THIS->unix_time = 0;
+
THIS->modified = 1;
+
}
+
+
/*! @decl void create( int year, int(0..11) mon, int(1..31) mday, @
+
*! int(0..24) hour, int(0..59) min, int(0..59) sec, @
+
*! string|void timezone )
+
*! Construct a new time using the given values.
+
*! Slightly faster than setting them individually.
+
*/
+
PIKEFUN void create( int year, int(0..11) mon, int(1..31) mday,
+
int(0..24) hour, int(0..59) min, int(0..59) sec,
+
string|void timezone )
+
{
+
struct tm *t = &THIS->t;
+
t->tm_isdst = -1;
+
t->tm_year = year - 1900;
+
t->tm_mon = mon;
+
t->tm_mday = mday;
+
t->tm_hour = hour;
+
t->tm_min = min;
+
t->tm_sec = sec;
+
if (THIS->set_zone) {
+
free_string(THIS->set_zone);
+
THIS->set_zone = NULL;
+
}
+
if( !timezone ) /* gmtime. */
+
t->tm_zone = "UTC";
+
else
+
{
+
add_ref(timezone);
+
THIS->set_zone = timezone;
+
t->tm_zone = timezone->str;
+
}
+
THIS->unix_time = mktime_zone( t );
+
}
+
+
INIT {
+
THIS->set_zone = 0;
+
THIS->modified = 0;
+
}
+
+
EXIT {
+
if( THIS->set_zone )
+
free_string( THIS->set_zone );
+
}
+
}
+
#undef FIX_THIS
+
#ifdef STRUCT_TM_HAS___TM_GMTOFF
+
#undef tm_zone
+
#endif
+
#endif
+
/*! @endmodule
+
*/
+
/*! @decl array(array(int|string|type)) describe_program(program p) *! @belongs Debug *! *! Debug function for showing the symbol table of a program. *! *! @returns *! Returns an array of arrays with the following information *! for each symbol in @[p]: *! @array *! @elem int modifiers
pike.git/src/builtin.cmod:981:
case 0: DO_IT (p_wchar0,SPACECASE8); break; case 1: DO_IT (p_wchar1,SPACECASE16); break; case 2: DO_IT (p_wchar2,SPACECASE16); break; #undef DO_IT #undef SPACECASE8 #undef SPACECASE16 } RETURN string_slice (s, start, end + 1 - start); }
+
/*! @decl string status(int verbose)
+
*! @belongs String
+
*!
+
*! Get string table statistics.
+
*!
+
*! @returns
+
*! Returns a string with an ASCII table containing
+
*! the current string table statistics.
+
*!
+
*! @note
+
*! Currently returns the empty string (@expr{""@})
+
*! if @[verbose] is zero.
+
*!
+
*! @note
+
*! The formatting and contents of the result
+
*! may vary between different versions of Pike.
+
*/
+
PIKEFUN string string_status(int verbose)
+
errname String.status;
+
{
+
RETURN add_string_status(verbose);
+
}
+
/*! @decl int implements(program prog, program api) *! @belongs Program *! *! Returns 1 if @[prog] implements @[api]. */ PMOD_EXPORT PIKEFUN int program_implements(program prog, program api) errname Program.implements; optflags OPT_TRY_OPTIMIZE; {
pike.git/src/builtin.cmod:1050:
} else push_int(0); } /*! @decl int(8..8)|int(16..16)|int(32..32) width(string s) *! @belongs String *! *! Returns the width of a string. *!
-
*! Three return values are possible:
-
*! @int
-
*! @value 8
-
*! The string @[s] only contains characters <= 255.
-
*! @value 16
-
*! The string @[s] only contains characters <= 65535.
-
*! @value 32
-
*! The string @[s] contains characters >= 65536.
-
*! @endint
+
*!
@returns
+
*!
Three return values are
currently
possible:
+
*!
@int
+
*!
@value 8
+
*!
The string @[s] only contains characters <= 255.
+
*!
@value 16
+
*!
The string @[s] only contains characters <= 65535.
+
*!
@value 32
+
*!
The string @[s] contains characters >= 65536.
+
*!
@endint
+
*!
+
*! @note
+
*! It is possible that a future version of Pike may return
+
*! further values. In particular the width @expr{7@} seems
+
*! like it could be useful.
*/ PMOD_EXPORT PIKEFUN int(8 .. 8)|int(16 .. 16)|int(32 .. 32) string_width(string s) errname String.width; optflags OPT_TRY_OPTIMIZE; { RETURN 8 * (1 << s->size_shift); } /*! @decl mixed m_delete(object|mapping map, mixed index)
pike.git/src/builtin.cmod:1403:
*! This function returns a random number in the range 0 - @[max]-1. *! *! @seealso *! @[random_seed()] */ PMOD_EXPORT PIKEFUN int random(int i) { if(i <= 0) RETURN 0;
-
#if
defined (AUTO_BIGNUM) &&
SIZEOF_INT_TYPE > 4
+
#if SIZEOF_INT_TYPE > 4
if(i >> 31) { unsigned INT_TYPE a = my_rand(); unsigned INT_TYPE b = my_rand(); RETURN (INT_TYPE)(((a<<32)|b) % i); } #endif RETURN my_rand() % i; } PMOD_EXPORT
pike.git/src/builtin.cmod:2132:
push_constant_text("bytecode_method"); push_constant_text(PIKE_BYTECODE_METHOD_NAME); push_constant_text("abi"); push_int(sizeof(void *) * 8); push_constant_text("native_byteorder"); push_int(PIKE_BYTEORDER); push_constant_text("int_size"); push_int(sizeof(INT_TYPE) * 8); push_constant_text("float_size"); push_int(sizeof(FLOAT_TYPE) * 8);
-
#ifdef AUTO_BIGNUM
+
push_constant_text("auto_bignum"); push_int(1); f_aggregate_mapping(6*2);
-
#else
-
f_aggregate_mapping(5*2);
-
#endif
+
} /*! @endmodule */ void low_backtrace(struct Pike_interpreter_struct *i) { struct svalue *stack_top = i->stack_pointer; struct pike_frame *f, *of = 0; int size = 0;
pike.git/src/builtin.cmod:2319:
*/ PIKECLASS Buffer { CVAR struct string_builder str; CVAR int initial; void f_Buffer_get_copy( INT32 args ); void f_Buffer_get( INT32 args ); void f_Buffer_add( INT32 args );
-
+
/*! @decl void create(int initial_size) *! *! Initializes a new buffer. *! *! If no @[initial_size] is specified, 256 is used. If you *! know approximately how big the buffer will be, you can optimize *! the operation of @[add()] (slightly) by passing the size to this *! function. */ PIKEFUN void create( int|void size ) { struct Buffer_struct *str = THIS;
-
if(
args
)
+
if(
size
)
str->initial = MAXIMUM( size->u.integer, 512 ); else str->initial = 256; } /*! @decl string _sprintf( int flag, mapping flags ) *! It is possible to @[sprintf] a String.Buffer object *! as @tt{%s@} just as if it was a string. */ PIKEFUN string _sprintf( int flag, mapping flags )
pike.git/src/builtin.cmod:2588:
/*! @decl void putchar(int c) *! Appends the character @[c] at the end of the string. */ PIKEFUN void putchar(int c) { struct Buffer_struct *str = THIS; if(!str->str.s) init_string_builder_alloc(&str->str, str->initial, 0); string_builder_putchar(&str->str, c); }
+
/*! @decl int sprintf(strict_sprintf_format format, sprintf_args ... args)
+
*! Appends the output from @[sprintf] at the end of the string.
+
*! Returns the resulting size of the String.Buffer.
+
*/
+
PIKEFUN int sprintf(mixed ... arguments)
+
rawtype tFuncV(tAttr("strict_sprintf_format", tOr(tStr, tObj)),
+
tAttr("sprintf_args", tMix), tStr);
+
+
{
+
// FIXME: Reset length on exception?
+
struct Buffer_struct *str = THIS;
+
if(!str->str.s)
+
init_string_builder_alloc(&str->str, str->initial, 0);
+
low_f_sprintf(args, 0, &str->str);
+
RETURN str->str.s->len;
+
}
+
/*! @decl string get_copy() *! *! Get the data from the buffer. Significantly slower than @[get], *! but does not clear the buffer. */ PIKEFUN string get_copy() { struct pike_string *str = THIS->str.s; if( str ) {
pike.git/src/builtin.cmod:3352:
PIKEFUN int `usec_full() { struct timeval now; if( THIS->hard_update ) ACCURATE_GETTIMEOFDAY( &now ); else INACCURATE_GETTIMEOFDAY( &now );
-
#ifdef AUTO_BIGNUM
+
push_int( now.tv_sec ); push_int( 1000000 ); f_multiply( 2 ); push_int( now.tv_usec ); f_add( 2 ); return;
-
#else
-
RETURN (now.tv_sec * 1000000 + now.tv_usec);
-
#endif
+
} /*! @decl protected void create( int fast ); *! *! If @[fast] is true, do not request a new time from the system, *! instead use the global current time variable. *! *! This will only work in callbacks, but can save significant amounts *! of CPU. */
pike.git/src/builtin.cmod:3568:
push_svalue(tmpargs+e); } } check_stack(depth * (args+1)); low_automap(1,depth,fun,tmpargs,args-1); stack_unlink(args); } /* Linked list stuff. */
-
#undef
INIT
_
BLOCK
-
#define
INIT
_
BLOCK(NODE)
do { \
-
(NODE)->next
=
(NODE)->prev = NULL; \
-
(NODE)->refs = 1; \
-
SET
_
SVAL
((
NODE)->val,
T
_
INT, NUMBER
_
UNDEFINED
,
\
-
integer, 0
);
\
-
} while(0)
+
static
struct block
_
allocator
pike
_
list_node_allocator
=
BA
_
INIT_PAGES
(
sizeof
(
struct
pike
_
list
_
node)
,
4
);
-
#undef EXIT_BLOCK
-
#define EXIT_BLOCK
(
NODE
)
do { \
-
if
(
(NODE
)
->prev)
{
\
-
free
_list_node
((NODE
)
->prev)
;
\
-
} \
-
if ((NODE)
->next
)
{
\
-
free_list_
node
((NODE)
->
next);
\
-
} \
-
free
_
svalue
(
&(NODE)
->val
);
\
-
}
while(0)
+
ATTRIBUTE
(
(malloc
)
)
+
static
struct
pike_list_node
*
alloc_pike_list_node
() {
+
struct
pike_list_node
*
node
=
ba
_
alloc(&pike_
list_node
_allocator
);
+
node
->next
=
node->prev
=
NULL;
+
node->
refs
=
1;
+
SET
_
SVAL
(
node
->val
,
T_INT,
NUMBER_UNDEFINED,
integer,
0);
+
return
node;
+
}
-
BLOCK
_
ALLOC
_
FILL
_
PAGES
(pike_list_node,
4
);
+
void count
_
memory
_
in
_
pike_list_nodes
(
size_t * n, size_t * s) {
+
ba_count_all(&
pike_list_node
_allocator
,
n, s
);
+
}
-
+
void free_all_pike_list_node_blocks() {
+
ba_destroy(&pike_list_node_allocator);
+
}
+
PMOD_EXPORT void free_list_node(struct pike_list_node *node) { if (!sub_ref(node)) {
-
really_
free_
pike_
list_node(node);
+
if (node->prev) {
+
free_list_node(node
->prev
);
}
-
+
if (node->next) {
+
free_list_node(node->next);
}
-
+
free_svalue(&node->val);
+
ba_free(&pike_list_node_allocator, node);
+
}
+
}
PMOD_EXPORT void unlink_list_node(struct pike_list_node *n) { #ifdef PIKE_DEBUG if (!n) { Pike_fatal("Unlinking NULL node.\n"); } if (!n->next || !n->prev) { Pike_fatal("Unlinking unlinked node.\n"); }
pike.git/src/builtin.cmod:3889:
*/ PIKEFUN string encode_json(...) { push_constant_text ("null"); } } /*! @endclass */
+
PMOD_EXPORT
+
PIKEFUN int levenshtein_distance(string a, string b)
+
{
+
int i, j, n, *lev_i, *lev_p;
+
+
/* Simple cases: strings are equal or one of them is empty: */
+
if (a == b) RETURN 0;
+
if (a->len == 0) RETURN b->len;
+
if (b->len == 0) RETURN a->len;
+
+
/* Return -1 if any of the strings is wider than 8 bits: */
+
if (a->size_shift || b->size_shift) RETURN -1;
+
+
/* Allocate two rows on the stack: */
+
n = b->len+1;
+
lev_i = alloca(n*sizeof(int));
+
lev_p = alloca(n*sizeof(int));
+
if (!lev_i || !lev_p) RETURN -1;
+
+
/* Initialise the first row */
+
for (j = 0; j < n; j++) lev_i[j] = j;
+
+
for (i = 0; i < a->len; i++)
+
{
+
/* lev_p = row for i, lev_i = row for i+1: */
+
memcpy(lev_p, lev_i, n*sizeof(int));
+
lev_i[0] = i + 1;
+
for (j = 0; j < b->len; j++)
+
{
+
int cost = (a->str[i] == b->str[j]) ? 0 : 1;
+
int test, min_val = lev_i[j]+1;
+
if ((test = lev_p[j+1]+1) < min_val) min_val = test;
+
if ((test = lev_p[j]+cost) < min_val) min_val = test;
+
lev_i[j+1] = min_val;
+
}
+
}
+
RETURN lev_i[b->len];
+
}
+
/*! @endmodule */ /*! @module Serializer */ /*! @class Serializable *! *! The base class for serializable objects. *!
pike.git/src/builtin.cmod:5147:
PIKECLASS __Backtrace_Tester__ { INIT { Pike_error("__Backtrace_Tester__\n"); } } void init_builtin(void) {
-
init_pike_list_node_blocks();
+
INIT } void exit_builtin(void) { if (val_module) free_object (val_module); EXIT #ifndef DO_PIKE_CLEANUP /* This is performed by exit_builtin_modules() at a later point * in this case, so that the pike_list_node's are valid at cleanup * time, thus avoiding "got invalid pointer" fatals at exit. */
-
free
_
all_
pike_list_node_
blocks(
);
+
ba
_
destroy(&
pike_list_node_
allocator
);
#endif #ifndef USE_SETENV if (env_allocs) free_mapping (env_allocs); #endif }