Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2010-01-23 01:31:31 +0300
committerCorinna Vinschen <corinna@vinschen.de>2010-01-23 01:31:31 +0300
commit326fb376dda24e2c3f445863791eb6073d91d69b (patch)
tree6f272a713b5deab3bead327e258592b887f3d528 /winsup/cygwin
parente894eef9f5bfa989029423afe729da554df8d17e (diff)
* Makefile.in (DLL_OFILES): Add nlsfunc.o and strfmon.o.
* autoload.cc (LocaleNameToLCID): Define. * cygwin.din (strfmon): Export. * nlsfuncs.cc: New file. Define a lot of internal functions called from setlocale. (wcscoll): Implement locale-aware here, using CompareStringW function. (strcoll): Ditto. (wcsxfrm): Implement locale-aware here, usingLCMapStringW function. (strxfrm): Ditto. (__set_charset_from_locale): Replace __set_charset_from_codepage. Return Linux-compatible charset. * strfuncs.cc (__set_charset_from_codepage): Remove. * wchar.h (__set_charset_from_codepage): Drop definition. * wincap.h (wincaps::has_localenames): New element. * wincap.cc: Implement above element throughout. * libc/strfmon.c: New file. * libc/strptime.cc: Remove locale constant strings in favor of access to locale-specifc data. (strptime): Point _CurrentTimeLocale to locale-specific data. Throughout use correct locale-specific format fields for all locale-specific formats. * include/monetary.h: New file. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog26
-rw-r--r--winsup/cygwin/Makefile.in14
-rw-r--r--winsup/cygwin/autoload.cc4
-rw-r--r--winsup/cygwin/cygwin.din1
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/monetary.h39
-rw-r--r--winsup/cygwin/libc/strfmon.c621
-rw-r--r--winsup/cygwin/libc/strptime.cc60
-rw-r--r--winsup/cygwin/nlsfuncs.cc764
-rw-r--r--winsup/cygwin/strfuncs.cc81
-rw-r--r--winsup/cygwin/wchar.h4
-rw-r--r--winsup/cygwin/wincap.cc14
-rw-r--r--winsup/cygwin/wincap.h5
13 files changed, 1491 insertions, 145 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ef89c70a1..fc312b759 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,29 @@
+2010-01-22 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in (DLL_OFILES): Add nlsfunc.o and strfmon.o.
+ * autoload.cc (LocaleNameToLCID): Define.
+ * cygwin.din (strfmon): Export.
+ * nlsfuncs.cc: New file. Define a lot of internal functions called
+ from setlocale.
+ (wcscoll): Implement locale-aware here, using CompareStringW function.
+ (strcoll): Ditto.
+ (wcsxfrm): Implement locale-aware here, usingLCMapStringW function.
+ (strxfrm): Ditto.
+ (__set_charset_from_locale): Replace __set_charset_from_codepage.
+ Return Linux-compatible charset.
+ * strfuncs.cc (__set_charset_from_codepage): Remove.
+ * wchar.h (__set_charset_from_codepage): Drop definition.
+ * wincap.h (wincaps::has_localenames): New element.
+ * wincap.cc: Implement above element throughout.
+ * libc/strfmon.c: New file.
+ * libc/strptime.cc: Remove locale constant strings in favor of
+ access to locale-specifc data.
+ (strptime): Point _CurrentTimeLocale to locale-specific data.
+ Throughout use correct locale-specific format fields for all
+ locale-specific formats.
+ * include/monetary.h: New file.
+ * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
+
2010-01-18 Corinna Vinschen <corinna@vinschen.de>
* strfuncs.cc: Remove needless includes.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index d23bde24a..6da49fabc 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -1,6 +1,6 @@
# Makefile.in for Cygwin.
# Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
+# 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
#
# This file is part of Cygwin.
#
@@ -148,12 +148,12 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \
glob_pattern_p.o globals.o grp.o heap.o hookapi.o inet_addr.o inet_network.o \
init.o ioctl.o ipc.o kernel32.o libstdcxx_wrapper.o localtime.o lsearch.o \
malloc_wrapper.o minires-os-if.o minires.o miscfuncs.o mktemp.o mmap.o msg.o \
- mount.o net.o netdb.o nfs.o nftw.o ntea.o passwd.o path.o pinfo.o pipe.o \
- poll.o posix_ipc.o pthread.o random.o regcomp.o regerror.o regexec.o \
- regfree.o registry.o resource.o rexec.o rcmd.o scandir.o sched.o \
- sec_acl.o sec_auth.o sec_helper.o security.o select.o sem.o \
- setlsapwd.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
- spawn.o strace.o strfuncs.o strptime.o strsep.o strsig.o sync.o \
+ mount.o net.o netdb.o nfs.o nftw.o nlsfuncs.o ntea.o passwd.o path.o \
+ pinfo.o pipe.o poll.o posix_ipc.o pthread.o random.o regcomp.o \
+ regerror.o regexec.o regfree.o registry.o resource.o rexec.o rcmd.o \
+ scandir.o sched.o sec_acl.o sec_auth.o sec_helper.o security.o select.o \
+ sem.o setlsapwd.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
+ spawn.o strace.o strfmon.o strfuncs.o strptime.o strsep.o strsig.o sync.o \
syscalls.o sysconf.o syslog.o termios.o thread.o timer.o times.o \
tls_pbuf.o tty.o uinfo.o uname.o wait.o wincap.o window.o winf.o \
xsique.o \
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index bac1c1979..eb16961c9 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -1,6 +1,7 @@
/* autoload.cc: all dynamic load stuff.
- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -422,6 +423,7 @@ LoadDLLfuncEx (GetSystemWindowsDirectoryW, 8, kernel32, 1)
LoadDLLfuncEx (GetVolumeNameForVolumeMountPointA, 12, kernel32, 1)
LoadDLLfuncEx (GetSystemDEPPolicy, 0, kernel32, 1)
LoadDLLfuncEx (GetProcessDEPPolicy, 12, kernel32, 1)
+LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
LoadDLLfuncEx (SetProcessDEPPolicy, 4, kernel32, 1)
LoadDLLfunc (SHGetDesktopFolder, 4, shell32)
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index b2d2b1e47..46f03582c 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -1527,6 +1527,7 @@ strerror SIGFE
_strerror = strerror SIGFE
strerror_r SIGFE
_strerror_r = strerror_r SIGFE
+strfmon SIGFE
strftime SIGFE
_strftime = strftime SIGFE
strlcat NOSIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 156d32ebd..f846ac22e 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -374,12 +374,13 @@ details. */
218: Export get_nprocs, get_nprocs_conf, get_phys_pages, get_avphys_pages.
219: Export dup3, pipe2, O_CLOEXEC, F_DUPFD_CLOEXEC.
220: Export accept4, SOCK_CLOEXEC, SOCK_NONBLOCK.
+ 221: Export strfmon.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 220
+#define CYGWIN_VERSION_API_MINOR 221
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/monetary.h b/winsup/cygwin/include/monetary.h
new file mode 100644
index 000000000..8b525e961
--- /dev/null
+++ b/winsup/cygwin/include/monetary.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MONETARY_H_
+#define _MONETARY_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+ssize_t strfmon(char * __restrict, size_t, const char * __restrict, ...);
+__END_DECLS
+
+#endif /* !_MONETARY_H_ */
diff --git a/winsup/cygwin/libc/strfmon.c b/winsup/cygwin/libc/strfmon.c
new file mode 100644
index 000000000..2c2523ee8
--- /dev/null
+++ b/winsup/cygwin/libc/strfmon.c
@@ -0,0 +1,621 @@
+/*-
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.19 2008/04/24 07:49:00 ru Exp $");
+#endif
+
+#include "winsup.h"
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <monetary.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* internal flags */
+#define NEED_GROUPING 0x01 /* print digits grouped (default) */
+#define SIGN_POSN_USED 0x02 /* '+' or '(' usage flag */
+#define LOCALE_POSN 0x04 /* use locale defined +/- (default) */
+#define PARENTH_POSN 0x08 /* enclose negative amount in () */
+#define SUPRESS_CURR_SYMBOL 0x10 /* supress the currency from output */
+#define LEFT_JUSTIFY 0x20 /* left justify */
+#define USE_INTL_CURRENCY 0x40 /* use international currency symbol */
+#define IS_NEGATIVE 0x80 /* is argument value negative ? */
+
+/* internal macros */
+#define PRINT(CH) do { \
+ if (dst >= s + maxsize) \
+ goto e2big_error; \
+ *dst++ = CH; \
+} while (0)
+
+#define PRINTS(STR) do { \
+ char *tmps = STR; \
+ while (*tmps != '\0') \
+ PRINT(*tmps++); \
+} while (0)
+
+#define GET_NUMBER(VAR) do { \
+ VAR = 0; \
+ while (isdigit((unsigned char)*fmt)) { \
+ if (VAR > INT_MAX / 10) \
+ goto e2big_error; \
+ VAR *= 10; \
+ VAR += *fmt - '0'; \
+ if (VAR < 0) \
+ goto e2big_error; \
+ fmt++; \
+ } \
+} while (0)
+
+#define GRPCPY(howmany) do { \
+ int i = howmany; \
+ while (i-- > 0) { \
+ avalue_size--; \
+ *--bufend = *(avalue+avalue_size+padded); \
+ } \
+} while (0)
+
+#define GRPSEP do { \
+ *--bufend = thousands_sep; \
+ groups++; \
+} while (0)
+
+static void __setup_vars(int, char *, char *, char *, char **);
+static int __calc_left_pad(int, char *);
+static char *__format_grouped_double(double, int *, int, int, int);
+
+ssize_t
+strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
+ ...)
+{
+ va_list ap;
+ char *dst; /* output destination pointer */
+ const char *fmt; /* current format poistion pointer */
+ struct lconv *lc; /* pointer to lconv structure */
+ char *asciivalue; /* formatted double pointer */
+
+ int flags; /* formatting options */
+ int pad_char; /* padding character */
+ int pad_size; /* pad size */
+ int width; /* field width */
+ int left_prec; /* left precision */
+ int right_prec; /* right precision */
+ double value; /* just value */
+ char space_char = ' '; /* space after currency */
+
+ char cs_precedes, /* values gathered from struct lconv */
+ sep_by_space,
+ sign_posn,
+ *signstr,
+ *currency_symbol;
+
+ char *tmpptr; /* temporary vars */
+ int sverrno;
+
+ va_start(ap, format);
+
+ lc = localeconv();
+ dst = s;
+ fmt = format;
+ asciivalue = NULL;
+ currency_symbol = NULL;
+ pad_size = 0;
+
+ while (*fmt) {
+ /* pass nonformating characters AS IS */
+ if (*fmt != '%')
+ goto literal;
+
+ /* '%' found ! */
+
+ /* "%%" mean just '%' */
+ if (*(fmt+1) == '%') {
+ fmt++;
+ literal:
+ PRINT(*fmt++);
+ continue;
+ }
+
+ /* set up initial values */
+ flags = (NEED_GROUPING|LOCALE_POSN);
+ pad_char = ' '; /* padding character is "space" */
+ left_prec = -1; /* no left precision specified */
+ right_prec = -1; /* no right precision specified */
+ width = -1; /* no width specified */
+ value = 0; /* we have no value to print now */
+
+ /* Flags */
+ while (1) {
+ switch (*++fmt) {
+ case '=': /* fill character */
+ pad_char = *++fmt;
+ if (pad_char == '\0')
+ goto format_error;
+ continue;
+ case '^': /* not group currency */
+ flags &= ~(NEED_GROUPING);
+ continue;
+ case '+': /* use locale defined signs */
+ if (flags & SIGN_POSN_USED)
+ goto format_error;
+ flags |= (SIGN_POSN_USED|LOCALE_POSN);
+ continue;
+ case '(': /* enclose negatives with () */
+ if (flags & SIGN_POSN_USED)
+ goto format_error;
+ flags |= (SIGN_POSN_USED|PARENTH_POSN);
+ continue;
+ case '!': /* suppress currency symbol */
+ flags |= SUPRESS_CURR_SYMBOL;
+ continue;
+ case '-': /* alignment (left) */
+ flags |= LEFT_JUSTIFY;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ /* field Width */
+ if (isdigit((unsigned char)*fmt)) {
+ GET_NUMBER(width);
+ /* Do we have enough space to put number with
+ * required width ?
+ */
+ if ((unsigned int)width >= maxsize - (dst - s))
+ goto e2big_error;
+ }
+
+ /* Left precision */
+ if (*fmt == '#') {
+ if (!isdigit((unsigned char)*++fmt))
+ goto format_error;
+ GET_NUMBER(left_prec);
+ if ((unsigned int)left_prec >= maxsize - (dst - s))
+ goto e2big_error;
+ }
+
+ /* Right precision */
+ if (*fmt == '.') {
+ if (!isdigit((unsigned char)*++fmt))
+ goto format_error;
+ GET_NUMBER(right_prec);
+ if ((unsigned int)right_prec >= maxsize - (dst - s) -
+ left_prec)
+ goto e2big_error;
+ }
+
+ /* Conversion Characters */
+ switch (*fmt++) {
+ case 'i': /* use internaltion currency format */
+ flags |= USE_INTL_CURRENCY;
+ break;
+ case 'n': /* use national currency format */
+ flags &= ~(USE_INTL_CURRENCY);
+ break;
+ default: /* required character is missing or
+ premature EOS */
+ goto format_error;
+ }
+
+ if (currency_symbol != NULL)
+ free(currency_symbol);
+ if (flags & USE_INTL_CURRENCY) {
+ currency_symbol = strdup(lc->int_curr_symbol);
+ if (currency_symbol != NULL) {
+ space_char = *(currency_symbol+3);
+ *(currency_symbol+3) = '\0';
+ }
+ } else
+ currency_symbol = strdup(lc->currency_symbol);
+
+ if (currency_symbol == NULL)
+ goto end_error; /* ENOMEM. */
+
+ /* value itself */
+ value = va_arg(ap, double);
+
+ /* detect sign */
+ if (value < 0) {
+ flags |= IS_NEGATIVE;
+ value = -value;
+ }
+
+ /* fill left_prec with amount of padding chars */
+ if (left_prec >= 0) {
+ pad_size = __calc_left_pad((flags ^ IS_NEGATIVE),
+ currency_symbol) -
+ __calc_left_pad(flags, currency_symbol);
+ if (pad_size < 0)
+ pad_size = 0;
+ }
+
+ if (asciivalue != NULL)
+ free(asciivalue);
+ asciivalue = __format_grouped_double(value, &flags,
+ left_prec, right_prec, pad_char);
+ if (asciivalue == NULL)
+ goto end_error; /* errno already set */
+ /* to ENOMEM by malloc() */
+
+ /* set some variables for later use */
+ __setup_vars(flags, &cs_precedes, &sep_by_space,
+ &sign_posn, &signstr);
+
+ /*
+ * Description of some LC_MONETARY's values:
+ *
+ * p_cs_precedes & n_cs_precedes
+ *
+ * = 1 - $currency_symbol precedes the value
+ * for a monetary quantity with a non-negative value
+ * = 0 - symbol succeeds the value
+ *
+ * p_sep_by_space & n_sep_by_space
+ *
+ * = 0 - no space separates $currency_symbol
+ * from the value for a monetary quantity with a
+ * non-negative value
+ * = 1 - space separates the symbol from the value
+ * = 2 - space separates the symbol and the sign string,
+ * if adjacent.
+ *
+ * p_sign_posn & n_sign_posn
+ *
+ * = 0 - parentheses enclose the quantity and the
+ * $currency_symbol
+ * = 1 - the sign string precedes the quantity and the
+ * $currency_symbol
+ * = 2 - the sign string succeeds the quantity and the
+ * $currency_symbol
+ * = 3 - the sign string precedes the $currency_symbol
+ * = 4 - the sign string succeeds the $currency_symbol
+ *
+ */
+
+ tmpptr = dst;
+
+ while (pad_size-- > 0)
+ PRINT(' ');
+
+ if (sign_posn == 0 && (flags & IS_NEGATIVE))
+ PRINT('(');
+
+ if (cs_precedes == 1) {
+ if (sign_posn == 1 || sign_posn == 3) {
+ PRINTS(signstr);
+ if (sep_by_space == 2) /* XXX: ? */
+ PRINT(' ');
+ }
+
+ if (!(flags & SUPRESS_CURR_SYMBOL)) {
+ PRINTS(currency_symbol);
+
+ if (sign_posn == 4) {
+ if (sep_by_space == 2)
+ PRINT(space_char);
+ PRINTS(signstr);
+ if (sep_by_space == 1)
+ PRINT(' ');
+ } else if (sep_by_space == 1)
+ PRINT(space_char);
+ }
+ } else if (sign_posn == 1)
+ PRINTS(signstr);
+
+ PRINTS(asciivalue);
+
+ if (cs_precedes == 0) {
+ if (sign_posn == 3) {
+ if (sep_by_space == 1)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+
+ if (!(flags & SUPRESS_CURR_SYMBOL)) {
+ if ((sign_posn == 3 && sep_by_space == 2)
+ || (sep_by_space == 1
+ && (sign_posn == 0
+ || sign_posn == 1
+ || sign_posn == 2
+ || sign_posn == 4)))
+ PRINT(space_char);
+ PRINTS(currency_symbol); /* XXX: len */
+ if (sign_posn == 4) {
+ if (sep_by_space == 2)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+ }
+ }
+
+ if (sign_posn == 2) {
+ if (sep_by_space == 2)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+
+ if (sign_posn == 0 && (flags & IS_NEGATIVE))
+ PRINT(')');
+
+ if (dst - tmpptr < width) {
+ if (flags & LEFT_JUSTIFY) {
+ while (dst - tmpptr < width)
+ PRINT(' ');
+ } else {
+ pad_size = dst-tmpptr;
+ memmove(tmpptr + width-pad_size, tmpptr,
+ pad_size);
+ memset(tmpptr, ' ', width-pad_size);
+ dst += width-pad_size;
+ }
+ }
+ }
+
+ PRINT('\0');
+ va_end(ap);
+ free(asciivalue);
+ free(currency_symbol);
+ return (dst - s - 1); /* return size of put data except trailing '\0' */
+
+e2big_error:
+ errno = E2BIG;
+ goto end_error;
+
+format_error:
+ errno = EINVAL;
+
+end_error:
+ sverrno = errno;
+ if (asciivalue != NULL)
+ free(asciivalue);
+ if (currency_symbol != NULL)
+ free(currency_symbol);
+ errno = sverrno;
+ va_end(ap);
+ return (-1);
+}
+
+static void
+__setup_vars(int flags, char *cs_precedes, char *sep_by_space,
+ char *sign_posn, char **signstr) {
+
+ struct lconv *lc = localeconv();
+
+ if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) {
+ *cs_precedes = lc->int_n_cs_precedes;
+ *sep_by_space = lc->int_n_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn;
+ *signstr = (lc->negative_sign == '\0') ? "-"
+ : lc->negative_sign;
+ } else if (flags & USE_INTL_CURRENCY) {
+ *cs_precedes = lc->int_p_cs_precedes;
+ *sep_by_space = lc->int_p_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_p_sign_posn;
+ *signstr = lc->positive_sign;
+ } else if (flags & IS_NEGATIVE) {
+ *cs_precedes = lc->n_cs_precedes;
+ *sep_by_space = lc->n_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn;
+ *signstr = (lc->negative_sign == '\0') ? "-"
+ : lc->negative_sign;
+ } else {
+ *cs_precedes = lc->p_cs_precedes;
+ *sep_by_space = lc->p_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->p_sign_posn;
+ *signstr = lc->positive_sign;
+ }
+
+ /* Set defult values for unspecified information. */
+ if (*cs_precedes != 0)
+ *cs_precedes = 1;
+ if (*sep_by_space == CHAR_MAX)
+ *sep_by_space = 0;
+ if (*sign_posn == CHAR_MAX)
+ *sign_posn = 0;
+}
+
+static int
+__calc_left_pad(int flags, char *cur_symb) {
+
+ char cs_precedes, sep_by_space, sign_posn, *signstr;
+ int left_chars = 0;
+
+ __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);
+
+ if (cs_precedes != 0) {
+ left_chars += strlen(cur_symb);
+ if (sep_by_space != 0)
+ left_chars++;
+ }
+
+ switch (sign_posn) {
+ case 1:
+ left_chars += strlen(signstr);
+ break;
+ case 3:
+ case 4:
+ if (cs_precedes != 0)
+ left_chars += strlen(signstr);
+ }
+ return (left_chars);
+}
+
+static int
+get_groups(int size, char *grouping) {
+
+ int chars = 0;
+
+ if (*grouping == CHAR_MAX || *grouping <= 0) /* no grouping ? */
+ return (0);
+
+ while (size > (int)*grouping) {
+ chars++;
+ size -= (int)*grouping++;
+ /* no more grouping ? */
+ if (*grouping == CHAR_MAX)
+ break;
+ /* rest grouping with same value ? */
+ if (*grouping == 0) {
+ chars += (size - 1) / *(grouping - 1);
+ break;
+ }
+ }
+ return (chars);
+}
+
+/* convert double to ASCII */
+static char *
+__format_grouped_double(double value, int *flags,
+ int left_prec, int right_prec, int pad_char) {
+
+ char *rslt;
+ char *avalue;
+ int avalue_size;
+ char fmt[32];
+
+ size_t bufsize;
+ char *bufend;
+
+ int padded;
+
+ struct lconv *lc = localeconv();
+ char *grouping;
+ char decimal_point;
+ char thousands_sep;
+
+ int groups = 0;
+
+ grouping = lc->mon_grouping;
+ decimal_point = *lc->mon_decimal_point;
+ if (decimal_point == '\0')
+ decimal_point = *lc->decimal_point;
+ thousands_sep = *lc->mon_thousands_sep;
+ if (thousands_sep == '\0')
+ thousands_sep = *lc->thousands_sep;
+
+ /* fill left_prec with default value */
+ if (left_prec == -1)
+ left_prec = 0;
+
+ /* fill right_prec with default value */
+ if (right_prec == -1) {
+ if (*flags & USE_INTL_CURRENCY)
+ right_prec = lc->int_frac_digits;
+ else
+ right_prec = lc->frac_digits;
+
+ if (right_prec == CHAR_MAX) /* POSIX locale ? */
+ right_prec = 2;
+ }
+
+ if (*flags & NEED_GROUPING)
+ left_prec += get_groups(left_prec, grouping);
+
+ /* convert to string */
+ snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1,
+ right_prec);
+ avalue_size = asprintf(&avalue, fmt, value);
+ if (avalue_size < 0)
+ return (NULL);
+
+ /* make sure that we've enough space for result string */
+ bufsize = strlen(avalue)*2+1;
+ rslt = calloc(1, bufsize);
+ if (rslt == NULL) {
+ free(avalue);
+ return (NULL);
+ }
+ bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */
+
+ /* skip spaces at beggining */
+ padded = 0;
+ while (avalue[padded] == ' ') {
+ padded++;
+ avalue_size--;
+ }
+
+ if (right_prec > 0) {
+ bufend -= right_prec;
+ memcpy(bufend, avalue + avalue_size+padded-right_prec,
+ right_prec);
+ *--bufend = decimal_point;
+ avalue_size -= (right_prec + 1);
+ }
+
+ if ((*flags & NEED_GROUPING) &&
+ thousands_sep != '\0' && /* XXX: need investigation */
+ *grouping != CHAR_MAX &&
+ *grouping > 0) {
+ while (avalue_size > (int)*grouping) {
+ GRPCPY(*grouping);
+ GRPSEP;
+ grouping++;
+
+ /* no more grouping ? */
+ if (*grouping == CHAR_MAX)
+ break;
+
+ /* rest grouping with same value ? */
+ if (*grouping == 0) {
+ grouping--;
+ while (avalue_size > *grouping) {
+ GRPCPY(*grouping);
+ GRPSEP;
+ }
+ }
+ }
+ if (avalue_size != 0)
+ GRPCPY(avalue_size);
+ padded -= groups;
+
+ } else {
+ bufend -= avalue_size;
+ memcpy(bufend, avalue+padded, avalue_size);
+ if (right_prec == 0)
+ padded--; /* decrease assumed $decimal_point */
+ }
+
+ /* do padding with pad_char */
+ if (padded > 0) {
+ bufend -= padded;
+ memset(bufend, pad_char, padded);
+ }
+
+ bufsize = bufsize - (bufend - rslt) + 1;
+ memmove(rslt, bufend, bufsize);
+ free(avalue);
+ return (rslt);
+}
diff --git a/winsup/cygwin/libc/strptime.cc b/winsup/cygwin/libc/strptime.cc
index e2f710ae9..e96de5917 100644
--- a/winsup/cygwin/libc/strptime.cc
+++ b/winsup/cygwin/libc/strptime.cc
@@ -45,53 +45,12 @@ __RCSID("$NetBSD: strptime.c,v 1.28 2008/04/28 20:23:01 martin Exp $");
#include <string.h>
#include <time.h>
#include <tzfile.h>
+#include "../locale/timelocal.h"
#ifdef __weak_alias
__weak_alias(strptime,_strptime)
#endif
-#ifdef __CYGWIN__
-typedef struct {
- const char *abday[7];
- const char *day[7];
- const char *abmon[12];
- const char *mon[12];
- const char *am_pm[2];
- const char *d_t_fmt;
- const char *d_fmt;
- const char *t_fmt;
- const char *t_fmt_ampm;
-} _TimeLocale;
-
-_TimeLocale _DefaultTimeLocale =
-{
- {
- "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
- },
- {
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
- "Friday", "Saturday"
- },
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- },
- {
- "January", "February", "March", "April", "May", "June", "July",
- "August", "September", "October", "November", "December"
- },
- {
- "AM", "PM"
- },
- "%a %b %e %H:%M:%S %Y",
- "%m/%d/%y",
- "%H:%M:%S",
- "%I:%M:%S %p"
-};
-
-_TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
-#endif
-
#define _ctloc(x) (_CurrentTimeLocale->x)
/*
@@ -118,6 +77,7 @@ strptime(const char *buf, const char *fmt, struct tm *tm)
const char *new_fmt;
bp = (const u_char *)buf;
+ struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
while (bp != NULL && (c = *fmt++) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
@@ -161,7 +121,7 @@ literal:
* "Complex" conversion rules, implemented through recursion.
*/
case 'c': /* Date and time, using the locale's format. */
- new_fmt = _ctloc(d_t_fmt);
+ new_fmt = _ctloc(c_fmt);
goto recurse;
case 'D': /* The date as "%m/%d/%y". */
@@ -180,7 +140,7 @@ literal:
goto recurse;
case 'r': /* The time in 12-hour clock representation. */
- new_fmt =_ctloc(t_fmt_ampm);
+ new_fmt =_ctloc(ampm_fmt);
LEGAL_ALT(0);
goto recurse;
@@ -190,11 +150,11 @@ literal:
goto recurse;
case 'X': /* The time, using the locale's format. */
- new_fmt =_ctloc(t_fmt);
+ new_fmt =_ctloc(X_fmt);
goto recurse;
case 'x': /* The date, using the locale's format. */
- new_fmt =_ctloc(d_fmt);
+ new_fmt =_ctloc(x_fmt);
recurse:
bp = (const u_char *)strptime((const char *)bp,
new_fmt, tm);
@@ -206,16 +166,16 @@ literal:
*/
case 'A': /* The day of week, using the locale's form. */
case 'a':
- bp = find_string(bp, &tm->tm_wday, _ctloc(day),
- _ctloc(abday), 7);
+ bp = find_string(bp, &tm->tm_wday, _ctloc(weekday),
+ _ctloc(wday), 7);
LEGAL_ALT(0);
continue;
case 'B': /* The month, using the locale's form. */
case 'b':
case 'h':
- bp = find_string(bp, &tm->tm_mon, _ctloc(mon),
- _ctloc(abmon), 12);
+ bp = find_string(bp, &tm->tm_mon, _ctloc(month),
+ _ctloc(mon), 12);
LEGAL_ALT(0);
continue;
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
new file mode 100644
index 000000000..073aa1329
--- /dev/null
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -0,0 +1,764 @@
+/* nlsfuncs.cc: NLS helper functions
+
+ Copyright 2010 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <stdlib.h>
+#include <winnls.h>
+#include <wchar.h>
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "tls_pbuf.h"
+/* Internal headers from newlib */
+#include "../locale/timelocal.h"
+#include "../locale/lnumeric.h"
+#include "../locale/lmonetary.h"
+
+static char *lc_time_buf;
+static char *lc_numeric_buf;
+static char *lc_monetary_buf;
+
+#define _LC(x) &lc_##x##_ptr,lc_##x##_end-lc_##x##_ptr
+
+#define getlocaleinfo(category,type) \
+ __getlocaleinfo(lcid,(type),_LC(category),f_wctomb,charset)
+#define eval_datetimefmt(type,force) \
+ __eval_datetimefmt(lcid,(type),(force),&lc_time_ptr,\
+ lc_time_end-lc_time_ptr,f_wctomb, charset)
+
+/* Vista and later. Not defined in w32api yet. */
+extern "C" {
+WINBASEAPI LCID WINAPI LocaleNameToLCID (LPCWSTR, DWORD);
+};
+
+static char last_locale[ENCODING_LEN + 1];
+static LCID last_lcid;
+
+/* Fetch LCID from POSIX locale specifier.
+ Return values:
+
+ -1: Invalid locale
+ 0: C or POSIX
+ >0: LCID
+*/
+static LCID
+__get_lcid_from_locale (const char *name)
+{
+ char locale[ENCODING_LEN + 1];
+ char *c;
+ LCID lcid;
+
+ if (!strcmp (name, last_locale))
+ {
+ debug_printf ("LCID=0x%04x", last_lcid);
+ return last_lcid;
+ }
+ stpcpy (last_locale, name);
+ stpcpy (locale, name);
+ /* Drop charset and modifier */
+ c = strchr (locale, '.');
+ if (!c)
+ c = strchr (locale, '@');
+ if (c)
+ *c = '\0';
+ /* "POSIX" already converted to "C" in loadlocale. */
+ if (!strcmp (locale, "C"))
+ return 0;
+ /* Convert to form understood by LocaleNameToLCID */
+ c = strchr (locale, '_');
+ if (c)
+ *c = '-';
+ if (wincap.has_localenames ())
+ {
+ wchar_t wlocale[ENCODING_LEN + 1];
+ mbstowcs (wlocale, locale, ENCODING_LEN + 1);
+ lcid = LocaleNameToLCID (wlocale, 0);
+ last_lcid = lcid ?: (LCID) -1;
+ debug_printf ("LCID=0x%04x", last_lcid);
+ return last_lcid;
+ }
+ /* Pre-Vista we have to loop through the LCID values and see if they
+ match language and TERRITORY. */
+ if (c)
+ *c++ = '\0';
+ /* locale now points to the language, c points to the TERRITORY */
+ const char *language = locale;
+ const char *territory = c;
+ LCID lang, sublang;
+ char iso[10];
+
+ /* In theory the lang part takes 10 bits (0x3ff), but up to Windows 2003 R2
+ the highest lang value is 0x81. */
+ for (lang = 1; lang <= 0x81; ++lang)
+ if (GetLocaleInfo (lang, LOCALE_SISO639LANGNAME, iso, 10)
+ && !strcmp (language, iso))
+ break;
+ if (lang > 0x81)
+ lcid = 0;
+ else if (!territory)
+ lcid = lang;
+ else
+ {
+ /* In theory the sublang part takes 7 bits (0x3f), but up to
+ Windows 2003 R2 the highest sublang value is 0x14. */
+ for (sublang = 1; sublang <= 0x14; ++sublang)
+ {
+ lcid = (sublang << 10) | lang;
+ if (GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso, 10)
+ && !strcmp (territory, iso))
+ break;
+ }
+ if (sublang > 0x14)
+ lcid = 0;
+ }
+ last_lcid = lcid ?: (LCID) -1;
+ debug_printf ("LCID=0x%04x", last_lcid);
+ return last_lcid;
+}
+
+/* Never returns -1, *iff* s is not NULL. Just skips invalid chars
+ instead. s==NULL returns -1 since it's used to recognize invalid
+ strings in the used charset. */
+static size_t
+lc_wcstombs (wctomb_p f_wctomb, const char *charset,
+ char *s, const wchar_t *pwcs, size_t n)
+{
+ char *ptr = s;
+ size_t max = n;
+ char buf[8];
+ size_t i, bytes, num_to_copy;
+ mbstate_t state;
+
+ memset (&state, 0, sizeof state);
+ if (s == NULL)
+ {
+ size_t num_bytes = 0;
+ while (*pwcs != 0)
+ {
+ bytes = f_wctomb (_REENT, buf, *pwcs++, charset, &state);
+ if (bytes == (size_t) -1)
+ return (size_t) -1;
+ num_bytes += bytes;
+ }
+ return num_bytes;
+ }
+ while (n > 0)
+ {
+ bytes = f_wctomb (_REENT, buf, *pwcs, charset, &state);
+ if (bytes == (size_t) -1)
+ {
+ memset (&state, 0, sizeof state);
+ ++pwcs;
+ continue;
+ }
+ num_to_copy = (n > bytes ? bytes : n);
+ for (i = 0; i < num_to_copy; ++i)
+ *ptr++ = buf[i];
+
+ if (*pwcs == 0x00)
+ return ptr - s - (n >= bytes);
+ ++pwcs;
+ n -= num_to_copy;
+ }
+ return max;
+}
+
+/* Never returns -1. Invalid sequences are translated to replacement
+ wide-chars. */
+static size_t
+lc_mbstowcs (mbtowc_p f_mbtowc, const char *charset,
+ wchar_t *pwcs, const char *s, size_t n)
+{
+ size_t ret = 0;
+ char *t = (char *) s;
+ size_t bytes;
+ mbstate_t state;
+
+ memset (&state, 0, sizeof state);
+ if (!pwcs)
+ n = 1;
+ while (n > 0)
+ {
+ bytes = f_mbtowc (_REENT, pwcs, t, MB_CUR_MAX, charset, &state);
+ if (bytes == (size_t) -1)
+ {
+ state.__count = 0;
+ bytes = 1;
+ if (pwcs)
+ *pwcs = L' ';
+ }
+ else if (bytes == 0)
+ break;
+ t += bytes;
+ ++ret;
+ if (pwcs)
+ {
+ ++pwcs;
+ --n;
+ }
+ }
+ return ret;
+}
+
+static char *
+__getlocaleinfo (LCID lcid, LCTYPE type, char **ptr, size_t size,
+ wctomb_p f_wctomb, const char *charset)
+{
+ wchar_t wbuf[80];
+ size_t num;
+ char *ret;
+
+ GetLocaleInfoW (lcid, type, wbuf, 80);
+ num = lc_wcstombs (f_wctomb, charset, ret = *ptr, wbuf, size);
+ *ptr += num + 1;
+ return ret;
+}
+
+static UINT
+getlocaleint (LCID lcid, LCTYPE type)
+{
+ UINT val;
+ return GetLocaleInfoW (lcid, type | LOCALE_RETURN_NUMBER, (PWCHAR) &val,
+ sizeof val) ? val : 0;
+}
+
+static char *
+__eval_datetimefmt (LCID lcid, LCTYPE type, int force, char **ptr,
+ size_t size, wctomb_p f_wctomb, const char *charset)
+{
+ wchar_t buf[80];
+ wchar_t fc;
+ size_t num;
+ mbstate_t mb;
+ size_t idx;
+ const char *day_str = "edaA";
+ const char *mon_str = "mmbB";
+ const char *year_str = "yyyY";
+ const char *hour12_str = "lI";
+ const char *hour24_str = "kH";
+ const char *t_str;
+ char *ret = *ptr;
+ char *p = *ptr;
+
+ GetLocaleInfoW (lcid, type, buf, 80);
+ memset (&mb, 0, sizeof mb);
+ for (wchar_t *fmt = buf; *fmt; ++fmt)
+ switch (fc = *fmt)
+ {
+ case L'\'':
+ if (fmt[1] == L'\'')
+ *p++ = '\'';
+ else
+ while (fmt[1] && *++fmt != L'\'')
+ {
+ num = f_wctomb (_REENT, p, *fmt, charset, &mb);
+ if (num == (size_t) -1)
+ memset (&mb, 0, sizeof mb);
+ else
+ p += num;
+ }
+ break;
+ case L'd':
+ case L'M':
+ case L'y':
+ t_str = (fc == L'd' ? day_str : fc == L'M' ? mon_str : year_str);
+ if (fc == L'y')
+ force = 0;
+ for (idx = 1; fmt[1] == fc; ++idx, ++fmt);
+ if (--idx > 3)
+ idx = 3;
+ if (force && idx == 3)
+ idx = 2;
+ *p++ = '%';
+ *p++ = t_str[idx];
+ break;
+ case L'g':
+ break;
+ case L'h':
+ case L'H':
+ t_str = (fc == L'h' || force ? hour12_str : hour24_str);
+ idx = 0;
+ if (fmt[1] == fc)
+ {
+ ++fmt;
+ idx = 1;
+ }
+ *p++ = '%';
+ *p++ = t_str[idx];
+ break;
+ case L'm':
+ case L's':
+ case L't':
+ if (fmt[1] == fc)
+ ++fmt;
+ *p++ = '%';
+ *p++ = (fc == L'm' ? 'M' : fc == L's' ? 'S' : 'p');
+ break;
+ case L'\t':
+ case L'\n':
+ case L'%':
+ *p++ = '%';
+ *p++ = (char) fc;
+ break;
+ default:
+ num = f_wctomb (_REENT, p, *fmt, charset, &mb);
+ if (num == (size_t) -1)
+ memset (&mb, 0, sizeof mb);
+ else
+ p += num;
+ break;
+ }
+ *p++ = '\0';
+ *ptr = p;
+ return ret;
+}
+
+/* Convert Windows grouping format into POSIX grouping format. */
+static char *
+conv_grouping (LCID lcid, LCTYPE type, char **lc_ptr)
+{
+ char buf[10]; /* Per MSDN max size of LOCALE_SGROUPING element incl. NUL */
+ bool repeat = false;
+ char *ptr = *lc_ptr;
+ char *ret = ptr;
+
+ GetLocaleInfoA (lcid, type, buf, 10);
+ /* Convert Windows grouping format into POSIX grouping format. */
+ for (char *c = buf; *c; ++c)
+ {
+ if (*c < '0' || *c > '9')
+ continue;
+ char val = *c - '0';
+ if (!val)
+ {
+ repeat = true;
+ break;
+ }
+ *ptr++ = val;
+ }
+ if (!repeat)
+ *ptr++ = CHAR_MAX;
+ *ptr++ = '\0';
+ *lc_ptr = ptr;
+ return ret;
+}
+
+/* Called from newlib's setlocale() via __time_load_locale() if category
+ is LC_TIME. Returns LC_TIME values fetched from Windows locale data
+ in the structure pointed to by _time_locale. This is subsequently
+ accessed by functions like nl_langinfo, strftime, strptime. */
+extern "C" int
+__set_lc_time_from_win (const char *name, struct lc_time_T *_time_locale,
+ wctomb_p f_wctomb, const char *charset)
+{
+ LCID lcid = __get_lcid_from_locale (name);
+ if (!lcid || lcid == (LCID) -1)
+ return lcid;
+
+ char *new_lc_time_buf = (char *) malloc (4096);
+ const char *lc_time_end = new_lc_time_buf + 4096;
+
+ if (!new_lc_time_buf)
+ return -1;
+ char *lc_time_ptr = new_lc_time_buf;
+ /* mon */
+ for (int i = 0; i < 12; ++i)
+ _time_locale->mon[i] = getlocaleinfo (time, LOCALE_SABBREVMONTHNAME1 + i);
+ /* month and alt_month */
+ for (int i = 0; i < 12; ++i)
+ _time_locale->month[i] = _time_locale->alt_month[i]
+ = getlocaleinfo (time, LOCALE_SMONTHNAME1 + i);
+ /* wday */
+ _time_locale->wday[0] = getlocaleinfo (time, LOCALE_SABBREVDAYNAME7);
+ for (int i = 0; i < 6; ++i)
+ _time_locale->wday[i + 1] = getlocaleinfo (time,
+ LOCALE_SABBREVDAYNAME1 + i);
+ /* weekday */
+ _time_locale->weekday[0] = getlocaleinfo (time, LOCALE_SDAYNAME7);
+ for (int i = 0; i < 6; ++i)
+ _time_locale->weekday[i + 1] = getlocaleinfo (time, LOCALE_SDAYNAME1 + i);
+ /* X_fmt */
+ _time_locale->X_fmt = eval_datetimefmt (LOCALE_STIMEFORMAT, 0);
+ /* x_fmt */
+ _time_locale->x_fmt = eval_datetimefmt (LOCALE_SSHORTDATE, 0);
+ /* c_fmt */
+ _time_locale->c_fmt = eval_datetimefmt (LOCALE_SLONGDATE, 1);
+ --lc_time_ptr;
+ *lc_time_ptr++ = ' ';
+ eval_datetimefmt (LOCALE_STIMEFORMAT, 0);
+ /* AM/PM */
+ _time_locale->am_pm[0] = getlocaleinfo (time, LOCALE_S1159);
+ _time_locale->am_pm[1] = getlocaleinfo (time, LOCALE_S2359);
+ /* date_fmt */
+ _time_locale->date_fmt = eval_datetimefmt (LOCALE_SLONGDATE, 1);
+ --lc_time_ptr;
+ *lc_time_ptr++ = ' ';
+ eval_datetimefmt (LOCALE_STIMEFORMAT, 0);
+ --lc_time_ptr;
+ lc_time_ptr = stpcpy (lc_time_ptr, " %Z") + 1;
+ /* md */
+ {
+ wchar_t buf[80];
+ GetLocaleInfoW (lcid, LOCALE_IDATE, buf, 80);
+ lc_time_ptr = stpcpy (lc_time_ptr, *buf == L'1' ? "dm" : "md") + 1;
+ }
+ /* ampm_fmt */
+ _time_locale->ampm_fmt = eval_datetimefmt (LOCALE_STIMEFORMAT, 1);
+
+ char *tmp = (char *) realloc (new_lc_time_buf, lc_time_ptr - new_lc_time_buf);
+ if (!tmp)
+ {
+ free (new_lc_time_buf);
+ return -1;
+ }
+ if (lc_time_buf)
+ free (lc_time_buf);
+ lc_time_buf = tmp;
+ return 1;
+}
+
+/* Called from newlib's setlocale() via __numeric_load_locale() if category
+ is LC_NUMERIC. Returns LC_NUMERIC values fetched from Windows locale data
+ in the structure pointed to by _numeric_locale. This is subsequently
+ accessed by functions like nl_langinfo, localeconv, printf, etc. */
+extern "C" int
+__set_lc_numeric_from_win (const char *name,
+ struct lc_numeric_T *_numeric_locale,
+ wctomb_p f_wctomb, const char *charset)
+{
+ LCID lcid = __get_lcid_from_locale (name);
+ if (!lcid || lcid == (LCID) -1)
+ return lcid;
+
+ char *new_lc_numeric_buf = (char *) malloc (48);
+ const char *lc_numeric_end = new_lc_numeric_buf + 48;
+
+ if (!new_lc_numeric_buf)
+ return -1;
+ char *lc_numeric_ptr = new_lc_numeric_buf;
+ /* decimal_point */
+ _numeric_locale->decimal_point = getlocaleinfo (numeric,
+ LOCALE_SDECIMAL);
+ /* thousands_sep */
+ _numeric_locale->thousands_sep = getlocaleinfo (numeric,
+ LOCALE_STHOUSAND);
+ /* grouping */
+ _numeric_locale->grouping = conv_grouping (lcid, LOCALE_SGROUPING,
+ &lc_numeric_ptr);
+
+ char *tmp = (char *) realloc (new_lc_numeric_buf,
+ lc_numeric_ptr - new_lc_numeric_buf);
+ if (!tmp)
+ {
+ free (new_lc_numeric_buf);
+ return -1;
+ }
+ if (lc_numeric_buf)
+ free (lc_numeric_buf);
+ lc_numeric_buf = tmp;
+ return 1;
+}
+
+/* Called from newlib's setlocale() via __monetary_load_locale() if category
+ is LC_MONETARY. Returns LC_MONETARY values fetched from Windows locale data
+ in the structure pointed to by _monetary_locale. This is subsequently
+ accessed by functions like nl_langinfo, localeconv, printf, etc. */
+extern "C" int
+__set_lc_monetary_from_win (const char *name,
+ struct lc_monetary_T *_monetary_locale,
+ wctomb_p f_wctomb, const char *charset)
+{
+ LCID lcid = __get_lcid_from_locale (name);
+ if (!lcid || lcid == (LCID) -1)
+ return lcid;
+
+ char *new_lc_monetary_buf = (char *) malloc (256);
+ const char *lc_monetary_end = new_lc_monetary_buf + 256;
+
+ if (!new_lc_monetary_buf)
+ return -1;
+ char *lc_monetary_ptr = new_lc_monetary_buf;
+ /* int_curr_symbol */
+ _monetary_locale->int_curr_symbol = getlocaleinfo (monetary,
+ LOCALE_SINTLSYMBOL);
+ /* No spacing char means space. */
+ if (!_monetary_locale->int_curr_symbol[3])
+ {
+ lc_monetary_ptr[-1] = ' ';
+ *lc_monetary_ptr++ = '\0';
+ }
+ /* currency_symbol */
+ {
+ /* As on Linux: If the currency_symbol can't be represented in the
+ given charset, use int_curr_symbol. */
+ wchar_t wbuf[14];
+ GetLocaleInfoW (lcid, LOCALE_SCURRENCY, wbuf, 14);
+ if (lc_wcstombs (f_wctomb, charset, NULL, wbuf, 0) == (size_t) -1)
+ {
+ _monetary_locale->currency_symbol = lc_monetary_ptr;
+ lc_monetary_ptr = stpncpy (lc_monetary_ptr,
+ _monetary_locale->int_curr_symbol, 3);
+ *lc_monetary_ptr++ = '\0';
+ }
+ else
+ _monetary_locale->currency_symbol = getlocaleinfo (monetary,
+ LOCALE_SCURRENCY);
+ }
+ /* mon_decimal_point */
+ _monetary_locale->mon_decimal_point = getlocaleinfo (monetary,
+ LOCALE_SMONDECIMALSEP);
+ /* mon_thousands_sep */
+ _monetary_locale->mon_thousands_sep = getlocaleinfo (monetary,
+ LOCALE_SMONTHOUSANDSEP);
+ /* mon_grouping */
+ _monetary_locale->mon_grouping = conv_grouping (lcid, LOCALE_SMONGROUPING,
+ &lc_monetary_ptr);
+ /* positive_sign */
+ _monetary_locale->positive_sign = getlocaleinfo (monetary,
+ LOCALE_SPOSITIVESIGN);
+ /* negative_sign */
+ _monetary_locale->negative_sign = getlocaleinfo (monetary,
+ LOCALE_SNEGATIVESIGN);
+ /* int_frac_digits */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_IINTLCURRDIGITS);
+ _monetary_locale->int_frac_digits = lc_monetary_ptr++;
+ /* frac_digits */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_ICURRDIGITS);
+ _monetary_locale->frac_digits = lc_monetary_ptr++;
+ /* p_cs_precedes */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_IPOSSYMPRECEDES);
+ _monetary_locale->p_cs_precedes = lc_monetary_ptr++;
+ /* p_sep_by_space */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_IPOSSEPBYSPACE);
+ _monetary_locale->p_sep_by_space = lc_monetary_ptr++;
+ /* n_cs_precedes */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_INEGSYMPRECEDES);
+ _monetary_locale->n_cs_precedes = lc_monetary_ptr++;
+ /* n_sep_by_space */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_INEGSEPBYSPACE);
+ _monetary_locale->n_sep_by_space = lc_monetary_ptr++;
+ /* p_sign_posn */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_IPOSSIGNPOSN);
+ _monetary_locale->p_sign_posn = lc_monetary_ptr++;
+ /* p_sign_posn */
+ *lc_monetary_ptr = (char) getlocaleint (lcid, LOCALE_INEGSIGNPOSN);
+ _monetary_locale->n_sign_posn = lc_monetary_ptr++;
+
+ char *tmp = (char *) realloc (new_lc_monetary_buf,
+ lc_monetary_ptr - new_lc_monetary_buf);
+ if (!tmp)
+ {
+ free (new_lc_monetary_buf);
+ return -1;
+ }
+ if (lc_monetary_buf)
+ free (lc_monetary_buf);
+ lc_monetary_buf = tmp;
+ return 1;
+}
+
+static LCID collate_lcid = 0;
+static mbtowc_p collate_mbtowc = __ascii_mbtowc;
+static char collate_charset[ENCODING_LEN + 1] = "ASCII";
+
+/* Called from newlib's setlocale() if category is LC_COLLATE. Stores
+ LC_COLLATE locale information. This is subsequently accessed by the
+ below functions strcoll, strxfrm, wcscoll, wcsxfrm. */
+extern "C" int
+__collate_load_locale (const char *name, mbtowc_p f_mbtowc, const char *charset)
+{
+ LCID lcid = __get_lcid_from_locale (name);
+ if (lcid == (LCID) -1)
+ return -1;
+ collate_lcid = lcid;
+ collate_mbtowc = f_mbtowc;
+ stpcpy (collate_charset, charset);
+ return 0;
+}
+
+/* We use the Windows functions for locale-specific string comparison and
+ transformation. The advantage is that we don't need any files with
+ collation information. */
+extern "C" int
+wcscoll (const wchar_t *ws1, const wchar_t *ws2)
+{
+ int ret;
+
+ if (!collate_lcid)
+ return wcscmp (ws1, ws2);
+ ret = CompareStringW (collate_lcid, 0, ws1, -1, ws2, -1);
+ if (!ret)
+ set_errno (EINVAL);
+ return ret - CSTR_EQUAL;
+}
+
+extern "C" int
+strcoll (const char *s1, const char *s2)
+{
+ size_t n1, n2;
+ wchar_t *ws1, *ws2;
+ tmp_pathbuf tp;
+ int ret;
+
+ if (!collate_lcid)
+ return strcmp (s1, s2);
+ /* The ANSI version of CompareString uses the default charset of the lcid,
+ so we must use the Unicode version. */
+ n1 = lc_mbstowcs (collate_mbtowc, collate_charset, NULL, s1, 0) + 1;
+ ws1 = (n1 > NT_MAX_PATH ? (wchar_t *) malloc (n1 * sizeof (wchar_t))
+ : tp.w_get ());
+ lc_mbstowcs (collate_mbtowc, collate_charset, ws1, s1, n1);
+ n2 = lc_mbstowcs (collate_mbtowc, collate_charset, NULL, s2, 0) + 1;
+ ws2 = (n2 > NT_MAX_PATH ? (wchar_t *) malloc (n2 * sizeof (wchar_t))
+ : tp.w_get ());
+ lc_mbstowcs (collate_mbtowc, collate_charset, ws2, s2, n2);
+ ret = CompareStringW (collate_lcid, 0, ws1, -1, ws2, -1);
+ if (n1 > NT_MAX_PATH)
+ free (ws1);
+ if (n2 > NT_MAX_PATH)
+ free (ws2);
+ if (!ret)
+ set_errno (EINVAL);
+ return ret - CSTR_EQUAL;
+}
+
+extern "C" size_t
+wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t wsn)
+{
+ size_t ret;
+
+ if (!collate_lcid)
+ return wcslcpy (ws1, ws2, wsn);
+ ret = LCMapStringW (collate_lcid, LCMAP_SORTKEY,
+ ws2, -1, ws1, wsn * sizeof (wchar_t));
+ /* LCMapStringW returns byte count including the terminating NUL character,
+ wcsxfrm is supposed to return length in wchar_t excluding the NUL.
+ Since the array is only single byte NUL-terminated we must make sure
+ the result is wchar_t-NUL terminated. */
+ if (ret)
+ {
+ ret = (ret + 1) / sizeof (wchar_t);
+ if (ret >= wsn)
+ return wsn;
+ ws1[ret] = L'\0';
+ return ret;
+ }
+ if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+ set_errno (EINVAL);
+ return wsn;
+}
+
+extern "C" size_t
+strxfrm (char *s1, const char *s2, size_t sn)
+{
+ size_t ret;
+ size_t n2;
+ wchar_t *ws2;
+ tmp_pathbuf tp;
+
+ if (!collate_lcid)
+ return strlcpy (s1, s2, sn);
+ /* The ANSI version of LCMapString uses the default charset of the lcid,
+ so we must use the Unicode version. */
+ n2 = lc_mbstowcs (collate_mbtowc, collate_charset, NULL, s2, 0) + 1;
+ ws2 = (n2 > NT_MAX_PATH ? (wchar_t *) malloc (n2 * sizeof (wchar_t))
+ : tp.w_get ());
+ lc_mbstowcs (collate_mbtowc, collate_charset, ws2, s2, n2);
+ /* The sort key is a NUL-terminated byte string. */
+ ret = LCMapStringW (collate_lcid, LCMAP_SORTKEY, ws2, -1, (PWCHAR) s1, sn);
+ if (n2 > NT_MAX_PATH)
+ free (ws2);
+ if (ret == 0)
+ {
+ if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+ set_errno (EINVAL);
+ return sn;
+ }
+ /* LCMapStringW returns byte count including the terminating NUL character.
+ strxfrm is supposed to return length excluding the NUL. */
+ return ret - 1;
+}
+
+/* Fetch default ANSI codepage from locale info and generate a setlocale
+ compatible character set code. Called from newlib's setlocale(), if the
+ charset isn't given explicitely in the POSIX compatible locale specifier.
+ The function also returns a pointer to the corresponding _mbtowc_r function
+ which is used subsequently. */
+extern "C" void
+__set_charset_from_locale (const char *locale, char *charset)
+{
+ UINT cp;
+ LCID lcid = __get_lcid_from_locale (locale);
+
+ /* "C" locale, or invalid locale? */
+ if (lcid == 0 || lcid == (LCID) -1)
+ {
+ __small_sprintf (charset, "ASCII");
+ return;
+ }
+ if (!GetLocaleInfoW (lcid,
+ LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
+ (PWCHAR) &cp, sizeof cp))
+ cp = 0;
+ /* codepage to de-facto standard charset transition. */
+ switch (cp)
+ {
+ case 874:
+ __small_sprintf (charset, "CP%u", cp);
+ break;
+ case 932:
+ strcpy (charset, "EUCJP");
+ break;
+ case 936:
+ strcpy (charset, "GBK");
+ break;
+ case 949:
+ strcpy (charset, "EUCKR");
+ break;
+ case 950:
+ strcpy (charset, "BIG5");
+ break;
+ case 1250:
+ strcpy (charset, "ISO-8859-2");
+ break;
+ case 1251:
+ strcpy (charset, "ISO-8859-5");
+ break;
+ case 1252:
+ strcpy (charset, "ISO-8859-1");
+ break;
+ case 1253:
+ strcpy (charset, "ISO-8859-7");
+ break;
+ case 1254:
+ strcpy (charset, "ISO-8859-9");
+ break;
+ case 1255:
+ strcpy (charset, "ISO-8859-8");
+ break;
+ case 1256:
+ strcpy (charset, "ISO-8859-6");
+ break;
+ case 1257:
+ strcpy (charset, "ISO-8859-13");
+ break;
+ case 1258:
+ default:
+ strcpy (charset, "UTF-8");
+ break;
+ }
+ if (cp >= 1250 && cp <= 1257)
+ {
+ char *c = strchr (locale, '@');
+ if (c && !strcmp (c + 1, "euro"))
+ strcpy (charset, "ISO-8859-15");
+ }
+}
diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc
index b62139409..849bd5dc9 100644
--- a/winsup/cygwin/strfuncs.cc
+++ b/winsup/cygwin/strfuncs.cc
@@ -352,87 +352,6 @@ __big5_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n,
return __db_mbtowc (r, pwc, s, n, 950, state);
}
-/* Convert Windows codepage to a setlocale compatible character set code.
- Called from newlib's setlocale() with codepage set to 0, if the
- charset isn't given explicitely in the POSIX compatible locale specifier.
- The function also returns a pointer to the corresponding _mbtowc_r
- function. */
-extern "C" mbtowc_p
-__set_charset_from_codepage (UINT cp, char *charset)
-{
- if (cp == 0)
- cp = GetACP ();
- switch (cp)
- {
- case 437:
- case 720:
- case 737:
- case 775:
- case 850:
- case 852:
- case 855:
- case 857:
- case 858:
- case 862:
- case 866:
- case 874:
- case 1125:
- case 1250:
- case 1251:
- case 1252:
- case 1253:
- case 1254:
- case 1255:
- case 1256:
- case 1257:
- case 1258:
- case 20866:
- case 21866:
- __small_sprintf (charset, "CP%u", cp);
- return __cp_mbtowc;
- case 28591:
- case 28592:
- case 28593:
- case 28594:
- case 28595:
- case 28596:
- case 28597:
- case 28598:
- case 28599:
- case 28603:
- case 28605:
- __small_sprintf (charset, "ISO-8859-%u", cp - 28590);
- return __iso_mbtowc;
- case 932:
- strcpy (charset, "SJIS");
- return __sjis_mbtowc;
- case 936:
- strcpy (charset, "GBK");
- return __gbk_mbtowc;
- case 949:
- case 51949:
- strcpy (charset, "EUCKR");
- return __kr_mbtowc;
- case 950:
- strcpy (charset, "BIG5");
- return __big5_mbtowc;
- case 50220:
- strcpy (charset, "JIS");
- return __jis_mbtowc;
- case 20932:
- case 51932:
- strcpy (charset, "EUCJP");
- return __eucjp_mbtowc;
- case 65001:
- strcpy (charset, "UTF-8");
- return __utf8_mbtowc;
- default:
- break;
- }
- strcpy (charset, "ASCII");
- return __ascii_mbtowc;
-}
-
/* Our own sys_wcstombs/sys_mbstowcs functions differ from the
wcstombs/mbstowcs API in three ways:
diff --git a/winsup/cygwin/wchar.h b/winsup/cygwin/wchar.h
index 1398238c1..820519af5 100644
--- a/winsup/cygwin/wchar.h
+++ b/winsup/cygwin/wchar.h
@@ -1,6 +1,6 @@
/* wchar.h: Extra wchar defs
- Copyright 2007, 2009 Red Hat, Inc.
+ Copyright 2007, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -44,8 +44,6 @@ extern wctomb_f __utf8_wctomb;
extern char *__locale_charset ();
-extern mbtowc_p __set_charset_from_codepage (unsigned int cp, char *charset);
-
#ifdef __cplusplus
}
#endif
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 2fc76b166..56aac2453 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -1,7 +1,8 @@
/* wincap.cc -- figure out on which OS we're running. Set the
capability class to the appropriate values.
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -57,6 +58,7 @@ wincaps wincap_unknown __attribute__((section (".cygwin_dll_common"), shared)) =
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -96,6 +98,7 @@ wincaps wincap_nt4 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -135,6 +138,7 @@ wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -174,6 +178,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -213,6 +218,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -252,6 +258,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -291,6 +298,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -330,6 +338,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -369,6 +378,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:false,
+ has_localenames:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -408,6 +418,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:false,
has_broken_alloc_console:false,
has_always_all_codepages:true,
+ has_localenames:true,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@@ -447,6 +458,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_console_handle_problem:true,
has_broken_alloc_console:true,
has_always_all_codepages:true,
+ has_localenames:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 74955ff63..6a698d2f0 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -1,6 +1,7 @@
/* wincap.h: Header for OS capability class.
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -49,6 +50,7 @@ struct wincaps
unsigned has_console_handle_problem : 1;
unsigned has_broken_alloc_console : 1;
unsigned has_always_all_codepages : 1;
+ unsigned has_localenames : 1;
};
class wincapc
@@ -104,6 +106,7 @@ public:
bool IMPLEMENT (has_console_handle_problem)
bool IMPLEMENT (has_broken_alloc_console)
bool IMPLEMENT (has_always_all_codepages)
+ bool IMPLEMENT (has_localenames)
#undef IMPLEMENT
};