From b9664b2cabe1017a3b0df6007f2e722274b07b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=C3=B6hler?= Date: Sat, 5 May 2007 20:44:24 +0000 Subject: [PATCH] Add Windows-specific code to lib/libc/strptime.c to eat %x, %X and %c. Originally, it came from evolution-data-server, /libedataserver/e-time-utils.c, but was modified to not depend on GLib. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16048 57a11ea4-9604-0410-9ed3-97b8803252fd --- lib/libc/Makefile.am | 4 + lib/libc/strptime.c | 372 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 376 insertions(+) diff --git a/lib/libc/Makefile.am b/lib/libc/Makefile.am index 67a4b35a73..8e258904ef 100644 --- a/lib/libc/Makefile.am +++ b/lib/libc/Makefile.am @@ -17,6 +17,10 @@ LTLIBOBJS = $(shell echo "$(LIBOBJS)" | sed '@LIBOBJS_SEDSCRIPT@' | \ libc_missing_la_LIBADD = $(LTLIBOBJS) +if OS_WIN32 + AM_CFLAGS = -DOS_WIN32 +endif + # Not currently used. If added to AC_REPLACE_FUNCS then this line # should be removed. EXTRA_DIST = scm_strptime.c diff --git a/lib/libc/strptime.c b/lib/libc/strptime.c index 0f1e4b823a..14189a7ba8 100644 --- a/lib/libc/strptime.c +++ b/lib/libc/strptime.c @@ -38,6 +38,166 @@ #include "strptime.h" + +#ifdef OS_WIN32 +/* The localtime_r() definition in pthreads-win32's pthread.h doesn't guard + * against localtime() returning NULL. + */ +#undef localtime_r +/* The localtime() in Microsoft's C library is MT-safe */ +#define localtime_r(tp,tmp) (localtime(tp)?(*(tmp)=*localtime(tp),(tmp)):0) + +#include + +static char * +get_locale_string (int lctype) +{ + int nbytes = GetLocaleInfo (GetThreadLocale (), lctype, NULL, 0); + char *tem; + + if (nbytes == 0) + return "???"; + + tem = malloc (nbytes); + + if (GetLocaleInfo (GetThreadLocale (), lctype, tem, nbytes) == 0) { + free (tem); + tem = malloc (4); + strcpy (tem, "???"); + } + + return tem; +} + +static void +append_char (char **str, int *size, int *i, char c) +{ + if (*size <= *i + 1) { + char *new; + *size *= 2; + new = malloc (*size); + strncpy (new, *str, *i); + free (*str); + *str = new; + } + (*str)[*i] = c; + (*str)[++(*i)] = '\0'; +} + +static char * +translate_picture (const char *picture) +{ + int size = strlen (picture) * 2; + char *str = malloc (size); + int i = 0; + + str[0] = '\0'; + + while (*picture) { + const char *q = picture + 1; + int count; + + while (*picture == *q) + q++; + count = q - picture; + + switch (*picture) { + case '\'': + picture++; + while (*picture && *picture != '\'') { + append_char (&str, &size, &i, *picture); + picture++; + } + break; + case 'd': + switch (count) { + case 1: + case 2: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'd'); + break; + case 3: + case 4: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'a'); + break; + } + picture += count - 1; + break; + case 'M': + switch (count) { + case 1: + case 2: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'm'); + break; + case 3: + case 4: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'b'); + break; + } + picture += count - 1; + break; + case 'y': + switch (count) { + case 1: /* Last digit of year. Ugh... */ + case 2: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'y'); + break; + case 4: + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'Y'); + break; + } + picture += count - 1; + break; + case 'g': + /* Era. Huh. Just ignore, as the era stuff + * implementation below depends on glibc. + */ + picture += count - 1; + break; + case 'h': + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'I'); + picture += count - 1; + break; + case 'H': + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'H'); + picture += count - 1; + break; + case 'm': + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'M'); + picture += count - 1; + break; + case 's': + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'S'); + picture += count - 1; + break; + case 't': + append_char (&str, &size, &i, '%'); + append_char (&str, &size, &i, 'p'); + picture += count - 1; + break; + default: + append_char (&str, &size, &i, *picture); + break; + } + if (*picture) + picture++; + } + + return str; +} + +#endif /* OS_WIN32 */ + + #ifndef __P # if defined (__GNUC__) || (defined (__STDC__) && __STDC__) # define __P(args) args @@ -332,6 +492,30 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) break; } } +#elif defined (OS_WIN32) + if (*decided !=raw) + { + char *locale_string = get_locale_string (LOCALE_SDAYNAME1 + cnt); + if (match_string (locale_string, rp)) + { + if (*decided == not + && strcmp (locale_string, weekday_name[cnt])) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + locale_string = get_locale_string (LOCALE_SABBREVDAYNAME1 + cnt); + if (match_string (locale_string, rp)) + { + if (*decided == not + && strcmp (locale_string, ab_weekday_name[cnt])) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + } #endif if (*decided != loc && (match_string (weekday_name[cnt], rp) @@ -373,6 +557,30 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) break; } } +#elif defined (OS_WIN32) + if (*decided !=raw) + { + char *locale_string = get_locale_string (LOCALE_SMONTHNAME1 + cnt); + if (match_string (locale_string, rp)) + { + if (*decided == not + && strcmp (locale_string, month_name[cnt])) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + locale_string = get_locale_string (LOCALE_SABBREVMONTHNAME1 + cnt); + if (match_string (locale_string, rp)) + { + if (*decided == not + && strcmp (locale_string, ab_month_name[cnt])) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + } #endif if (match_string (month_name[cnt], rp) || match_string (ab_month_name[cnt], rp)) @@ -409,6 +617,50 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) } *decided = raw; } +#elif defined (OS_WIN32) + if (*decided != raw) + { + char *date_locale_string = get_locale_string (LOCALE_SSHORTDATE); + char *time_locale_string = get_locale_string (LOCALE_STIMEFORMAT); + int date_len = strlen (date_locale_string); + int time_len = strlen (time_locale_string); + char *d_t_fmt = malloc (date_len + time_len + 2); + char *posix_d_t_fmt; + + strncpy (d_t_fmt, date_locale_string, date_len); + strncat (d_t_fmt, " ", 1); + strncat (d_t_fmt, time_locale_string, time_len); + free (date_locale_string); + free (time_locale_string); + + posix_d_t_fmt = translate_picture (d_t_fmt); + + free (d_t_fmt); + + if (!recursive (posix_d_t_fmt)) + { + if (*decided == loc) + { + free (posix_d_t_fmt); + return NULL; + } + else + { + rp = rp_backup; + } + } + else + { + if (*decided == not && + strcmp (posix_d_t_fmt, HERE_D_T_FMT)) + *decided = loc; + want_xday = 1; + free (posix_d_t_fmt); + break; + } + free (posix_d_t_fmt); + *decided = raw; + } #endif if (!recursive (HERE_D_T_FMT)) return NULL; @@ -457,6 +709,38 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) } *decided = raw; } +#elif defined (OS_WIN32) + if (*decided != raw) + { + char *locale_string = get_locale_string (LOCALE_SSHORTDATE); + char *posix_d_fmt = translate_picture (locale_string); + + free (locale_string); + + if (!recursive (posix_d_fmt)) + { + if (*decided == loc) + { + free(posix_d_fmt); + return NULL; + } + else + { + rp = rp_backup; + } + } + else + { + if (*decided == not + && strcmp (posix_d_fmt, HERE_D_FMT)) + *decided = loc; + want_xday = 1; + free(posix_d_fmt); + break; + } + free(posix_d_fmt); + *decided = raw; + } #endif /* Fall through. */ case 'D': @@ -522,6 +806,30 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) } *decided = raw; } +#elif defined (OS_WIN32) + if (*decided != raw) + { + char *locale_string = get_locale_string (LOCALE_S1159); + if (match_string (locale_string, rp)) + { + if (strcmp (locale_string, HERE_AM_STR)) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + locale_string = get_locale_string (LOCALE_S2359); + if (match_string (locale_string, rp)) + { + if (strcmp (locale_string, HERE_PM_STR)) + *decided = loc; + is_pm = 1; + free (locale_string); + break; + } + *decided = raw; + free (locale_string); + } #endif if (!match_string (HERE_AM_STR, rp)) if (match_string (HERE_PM_STR, rp)) @@ -550,6 +858,45 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) } *decided = raw; } +#elif defined (OS_WIN32) + if (*decided != raw) + { + char *locale_string = get_locale_string (LOCALE_STIMEFORMAT); + int locale_len = strlen (locale_string); + char *t_p_fmt = malloc (locale_len + 4); + char *posix_t_p_fmt; + + strncpy (t_p_fmt, locale_string, locale_len); + strncat (t_p_fmt, " tt", 3); + + posix_t_p_fmt = translate_picture (t_p_fmt); + + free (t_p_fmt); + + if (!recursive (posix_t_p_fmt)) + { + if (*decided == loc) + { + free (posix_t_p_fmt); + return NULL; + } + else + { + rp = rp_backup; + } + } + else + { + if (*decided == not && + strcmp (posix_t_p_fmt, + HERE_T_FMT_AMPM)) + *decided = loc; + free (posix_t_p_fmt); + break; + } + free (posix_t_p_fmt); + *decided = raw; + } #endif if (!recursive (HERE_T_FMT_AMPM)) return NULL; @@ -604,6 +951,29 @@ strptime_internal (rp, fmt, tm, decided, era_cnt) } *decided = raw; } +#elif defined (OS_WIN32) + if (*decided != raw) + { + char *locale_string = get_locale_string (LOCALE_STIMEFORMAT); + if (!recursive (locale_string)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + free (locale_string); + locale_string = get_locale_string (LOCALE_STIMEFORMAT); + if (strcmp (locale_string, HERE_T_FMT)) + *decided = loc; + free (locale_string); + break; + } + free (locale_string); + *decided = raw; + } #endif /* Fall through. */ case 'T': @@ -984,6 +1354,8 @@ strptime (buf, format, tm) #ifdef _NL_CURRENT decided = not; +#elif defined (OS_WIN32) + decided = not; #else decided = raw; #endif