celibc.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Legalese:
  4. // This file is part of the OpenNETCF time.h port for Windows CE.
  5. // You are free to use, modify or distribute this code or any
  6. // derivative work that you create. This code is provided WITHOUT
  7. // WARRANTY and OpenNETCF does NOT claim in any way that this code
  8. // is fit for any specific or general use and holds NO RESPONSIBILITY
  9. // for consequences of using any of it. It is simply provided as-is.
  10. //
  11. // About:
  12. // This is part of a free and open project to provide a simply way to
  13. // port that uses time.h functions to Windows CE. For the latest
  14. // code, or to submit fixes, feature additions, etc. visit:
  15. //
  16. // http://www.opennetcf.com
  17. //
  18. // Version 0.01 - March 22, 2007
  19. // Initial Release
  20. //
  21. // Version 0.02 - July 5, 2007
  22. // Bug fixes. UTC offset not properly accounted for unless SetTz had been previously called.
  23. // UTC offset used for functions like localtime using old, rather than current data
  24. //
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // Many but not all of the functions were created from the following source:
  27. //
  28. // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
  29. //
  30. // Redistribution and use in source and binary forms, with or without
  31. // modification, are permitted provided that the following conditions
  32. // are met:
  33. //
  34. // 1. Redistributions of source code must retain the above copyright
  35. // notice, this list of conditions and the following disclaimer.
  36. // 2. Redistributions in binary form must reproduce the above copyright
  37. // notice, this list of conditions and the following disclaimer in the
  38. // documentation and/or other materials provided with the distribution.
  39. // 3. Neither the name of the project nor the names of its contributors
  40. // may be used to endorse or promote products derived from this software
  41. // without specific prior written permission.
  42. //
  43. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  44. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  45. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  46. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  47. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  48. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  49. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  50. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  51. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  52. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  53. // SUCH DAMAGE.
  54. ///////////////////////////////////////////////////////////////////////////////
  55. #include <windows.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include "celibc.h"
  59. #ifndef __GNUC__
  60. ///////////////////////////////////////////////////////////////////////////////
  61. // Macros
  62. ///////////////////////////////////////////////////////////////////////////////
  63. #define TIME_FAILURE 0xFFFFFFFF
  64. #define ASC_BUFF_SIZE 26 // Ascii buffer size is 26 bytes, (24 chars and CR+LF)
  65. #define SEC_IN_HOUR 3600L
  66. #define SECS_IN_MIN 60L
  67. #define DAYSPERWEEK 7
  68. #define YEAR0 1900
  69. #define EPOCH_YR 1970
  70. #define SECS_DAY (24L * 60L * 60L)
  71. #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
  72. #define TIME_MAX 2147483647L
  73. ///////////////////////////////////////////////////////////////////////////////
  74. // Local Variables
  75. ///////////////////////////////////////////////////////////////////////////////
  76. // Number of seconds between local time and UTC time, includes DST bias
  77. //
  78. LONG _localtime;
  79. // Is the local time in daylight savings time
  80. //
  81. DWORD _isdst;
  82. // Bias for daylight savings time
  83. //
  84. int _dstBias;
  85. // Contains the time zone string
  86. //
  87. char tz_name[2][32];
  88. // Contains the 1/1/1970 reference date/time
  89. //
  90. const SYSTEMTIME st1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
  91. // Contains the number of days per month for
  92. // non leap and leap years
  93. //
  94. const int _ytab[2][12] =
  95. {
  96. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
  97. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
  98. };
  99. // Contains the days of the week abreviation
  100. //
  101. static char *aday[] = {
  102. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  103. };
  104. // Contains the days of the week full name
  105. //
  106. static char *day[] = {
  107. "Sunday", "Monday", "Tuesday", "Wednesday",
  108. "Thursday", "Friday", "Saturday"
  109. };
  110. // Contains the months of the year abreviation
  111. //
  112. static char *amonth[] = {
  113. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  114. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  115. };
  116. // Contains the months of the year full name
  117. //
  118. static char *month[] = {
  119. "January", "February", "March", "April", "May", "June",
  120. "July", "August", "September", "October", "November", "December"
  121. };
  122. ///////////////////////////////////////////////////////////////////////////////
  123. // Forward declaration of internal functions
  124. ///////////////////////////////////////////////////////////////////////////////
  125. // Convert system time into seconds since 1970
  126. //
  127. LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME * st);
  128. // Convert seconds since 1970 into a system time
  129. //
  130. void SecondsSince1970ToSystemTime(const time_t * timer, SYSTEMTIME * st,
  131. BOOLEAN local);
  132. // Initialize the time zone information needed for the time methods
  133. //
  134. void SetTz(SYSTEMTIME *_st);
  135. // Copy system time structure to tm structure
  136. //
  137. void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer);
  138. void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st);
  139. // Get Julian Days from the begining of the year
  140. //
  141. DWORD JulianDays(SYSTEMTIME * st);
  142. // Method parses and formats strings
  143. //
  144. static void strfmt(char *str, const char *fmt, ...);
  145. // Reentrant version of gmttime
  146. //
  147. struct tm *gmtime_r_ce(const time_t *timer, struct tm *tmbuf, BOOLEAN local);
  148. // Reentrant version of localtime
  149. //
  150. struct tm *localtime_r_ce(const time_t *timer, struct tm *tmbuf);
  151. ///////////////////////////////////////////////////////////////////////////////
  152. // Methods - The meat
  153. ///////////////////////////////////////////////////////////////////////////////
  154. // Convert tm to a string in the format "Www Mmm dd hh:mm:ss yyyy",
  155. // where Www is the weekday, Mmm the month in letters, dd the day
  156. // of the month, hh:mm:ss the time, and yyyy the year. The string
  157. // is followed by a newline and a terminating null character,
  158. // conforming a total of 26 characters.
  159. //
  160. char *asctime(const struct tm* tmptr)
  161. {
  162. static char ascbuf[ASC_BUFF_SIZE];
  163. strftime(ascbuf, ASC_BUFF_SIZE, "%c\n", tmptr);
  164. return ascbuf;
  165. }
  166. #endif //__GNUC__
  167. // Return number of clock ticks since process start.
  168. // NOTE: This differs from standard clock since GetTickCount is the
  169. // number of milliseconds since system startup not process start.
  170. // This will also rollover after 49.7 days of continuous system
  171. // runtime.
  172. //
  173. clock_t clock(void)
  174. {
  175. return GetTickCount();
  176. }
  177. #ifndef __GNUC__
  178. // Convert time_t value to string in the same format as asctime.
  179. //
  180. char* ctime(const time_t* timer)
  181. {
  182. return asctime(localtime(timer));
  183. }
  184. // Reentrant version of gmttime_ce
  185. //
  186. struct tm *gmtime_r_ce(const time_t *timer, struct tm *tmbuf, BOOLEAN local)
  187. {
  188. SYSTEMTIME st;
  189. SecondsSince1970ToSystemTime(timer, &st, local);
  190. SetTz(&st);
  191. if(_isdst) {
  192. SecondsSince1970ToSystemTime(timer, &st, local);
  193. }
  194. // copy SYSTEMTIME data to tm structure
  195. //
  196. SystemTimeToTm(&st, tmbuf);
  197. return tmbuf;
  198. }
  199. // Reentrant version of localtime
  200. //
  201. struct tm *localtime_r_ce(const time_t *timer, struct tm *tmbuf)
  202. {
  203. return gmtime_r_ce(timer, tmbuf, TRUE);
  204. }
  205. // Convert a time_t value to a tm structure as UTC time.
  206. //
  207. struct tm *gmtime(const time_t *timer)
  208. {
  209. return gmtime_r_ce(timer, &tmbuf, FALSE);
  210. }
  211. // Convert a time_t value to a tm structure as local time.
  212. //
  213. struct tm *localtime(const time_t *timer)
  214. {
  215. return localtime_r_ce(timer, &tmbuf);
  216. }
  217. // time_t represents seconds since midnight January 1, 1970 UTC
  218. // (coordinated universal time) in 32-bits Win32 FILETIME structure is 64-bit,
  219. // which represents the number of 100-nanosecond (hns) intervals since
  220. // January 1, 1601 UTC (coordinate universal time) the time difference
  221. // between midnight January 1, 1970 and midnight January 1, 1601 is 11644473600 seconds
  222. //
  223. time_t mktime(struct tm *tptr)
  224. {
  225. SYSTEMTIME st;
  226. int day = 0;
  227. int year = 0;
  228. int seconds = 0;
  229. int overflow;
  230. int tm_year;
  231. int yday, month;
  232. TmToSystemTime(tptr, &st);
  233. SetTz(&st);
  234. // see if seconds are < 0
  235. while(tptr->tm_sec < 0)
  236. {
  237. // steal 60 seconds from the minutes
  238. tptr->tm_sec += 60;
  239. tptr->tm_min--;
  240. }
  241. // roll any seconds > 60 into the minutes
  242. tptr->tm_min += tptr->tm_sec / 60;
  243. // then crop them off
  244. tptr->tm_sec %= 60;
  245. // see if minutes are < 0
  246. while(tptr->tm_min < 0)
  247. {
  248. // steal 60 minutes from the hours
  249. tptr->tm_min += 60;
  250. tptr->tm_hour--;
  251. }
  252. // roll any minutes > 60 into the hours
  253. tptr->tm_hour += tptr->tm_min / 60;
  254. // then crop them off
  255. tptr->tm_min %= 60;
  256. // see if hours are < 0
  257. while(tptr->tm_hour < 0)
  258. {
  259. // steal 24 hours from the days
  260. tptr->tm_hour += 24;
  261. day--;
  262. }
  263. // keep any "excess" days (tm doesn't have a convenient place for this)
  264. day += tptr->tm_hour / 24;
  265. // crop
  266. tptr->tm_hour %= 24;
  267. // roll any months > 12 into the years
  268. tptr->tm_year += tptr->tm_mon / 12;
  269. // then crop the off
  270. tptr->tm_mon %= 12;
  271. // see if months are < 0
  272. if (tptr->tm_mon < 0)
  273. {
  274. // steal 12 months from the years
  275. tptr->tm_mon += 12;
  276. tptr->tm_year--;
  277. }
  278. // add number of days into the month to total day
  279. day += (tptr->tm_mday - 1);
  280. // if days are < 0 then calculate the number of days
  281. // checking to see if the month is a leap year month
  282. while (day < 0)
  283. {
  284. // If months are < 0 then steal 12 months from number of years
  285. // for the day calculation
  286. if(--tptr->tm_mon < 0)
  287. {
  288. tptr->tm_year--;
  289. tptr->tm_mon = 11;
  290. }
  291. day += _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
  292. }
  293. // if day is greater then the number of days in the month
  294. // subtract the number of days in the month and adjust the
  295. // month
  296. while (day >= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon])
  297. {
  298. day -= _ytab[LEAPYEAR(YEAR0 + tptr->tm_year)][tptr->tm_mon];
  299. if (++(tptr->tm_mon) == 12)
  300. {
  301. tptr->tm_mon = 0;
  302. tptr->tm_year++;
  303. }
  304. }
  305. tptr->tm_mday = day + 1;
  306. year = EPOCH_YR;
  307. // if year is less then 1970 then return error
  308. if (tptr->tm_year < year - YEAR0) return (time_t) -1;
  309. seconds = 0;
  310. day = 0; // Means days since day 0 now
  311. overflow = 0;
  312. // Assume that when day becomes negative, there will certainly
  313. // be overflow on seconds.
  314. // The check for overflow needs not to be done for leapyears
  315. // divisible by 400.
  316. // The code only works when year (1970) is not a leapyear.
  317. tm_year = tptr->tm_year + YEAR0;
  318. // make sure we are not past the max year for 32-bit number
  319. if (TIME_MAX / 365 < tm_year - year) overflow++;
  320. // calculate number of days since EPOCH
  321. day = (tm_year - year) * 365;
  322. if (TIME_MAX - day < (tm_year - year) / 4 + 1) overflow++;
  323. day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
  324. day -= (tm_year - year) / 100 + ((tm_year % 100) && tm_year % 100 < year % 100);
  325. day += (tm_year - year) / 400 + ((tm_year % 400) && tm_year % 400 < year % 400);
  326. // setup for calculation of the yday or Julian day since Jan 1
  327. yday = month = 0;
  328. // add up the number of days for the preceding months
  329. while (month < tptr->tm_mon)
  330. {
  331. yday += _ytab[LEAPYEAR(tm_year)][month];
  332. month++;
  333. }
  334. // add the number of days in the current month
  335. yday += (tptr->tm_mday - 1);
  336. // make sure the didn't overflow
  337. if (day + yday < 0) overflow++;
  338. day += yday;
  339. // set the year day in the structure
  340. tptr->tm_yday = yday;
  341. // calculate the weekday
  342. tptr->tm_wday = (day + 4) % 7; // Day 0 was thursday (4)
  343. // start the seconds calculation by totaling the hours, min, seconds
  344. seconds = ((tptr->tm_hour * 60L) + tptr->tm_min) * 60L + tptr->tm_sec;
  345. // make sure we are not going to overflow
  346. if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
  347. // calculate the number of seconds for the number of days
  348. seconds += day * SECS_DAY;
  349. // Now adjust according to timezone and daylight saving time
  350. if (((_localtime > 0) && (TIME_MAX - _localtime < seconds))
  351. || ((_localtime < 0) && (seconds < -_localtime)))
  352. overflow++;
  353. // Adjust for local time zone
  354. seconds += _localtime;
  355. // return error if we are going to blow the max values
  356. if (overflow) return (time_t) -1;
  357. if ((time_t) seconds != seconds) return (time_t) -1;
  358. // return the number of seconds since EPOCH
  359. return (time_t) seconds;
  360. }
  361. // Get the current system time and convert to seconds since
  362. // 1/1/1970. Store the seconds value in tloc if not a NULL pointer then
  363. // return the seconds value.
  364. //
  365. time_t time(time_t *tloc)
  366. {
  367. SYSTEMTIME st;
  368. LONGLONG secs = 0;
  369. // Get current system time
  370. GetSystemTime(&st);
  371. // Set time zone information
  372. //
  373. SetTz(&st);
  374. // convert system time to number of seconds since 1970
  375. //
  376. secs = SystemTimeToSecondsSince1970(&st);
  377. // check for failure
  378. //
  379. if(secs == TIME_FAILURE)
  380. {
  381. return TIME_FAILURE;
  382. }
  383. // If tloc is not NULL, the return value is also stored in the location to which tloc points
  384. //
  385. if(tloc != NULL)
  386. {
  387. if(IsBadWritePtr(tloc, sizeof(time_t)))
  388. {
  389. return TIME_FAILURE;
  390. }
  391. memcpy(tloc, &secs, sizeof(time_t));
  392. }
  393. return secs;
  394. }
  395. // The strftime function is a modified version created by the following:
  396. // written 6 september 1989 by jim nutt
  397. // released into the public domain by jim nutt
  398. //
  399. // modified 21-Oct-89 by Rob Duff
  400. //
  401. //
  402. // size_t strftime(char *str,
  403. // size_t maxs,
  404. // const char *fmt,
  405. // const struct tm *t)
  406. //
  407. // this functions acts much like a sprintf for time/date output.
  408. // given a pointer to an output buffer, a format string and a
  409. // time, it copies the time to the output buffer formatted in
  410. // accordance with the format string. the parameters are used
  411. // as follows:
  412. //
  413. // str is a pointer to the output buffer, there should
  414. // be at least maxs characters available at the address
  415. // pointed to by str.
  416. //
  417. // maxs is the maximum number of characters to be copied
  418. // into the output buffer, included the '\0' terminator
  419. //
  420. // fmt is the format string. a percent sign (%) is used
  421. // to indicate that the following character is a special
  422. // format character. the following are valid format
  423. // characters:
  424. //
  425. // %A full weekday name (Monday)
  426. // %a abbreviated weekday name (Mon)
  427. // %B full month name (January)
  428. // %b abbreviated month name (Jan)
  429. // %c standard date and time representation
  430. // %d day-of-month (01-31)
  431. // %H hour (24 hour clock) (00-23)
  432. // %I hour (12 hour clock) (01-12)
  433. // %j day-of-year (001-366)
  434. // %M minute (00-59)
  435. // %m month (01-12)
  436. // %p local equivalent of AM or PM
  437. // %S second (00-59)
  438. // %U week-of-year, first day sunday (00-53)
  439. // %W week-of-year, first day monday (00-53)
  440. // %w weekday (0-6, sunday is 0)
  441. // %X standard time representation
  442. // %x standard date representation
  443. // %Y year with century
  444. // %y year without century (00-99)
  445. // %Z timezone name
  446. // %% percent sign
  447. //
  448. // the standard date string is equivalent to:
  449. //
  450. // %a %b %d %Y
  451. //
  452. // the standard time string is equivalent to:
  453. //
  454. // %H:%M:%S
  455. //
  456. // the standard date and time string is equivalent to:
  457. //
  458. // %a %b %d %H:%M:%S %Y
  459. //
  460. // strftime returns the number of characters placed in the
  461. // buffer, not including the terminating \0, or zero if more
  462. // than maxs characters were produced.
  463. //
  464. size_t strftime(char *s, size_t maxs, const char *f, const struct tm *t)
  465. {
  466. int w;
  467. char *p, *q, *r;
  468. static char buf[26];
  469. p = s;
  470. q = s + maxs - 1;
  471. while ((*f != '\0'))
  472. {
  473. if (*f++ == '%')
  474. {
  475. r = buf;
  476. switch (*f++)
  477. {
  478. case '%' :
  479. r = "%";
  480. break;
  481. case 'a' :
  482. r = aday[t->tm_wday];
  483. break;
  484. case 'A' :
  485. r = day[t->tm_wday];
  486. break;
  487. case 'b' :
  488. r = amonth[t->tm_mon];
  489. break;
  490. case 'B' :
  491. r = month[t->tm_mon];
  492. break;
  493. case 'c' :
  494. strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
  495. aday[t->tm_wday], amonth[t->tm_mon],
  496. t->tm_mday,t->tm_hour, t->tm_min,
  497. t->tm_sec, t->tm_year+1900);
  498. break;
  499. case 'd' :
  500. strfmt(r,"%2",t->tm_mday);
  501. break;
  502. case 'H' :
  503. strfmt(r,"%2",t->tm_hour);
  504. break;
  505. case 'I' :
  506. strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
  507. break;
  508. case 'j' :
  509. strfmt(r,"%3",t->tm_yday+1);
  510. break;
  511. case 'm' :
  512. strfmt(r,"%2",t->tm_mon+1);
  513. break;
  514. case 'M' :
  515. strfmt(r,"%2",t->tm_min);
  516. break;
  517. case 'p' :
  518. r = (t->tm_hour>11)?"PM":"AM";
  519. break;
  520. case 'S' :
  521. strfmt(r,"%2",t->tm_sec);
  522. break;
  523. case 'U' :
  524. w = t->tm_yday/7;
  525. if (t->tm_yday%7 > t->tm_wday)
  526. w++;
  527. strfmt(r, "%2", w);
  528. break;
  529. case 'W' :
  530. w = (t->tm_yday + DAYSPERWEEK -
  531. (t->tm_wday ?
  532. (t->tm_wday - 1) :
  533. (DAYSPERWEEK - 1))) / DAYSPERWEEK;
  534. strfmt(r, "%2", w);
  535. break;
  536. case 'w' :
  537. strfmt(r,"%1",t->tm_wday);
  538. break;
  539. case 'x' :
  540. strfmt(r, "%2/%2/%2", t->tm_mon + 1,
  541. t->tm_mday, t->tm_year+1900);
  542. break;
  543. case 'X' :
  544. strfmt(r, "%2:%2:%2", t->tm_hour,
  545. t->tm_min, t->tm_sec);
  546. break;
  547. case 'y' :
  548. strfmt(r,"%2",t->tm_year%100);
  549. break;
  550. case 'Y' :
  551. strfmt(r,"%4",t->tm_year+1900);
  552. break;
  553. case 'Z' :
  554. r = (t->tm_isdst && tz_name[1][0])?tz_name[1]:tz_name[0];
  555. break;
  556. default:
  557. buf[0] = '%'; // reconstruct the format
  558. buf[1] = f[-1];
  559. buf[2] = '\0';
  560. if (buf[1] == 0)
  561. f--; // back up if at end of string
  562. }
  563. while (*r)
  564. {
  565. if (p == q)
  566. {
  567. *q = '\0';
  568. return 0;
  569. }
  570. *p++ = *r++;
  571. }
  572. }
  573. else
  574. {
  575. if (p == q)
  576. {
  577. *q = '\0';
  578. return 0;
  579. }
  580. *p++ = f[-1];
  581. }
  582. }
  583. *p = '\0';
  584. return p - s;
  585. }
  586. //
  587. // static void strfmt(char *str, char *fmt);
  588. //
  589. // simple sprintf for strftime
  590. //
  591. // each format descriptor is of the form %n
  592. // where n goes from zero to four
  593. //
  594. // 0 -- string %s
  595. // 1..4 -- int %?.?d
  596. //
  597. static void strfmt(char *str, const char *fmt, ...)
  598. {
  599. int ival, ilen;
  600. char *sval;
  601. static int pow[5] = { 1, 10, 100, 1000, 10000 };
  602. va_list vp;
  603. va_start(vp, fmt);
  604. while (*fmt)
  605. {
  606. if (*fmt++ == '%')
  607. {
  608. ilen = *fmt++ - '0';
  609. if (ilen == 0) // zero means string arg
  610. {
  611. sval = va_arg(vp, char*);
  612. while (*sval)
  613. *str++ = *sval++;
  614. }
  615. else // always leading zeros
  616. {
  617. ival = va_arg(vp, int);
  618. while (ilen)
  619. {
  620. ival %= pow[ilen--];
  621. *str++ = (char)('0' + ival / pow[ilen]);
  622. }
  623. }
  624. }
  625. else *str++ = fmt[-1];
  626. }
  627. *str = '\0';
  628. va_end(vp);
  629. }
  630. // internal functions
  631. //-----------------------------------------------------------------------------
  632. // Convert 100ns units since 1601 to seconds since 1970
  633. //
  634. LONGLONG SystemTimeToSecondsSince1970(SYSTEMTIME *st)
  635. {
  636. ULARGE_INTEGER uli;
  637. FILETIME ft;
  638. ULARGE_INTEGER uli1970;
  639. FILETIME ft1970;
  640. // convert to a FILETIME
  641. // Gives number of 100-nanosecond intervals since January 1, 1601 (UTC)
  642. //
  643. if(!SystemTimeToFileTime(st, &ft))
  644. {
  645. return TIME_FAILURE;
  646. }
  647. // convert to a FILETIME
  648. // Gives number of 100-nanosecond intervals since January 1, 1970 (UTC)
  649. //
  650. if(!SystemTimeToFileTime(&st1970, &ft1970))
  651. {
  652. return TIME_FAILURE;
  653. }
  654. // Copy file time structures into ularge integer so we can do
  655. // the math more easily
  656. //
  657. memcpy(&uli, &ft, sizeof(uli));
  658. memcpy(&uli1970, &ft1970, sizeof(uli1970));
  659. // Subtract the 1970 number of 100 ns value from the 1601 100 ns value
  660. // so we can get the number of 100 ns value between 1970 and now
  661. // then devide be 10,000,000 to get the number of seconds since 1970
  662. //
  663. uli.QuadPart = ((uli.QuadPart - uli1970.QuadPart) / 10000000);
  664. return (LONGLONG)uli.QuadPart;
  665. }
  666. // Convert seconds since 1970 to a file time in 100ns units since 1601
  667. // then to a system time.
  668. //
  669. void SecondsSince1970ToSystemTime(const time_t * timer, SYSTEMTIME * st,
  670. BOOLEAN local)
  671. {
  672. ULARGE_INTEGER uli;
  673. FILETIME ft;
  674. ULARGE_INTEGER uli1970;
  675. FILETIME ft1970;
  676. // Convert system time to file time
  677. //
  678. if(!SystemTimeToFileTime(&st1970, &ft1970))
  679. {
  680. st = NULL;
  681. return;
  682. }
  683. // convert hundreds of nanosecs to secs: 1 sec = 1e7 100ns
  684. // Gives number of seconds since 1/1/1601 (UTC)
  685. //
  686. memcpy(&uli, timer, sizeof(uli));
  687. memcpy(&uli1970, &ft1970, sizeof(uli1970));
  688. // If we want local time then subtract the number of seconds between
  689. // UTC and current local time
  690. //
  691. if (local)
  692. {
  693. // Calculate 100ns since 1/1/1601 local time
  694. //
  695. uli.QuadPart = (((uli.QuadPart - _localtime)*10000000) + uli1970.QuadPart);
  696. }
  697. else
  698. {
  699. // Calculate 100ns since 1/1/1601 UTC
  700. //
  701. uli.QuadPart = ((uli.QuadPart)*10000000 + uli1970.QuadPart);
  702. }
  703. // copy data back into the ft
  704. //
  705. memcpy(&ft, &uli, sizeof(uli));
  706. // convert to a SYSTEMTIME
  707. //
  708. if(!FileTimeToSystemTime(&ft, st))
  709. {
  710. st = NULL;
  711. return;
  712. }
  713. return;
  714. }
  715. // Set the time zone information needed for the rest of the methods
  716. //
  717. void SetTz(SYSTEMTIME *_st)
  718. {
  719. TIME_ZONE_INFORMATION tz;
  720. SYSTEMTIME st = *_st;
  721. FILETIME ftDT; // Daylight savings file time
  722. FILETIME ftST; // Standard time file time
  723. FILETIME ft; // file time to compare
  724. int i;
  725. GetTimeZoneInformation(&tz);
  726. // Convert current system time, daylight savings changover time
  727. // and standard time to file time to see if current time is between
  728. // the two dates. If so then we are in daylight savings otherwise we
  729. // are not.
  730. //
  731. SystemTimeToFileTime(&st, &ft);
  732. tz.DaylightDate.wYear = st.wYear;
  733. tz.StandardDate.wYear = st.wYear;
  734. SystemTimeToFileTime(&tz.DaylightDate, &ftDT);
  735. SystemTimeToFileTime(&tz.StandardDate, &ftST);
  736. // -1 First file time is earlier than second file time.
  737. // 0 First file time is equal to second file time.
  738. // 1 First file time is later than second file time.
  739. //
  740. if ((CompareFileTime(&ft,&ftDT) >= 0) && (CompareFileTime(&ft,&ftST) <= 0) )
  741. {
  742. _isdst = TRUE;
  743. }
  744. else
  745. {
  746. _isdst = FALSE;
  747. }
  748. // Set localtime difference in seconds from UTC
  749. //
  750. if (_isdst)
  751. {
  752. // Adjust for Daylight Savings Time and convert to seconds
  753. //
  754. _localtime = (tz.Bias + tz.DaylightBias) * SECS_IN_MIN;
  755. }
  756. else
  757. {
  758. // Convert to seconds
  759. //
  760. _localtime = tz.Bias * SECS_IN_MIN;
  761. }
  762. _dstBias = tz.DaylightBias;
  763. // Set the standard and daylight strings
  764. //
  765. for (i=0;i<32;i++)
  766. {
  767. tz_name[0][i] = (char)tz.StandardName[i];
  768. tz_name[1][i] = (char)tz.DaylightName[i];
  769. }
  770. }
  771. // Copy system time structure to tm structure
  772. //
  773. void SystemTimeToTm(SYSTEMTIME *st, struct tm * tmbuffer)
  774. {
  775. tmbuffer->tm_hour = st->wHour;
  776. tmbuffer->tm_mday = st->wDay;
  777. tmbuffer->tm_min = st->wMinute;
  778. tmbuffer->tm_mon = st->wMonth - 1;
  779. tmbuffer->tm_sec = st->wSecond;
  780. tmbuffer->tm_wday = st->wDayOfWeek;
  781. tmbuffer->tm_yday = JulianDays(st); // Julian days, numer of days since Jan 1
  782. tmbuffer->tm_year = st->wYear - 1900;
  783. tmbuffer->tm_isdst = _isdst; // Is Daylight Savings Time
  784. }
  785. void TmToSystemTime(struct tm * tmbuffer, SYSTEMTIME *st)
  786. {
  787. st->wHour = tmbuffer->tm_hour;
  788. st->wDay = tmbuffer->tm_mday;
  789. st->wMinute = tmbuffer->tm_min;
  790. st->wMonth = tmbuffer->tm_mon + 1;
  791. st->wSecond = tmbuffer->tm_sec;
  792. st->wDayOfWeek = tmbuffer->tm_wday;
  793. st->wYear = tmbuffer->tm_year + 1900;
  794. st->wMilliseconds = 0;
  795. }
  796. // Get the JulianDay from a Gregorian Date for number of days into the current
  797. // year
  798. // Algorithm from: http://www.vsg.cape.com/~pbaum/date/jdalg2.htm
  799. //
  800. DWORD JulianDays(SYSTEMTIME * st)
  801. {
  802. int m = 0;
  803. int y = 0;
  804. double jdd = 0;
  805. double jddYearStart = 0;
  806. // Calculate the Julian day for the beginning of the year
  807. //
  808. m = 13;
  809. y = st->wYear - 1;
  810. jddYearStart = 1 + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;
  811. // Calculate Julian Day for Current Date
  812. //
  813. if (st->wMonth >= 3)
  814. {
  815. m = st->wMonth;
  816. y = st->wYear;
  817. }
  818. jdd = st->wDay + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721118.5;
  819. // Subract the year start Julian date from the Current Julian date to get
  820. // the number of Julian days from the year start
  821. //
  822. return (DWORD)(jdd - jddYearStart);
  823. }
  824. #endif //__GNUC__
  825. /**
  826. * LuaCE
  827. *
  828. * Pedro Miller Rabinovitch, <[email protected]>
  829. * http://www.inf.puc-rio.br/~miller/luace
  830. *
  831. * A quick port of Lua for Windows CE.
  832. **/
  833. //int errno = 0;
  834. const char *getenv( const char *name ) {
  835. return NULL;
  836. }
  837. char *strdup( const char *str ) {
  838. char *ptr = (char *)malloc( sizeof(char) * strlen( str ) + 1 );
  839. strcpy( ptr, str );
  840. return ptr;
  841. }
  842. FILE *tmpfile() {
  843. return NULL;
  844. }
  845. char *tmpnam( char *str ) {
  846. return NULL;
  847. }
  848. #define _tcslen wcslen
  849. #define _tcsncpy wcsncpy
  850. #define _T(a) L##a
  851. int system( const char *cmd ) {
  852. TCHAR tpath[MAX_PATH], args[1024], cmds[1024];
  853. BOOL ret, cont = TRUE;
  854. int i, len, exit_code = -100;
  855. PROCESS_INFORMATION pi;
  856. ZeroMemory( &pi, sizeof(pi) );
  857. memset(tpath,0,MAX_PATH*sizeof(TCHAR));
  858. memset(cmds,0,1024*sizeof(TCHAR));
  859. memset(args,0,1024*sizeof(TCHAR));
  860. mbstowcs(cmds, cmd, 1024);
  861. len = _tcslen(cmds);
  862. if (cmds[0] == _T('"')) {
  863. for (i = 1; i < len; i++) {
  864. if (cmds[i] == _T('"'))
  865. break;
  866. }
  867. if (i >= len)
  868. return -1;
  869. i++;
  870. _tcsncpy(tpath, cmds + 1, i - 2);
  871. _tcsncpy(args, cmds + i, len - i);
  872. }
  873. else {
  874. for (i = 0; i < len; i++) {
  875. if (cmds[i] == _T(' '))
  876. break;
  877. }
  878. _tcsncpy(tpath, cmds, i);
  879. _tcsncpy(args, cmds + i, len - i);
  880. }
  881. #ifdef DEBUGGING_PROCESS
  882. ret = CreateProcess(tpath, args, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, NULL, &pi);
  883. #else
  884. ret = CreateProcess(tpath, args, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
  885. #endif
  886. if (!ret) {
  887. return GetLastError();
  888. }
  889. #ifdef DEBUGGING_PROCESS
  890. // Enter debug loop
  891. while (cont) {
  892. DEBUG_EVENT dbgEvt;
  893. if ( WaitForDebugEvent( &dbgEvt, INFINITE ) ) {
  894. switch (dbgEvt.dwDebugEventCode) {
  895. case EXCEPTION_DEBUG_EVENT:
  896. exit_code = (int) (dbgEvt.u.Exception.ExceptionRecord.ExceptionCode - 0xC0000000);
  897. TerminateProcess( pi.hProcess, exit_code + (1 << 16) );
  898. break;
  899. case EXIT_PROCESS_DEBUG_EVENT:
  900. cont = FALSE;
  901. break;
  902. }
  903. ContinueDebugEvent( dbgEvt.dwProcessId, dbgEvt.dwThreadId, DBG_CONTINUE );
  904. }
  905. }
  906. #else
  907. // Wait until child process exits.
  908. WaitForSingleObject( pi.hProcess, INFINITE );
  909. #endif
  910. GetExitCodeProcess( pi.hProcess, &exit_code );
  911. // Close process and thread handles.
  912. CloseHandle( pi.hProcess );
  913. return exit_code;
  914. }
  915. /* alloc's and returns a converted wide-char string from a normal one */
  916. wchar_t *atowcs( const char *str ) {
  917. int len;
  918. wchar_t *wstr;
  919. if( str == NULL )
  920. return NULL;
  921. len = strlen( str );
  922. wstr = (wchar_t *)malloc( sizeof( wchar_t )*2*(len + 1) );
  923. wsprintf( wstr, L"%hs", str );
  924. return wstr;
  925. }
  926. int rename( const char *src, const char *dst ) {
  927. wchar_t *wsrc = atowcs( src ),
  928. *wdst = atowcs( dst );
  929. int res = 0;
  930. if( !MoveFile( wsrc, wdst ))
  931. res = GetLastError();
  932. free( wsrc );
  933. free( wdst );
  934. return res;
  935. }
  936. int remove( const char *fname ) {
  937. wchar_t *wfname = atowcs( fname );
  938. int res = 0;
  939. if( !DeleteFile( wfname ))
  940. res = GetLastError();
  941. free( wfname );
  942. return res;
  943. }
  944. char *setlocale( int category, const char *locale ) {
  945. return NULL;
  946. }
  947. struct lconv *localeconv( void )
  948. {
  949. return NULL;
  950. }
  951. static int file_exists(const char* filename) {
  952. FILE* f = fopen(filename, "r");
  953. if(f != NULL)
  954. {
  955. fclose(f);
  956. return 1;
  957. }
  958. return 0;
  959. }
  960. static char* conv_filename(char *filename) {
  961. size_t i;
  962. for (i = 0; i < strlen(filename); i++) {
  963. if (filename[i] == '/')
  964. filename[i] = '\\';
  965. }
  966. return filename;
  967. }
  968. static char* find_file(const char* filename) {
  969. char* fullpath = malloc(sizeof(char) * (MAX_PATH + 1));
  970. if(!fullpath)
  971. return NULL;
  972. if (filename != NULL && strlen(filename) > 0)
  973. {
  974. if (filename[0] == '\\' || filename[0] == '/')//absolute path
  975. {
  976. strcpy(fullpath, filename);
  977. return conv_filename(fullpath);
  978. }
  979. else
  980. {
  981. TCHAR tpath[MAX_PATH + 1];
  982. char* lastDash;
  983. memset(tpath, 0, (MAX_PATH+1) * sizeof(TCHAR));
  984. GetModuleFileName(NULL, tpath, MAX_PATH);
  985. wcstombs(fullpath, tpath, MAX_PATH);
  986. lastDash = strrchr(fullpath,'\\');
  987. fullpath[lastDash - fullpath+1] = 0;
  988. strncat(fullpath, filename, MAX_PATH - strlen(filename));
  989. return conv_filename(fullpath);
  990. }
  991. }
  992. free(fullpath);
  993. return NULL;
  994. }
  995. FILE* _fopen(const char *filename, const char *flags) {
  996. FILE *fp = NULL;
  997. char *full_path = find_file(filename);
  998. if (full_path) {
  999. fp = fopen(full_path, flags);
  1000. free(full_path);
  1001. }
  1002. return fp;
  1003. }
  1004. #if 0
  1005. int chdir(const char *path) {
  1006. wchar_t *wpath = atowcs( path );
  1007. int res = 0;
  1008. if( !_wchdir( wpath ))
  1009. res = GetLastError();
  1010. free( wpath );
  1011. return res;
  1012. }
  1013. #endif
  1014. int mkdir(const char *path) {
  1015. wchar_t *wpath = atowcs( path );
  1016. int res = 0;
  1017. if( !CreateDirectory(wpath, NULL))
  1018. res = GetLastError();
  1019. free( wpath );
  1020. return res;
  1021. }
  1022. HINSTANCE LoadLibraryA(LPCSTR path)
  1023. {
  1024. wchar_t *wpath = atowcs( path );
  1025. HINSTANCE res = LoadLibrary( wpath );
  1026. free( wpath );
  1027. return res;
  1028. }
  1029. HMODULE GetModuleHandleA(LPCSTR module)
  1030. {
  1031. wchar_t *wmodule = atowcs( module );
  1032. HMODULE res = GetModuleHandle( module );
  1033. free( module );
  1034. return res;
  1035. }