os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/strftime.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/compat/strftime.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,521 @@
1.4 +/*
1.5 + * strftime.c --
1.6 + *
1.7 + * This file contains a modified version of the BSD 4.4 strftime
1.8 + * function.
1.9 + *
1.10 + * This file is a modified version of the strftime.c file from the BSD 4.4
1.11 + * source. See the copyright notice below for details on redistribution
1.12 + * restrictions. The "license.terms" file does not apply to this file.
1.13 + *
1.14 + * Changes 2002 Copyright (c) 2002 ActiveState Corporation.
1.15 + *
1.16 + * RCS: @(#) $Id: strftime.c,v 1.10.2.3 2005/11/04 18:18:04 kennykb Exp $
1.17 + */
1.18 +
1.19 +/*
1.20 + * Copyright (c) 1989 The Regents of the University of California.
1.21 + * All rights reserved.
1.22 + *
1.23 + * Redistribution and use in source and binary forms, with or without
1.24 + * modification, are permitted provided that the following conditions
1.25 + * are met:
1.26 + * 1. Redistributions of source code must retain the above copyright
1.27 + * notice, this list of conditions and the following disclaimer.
1.28 + * 2. Redistributions in binary form must reproduce the above copyright
1.29 + * notice, this list of conditions and the following disclaimer in the
1.30 + * documentation and/or other materials provided with the distribution.
1.31 + * 3. All advertising materials mentioning features or use of this software
1.32 + * must display the following acknowledgement:
1.33 + * This product includes software developed by the University of
1.34 + * California, Berkeley and its contributors.
1.35 + * 4. Neither the name of the University nor the names of its contributors
1.36 + * may be used to endorse or promote products derived from this software
1.37 + * without specific prior written permission.
1.38 + *
1.39 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1.40 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.41 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.42 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1.43 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.44 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.45 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.46 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.47 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.48 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.49 + * SUCH DAMAGE.
1.50 + */
1.51 +
1.52 +#if defined(LIBC_SCCS)
1.53 +static char *rcsid = "$Id: strftime.c,v 1.10.2.3 2005/11/04 18:18:04 kennykb Exp $";
1.54 +#endif /* LIBC_SCCS */
1.55 +
1.56 +#include <time.h>
1.57 +#include <string.h>
1.58 +#include <locale.h>
1.59 +#include "tclInt.h"
1.60 +#include "tclPort.h"
1.61 +
1.62 +#define TM_YEAR_BASE 1900
1.63 +#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
1.64 +
1.65 +typedef struct {
1.66 + const char *abday[7];
1.67 + const char *day[7];
1.68 + const char *abmon[12];
1.69 + const char *mon[12];
1.70 + const char *am_pm[2];
1.71 + const char *d_t_fmt;
1.72 + const char *d_fmt;
1.73 + const char *t_fmt;
1.74 + const char *t_fmt_ampm;
1.75 +} _TimeLocale;
1.76 +
1.77 +/*
1.78 + * This is the C locale default. On Windows, if we wanted to make this
1.79 + * localized, we would use GetLocaleInfo to get the correct values.
1.80 + * It may be acceptable to do localization of month/day names, as the
1.81 + * numerical values would be considered the locale-independent versions.
1.82 + */
1.83 +static const _TimeLocale _DefaultTimeLocale =
1.84 +{
1.85 + {
1.86 + "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
1.87 + },
1.88 + {
1.89 + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
1.90 + "Friday", "Saturday"
1.91 + },
1.92 + {
1.93 + "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1.94 + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1.95 + },
1.96 + {
1.97 + "January", "February", "March", "April", "May", "June", "July",
1.98 + "August", "September", "October", "November", "December"
1.99 + },
1.100 + {
1.101 + "AM", "PM"
1.102 + },
1.103 + "%a %b %d %H:%M:%S %Y",
1.104 + "%m/%d/%y",
1.105 + "%H:%M:%S",
1.106 + "%I:%M:%S %p"
1.107 +};
1.108 +
1.109 +static const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
1.110 +
1.111 +static int isGMT;
1.112 +static size_t gsize;
1.113 +static char *pt;
1.114 +static int _add _ANSI_ARGS_((const char* str));
1.115 +static int _conv _ANSI_ARGS_((int n, int digits, int pad));
1.116 +static int _secs _ANSI_ARGS_((const struct tm *t));
1.117 +static size_t _fmt _ANSI_ARGS_((const char *format,
1.118 + const struct tm *t));
1.119 +static int ISO8601Week _ANSI_ARGS_((CONST struct tm* t, int *year ));
1.120 +
1.121 +size_t
1.122 +TclpStrftime(s, maxsize, format, t, useGMT)
1.123 + char *s;
1.124 + size_t maxsize;
1.125 + const char *format;
1.126 + const struct tm *t;
1.127 + int useGMT;
1.128 +{
1.129 + if (format[0] == '%' && format[1] == 'Q') {
1.130 + /* Format as a stardate */
1.131 + sprintf(s, "Stardate %2d%03d.%01d",
1.132 + (((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
1.133 + (((t->tm_yday + 1) * 1000) /
1.134 + (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
1.135 + (((t->tm_hour * 60) + t->tm_min)/144));
1.136 + return(strlen(s));
1.137 + }
1.138 +
1.139 + isGMT = useGMT;
1.140 + /*
1.141 + * We may be able to skip this for useGMT, but it should be harmless.
1.142 + * -- hobbs
1.143 + */
1.144 + tzset();
1.145 +
1.146 + pt = s;
1.147 + if ((gsize = maxsize) < 1)
1.148 + return(0);
1.149 + if (_fmt(format, t)) {
1.150 + *pt = '\0';
1.151 + return(maxsize - gsize);
1.152 + }
1.153 + return(0);
1.154 +}
1.155 +
1.156 +#define SUN_WEEK(t) (((t)->tm_yday + 7 - \
1.157 + ((t)->tm_wday)) / 7)
1.158 +#define MON_WEEK(t) (((t)->tm_yday + 7 - \
1.159 + ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
1.160 +
1.161 +static size_t
1.162 +_fmt(format, t)
1.163 + const char *format;
1.164 + const struct tm *t;
1.165 +{
1.166 +#ifdef WIN32
1.167 +#define BUF_SIZ 256
1.168 + TCHAR buf[BUF_SIZ];
1.169 + SYSTEMTIME syst = {
1.170 + t->tm_year + 1900,
1.171 + t->tm_mon + 1,
1.172 + t->tm_wday,
1.173 + t->tm_mday,
1.174 + t->tm_hour,
1.175 + t->tm_min,
1.176 + t->tm_sec,
1.177 + 0,
1.178 + };
1.179 +#endif
1.180 + for (; *format; ++format) {
1.181 + if (*format == '%') {
1.182 + ++format;
1.183 + if (*format == 'E') {
1.184 + /* Alternate Era */
1.185 + ++format;
1.186 + } else if (*format == 'O') {
1.187 + /* Alternate numeric symbols */
1.188 + ++format;
1.189 + }
1.190 + switch(*format) {
1.191 + case '\0':
1.192 + --format;
1.193 + break;
1.194 + case 'A':
1.195 + if (t->tm_wday < 0 || t->tm_wday > 6)
1.196 + return(0);
1.197 + if (!_add(_CurrentTimeLocale->day[t->tm_wday]))
1.198 + return(0);
1.199 + continue;
1.200 + case 'a':
1.201 + if (t->tm_wday < 0 || t->tm_wday > 6)
1.202 + return(0);
1.203 + if (!_add(_CurrentTimeLocale->abday[t->tm_wday]))
1.204 + return(0);
1.205 + continue;
1.206 + case 'B':
1.207 + if (t->tm_mon < 0 || t->tm_mon > 11)
1.208 + return(0);
1.209 + if (!_add(_CurrentTimeLocale->mon[t->tm_mon]))
1.210 + return(0);
1.211 + continue;
1.212 + case 'b':
1.213 + case 'h':
1.214 + if (t->tm_mon < 0 || t->tm_mon > 11)
1.215 + return(0);
1.216 + if (!_add(_CurrentTimeLocale->abmon[t->tm_mon]))
1.217 + return(0);
1.218 + continue;
1.219 + case 'C':
1.220 + if (!_conv((t->tm_year + TM_YEAR_BASE) / 100,
1.221 + 2, '0'))
1.222 + return(0);
1.223 + continue;
1.224 + case 'D':
1.225 + if (!_fmt("%m/%d/%y", t))
1.226 + return(0);
1.227 + continue;
1.228 + case 'd':
1.229 + if (!_conv(t->tm_mday, 2, '0'))
1.230 + return(0);
1.231 + continue;
1.232 + case 'e':
1.233 + if (!_conv(t->tm_mday, 2, ' '))
1.234 + return(0);
1.235 + continue;
1.236 + case 'g':
1.237 + {
1.238 + int year;
1.239 + ISO8601Week( t, &year );
1.240 + if ( !_conv( year%100, 2, '0' ) ) {
1.241 + return( 0 );
1.242 + }
1.243 + continue;
1.244 + }
1.245 + case 'G':
1.246 + {
1.247 + int year;
1.248 + ISO8601Week( t, &year );
1.249 + if ( !_conv( year, 4, '0' ) ) {
1.250 + return( 0 );
1.251 + }
1.252 + continue;
1.253 + }
1.254 + case 'H':
1.255 + if (!_conv(t->tm_hour, 2, '0'))
1.256 + return(0);
1.257 + continue;
1.258 + case 'I':
1.259 + if (!_conv(t->tm_hour % 12 ?
1.260 + t->tm_hour % 12 : 12, 2, '0'))
1.261 + return(0);
1.262 + continue;
1.263 + case 'j':
1.264 + if (!_conv(t->tm_yday + 1, 3, '0'))
1.265 + return(0);
1.266 + continue;
1.267 + case 'k':
1.268 + if (!_conv(t->tm_hour, 2, ' '))
1.269 + return(0);
1.270 + continue;
1.271 + case 'l':
1.272 + if (!_conv(t->tm_hour % 12 ?
1.273 + t->tm_hour % 12: 12, 2, ' '))
1.274 + return(0);
1.275 + continue;
1.276 + case 'M':
1.277 + if (!_conv(t->tm_min, 2, '0'))
1.278 + return(0);
1.279 + continue;
1.280 + case 'm':
1.281 + if (!_conv(t->tm_mon + 1, 2, '0'))
1.282 + return(0);
1.283 + continue;
1.284 + case 'n':
1.285 + if (!_add("\n"))
1.286 + return(0);
1.287 + continue;
1.288 + case 'p':
1.289 + if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour >= 12]))
1.290 + return(0);
1.291 + continue;
1.292 + case 'R':
1.293 + if (!_fmt("%H:%M", t))
1.294 + return(0);
1.295 + continue;
1.296 + case 'r':
1.297 + if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t))
1.298 + return(0);
1.299 + continue;
1.300 + case 'S':
1.301 + if (!_conv(t->tm_sec, 2, '0'))
1.302 + return(0);
1.303 + continue;
1.304 + case 's':
1.305 + if (!_secs(t))
1.306 + return(0);
1.307 + continue;
1.308 + case 'T':
1.309 + if (!_fmt("%H:%M:%S", t))
1.310 + return(0);
1.311 + continue;
1.312 + case 't':
1.313 + if (!_add("\t"))
1.314 + return(0);
1.315 + continue;
1.316 + case 'U':
1.317 + if (!_conv(SUN_WEEK(t), 2, '0'))
1.318 + return(0);
1.319 + continue;
1.320 + case 'u':
1.321 + if (!_conv(t->tm_wday ? t->tm_wday : 7, 1, '0'))
1.322 + return(0);
1.323 + continue;
1.324 + case 'V':
1.325 + {
1.326 + int week = ISO8601Week( t, NULL );
1.327 + if (!_conv(week, 2, '0'))
1.328 + return(0);
1.329 + continue;
1.330 + }
1.331 + case 'W':
1.332 + if (!_conv(MON_WEEK(t), 2, '0'))
1.333 + return(0);
1.334 + continue;
1.335 + case 'w':
1.336 + if (!_conv(t->tm_wday, 1, '0'))
1.337 + return(0);
1.338 + continue;
1.339 +#ifdef WIN32
1.340 + /*
1.341 + * To properly handle the localized time routines on Windows,
1.342 + * we must make use of the special localized calls.
1.343 + */
1.344 + case 'c':
1.345 + if (!GetDateFormat(LOCALE_USER_DEFAULT,
1.346 + DATE_LONGDATE | LOCALE_USE_CP_ACP,
1.347 + &syst, NULL, buf, BUF_SIZ)
1.348 + || !_add(buf)
1.349 + || !_add(" ")) {
1.350 + return(0);
1.351 + }
1.352 + /*
1.353 + * %c is created with LONGDATE + " " + TIME on Windows,
1.354 + * so continue to %X case here.
1.355 + */
1.356 + case 'X':
1.357 + if (!GetTimeFormat(LOCALE_USER_DEFAULT,
1.358 + LOCALE_USE_CP_ACP,
1.359 + &syst, NULL, buf, BUF_SIZ)
1.360 + || !_add(buf)) {
1.361 + return(0);
1.362 + }
1.363 + continue;
1.364 + case 'x':
1.365 + if (!GetDateFormat(LOCALE_USER_DEFAULT,
1.366 + DATE_SHORTDATE | LOCALE_USE_CP_ACP,
1.367 + &syst, NULL, buf, BUF_SIZ)
1.368 + || !_add(buf)) {
1.369 + return(0);
1.370 + }
1.371 + continue;
1.372 +#else
1.373 + case 'c':
1.374 + if (!_fmt(_CurrentTimeLocale->d_t_fmt, t))
1.375 + return(0);
1.376 + continue;
1.377 + case 'x':
1.378 + if (!_fmt(_CurrentTimeLocale->d_fmt, t))
1.379 + return(0);
1.380 + continue;
1.381 + case 'X':
1.382 + if (!_fmt(_CurrentTimeLocale->t_fmt, t))
1.383 + return(0);
1.384 + continue;
1.385 +#endif
1.386 + case 'y':
1.387 + if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
1.388 + 2, '0'))
1.389 + return(0);
1.390 + continue;
1.391 + case 'Y':
1.392 + if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0'))
1.393 + return(0);
1.394 + continue;
1.395 + case 'Z': {
1.396 + char *name = (isGMT ? "GMT" : TclpGetTZName(t->tm_isdst));
1.397 + int wrote;
1.398 + Tcl_UtfToExternal(NULL, NULL, name, -1, 0, NULL,
1.399 + pt, gsize, NULL, &wrote, NULL);
1.400 + pt += wrote;
1.401 + gsize -= wrote;
1.402 + continue;
1.403 + }
1.404 + case '%':
1.405 + /*
1.406 + * X311J/88-090 (4.12.3.5): if conversion char is
1.407 + * undefined, behavior is undefined. Print out the
1.408 + * character itself as printf(3) does.
1.409 + */
1.410 + default:
1.411 + break;
1.412 + }
1.413 + }
1.414 + if (!gsize--)
1.415 + return(0);
1.416 + *pt++ = *format;
1.417 + }
1.418 + return(gsize);
1.419 +}
1.420 +
1.421 +static int
1.422 +_secs(t)
1.423 + const struct tm *t;
1.424 +{
1.425 + static char buf[15];
1.426 + register time_t s;
1.427 + register char *p;
1.428 + struct tm tmp;
1.429 +
1.430 + /* Make a copy, mktime(3) modifies the tm struct. */
1.431 + tmp = *t;
1.432 + s = mktime(&tmp);
1.433 + for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
1.434 + *p-- = (char)(s % 10 + '0');
1.435 + return(_add(++p));
1.436 +}
1.437 +
1.438 +static int
1.439 +_conv(n, digits, pad)
1.440 + int n, digits;
1.441 + int pad;
1.442 +{
1.443 + static char buf[10];
1.444 + register char *p;
1.445 +
1.446 + p = buf + sizeof( buf ) - 1;
1.447 + *p-- = '\0';
1.448 + if ( n == 0 ) {
1.449 + *p-- = '0'; --digits;
1.450 + } else {
1.451 + for (; n > 0 && p > buf; n /= 10, --digits)
1.452 + *p-- = (char)(n % 10 + '0');
1.453 + }
1.454 + while (p > buf && digits-- > 0)
1.455 + *p-- = (char) pad;
1.456 + return(_add(++p));
1.457 +}
1.458 +
1.459 +static int
1.460 +_add(str)
1.461 + const char *str;
1.462 +{
1.463 + for (;; ++pt, --gsize) {
1.464 + if (!gsize)
1.465 + return(0);
1.466 + if (!(*pt = *str++))
1.467 + return(1);
1.468 + }
1.469 +}
1.470 +
1.471 +static int
1.472 +ISO8601Week( t, year )
1.473 + CONST struct tm* t;
1.474 + int* year;
1.475 +{
1.476 + /* Find the day-of-year of the Thursday in
1.477 + * the week in question. */
1.478 +
1.479 + int ydayThursday;
1.480 + int week;
1.481 + if ( t->tm_wday == 0 ) {
1.482 + ydayThursday = t->tm_yday - 3;
1.483 + } else {
1.484 + ydayThursday = t->tm_yday - t->tm_wday + 4;
1.485 + }
1.486 +
1.487 + if ( ydayThursday < 0 ) {
1.488 +
1.489 + /* This is the last week of the previous year. */
1.490 + if ( IsLeapYear(( t->tm_year + TM_YEAR_BASE - 1 )) ) {
1.491 + ydayThursday += 366;
1.492 + } else {
1.493 + ydayThursday += 365;
1.494 + }
1.495 + week = ydayThursday / 7 + 1;
1.496 + if ( year != NULL ) {
1.497 + *year = t->tm_year + 1899;
1.498 + }
1.499 +
1.500 + } else if ( ( IsLeapYear(( t -> tm_year + TM_YEAR_BASE ))
1.501 + && ydayThursday >= 366 )
1.502 + || ( !IsLeapYear(( t -> tm_year
1.503 + + TM_YEAR_BASE ))
1.504 + && ydayThursday >= 365 ) ) {
1.505 +
1.506 + /* This is week 1 of the following year */
1.507 +
1.508 + week = 1;
1.509 + if ( year != NULL ) {
1.510 + *year = t->tm_year + 1901;
1.511 + }
1.512 +
1.513 + } else {
1.514 +
1.515 + week = ydayThursday / 7 + 1;
1.516 + if ( year != NULL ) {
1.517 + *year = t->tm_year + 1900;
1.518 + }
1.519 +
1.520 + }
1.521 +
1.522 + return week;
1.523 +
1.524 +}