1 2/* 3 * tcl_clock.c 4 * 5 * Implements the clock command 6 */ 7 8/* For strptime() */ 9#ifndef _XOPEN_SOURCE 10#define _XOPEN_SOURCE 500 11#endif 12 13#include <stdlib.h> 14#include <string.h> 15#include <stdio.h> 16#include <time.h> 17#include <sys/time.h> 18 19#include "jim.h" 20#include "jimautoconf.h" 21#include "jim-subcmd.h" 22 23static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 24{ 25 /* How big is big enough? */ 26 char buf[100]; 27 time_t t; 28 long seconds; 29 30 const char *format = "%a %b %d %H:%M:%S %Z %Y"; 31 32 if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { 33 return -1; 34 } 35 36 if (argc == 3) { 37 format = Jim_String(argv[2]); 38 } 39 40 if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { 41 return JIM_ERR; 42 } 43 t = seconds; 44 45 strftime(buf, sizeof(buf), format, localtime(&t)); 46 47 Jim_SetResultString(interp, buf, -1); 48 49 return JIM_OK; 50} 51 52#ifdef HAVE_STRPTIME 53static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 54{ 55 char *pt; 56 struct tm tm; 57 time_t now = time(0); 58 59 if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { 60 return -1; 61 } 62 63 /* Initialise with the current date/time */ 64 localtime_r(&now, &tm); 65 66 pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); 67 if (pt == 0 || *pt != 0) { 68 Jim_SetResultString(interp, "Failed to parse time according to format", -1); 69 return JIM_ERR; 70 } 71 72 /* Now convert into a time_t */ 73 Jim_SetResultInt(interp, mktime(&tm)); 74 75 return JIM_OK; 76} 77#endif 78 79static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 80{ 81 Jim_SetResultInt(interp, time(NULL)); 82 83 return JIM_OK; 84} 85 86static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 87{ 88 struct timeval tv; 89 90 gettimeofday(&tv, NULL); 91 92 Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec); 93 94 return JIM_OK; 95} 96 97static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 98{ 99 struct timeval tv; 100 101 gettimeofday(&tv, NULL); 102 103 Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); 104 105 return JIM_OK; 106} 107 108static const jim_subcmd_type clock_command_table[] = { 109 { .cmd = "seconds", 110 .function = clock_cmd_seconds, 111 .minargs = 0, 112 .maxargs = 0, 113 .description = "Returns the current time as seconds since the epoch" 114 }, 115 { .cmd = "clicks", 116 .function = clock_cmd_micros, 117 .minargs = 0, 118 .maxargs = 0, 119 .description = "Returns the current time in 'clicks'" 120 }, 121 { .cmd = "microseconds", 122 .function = clock_cmd_micros, 123 .minargs = 0, 124 .maxargs = 0, 125 .description = "Returns the current time in microseconds" 126 }, 127 { .cmd = "milliseconds", 128 .function = clock_cmd_millis, 129 .minargs = 0, 130 .maxargs = 0, 131 .description = "Returns the current time in milliseconds" 132 }, 133 { .cmd = "format", 134 .args = "seconds ?-format format?", 135 .function = clock_cmd_format, 136 .minargs = 1, 137 .maxargs = 3, 138 .description = "Format the given time" 139 }, 140#ifdef HAVE_STRPTIME 141 { .cmd = "scan", 142 .args = "str -format format", 143 .function = clock_cmd_scan, 144 .minargs = 3, 145 .maxargs = 3, 146 .description = "Determine the time according to the given format" 147 }, 148#endif 149 { 0 } 150}; 151 152int Jim_clockInit(Jim_Interp *interp) 153{ 154 if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) 155 return JIM_ERR; 156 157 Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); 158 return JIM_OK; 159} 160