* 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.
This commit is contained in:
parent
e894eef9f5
commit
326fb376dd
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue