File: mod_time.c

package info (click to toggle)
spl 1.0~pre2-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,240 kB
  • ctags: 1,987
  • sloc: ansic: 15,272; yacc: 3,167; sh: 272; makefile: 186; xml: 156
file content (202 lines) | stat: -rw-r--r-- 7,452 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 *  SPL - The SPL Programming Language
 *  Copyright (C) 2005, 2006  Michael Bauer <mihi@lo-res.org>
 *  Copyright (C) 2006  Clifford Wolf <clifford@clifford.at>
 *
 *  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
 */

#define _GNU_SOURCE

#include <stdlib.h>
#include <time.h>

#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 *task UNUSED, void *data UNUSED)
{
	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 *data UNUSED)
{
	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 *data UNUSED)
{
	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 *data UNUSED)
{
	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 *data UNUSED)
{
	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 *data UNUSED)
{
	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 *data UNUSED)
{
	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 *mod UNUSED, int restore UNUSED)
{
	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 *vm UNUSED, struct spl_module *mod UNUSED)
{
	return;
}