3 /// Wrapper function implementations to aid porting to WinCE
7 Copyright (C) 2012, RealVNC Ltd.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
29 // Needs to be last as it re-defines any missing errno
32 #define MAX_ERR_LEN 128
33 static char errorString
[MAX_ERR_LEN
];
35 // Various WinCE time functions must be manually implemented, including
36 // the non-reentrant implementations. These variables are for those.
39 #define MAX_CTIME_LEN 128
40 static char ctimeBuf
[MAX_CTIME_LEN
];
44 char *strerror(int errnum
) {
45 sprintf(errorString
, "error number %d", errnum
);
49 unsigned int sleep(unsigned int seconds
) {
50 Sleep(seconds
* 1000);
54 int usleep(useconds_t usec
) {
59 // From http://support.microsoft.com/kb/167296
60 static void UnixTimeToFileTime(time_t t
, LPFILETIME pft
) {
62 ll
= Int32x32To64(t
, 10000000) + 116444736000000000;
63 pft
->dwLowDateTime
= static_cast<DWORD
>(ll
);
64 pft
->dwHighDateTime
= static_cast<DWORD
>(ll
>> 32);
67 static void FileTimeToUnixTime(const LPFILETIME pft
, time_t *t
) {
69 ll
= (static_cast<LONGLONG
>(pft
->dwHighDateTime
) << 32) |
70 static_cast<LONGLONG
>(pft
->dwLowDateTime
);
71 // Adjust the offset to 100ns periods from UNIX epoc
72 ll
-= 116444736000000000;
73 // Adjust it to seconds
75 *t
= static_cast<time_t>(ll
);
78 static BOOL
isLeapYear(DWORD year
) {
79 if( (year
% 400) == 0 )
81 if( (year
% 100) == 0 )
88 /* Static lookup table for how many days in the year each month starts on.
89 * Jan = 0, Feb = 1. */
90 static int monthLookup
[] = {
96 31 + 28 + 31 + 30 + 31,
97 31 + 28 + 31 + 30 + 31 + 30,
98 31 + 28 + 31 + 30 + 31 + 30 + 31,
99 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
100 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
101 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
102 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
105 struct tm
*localtime_r(const time_t *timep
, struct tm
*result
) {
108 UnixTimeToFileTime(*timep
, &ft
);
109 FileTimeToSystemTime(&ft
, &st
);
111 result
->tm_sec
= st
.wSecond
;
112 result
->tm_min
= st
.wMinute
;
113 result
->tm_hour
= st
.wHour
;
114 result
->tm_mday
= st
.wDay
;
115 result
->tm_mon
= st
.wMonth
- 1;
116 result
->tm_year
= st
.wYear
- 1900;
117 result
->tm_wday
= st
.wDayOfWeek
;
118 result
->tm_yday
= monthLookup
[st
.wMonth
- 1] +
119 ((isLeapYear(st
.wYear
) && st
.wMonth
> 2)? 1 : 0) +
121 result
->tm_isdst
= false;
131 int getopt(int argc
, char * const argv
[],
132 const char *optstring
)
134 if( optind
>= argc
||
135 argv
[optind
][0] == '-' && argv
[optind
][1] == '-' ) {
138 } else if( argv
[optind
][0] == '-' ) {
139 /* Found an option */
140 const char optchar
= argv
[optind
][1];
141 /* Look for it in optstring */
142 while ( *optstring
!= '\0' ) {
143 if( *optstring
== optchar
)
146 if( *optstring
== ':' )
149 if( *optstring
== '\0' ) {
151 fprintf(stderr
, "Unknown option '%c'\n", optchar
);
155 /* See if it has a parameter */
156 if( optstring
[1] == ':' ) {
157 if( optind
+ 1 >= argc
) {
159 fprintf(stderr
, "No additional parameter for option '%c'\n", optchar
);
164 optarg
= argv
[optind
];
169 /* Found a non-option argument, should really move it to the end for complete
171 /* TODO: move it to the end rather than just giving up */
177 #define MAX_LOCALE_LEN 128
178 static TCHAR localeStrW
[MAX_LOCALE_LEN
];
179 static char localeStr
[MAX_LOCALE_LEN
];
181 char *setlocale(int category
, const char *locale
)
183 // Non-functional on WinCE
187 sighandler_t
signal(int signum
, sighandler_t handler
)
189 if( signum
== SIGINT
) {
190 DWORD bytesReturned
= 0;
191 if( !DeviceIoControl(
193 /* This is the value of IOCTL_CONSOLE_SETCONTROLCHANDLER */
194 CTL_CODE(FILE_DEVICE_CONSOLE
, 8, METHOD_BUFFERED
, FILE_ANY_ACCESS
),
195 (LPVOID
)handler
, sizeof(handler
),
196 NULL
, 0, &bytesReturned
, NULL
) )
201 // All other signal handling is non-functional on WinCE
206 /* WinCE doesn't provide a getenv */
207 char *getenv(const char *name
)
209 // Pretend there are no environment variables
215 // WinCE declares various time methods but doesn't provide them
216 // (see http://blogs.msdn.com/b/cenet/archive/2006/04/29/time-h-on-windows-ce.aspx).
217 struct tm
*localtime(const time_t *timep
) {
218 return localtime_r(timep
, &gLocalTime
);
221 time_t time(time_t *t
) {
227 SystemTimeToFileTime(&st
, &ft
);
228 FileTimeToUnixTime(&ft
, &ret
);
235 // This isn't locale friendly, assuming English weeknames and month names,
236 // but it seems to be what the standard says.
237 const static char weekdayStrLookup
[7][4] = {
238 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
240 const static char monthStrLookup
[12][4] = {
241 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
244 char *ctime(const time_t *timep
) {
247 UnixTimeToFileTime(*timep
, &ft
);
248 FileTimeToSystemTime(&ft
, &st
);
249 _snprintf(ctimeBuf
, MAX_CTIME_LEN
,
250 "%s %s %02d %02d:%02d:%02d %04d\n",
251 weekdayStrLookup
[st
.wDayOfWeek
], monthStrLookup
[st
.wMonth
- 1],
252 st
.wDay
, st
.wHour
, st
.wMinute
, st
.wSecond
, st
.wYear
);
253 ctimeBuf
[MAX_CTIME_LEN
- 1] = 0; // Make sure it's NUL terminated
257 time_t mktime(struct tm
*tm
) {
262 // Convert struct tm to a SYSTEMTIME
263 st
.wDay
= tm
->tm_mday
;
265 st
.wHour
= tm
->tm_hour
;
266 st
.wMilliseconds
= 0;
267 st
.wMinute
= tm
->tm_min
;
268 st
.wMonth
= tm
->tm_mon
+ 1;
269 st
.wSecond
= tm
->tm_sec
;
270 st
.wYear
= tm
->tm_year
+ 1900;
272 // Convert the system time to unix time
273 SystemTimeToFileTime(&st
, &ft
);
274 FileTimeToUnixTime(&ft
, &ret
);
275 // Convert the filetime back so we can set tm_wday and tm_yday
276 FileTimeToSystemTime(&ft
, &st
);
277 tm
->tm_wday
= st
.wDayOfWeek
;
278 tm
->tm_yday
= monthLookup
[st
.wMonth
- 1] +
279 ((isLeapYear(st
.wYear
) && st
.wMonth
> 2)? 1 : 0) +
285 // Currently this only implements the strftime format specifiers
286 // needed by libbarry.
287 size_t strftime(char *s
, size_t max
, const char *format
,
288 const struct tm
*tm
) {
290 const char* curIn
= format
;
291 while (*curIn
!= 0 && (size_t)(curOut
- s
) <= max
) {
292 if( *curIn
== '%' ) {
293 const int remainingSpace
= max
- (curOut
- s
);
294 // Start of format specifier
303 // Year as decimal, including century
304 curOut
+= _snprintf(curOut
, remainingSpace
,
305 "%04d", tm
->tm_year
+ 1900);
309 // Month as a decimal (01-12)
310 curOut
+= _snprintf(curOut
, remainingSpace
,
311 "%02d", tm
->tm_mon
+ 1);
315 // Day of month in decimal (01-31)
316 curOut
+= _snprintf(curOut
, remainingSpace
,
317 "%02d", tm
->tm_mday
);
321 // Hour in decimal (00-23)
322 curOut
+= _snprintf(curOut
, remainingSpace
,
323 "%02d", tm
->tm_hour
);
327 // Minutes in decimal (00-59)
328 curOut
+= _snprintf(curOut
, remainingSpace
,
333 // Seconds as a decimal (00-60)
334 curOut
+= _snprintf(curOut
, remainingSpace
,
339 // Unsupported format specifier, including NUL
340 // just write it out as is.
341 if( remainingSpace
>= 2 ) {
357 // NUL terminate if possible
358 if( (size_t)(curOut
- s
) < max
) {