/* * SPL - The SPL Programming Language * Copyright (C) 2005, 2006 Michael Bauer * Copyright (C) 2006 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * mod_time.c: A simple spl module for time and time manipulations. */ /** * A module for time and time manipulations */ #include #include #include "spl.h" #include "compat.h" extern void SPL_ABI(spl_mod_time_init)(struct spl_vm *vm, struct spl_module *mod, int restore); extern void SPL_ABI(spl_mod_time_done)(struct spl_vm *vm, struct spl_module *mod); /* conversion of node to struct tm */ static void convert_node_to_tm(struct spl_task *task, struct spl_node *node, struct tm *ttm) { memset(ttm, 0, sizeof(struct tm)); ttm->tm_sec = spl_get_int(spl_lookup(task, node, "sec", SPL_LOOKUP_TEST)); ttm->tm_min = spl_get_int(spl_lookup(task, node, "min", SPL_LOOKUP_TEST)); ttm->tm_hour = spl_get_int(spl_lookup(task, node, "hour", SPL_LOOKUP_TEST)); ttm->tm_mday = spl_get_int(spl_lookup(task, node, "mday", SPL_LOOKUP_TEST)); ttm->tm_mon = spl_get_int(spl_lookup(task, node, "mon", SPL_LOOKUP_TEST)); ttm->tm_year = spl_get_int(spl_lookup(task, node, "year", SPL_LOOKUP_TEST)); ttm->tm_wday = spl_get_int(spl_lookup(task, node, "wday", SPL_LOOKUP_TEST)); ttm->tm_yday = spl_get_int(spl_lookup(task, node, "yday", SPL_LOOKUP_TEST)); ttm->tm_isdst = spl_get_int(spl_lookup(task, node, "isdst", SPL_LOOKUP_TEST)); #if !defined USECYGWINAPI && !defined USEWIN32API && !defined USEIRIXAPI ttm->tm_zone = spl_get_string(spl_lookup(task, node, "zone", SPL_LOOKUP_TEST)); ttm->tm_gmtoff = spl_get_int(spl_lookup(task, node, "gmtoff", SPL_LOOKUP_TEST)); #endif spl_put(task->vm, node); } /* conversion of struct tm to node */ static struct spl_node *convert_tm_to_node(struct spl_task *task, struct tm *ttm) { struct spl_node *result = spl_get(0); spl_create(task, result, "sec", SPL_NEW_INT(ttm->tm_sec), SPL_CREATE_LOCAL); spl_create(task, result, "min", SPL_NEW_INT(ttm->tm_min), SPL_CREATE_LOCAL); spl_create(task, result, "hour", SPL_NEW_INT(ttm->tm_hour), SPL_CREATE_LOCAL); spl_create(task, result, "mday", SPL_NEW_INT(ttm->tm_mday), SPL_CREATE_LOCAL); spl_create(task, result, "mon", SPL_NEW_INT(ttm->tm_mon), SPL_CREATE_LOCAL); spl_create(task, result, "year", SPL_NEW_INT(ttm->tm_year), SPL_CREATE_LOCAL); spl_create(task, result, "wday", SPL_NEW_INT(ttm->tm_wday), SPL_CREATE_LOCAL); spl_create(task, result, "yday", SPL_NEW_INT(ttm->tm_yday), SPL_CREATE_LOCAL); spl_create(task, result, "isdst", SPL_NEW_INT(ttm->tm_isdst), SPL_CREATE_LOCAL); #if !defined USECYGWINAPI && !defined USEWIN32API && !defined USEIRIXAPI spl_create(task, result, "zone", SPL_NEW_STRING_DUP(ttm->tm_zone), SPL_CREATE_LOCAL); spl_create(task, result, "gmtoff", SPL_NEW_INT(ttm->tm_gmtoff), SPL_CREATE_LOCAL); #endif return result; } /** * This function returns the number of seconds since the epoch. */ // builtin time() static struct spl_node *handler_time(struct spl_task UNUSED(*task), void UNUSED(*data)) { return SPL_NEW_INT(time(NULL)); } /** * This function converts the number of seconds since the epoch (as * returned by [[time()]]) so a node with the childs .sec, .min, .hour, .mday * .month, .wday, .year, .yday, .gmtoff, .isdst and .zone. (It is simply a * wrapper to the struct tm as defined in time.h.) */ // builtin time_local(time) static struct spl_node *handler_localtime(struct spl_task *task, void UNUSED(*data)) { time_t tt = spl_clib_get_int(task); struct tm ttm; #ifdef USEWIN32API ttm = *localtime(&tt); #else localtime_r(&tt, &ttm); #endif return convert_tm_to_node(task, &ttm); } /** * This function converts the nuber of seconds since the epoch (as * treturned by [[time()]]) to a time node as returned by [[time_local()]], * but in GMT. */ // builtin time_gm(time) static struct spl_node *handler_gmtime(struct spl_task *task, void UNUSED(*data)) { time_t tt = spl_clib_get_int(task); struct tm ttm; #ifdef USEWIN32API ttm = *gmtime(&tt); #else gmtime_r(&tt, &ttm); #endif return convert_tm_to_node(task, &ttm); } /** * This function returns the difference in seconds between time1 and time0. * It expects two ints containing the number of seconds since the epoch as * returned by [[time()]]. */ // builtin time_diff(time1, time0) static struct spl_node *handler_difftime(struct spl_task *task, void UNUSED(*data)) { return SPL_NEW_INT(difftime(spl_clib_get_int(task), spl_clib_get_int(task))); } /** * This Function formats a time node as returned by [[time_local()]] according * to the strftime manpage. This is simply a wrapper to the strftime() C * library function. */ // builtin time_fmt(format, tm) static struct spl_node *handler_fmttime(struct spl_task *task, void UNUSED(*data)) { char *format = spl_clib_get_string(task); struct tm ttm; convert_node_to_tm(task, spl_clib_get_node(task), &ttm); int buffer_len = strlen(format) + 1024; char buffer[buffer_len]; int rc = strftime(buffer, buffer_len-1, format, &ttm); return rc > 0 ? SPL_NEW_STRING_DUP(buffer) : SPL_NEW_STRING_DUP(""); } /** * This function converts a time node as returned by [[time_local()]] to the * count of seconds since the epoch as returned by [[time()]]. */ // builtin time_mk(tm) static struct spl_node *handler_mktime(struct spl_task *task, void UNUSED(*data)) { struct tm ttm; convert_node_to_tm(task, spl_clib_get_node(task), &ttm); return SPL_NEW_INT(mktime(&ttm)); } /** * This function converts a time node as returned by [[time_gm()]] to the * count of seconds since the epoch as returned by [[time()]], it works similar * to mktime but assumes the time node is in GMT. * * This function is not available on the CYGWIN platform. */ // builtin time_mkgm(tm) #if !defined USECYGWINAPI && !defined USEWIN32API && !defined USEIRIXAPI static struct spl_node *handler_timegm(struct spl_task *task, void UNUSED(*data)) { struct tm ttm; convert_node_to_tm(task, spl_clib_get_node(task), &ttm); return SPL_NEW_INT(timegm(&ttm)); } #endif void SPL_ABI(spl_mod_time_init)(struct spl_vm *vm, struct spl_module UNUSED(*mod), int UNUSED(restore)) { spl_clib_reg(vm, "time", handler_time, 0); spl_clib_reg(vm, "time_local", handler_localtime, 0); spl_clib_reg(vm, "time_gm", handler_gmtime, 0); spl_clib_reg(vm, "time_diff", handler_difftime, 0); spl_clib_reg(vm, "time_fmt", handler_fmttime, 0); spl_clib_reg(vm, "time_mk", handler_mktime, 0); #if !defined USECYGWINAPI && !defined USEWIN32API && !defined USEIRIXAPI spl_clib_reg(vm, "time_mkgm", handler_timegm, 0); #endif return; } void SPL_ABI(spl_mod_time_done)(struct spl_vm UNUSED(*vm), struct spl_module UNUSED(*mod)) { return; }