pike.git / src / builtin.cmod

version» Context lines:

pike.git/src/builtin.cmod:37:   #include <errno.h>   #include <math.h>   #include <fcntl.h>      #ifdef HAVE_ARPA_INET_H   #include <arpa/inet.h>   #endif /* HAVE_ARPA_INET_H */      #define DEFAULT_CMOD_STORAGE    + #ifdef STRUCT_TM_HAS___TM_GMTOFF +  struct tm_extra { }; + #define tm_zone __tm_zone + #define tm_gmtoff __tm_gmtoff + #define GET_GMTOFF(TM) ((TM)->tm_gmtoff) + #define GET_ZONE(this) ((this)->t.tm_zone) + #define SET_GMTOFF(TM, VAL) (((TM)->tm_gmtoff) = (VAL)) + #define SET_ZONE(this, VAL) ((this)->t.tm_zone = (VAL)) + #elif defined(STRUCT_TM_HAS_GMTOFF) +  struct tm_extra { }; + #define GET_GMTOFF(TM) ((TM)->tm_gmtoff) + #define GET_ZONE(this) ((this)->t.tm_zone) + #define SET_GMTOFF(TM, VAL) (((TM)->tm_gmtoff) = (VAL)) + #define SET_ZONE(this, VAL) ((this)->t.tm_zone = (VAL)) + #else +  struct tm_extra { const char *tm_zone; }; + #define GET_GMTOFF(TM) 0 + #define GET_ZONE(this) ((this)->extra.tm_zone) + #define SET_GMTOFF(TM, VAL) (VAL) + #define SET_ZONE(this, VAL) ((this)->extra.tm_zone = (VAL)) + #endif +    DECLARATIONS    -  +    /*! @module System    */      /*! @class TM    *! A wrapper for the system struct tm time keeping structure.    *! This can be used as a (very) lightweight alternative to Calendar.    */   PIKECLASS TM   {    CVAR struct tm t;    CVAR time_t unix_time;    CVAR int modified; -  CVAR struct pike_string *set_zone; +  CVAR struct tm_extra extra;    - #ifdef STRUCT_TM_HAS___TM_GMTOFF - #define tm_zone __tm_zone - #define tm_gmtoff __tm_gmtoff - #define GET_GMTOFF(TM) ((TM)->tm_gmtoff) - #define GET_ZONE(TM) ((TM)->tm_zone) - #define SET_GMTOFF(TM, VAL) (((TM)->tm_gmtoff) = (VAL)) - #define SET_ZONE(TM, VAL) (((TM)->tm_zone) = (VAL)) - #elif defined(STRUCT_TM_HAS_GMTOFF) - #define GET_GMTOFF(TM) ((TM)->tm_gmtoff) - #define GET_ZONE(TM) ((TM)->tm_zone) - #define SET_GMTOFF(TM, VAL) (((TM)->tm_gmtoff) = (VAL)) - #define SET_ZONE(TM, VAL) (((TM)->tm_zone) = (VAL)) - #else - #define GET_GMTOFF(TM) 0 - #define GET_ZONE(TM) ((char*)NULL) - #define SET_GMTOFF(TM, VAL) (VAL) - #define SET_ZONE(TM, VAL) (VAL) - #endif -  +    #define strftime_zone strftime - #define mktime_zone mktime +    #define strptime_zone strptime   #define localtime_zone(X,Y) localtime(X)   #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; \ -  } \ +  if(THIS->modified) \ +  fix_tm(THIS); \    } while(0)    -  +  static void fix_tm(struct TM_struct *this) +  { +  const char *tm_zone = GET_ZONE(this); +  int is_utc_zone = tm_zone && !strcmp(tm_zone, "UTC"); +  if (is_utc_zone) +  this->t.tm_isdst = 0; +  this->unix_time = mktime_zone(&this->t, is_utc_zone, 0); +  this->modified = 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.    *!    *! @dl    *! @item %%    *! The % character.    *!    *! @item %a or %A
pike.git/src/builtin.cmod:355:    *!    *! 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 `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 +  *! True if daylight-saving is 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; } +  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;    }
pike.git/src/builtin.cmod:407:    *! 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();    {   #define STRFTIME_MAXSIZE 26    char s[STRFTIME_MAXSIZE]; -  if( !strftime(s, STRFTIME_MAXSIZE, "%c", &THIS->t) ) +  if( !strftime(s, STRFTIME_MAXSIZE, "%c\n", &THIS->t) )    push_undefined();    else    push_text(s);    }    }       PIKEFUN string _sprintf( int flag, mapping options )    { -  int post_sum = 1; +  int post_sum = 0;    switch( flag )    {    case 'O':    push_static_text("System.TM(");    post_sum = 1;    /* fallthrough */    case 's':    f_TM_asctime(0);    push_static_text("\n"); -  if( GET_ZONE(&(THIS->t)) ) +  if( GET_ZONE(THIS) )    {    push_static_text(" "); -  push_text( GET_ZONE(&(THIS->t)) ); +  push_text( GET_ZONE(THIS) );    f_add( 2 );    }    else    push_static_text("");    f_replace( 3 );    break;    case 'd':    f_TM_unix_time(0);    break;    default:
pike.git/src/builtin.cmod:479:    pop_stack();    push_undefined();    }       /*! @decl string zone    *!    *! The timezone of this structure    */    PIKEFUN string `zone() {    FIX_THIS(); -  if( GET_ZONE(&(THIS->t)) ) -  push_text( GET_ZONE(&(THIS->t)) ); +  if( GET_ZONE(THIS) ) +  push_text( GET_ZONE(THIS) );    else    push_undefined();    }       /*! @decl int gmtoff    *! The offset from GMT for the time in this tm-struct    */    PIKEFUN int `gmtoff() {    FIX_THIS();    push_int( GET_GMTOFF(&(THIS->t)) );    }    -  /* 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 );    if( !res )    RETURN 0;    -  /* These are supposedly correctly by localtime_zone. */ -  SET_GMTOFF(res, GET_GMTOFF(&(THIS->t))); -  SET_ZONE(res, GET_ZONE(&(THIS->t))); -  +     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; -  +  SET_ZONE(THIS, "UTC"); /* Override timezone */    THIS->modified = 1;    RETURN 1;    }    -  /*! @decl void create(int t) +  /*! @decl int(0..1) gmtime( Gmp.mpz time ) +  *! Initialize the struct tm to the UTC time for the specified +  *! unix time_t. +  */ +  PIKEFUN int(0..1) gmtime( object(Gmp.mpz)|object(Gmp.bignum) _t ) +  { +  INT64 t_int64 = 0; +  time_t t; +  struct tm *res; +  +  if (!low_int64_from_bignum(&t_int64, _t)) +  RETURN 0; +  +  t = t_int64; +  res = gmtime( &t ); +  +  if( !res ) +  RETURN 0; +  +  THIS->t = *res; +  SET_ZONE(THIS, "UTC"); /* Override timezone */ +  THIS->modified = 1; +  RETURN 1; +  } +  +  /*! @decl void create(int|Gmp.mpz 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 ) +  PIKEFUN void create( int|object(Gmp.mpz)|object(Gmp.bignum) _t )    {    f_TM_gmtime( 1 );    if( Pike_sp[-1].u.integer == 0 )    Pike_error("time out of range\n"); -  +  pop_stack();    }       /*! @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->t.tm_mday = 1;
pike.git/src/builtin.cmod:575:    *! 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; +  int use_utc = 0;    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) { +  if (strcmp(timezone->str, "UTC")) +  Pike_error("Timezone must either be UTC or omitted.\n"); +  use_utc = 1;    } -  if( !timezone ) /* gmtime. */ -  SET_ZONE(t, "UTC"); -  else -  { -  add_ref(timezone); -  THIS->set_zone = timezone; -  SET_ZONE(t, timezone->str); +  if (use_utc) +  t->tm_isdst = 0; +  THIS->unix_time = mktime_zone(&THIS->t, use_utc, 0); +  /* Setting it to other timezones than UTC is not supported (yet) */ +  if (use_utc) +  SET_ZONE(THIS, "UTC"); +  pop_n_elems(args);    } -  THIS->unix_time = mktime_zone( t ); -  } +       #ifdef PIKE_NULL_IS_SPECIAL    INIT { -  THIS->set_zone = 0; +     THIS->modified = 0;    }   #endif -  -  EXIT -  gc_trivial; -  { -  if( THIS->set_zone ) -  free_string( THIS->set_zone ); +    } - } +    /*! @endclass    */   #undef FIX_THIS   #ifdef STRUCT_TM_HAS___TM_GMTOFF   #undef tm_zone   #undef tm_gmtoff   #endif      /*! @endmodule    */
pike.git/src/builtin.cmod:3150:    *! the operation of @[add()] (slightly) by passing the size to this    *! function.    */    PIKEFUN void create( int|void size )    {    struct Buffer_struct *str = THIS;    if( size )    str->initial = MAXIMUM( size->u.integer, 512 );    else    str->initial = 256; +  pop_n_elems(args);    }       /*! @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 )    {    switch( flag )    {
pike.git/src/builtin.cmod:3648:    if (!from_arg || (TYPEOF(*from_arg) != T_ARRAY)) {    SIMPLE_ARG_TYPE_ERROR("replace", 1,    "array(string)|mapping(string:string)");    }    if (TYPEOF(*to_arg) == T_STRING) {    push_int(from_arg->u.array->size);    stack_swap();    f_allocate(2);    to_arg = Pike_sp - 1;    } -  if (TYPEOF(*to_arg) != T_ARRAY) { +  else if (TYPEOF(*to_arg) != T_ARRAY) {    SIMPLE_ARG_TYPE_ERROR("replace", 2, "array(string)|string");    } -  if (from_arg->u.array->size != to_arg->u.array->size) { +  else if (from_arg->u.array->size != to_arg->u.array->size) {    Pike_error("Replace must have equal-sized from and to arrays.\n");    }    add_ref(THIS->from = from_arg->u.array);    add_ref(THIS->to = to_arg->u.array);    } else if (from_arg) {    if (TYPEOF(*from_arg) != T_MAPPING)    Pike_error("Illegal arguments to create().\n");    THIS->from = mapping_indices(from_arg->u.mapping);    THIS->to = mapping_values(from_arg->u.mapping);    } else { -  +  pop_n_elems(args);    return;    }       if (!THIS->from->size) {    /* Enter no-op mode. */ -  +  pop_n_elems(args);    return;    }       if( (THIS->from->type_field & ~BIT_STRING) &&    (array_fix_type_field(THIS->from) & ~BIT_STRING) )    SIMPLE_ARG_TYPE_ERROR("replace", 1,    "array(string)|mapping(string:string)");       if( (THIS->to->type_field & ~BIT_STRING) &&    (array_fix_type_field(THIS->to) & ~BIT_STRING) )    SIMPLE_ARG_TYPE_ERROR("replace", 2, "array(string)|string");       compile_replace_many(&THIS->ctx, THIS->from, THIS->to, 1); -  +  pop_n_elems(args);    }       /*! @decl string `()(string str)    */    PIKEFUN string `()(string str)    {    if (!THIS->ctx.v) {    /* The result is already on the stack in the correct place... */    return;    }
pike.git/src/builtin.cmod:3779:    {    if (THIS->del) {    free_string(THIS->del);    THIS->del = NULL;    }    if (THIS->to) {    free_string(THIS->to);    THIS->to = NULL;    }    -  if (!del) return; +  if (!del) { +  pop_n_elems(args); +  return; +  }       if (!to) {    SIMPLE_ARG_TYPE_ERROR("replace", 2, "string");    }       if (del == to) {    /* No-op... */ -  +  pop_n_elems(args);    return;    }       copy_shared_string(THIS->del, del);    copy_shared_string(THIS->to, to);       if (del->len) {    THIS->mojt = simple_compile_memsearcher(del);    } -  +  pop_n_elems(args);    }       /*** replace function ***/    typedef char *(* replace_searchfunc)(void *,void *,size_t);       /*! @decl string `()(string str)    */    PIKEFUN string `()(string str)    {    int shift;
pike.git/src/builtin.cmod:4370:    *! Array that @[__automap__()] is to loop over.    *!    *! @param depth    *! Recursion depth of @[arr] where the loop will be.    */    PIKEFUN void create(array a, int d)    {    if(THIS->arg) free_array(THIS->arg);    add_ref(THIS->arg=a);    THIS->depth=d; +  pop_n_elems(2);    }       PIKEFUN string _sprintf(int mode, mapping flags)    {    pop_n_elems(args);    if (mode != 'O') {    push_undefined ();    return;    }    push_static_text("%O%*'[*]'n");