PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/system.c

http://github.com/adh/dfsch
C | 269 lines | 202 code | 47 blank | 20 comment | 46 complexity | 6a630630d90c19be607d5b5bd1a1eb97 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, JSON, 0BSD
  1. /*
  2. * dfsch - dfox's quick and dirty scheme implementation
  3. * Basic operating system services
  4. * Copyright (C) 2005-2008 Ales Hakl
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. #include "internal.h"
  22. #include "util.h"
  23. #include <dfsch/dfsch.h>
  24. #include <dfsch/number.h>
  25. #include <time.h>
  26. #ifdef unix
  27. #include <sys/times.h>
  28. #endif
  29. #include <unistd.h>
  30. #include <limits.h>
  31. #include <errno.h>
  32. typedef struct decoded_time_t {
  33. dfsch_type_t* type;
  34. struct tm tm;
  35. } decoded_time_t;
  36. static int decoded_time_equal_p(decoded_time_t* a, decoded_time_t* b){
  37. return (a->tm.tm_sec == b->tm.tm_sec)
  38. && (a->tm.tm_min == b->tm.tm_min)
  39. && (a->tm.tm_hour == b->tm.tm_hour)
  40. && (a->tm.tm_mday == b->tm.tm_mday)
  41. && (a->tm.tm_mon == b->tm.tm_mon)
  42. && (a->tm.tm_year == b->tm.tm_year)
  43. && (a->tm.tm_wday == b->tm.tm_wday)
  44. && (a->tm.tm_yday == b->tm.tm_yday)
  45. && (a->tm.tm_isdst == b->tm.tm_isdst);
  46. }
  47. static void decoded_time_write(decoded_time_t* time,
  48. dfsch_writer_state_t* state){
  49. dfsch_write_unreadable(state, (dfsch_object_t*)time,
  50. "%04d-%02d-%02dT%02d:%02d:%02d",
  51. time->tm.tm_year+1900, time->tm.tm_mon+1,
  52. time->tm.tm_mday,
  53. time->tm.tm_hour, time->tm.tm_min, time->tm.tm_sec);
  54. }
  55. static dfsch_object_t* decoded_time_apply(decoded_time_t* time,
  56. dfsch_object_t* args,
  57. dfsch_tail_escape_t* esc){
  58. dfsch_object_t* selector;
  59. DFSCH_OBJECT_ARG(args, selector);
  60. DFSCH_ARG_END(args);
  61. if (dfsch_compare_keyword(selector, "sec")){
  62. return dfsch_make_number_from_long(time->tm.tm_sec);
  63. } else if (dfsch_compare_keyword(selector, "min")){
  64. return dfsch_make_number_from_long(time->tm.tm_min);
  65. } else if (dfsch_compare_keyword(selector, "hour")){
  66. return dfsch_make_number_from_long(time->tm.tm_hour);
  67. } else if (dfsch_compare_keyword(selector, "date")){
  68. return dfsch_make_number_from_long(time->tm.tm_mday);
  69. } else if (dfsch_compare_keyword(selector, "month")){
  70. return dfsch_make_number_from_long(time->tm.tm_mon + 1);
  71. } else if (dfsch_compare_keyword(selector, "year")){
  72. return dfsch_make_number_from_long(time->tm.tm_year + 1900);
  73. } else if (dfsch_compare_keyword(selector, "day")){
  74. return dfsch_make_number_from_long(time->tm.tm_wday);
  75. } else if (dfsch_compare_keyword(selector, "year-day")){
  76. return dfsch_make_number_from_long(time->tm.tm_yday + 1);
  77. } else if (dfsch_compare_keyword(selector, "dst?")){
  78. return dfsch_bool(time->tm.tm_isdst == 1);
  79. }
  80. dfsch_error("Unknown field requested", selector);
  81. }
  82. size_t decoded_time_hash(decoded_time_t* time){
  83. return time->tm.tm_sec ^ time->tm.tm_min ^ time->tm.tm_hour
  84. ^ time->tm.tm_yday ^ time->tm.tm_year;
  85. }
  86. dfsch_type_t decoded_time_type = {
  87. DFSCH_STANDARD_TYPE,
  88. NULL,
  89. sizeof(decoded_time_t),
  90. "decoded-time",
  91. (dfsch_type_equal_p_t)decoded_time_equal_p,
  92. (dfsch_type_write_t)decoded_time_write,
  93. (dfsch_type_apply_t)decoded_time_apply,
  94. (dfsch_type_hash_t)decoded_time_hash
  95. };
  96. dfsch_object_t* dfsch_make_decoded_time(){
  97. return dfsch_make_object(&decoded_time_type);
  98. }
  99. struct tm* dfsch_decoded_time_get_tm(dfsch_object_t* time){
  100. if (DFSCH_TYPE_OF(time) != &decoded_time_type){
  101. dfsch_error("Not a decoded time", time);
  102. }
  103. return &(((decoded_time_t*)time)->tm);
  104. }
  105. DFSCH_DEFINE_PRIMITIVE(decode_universal_time, NULL){
  106. time_t time;
  107. dfsch_object_t* utc;
  108. dfsch_object_t* ret;
  109. DFSCH_LONG_ARG(args, time);
  110. DFSCH_OBJECT_ARG_OPT(args, utc, NULL);
  111. DFSCH_ARG_END(args);
  112. ret = dfsch_make_decoded_time();
  113. if (utc){
  114. gmtime_r(&time, dfsch_decoded_time_get_tm(ret));
  115. } else {
  116. localtime_r(&time, dfsch_decoded_time_get_tm(ret));
  117. }
  118. return ret;
  119. }
  120. DFSCH_DEFINE_PRIMITIVE(encode_universal_time, NULL){
  121. struct tm tm;
  122. time_t t;
  123. DFSCH_LONG_ARG(args, tm.tm_sec);
  124. DFSCH_LONG_ARG(args, tm.tm_min);
  125. DFSCH_LONG_ARG(args, tm.tm_hour);
  126. DFSCH_LONG_ARG(args, tm.tm_mday);
  127. DFSCH_LONG_ARG(args, tm.tm_mon);
  128. DFSCH_LONG_ARG(args, tm.tm_year);
  129. DFSCH_ARG_END(args);
  130. tm.tm_mon -= 1;
  131. tm.tm_year -= 1900;
  132. tm.tm_isdst = -1;
  133. errno = 0;
  134. t = mktime(&tm);
  135. if (t == -1 && errno != 0){
  136. dfsch_operating_system_error("mktime");
  137. }
  138. return dfsch_make_number_from_long(t);
  139. }
  140. DFSCH_DEFINE_PRIMITIVE(get_decoded_time, NULL){
  141. time_t t;
  142. dfsch_object_t* utc;
  143. dfsch_object_t* ret;
  144. DFSCH_OBJECT_ARG_OPT(args, utc, NULL);
  145. DFSCH_ARG_END(args);
  146. ret = dfsch_make_decoded_time();
  147. t = time(NULL);
  148. if (utc){
  149. gmtime_r(&t, dfsch_decoded_time_get_tm(ret));
  150. } else {
  151. localtime_r(&t, dfsch_decoded_time_get_tm(ret));
  152. }
  153. return ret;
  154. }
  155. DFSCH_DEFINE_PRIMITIVE(get_universal_time, NULL){
  156. DFSCH_ARG_END(args);
  157. return dfsch_make_number_from_long(time(NULL));
  158. }
  159. DFSCH_DEFINE_PRIMITIVE(iso_format_time, NULL){
  160. char t = ' ';
  161. dfsch_object_t* use_t;
  162. dfsch_object_t* time;
  163. struct tm* tm;
  164. DFSCH_OBJECT_ARG(args, time);
  165. DFSCH_OBJECT_ARG_OPT(args, use_t, NULL);
  166. DFSCH_ARG_END(args);
  167. if (use_t){
  168. t = 'T';
  169. }
  170. tm = dfsch_decoded_time_get_tm(time);
  171. return dfsch_make_string_cstr(saprintf("%04d-%02d-%02d%c%02d:%02d:%02d",
  172. tm->tm_year+1900, tm->tm_mon+1,
  173. tm->tm_mday, t,
  174. tm->tm_hour, tm->tm_min, tm->tm_sec));
  175. }
  176. #ifdef unix
  177. DFSCH_DEFINE_PRIMITIVE(get_internal_real_time, NULL){
  178. struct tms t;
  179. DFSCH_ARG_END(args);
  180. return dfsch_make_number_from_long(times(&t) & LONG_MAX);
  181. }
  182. DFSCH_DEFINE_PRIMITIVE(get_internal_run_time, NULL){
  183. struct tms t;
  184. DFSCH_ARG_END(args);
  185. times(&t);
  186. return dfsch_make_number_from_long((t.tms_utime + t.tms_stime) & LONG_MAX);
  187. }
  188. #endif
  189. DFSCH_DEFINE_PRIMITIVE(sleep, NULL){
  190. long time;
  191. DFSCH_LONG_ARG(args, time);
  192. DFSCH_ARG_END(args);
  193. #ifdef __WIN32__
  194. Sleep(time * 1000); /* Why? :) */
  195. #else
  196. sleep(time);
  197. #endif
  198. return NULL;
  199. }
  200. void dfsch__system_register(dfsch_object_t *ctx){
  201. dfsch_defcanon_cstr(ctx, "<decoded-time>", &decoded_time_type);
  202. dfsch_defcanon_cstr(ctx, "decode-universal-time",
  203. DFSCH_PRIMITIVE_REF(decode_universal_time));
  204. dfsch_defcanon_cstr(ctx, "encode-universal-time",
  205. DFSCH_PRIMITIVE_REF(encode_universal_time));
  206. dfsch_defcanon_cstr(ctx, "get-decoded-time",
  207. DFSCH_PRIMITIVE_REF(get_decoded_time));
  208. dfsch_defcanon_cstr(ctx, "get-universal-time",
  209. DFSCH_PRIMITIVE_REF(get_universal_time));
  210. dfsch_defcanon_cstr(ctx, "iso-format-time",
  211. DFSCH_PRIMITIVE_REF(iso_format_time));
  212. #ifdef unix
  213. dfsch_defcanon_cstr(ctx, "get-internal-real-time",
  214. DFSCH_PRIMITIVE_REF(get_internal_real_time));
  215. dfsch_defcanon_cstr(ctx, "get-internal-run-time",
  216. DFSCH_PRIMITIVE_REF(get_internal_run_time));
  217. dfsch_defcanon_cstr(ctx, "internal-time-units-per-second",
  218. dfsch_make_number_from_long(sysconf(_SC_CLK_TCK)));
  219. #endif
  220. dfsch_defcanon_cstr(ctx, "sleep",
  221. DFSCH_PRIMITIVE_REF(sleep));
  222. }