mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
Update.
2004-03-14 Ulrich Drepper <drepper@redhat.com> Make the non-_l functions wrappers around the _l functions. * include/monetary.h: Declare __vstrmon_l. * include/string.h: Add libc_hidden_proto for __strcoll_l and __strxfrm_l. * include/time.h: Define ptime_locale_status. Declare __strptime_internal. * include/wchar.h: Add libc_hidden_proto for __wcscoll_l and __wcsxfrm_l. * stdlib/strfmon.c: Move the code to strfmon_l.c. Add little wrapper around __vstrfmon_l. * stdlib/strfmon_l.c: Add real implementation. Split into new function __vstrfmon_l to allow calling it from strfmon. * stdlib/strtod.c: Move real code to strtod_l.c and add wrapper. * stdlib/strtod_l.c: Add real implementation. * stdlib/strtof.c: Adjust to changed strtod.c. * stdlib/strtof_l.c: Include strtod_l.c now. * stdlib/strtold.c: New file. * stdlib/strtold_l.c: Removed. * string/strcoll.c: Move real code to strcoll_l.c: Add wrapper. * string/strcoll_l.c: Add real implementation. * string/strxfrm.c: Move real code to strxfrm_l.c: Add wrapper. * string/strxfrm_l.c: Add real implementation. * sysdeps/generic/strtol.c: Move real implementation to strtol_l.c. Add wrappers. * sysdeps/generic/strtol_l.c: Add real implementation. * sysdeps/generic/strtold.c: Removed. * sysdeps/generic/strtold_l.c: New file. * sysdeps/generic/strtoll_l.c: Include strtol_l.c now. Adjust #defines. * sysdeps/generic/strtoul_l.c: Likewise. * sysdeps/generic/strtoull_l.c: Likewise. * sysdeps/generic/wcstol_l.c: Likewise. * sysdeps/generic/wcstoll_l.c: Likewise. * sysdeps/generic/wcstoul_l.c: Likewise. * sysdeps/generic/wcstoull_l.c: Likewise. * sysdeps/ieee754/ldbl-128/strtold.c: Removed. * sysdeps/ieee754/ldbl-128/strtold_l.c: New file. * sysdeps/ieee754/ldbl-96/strtold.c: Removed. * sysdeps/ieee754/ldbl-96/strtold_l.c: New file. * sysdeps/m68k/strtold.c: Removed. * sysdeps/m68k/strtold_l.c: New file. * time/strftime.c: Move real code to strftime_l.c. Add wrapper. * time/strftime_l.c: Add real implementation. * time/strptime.c: Move real code to strptime_l.c. Add wrapper. * time/strptime_l.c: Add real implementation. * time/wcsftime.c: Simplify since only wrappers are defined in strftime.c. * time/wcsftime_l.c: Include strftime_l.c. * wcsmbs/wcscoll.c: Simplify since the file is not used by wcscoll_l.c anymore. * wcsmbs/wcscoll_l.c: Include strcoll_l.c. * wcsmbs/wcsxfrm.c: Simplify since the file is not used by wcsxfrm_l.c anymore. * wcsmbs/wcsxfrm_l.c: Include strxfrm_l.c. * wcsmbs/wcstod.c: Prepare to include new strtod.c. * wcsmbs/wcstod_l.c: Include strtod_l.c. * wcsmbs/wcstof.c: Prepare to include new strtof.c. * wcsmbs/wcstof_l.c: Include strtof_l.c. * wcsmbs/wcstold.c: Prepare to include new strtold.c. * wcsmbs/wcstold_l.c: Include strtold_l.c. * locale/uselocale.c: Use _NL_CURRENT_LOCALE instead of __libc_tsd_get. * sysdeps/generic/strcasecmp.c: Optimize a bit. It's better to get a reference to the current locale and then use the _l functions. * sysdeps/generic/strncase.c: Likewise.
This commit is contained in:
parent
3bc9b83f49
commit
ccadf7b534
69
ChangeLog
69
ChangeLog
@ -1,3 +1,72 @@
|
||||
2004-03-14 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
Make the non-_l functions wrappers around the _l functions.
|
||||
* include/monetary.h: Declare __vstrmon_l.
|
||||
* include/string.h: Add libc_hidden_proto for __strcoll_l and
|
||||
__strxfrm_l.
|
||||
* include/time.h: Define ptime_locale_status. Declare
|
||||
__strptime_internal.
|
||||
* include/wchar.h: Add libc_hidden_proto for __wcscoll_l and
|
||||
__wcsxfrm_l.
|
||||
* stdlib/strfmon.c: Move the code to strfmon_l.c. Add little
|
||||
wrapper around __vstrfmon_l.
|
||||
* stdlib/strfmon_l.c: Add real implementation. Split into new
|
||||
function __vstrfmon_l to allow calling it from strfmon.
|
||||
* stdlib/strtod.c: Move real code to strtod_l.c and add wrapper.
|
||||
* stdlib/strtod_l.c: Add real implementation.
|
||||
* stdlib/strtof.c: Adjust to changed strtod.c.
|
||||
* stdlib/strtof_l.c: Include strtod_l.c now.
|
||||
* stdlib/strtold.c: New file.
|
||||
* stdlib/strtold_l.c: Removed.
|
||||
* string/strcoll.c: Move real code to strcoll_l.c: Add wrapper.
|
||||
* string/strcoll_l.c: Add real implementation.
|
||||
* string/strxfrm.c: Move real code to strxfrm_l.c: Add wrapper.
|
||||
* string/strxfrm_l.c: Add real implementation.
|
||||
* sysdeps/generic/strtol.c: Move real implementation to strtol_l.c.
|
||||
Add wrappers.
|
||||
* sysdeps/generic/strtol_l.c: Add real implementation.
|
||||
* sysdeps/generic/strtold.c: Removed.
|
||||
* sysdeps/generic/strtold_l.c: New file.
|
||||
* sysdeps/generic/strtoll_l.c: Include strtol_l.c now. Adjust
|
||||
#defines.
|
||||
* sysdeps/generic/strtoul_l.c: Likewise.
|
||||
* sysdeps/generic/strtoull_l.c: Likewise.
|
||||
* sysdeps/generic/wcstol_l.c: Likewise.
|
||||
* sysdeps/generic/wcstoll_l.c: Likewise.
|
||||
* sysdeps/generic/wcstoul_l.c: Likewise.
|
||||
* sysdeps/generic/wcstoull_l.c: Likewise.
|
||||
* sysdeps/ieee754/ldbl-128/strtold.c: Removed.
|
||||
* sysdeps/ieee754/ldbl-128/strtold_l.c: New file.
|
||||
* sysdeps/ieee754/ldbl-96/strtold.c: Removed.
|
||||
* sysdeps/ieee754/ldbl-96/strtold_l.c: New file.
|
||||
* sysdeps/m68k/strtold.c: Removed.
|
||||
* sysdeps/m68k/strtold_l.c: New file.
|
||||
* time/strftime.c: Move real code to strftime_l.c. Add wrapper.
|
||||
* time/strftime_l.c: Add real implementation.
|
||||
* time/strptime.c: Move real code to strptime_l.c. Add wrapper.
|
||||
* time/strptime_l.c: Add real implementation.
|
||||
* time/wcsftime.c: Simplify since only wrappers are defined in
|
||||
strftime.c.
|
||||
* time/wcsftime_l.c: Include strftime_l.c.
|
||||
* wcsmbs/wcscoll.c: Simplify since the file is not used by wcscoll_l.c
|
||||
anymore.
|
||||
* wcsmbs/wcscoll_l.c: Include strcoll_l.c.
|
||||
* wcsmbs/wcsxfrm.c: Simplify since the file is not used by wcsxfrm_l.c
|
||||
anymore.
|
||||
* wcsmbs/wcsxfrm_l.c: Include strxfrm_l.c.
|
||||
* wcsmbs/wcstod.c: Prepare to include new strtod.c.
|
||||
* wcsmbs/wcstod_l.c: Include strtod_l.c.
|
||||
* wcsmbs/wcstof.c: Prepare to include new strtof.c.
|
||||
* wcsmbs/wcstof_l.c: Include strtof_l.c.
|
||||
* wcsmbs/wcstold.c: Prepare to include new strtold.c.
|
||||
* wcsmbs/wcstold_l.c: Include strtold_l.c.
|
||||
|
||||
* locale/uselocale.c: Use _NL_CURRENT_LOCALE instead of __libc_tsd_get.
|
||||
|
||||
* sysdeps/generic/strcasecmp.c: Optimize a bit. It's better to get
|
||||
a reference to the current locale and then use the _l functions.
|
||||
* sysdeps/generic/strncase.c: Likewise.
|
||||
|
||||
2004-03-11 Jeroen Dekkers <jeroen@dekkers.cx>
|
||||
|
||||
* cppflags-iterator.mk: Change libof-$(cpp-src) to
|
||||
|
@ -1 +1,5 @@
|
||||
#include <stdlib/monetary.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern ssize_t __vstrfmon_l (char *s, size_t maxsize, __locale_t loc,
|
||||
const char *format, va_list ap);
|
||||
|
@ -78,6 +78,8 @@ libc_hidden_proto (__strerror_r)
|
||||
libc_hidden_proto (__strverscmp)
|
||||
libc_hidden_proto (basename)
|
||||
libc_hidden_proto (strcoll)
|
||||
libc_hidden_proto (__strcoll_l)
|
||||
libc_hidden_proto (__strxfrm_l)
|
||||
|
||||
libc_hidden_builtin_proto (memchr)
|
||||
libc_hidden_builtin_proto (memcpy)
|
||||
|
@ -3,6 +3,7 @@
|
||||
# include <time/time.h>
|
||||
#else
|
||||
# include <time/time.h>
|
||||
# include <xlocale.h>
|
||||
|
||||
extern __typeof (strftime_l) __strftime_l;
|
||||
libc_hidden_proto (__strftime_l)
|
||||
@ -84,6 +85,18 @@ extern int __getdate_r (__const char *__string, struct tm *__resbufp);
|
||||
extern int __getclktck (void);
|
||||
|
||||
|
||||
/* strptime support. */
|
||||
/* Status of lookup: do we use the locale data or the raw data? */
|
||||
enum ptime_locale_status { not, loc, raw };
|
||||
|
||||
extern char * __strptime_internal (const char *rp, const char *fmt,
|
||||
struct tm *tm,
|
||||
enum ptime_locale_status *decided,
|
||||
int era_cnt, __locale_t loc)
|
||||
internal_function;
|
||||
|
||||
|
||||
|
||||
/* Use in the clock_* functions. Size of the field representing the
|
||||
actual clock ID. */
|
||||
#ifndef _ISOMAC
|
||||
|
@ -29,6 +29,9 @@ libc_hidden_proto (__wcstoull_internal)
|
||||
libc_hidden_proto (__wcscasecmp_l)
|
||||
libc_hidden_proto (__wcsncasecmp_l)
|
||||
|
||||
libc_hidden_proto (__wcscoll_l)
|
||||
libc_hidden_proto (__wcsxfrm_l)
|
||||
|
||||
libc_hidden_proto (fputws_unlocked)
|
||||
libc_hidden_proto (putwc_unlocked)
|
||||
libc_hidden_proto (putwc)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* uselocale -- fetch and set the current per-thread locale
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -29,7 +29,7 @@
|
||||
locale_t
|
||||
__uselocale (locale_t newloc)
|
||||
{
|
||||
locale_t oldloc = __libc_tsd_get (LOCALE);
|
||||
locale_t oldloc = _NL_CURRENT_LOCALE;
|
||||
|
||||
if (newloc != NULL)
|
||||
{
|
||||
|
632
stdlib/strfmon.c
632
stdlib/strfmon.c
@ -19,645 +19,21 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <monetary.h>
|
||||
#ifdef USE_IN_LIBIO
|
||||
# include "../libio/libioP.h"
|
||||
# include "../libio/strfile.h"
|
||||
#endif
|
||||
#include <printf.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../locale/localeinfo.h"
|
||||
#include <locale/localeinfo.h>
|
||||
|
||||
|
||||
#define out_char(Ch) \
|
||||
do { \
|
||||
if (dest >= s + maxsize - 1) \
|
||||
{ \
|
||||
__set_errno (E2BIG); \
|
||||
va_end (ap); \
|
||||
return -1; \
|
||||
} \
|
||||
*dest++ = (Ch); \
|
||||
} while (0)
|
||||
|
||||
#define out_string(String) \
|
||||
do { \
|
||||
const char *_s = (String); \
|
||||
while (*_s) \
|
||||
out_char (*_s++); \
|
||||
} while (0)
|
||||
|
||||
#define out_nstring(String, N) \
|
||||
do { \
|
||||
int _n = (N); \
|
||||
const char *_s = (String); \
|
||||
while (_n-- > 0) \
|
||||
out_char (*_s++); \
|
||||
} while (0)
|
||||
|
||||
#define to_digit(Ch) ((Ch) - '0')
|
||||
|
||||
|
||||
/* We use this code also for the extended locale handling where the
|
||||
function gets as an additional argument the locale which has to be
|
||||
used. To access the values we have to redefine the _NL_CURRENT
|
||||
macro. */
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# undef _NL_CURRENT
|
||||
# define _NL_CURRENT(category, item) \
|
||||
(current->values[_NL_ITEM_INDEX (item)].string)
|
||||
#endif
|
||||
|
||||
extern int __printf_fp (FILE *, const struct printf_info *,
|
||||
const void *const *);
|
||||
libc_hidden_proto (__printf_fp)
|
||||
/* This function determines the number of digit groups in the output.
|
||||
The definition is in printf_fp.c. */
|
||||
extern unsigned int __guess_grouping (unsigned int intdig_max,
|
||||
const char *grouping, wchar_t sepchar);
|
||||
|
||||
|
||||
/* We have to overcome some problems with this implementation. On the
|
||||
one hand the strfmon() function is specified in XPG4 and of course
|
||||
it has to follow this. But on the other hand POSIX.2 specifies
|
||||
some information in the LC_MONETARY category which should be used,
|
||||
too. Some of the information contradicts the information which can
|
||||
be specified in format string. */
|
||||
#ifndef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
ssize_t
|
||||
strfmon (char *s, size_t maxsize, const char *format, ...)
|
||||
#else
|
||||
ssize_t
|
||||
__strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...)
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
struct locale_data *current = loc->__locales[LC_MONETARY];
|
||||
#endif
|
||||
#ifdef USE_IN_LIBIO
|
||||
_IO_strfile f;
|
||||
# ifdef _IO_MTSAFE_IO
|
||||
_IO_lock_t lock;
|
||||
# endif
|
||||
#else
|
||||
FILE f;
|
||||
#endif
|
||||
struct printf_info info;
|
||||
va_list ap; /* Scan through the varargs. */
|
||||
char *dest; /* Pointer so copy the output. */
|
||||
const char *fmt; /* Pointer that walks through format. */
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
dest = s;
|
||||
fmt = format;
|
||||
|
||||
/* Loop through the format-string. */
|
||||
while (*fmt != '\0')
|
||||
{
|
||||
/* The floating-point value to output. */
|
||||
union
|
||||
{
|
||||
double dbl;
|
||||
__long_double_t ldbl;
|
||||
}
|
||||
fpnum;
|
||||
int int_format;
|
||||
int print_curr_symbol;
|
||||
int left_prec;
|
||||
int left_pad;
|
||||
int right_prec;
|
||||
int group;
|
||||
char pad;
|
||||
int is_long_double;
|
||||
int p_sign_posn;
|
||||
int n_sign_posn;
|
||||
int sign_posn;
|
||||
int other_sign_posn;
|
||||
int left;
|
||||
int is_negative;
|
||||
int sep_by_space;
|
||||
int other_sep_by_space;
|
||||
int cs_precedes;
|
||||
int other_cs_precedes;
|
||||
const char *sign_string;
|
||||
const char *other_sign_string;
|
||||
int done;
|
||||
const char *currency_symbol;
|
||||
size_t currency_symbol_len;
|
||||
int width;
|
||||
char *startp;
|
||||
const void *ptr;
|
||||
char space_char;
|
||||
|
||||
/* Process all character which do not introduce a format
|
||||
specification. */
|
||||
if (*fmt != '%')
|
||||
{
|
||||
out_char (*fmt++);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "%%" means a single '%' character. */
|
||||
if (fmt[1] == '%')
|
||||
{
|
||||
out_char (*++fmt);
|
||||
++fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Defaults for formatting. */
|
||||
int_format = 0; /* Use international curr. symbol */
|
||||
print_curr_symbol = 1; /* Print the currency symbol. */
|
||||
left_prec = -1; /* No left precision specified. */
|
||||
right_prec = -1; /* No right precision specified. */
|
||||
group = 1; /* Print digits grouped. */
|
||||
pad = ' '; /* Fill character is <SP>. */
|
||||
is_long_double = 0; /* Double argument by default. */
|
||||
p_sign_posn = -1; /* This indicates whether the */
|
||||
n_sign_posn = -1; /* '(' flag is given. */
|
||||
width = -1; /* No width specified so far. */
|
||||
left = 0; /* Right justified by default. */
|
||||
|
||||
/* Parse group characters. */
|
||||
while (1)
|
||||
{
|
||||
switch (*++fmt)
|
||||
{
|
||||
case '=': /* Set fill character. */
|
||||
pad = *++fmt;
|
||||
if (pad == '\0')
|
||||
{
|
||||
/* Premature EOS. */
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
case '^': /* Don't group digits. */
|
||||
group = 0;
|
||||
continue;
|
||||
case '+': /* Use +/- for sign of number. */
|
||||
if (n_sign_posn != -1)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN);
|
||||
n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN);
|
||||
continue;
|
||||
case '(': /* Use ( ) for negative sign. */
|
||||
if (n_sign_posn != -1)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
p_sign_posn = 0;
|
||||
n_sign_posn = 0;
|
||||
continue;
|
||||
case '!': /* Don't print the currency symbol. */
|
||||
print_curr_symbol = 0;
|
||||
continue;
|
||||
case '-': /* Print left justified. */
|
||||
left = 1;
|
||||
continue;
|
||||
default:
|
||||
/* Will stop the loop. */;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (isdigit (*fmt))
|
||||
{
|
||||
/* Parse field width. */
|
||||
width = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
width *= 10;
|
||||
width += to_digit (*fmt);
|
||||
}
|
||||
|
||||
/* If we don't have enough room for the demanded width we
|
||||
can stop now and return an error. */
|
||||
if (dest + width >= s + maxsize)
|
||||
{
|
||||
__set_errno (E2BIG);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recognize left precision. */
|
||||
if (*fmt == '#')
|
||||
{
|
||||
if (!isdigit (*++fmt))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
left_prec = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
left_prec *= 10;
|
||||
left_prec += to_digit (*fmt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recognize right precision. */
|
||||
if (*fmt == '.')
|
||||
{
|
||||
if (!isdigit (*++fmt))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
right_prec = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
right_prec *= 10;
|
||||
right_prec += to_digit (*fmt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle modifier. This is an extension. */
|
||||
if (*fmt == 'L')
|
||||
{
|
||||
++fmt;
|
||||
is_long_double = 1;
|
||||
}
|
||||
|
||||
/* Handle format specifier. */
|
||||
char int_symbol[4];
|
||||
switch (*fmt++)
|
||||
{
|
||||
case 'i': { /* Use international currency symbol. */
|
||||
const char *int_curr_symbol;
|
||||
|
||||
int_curr_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
|
||||
strncpy(int_symbol, int_curr_symbol, 3);
|
||||
int_symbol[3] = '\0';
|
||||
|
||||
currency_symbol_len = 3;
|
||||
currency_symbol = &int_symbol[0];
|
||||
space_char = int_curr_symbol[3];
|
||||
int_format = 1;
|
||||
break;
|
||||
}
|
||||
case 'n': /* Use national currency symbol. */
|
||||
currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL);
|
||||
currency_symbol_len = strlen (currency_symbol);
|
||||
space_char = ' ';
|
||||
int_format = 0;
|
||||
break;
|
||||
default: /* Any unrecognized format is an error. */
|
||||
__set_errno (EINVAL);
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If not specified by the format string now find the values for
|
||||
the format specification. */
|
||||
if (p_sign_posn == -1)
|
||||
p_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SIGN_POSN : P_SIGN_POSN);
|
||||
if (n_sign_posn == -1)
|
||||
n_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SIGN_POSN : N_SIGN_POSN);
|
||||
|
||||
if (right_prec == -1)
|
||||
{
|
||||
right_prec = *_NL_CURRENT (LC_MONETARY, int_format ? INT_FRAC_DIGITS : FRAC_DIGITS);
|
||||
|
||||
if (right_prec == CHAR_MAX)
|
||||
right_prec = 2;
|
||||
}
|
||||
|
||||
/* If we have to print the digits grouped determine how many
|
||||
extra characters this means. */
|
||||
if (group && left_prec != -1)
|
||||
left_prec += __guess_grouping (left_prec,
|
||||
_NL_CURRENT (LC_MONETARY, MON_GROUPING),
|
||||
*_NL_CURRENT (LC_MONETARY,
|
||||
MON_THOUSANDS_SEP));
|
||||
|
||||
/* Now it's time to get the value. */
|
||||
if (is_long_double == 1)
|
||||
{
|
||||
fpnum.ldbl = va_arg (ap, long double);
|
||||
is_negative = fpnum.ldbl < 0;
|
||||
if (is_negative)
|
||||
fpnum.ldbl = -fpnum.ldbl;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpnum.dbl = va_arg (ap, double);
|
||||
is_negative = fpnum.dbl < 0;
|
||||
if (is_negative)
|
||||
fpnum.dbl = -fpnum.dbl;
|
||||
}
|
||||
|
||||
/* We now know the sign of the value and can determine the format. */
|
||||
if (is_negative)
|
||||
{
|
||||
sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
|
||||
/* If the locale does not specify a character for the
|
||||
negative sign we use a '-'. */
|
||||
if (*sign_string == '\0')
|
||||
sign_string = (const char *) "-";
|
||||
cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
|
||||
sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
|
||||
sign_posn = n_sign_posn;
|
||||
|
||||
other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
|
||||
other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
|
||||
other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
|
||||
other_sign_posn = p_sign_posn;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
|
||||
cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
|
||||
sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
|
||||
sign_posn = p_sign_posn;
|
||||
|
||||
other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
|
||||
if (*other_sign_string == '\0')
|
||||
other_sign_string = (const char *) "-";
|
||||
other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
|
||||
other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
|
||||
other_sign_posn = n_sign_posn;
|
||||
}
|
||||
|
||||
/* Set default values for unspecified information. */
|
||||
if (cs_precedes != 0)
|
||||
cs_precedes = 1;
|
||||
if (other_cs_precedes != 0)
|
||||
other_cs_precedes = 1;
|
||||
if (sep_by_space == CHAR_MAX)
|
||||
sep_by_space = 0;
|
||||
if (other_sep_by_space == CHAR_MAX)
|
||||
other_sep_by_space = 0;
|
||||
if (sign_posn == CHAR_MAX)
|
||||
sign_posn = 1;
|
||||
if (other_sign_posn == CHAR_MAX)
|
||||
other_sign_posn = 1;
|
||||
|
||||
/* Check for degenerate cases */
|
||||
if (sep_by_space == 2)
|
||||
{
|
||||
if (sign_posn == 0 ||
|
||||
(sign_posn == 1 && !cs_precedes) ||
|
||||
(sign_posn == 2 && cs_precedes))
|
||||
/* sign and symbol are not adjacent, so no separator */
|
||||
sep_by_space = 0;
|
||||
}
|
||||
if (other_sep_by_space == 2)
|
||||
{
|
||||
if (other_sign_posn == 0 ||
|
||||
(other_sign_posn == 1 && !other_cs_precedes) ||
|
||||
(other_sign_posn == 2 && other_cs_precedes))
|
||||
/* sign and symbol are not adjacent, so no separator */
|
||||
other_sep_by_space = 0;
|
||||
}
|
||||
|
||||
/* Set the left precision and padding needed for alignment */
|
||||
if (left_prec == -1)
|
||||
{
|
||||
left_prec = 0;
|
||||
left_pad = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set left_pad to number of spaces needed to align positive
|
||||
and negative formats */
|
||||
|
||||
int left_bytes = 0;
|
||||
int other_left_bytes = 0;
|
||||
|
||||
/* Work out number of bytes for currency string and separator
|
||||
preceding the value */
|
||||
if (cs_precedes)
|
||||
{
|
||||
left_bytes += currency_symbol_len;
|
||||
if (sep_by_space != 0)
|
||||
++left_bytes;
|
||||
}
|
||||
|
||||
if (other_cs_precedes)
|
||||
{
|
||||
other_left_bytes += currency_symbol_len;
|
||||
if (other_sep_by_space != 0)
|
||||
++other_left_bytes;
|
||||
}
|
||||
|
||||
/* Work out number of bytes for the sign (or left parenthesis)
|
||||
preceding the value */
|
||||
if (sign_posn == 0 && is_negative)
|
||||
++left_bytes;
|
||||
else if (sign_posn == 1)
|
||||
left_bytes += strlen (sign_string);
|
||||
else if (cs_precedes && (sign_posn == 3 || sign_posn == 4))
|
||||
left_bytes += strlen (sign_string);
|
||||
|
||||
if (other_sign_posn == 0 && !is_negative)
|
||||
++other_left_bytes;
|
||||
else if (other_sign_posn == 1)
|
||||
other_left_bytes += strlen (other_sign_string);
|
||||
else if (other_cs_precedes &&
|
||||
(other_sign_posn == 3 || other_sign_posn == 4))
|
||||
other_left_bytes += strlen (other_sign_string);
|
||||
|
||||
/* Compare the number of bytes preceding the value for
|
||||
each format, and set the padding accordingly */
|
||||
if (other_left_bytes > left_bytes)
|
||||
left_pad = other_left_bytes - left_bytes;
|
||||
else
|
||||
left_pad = 0;
|
||||
}
|
||||
|
||||
/* Perhaps we'll someday make these things configurable so
|
||||
better start using symbolic names now. */
|
||||
#define left_paren '('
|
||||
#define right_paren ')'
|
||||
|
||||
startp = dest; /* Remember start so we can compute length. */
|
||||
|
||||
while (left_pad-- > 0)
|
||||
out_char (' ');
|
||||
|
||||
if (sign_posn == 0 && is_negative)
|
||||
out_char (left_paren);
|
||||
|
||||
if (cs_precedes)
|
||||
{
|
||||
if (sign_posn != 0 && sign_posn != 2 && sign_posn != 4
|
||||
&& sign_posn != 5)
|
||||
{
|
||||
out_string (sign_string);
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
}
|
||||
|
||||
if (print_curr_symbol)
|
||||
{
|
||||
out_string (currency_symbol);
|
||||
|
||||
if (sign_posn == 4)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (space_char);
|
||||
out_string (sign_string);
|
||||
if (sep_by_space == 1)
|
||||
/* POSIX.2 and SUS are not clear on this case, but C99
|
||||
says a space follows the adjacent-symbol-and-sign */
|
||||
out_char (' ');
|
||||
}
|
||||
else
|
||||
if (sep_by_space == 1)
|
||||
out_char (space_char);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3
|
||||
&& sign_posn != 4 && sign_posn != 5)
|
||||
out_string (sign_string);
|
||||
|
||||
/* Print the number. */
|
||||
#ifdef USE_IN_LIBIO
|
||||
# ifdef _IO_MTSAFE_IO
|
||||
f._sbf._f._lock = &lock;
|
||||
# endif
|
||||
INTUSE(_IO_init) ((_IO_FILE *) &f, 0);
|
||||
_IO_JUMPS ((struct _IO_FILE_plus *) &f) = &_IO_str_jumps;
|
||||
INTUSE(_IO_str_init_static) ((_IO_strfile *) &f, dest,
|
||||
(s + maxsize) - dest, dest);
|
||||
#else
|
||||
memset ((void *) &f, 0, sizeof (f));
|
||||
f.__magic = _IOMAGIC;
|
||||
f.__mode.__write = 1;
|
||||
/* The buffer size is one less than MAXLEN
|
||||
so we have space for the null terminator. */
|
||||
f.__bufp = f.__buffer = (char *) dest;
|
||||
f.__bufsize = (s + maxsize) - dest;
|
||||
f.__put_limit = f.__buffer + f.__bufsize;
|
||||
f.__get_limit = f.__buffer;
|
||||
/* After the buffer is full (MAXLEN characters have been written),
|
||||
any more characters written will go to the bit bucket. */
|
||||
f.__room_funcs = __default_room_functions;
|
||||
f.__io_funcs.__write = NULL;
|
||||
f.__seen = 1;
|
||||
#endif
|
||||
/* We clear the last available byte so we can find out whether
|
||||
the numeric representation is too long. */
|
||||
s[maxsize - 1] = '\0';
|
||||
|
||||
info.prec = right_prec;
|
||||
info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
|
||||
info.spec = 'f';
|
||||
info.is_long_double = is_long_double;
|
||||
info.is_short = 0;
|
||||
info.is_long = 0;
|
||||
info.alt = 0;
|
||||
info.space = 0;
|
||||
info.left = 0;
|
||||
info.showsign = 0;
|
||||
info.group = group;
|
||||
info.pad = pad;
|
||||
info.extra = 1; /* This means use values from LC_MONETARY. */
|
||||
info.wide = 0;
|
||||
|
||||
ptr = &fpnum;
|
||||
done = __printf_fp ((FILE *) &f, &info, &ptr);
|
||||
if (done < 0)
|
||||
{
|
||||
va_end (ap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s[maxsize - 1] != '\0')
|
||||
{
|
||||
__set_errno (E2BIG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest += done;
|
||||
|
||||
if (!cs_precedes)
|
||||
{
|
||||
if (sign_posn == 3)
|
||||
{
|
||||
if (sep_by_space == 1)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
|
||||
if (print_curr_symbol)
|
||||
{
|
||||
if ((sign_posn == 3 && sep_by_space == 2)
|
||||
|| (sign_posn == 4 && sep_by_space == 1)
|
||||
|| (sign_posn == 2 && sep_by_space == 1)
|
||||
|| (sign_posn == 1 && sep_by_space == 1)
|
||||
|| (sign_posn == 0 && sep_by_space == 1))
|
||||
out_char (space_char);
|
||||
out_nstring (currency_symbol, currency_symbol_len);
|
||||
if (sign_posn == 4)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sign_posn == 2)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
|
||||
if (sign_posn == 0 && is_negative)
|
||||
out_char (right_paren);
|
||||
|
||||
/* Now test whether the output width is filled. */
|
||||
if (dest - startp < width)
|
||||
{
|
||||
if (left)
|
||||
/* We simply have to fill using spaces. */
|
||||
do
|
||||
out_char (' ');
|
||||
while (dest - startp < width);
|
||||
else
|
||||
{
|
||||
int dist = width - (dest - startp);
|
||||
char *cp;
|
||||
for (cp = dest - 1; cp >= startp; --cp)
|
||||
cp[dist] = cp[0];
|
||||
|
||||
dest += dist;
|
||||
|
||||
do
|
||||
startp[--dist] = ' ';
|
||||
while (dist > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the string. */
|
||||
*dest = '\0';
|
||||
ssize_t res = __vstrfmon_l (s, maxsize, _NL_CURRENT_LOCALE, format, ap);
|
||||
|
||||
va_end (ap);
|
||||
|
||||
return dest - s;
|
||||
return res;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Formatting a monetary value according to the given locale.
|
||||
Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996, 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
@ -18,7 +18,637 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <strfmon.c>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <monetary.h>
|
||||
#ifdef USE_IN_LIBIO
|
||||
# include "../libio/libioP.h"
|
||||
# include "../libio/strfile.h"
|
||||
#endif
|
||||
#include <printf.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../locale/localeinfo.h"
|
||||
|
||||
|
||||
#define out_char(Ch) \
|
||||
do { \
|
||||
if (dest >= s + maxsize - 1) \
|
||||
{ \
|
||||
__set_errno (E2BIG); \
|
||||
va_end (ap); \
|
||||
return -1; \
|
||||
} \
|
||||
*dest++ = (Ch); \
|
||||
} while (0)
|
||||
|
||||
#define out_string(String) \
|
||||
do { \
|
||||
const char *_s = (String); \
|
||||
while (*_s) \
|
||||
out_char (*_s++); \
|
||||
} while (0)
|
||||
|
||||
#define out_nstring(String, N) \
|
||||
do { \
|
||||
int _n = (N); \
|
||||
const char *_s = (String); \
|
||||
while (_n-- > 0) \
|
||||
out_char (*_s++); \
|
||||
} while (0)
|
||||
|
||||
#define to_digit(Ch) ((Ch) - '0')
|
||||
|
||||
|
||||
/* We use this code also for the extended locale handling where the
|
||||
function gets as an additional argument the locale which has to be
|
||||
used. To access the values we have to redefine the _NL_CURRENT
|
||||
macro. */
|
||||
#undef _NL_CURRENT
|
||||
#define _NL_CURRENT(category, item) \
|
||||
(current->values[_NL_ITEM_INDEX (item)].string)
|
||||
|
||||
extern int __printf_fp (FILE *, const struct printf_info *,
|
||||
const void *const *);
|
||||
libc_hidden_proto (__printf_fp)
|
||||
/* This function determines the number of digit groups in the output.
|
||||
The definition is in printf_fp.c. */
|
||||
extern unsigned int __guess_grouping (unsigned int intdig_max,
|
||||
const char *grouping, wchar_t sepchar);
|
||||
|
||||
|
||||
/* We have to overcome some problems with this implementation. On the
|
||||
one hand the strfmon() function is specified in XPG4 and of course
|
||||
it has to follow this. But on the other hand POSIX.2 specifies
|
||||
some information in the LC_MONETARY category which should be used,
|
||||
too. Some of the information contradicts the information which can
|
||||
be specified in format string. */
|
||||
ssize_t
|
||||
__vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
|
||||
va_list ap)
|
||||
{
|
||||
struct locale_data *current = loc->__locales[LC_MONETARY];
|
||||
#ifdef USE_IN_LIBIO
|
||||
_IO_strfile f;
|
||||
# ifdef _IO_MTSAFE_IO
|
||||
_IO_lock_t lock;
|
||||
# endif
|
||||
#else
|
||||
FILE f;
|
||||
#endif
|
||||
struct printf_info info;
|
||||
char *dest; /* Pointer so copy the output. */
|
||||
const char *fmt; /* Pointer that walks through format. */
|
||||
|
||||
dest = s;
|
||||
fmt = format;
|
||||
|
||||
/* Loop through the format-string. */
|
||||
while (*fmt != '\0')
|
||||
{
|
||||
/* The floating-point value to output. */
|
||||
union
|
||||
{
|
||||
double dbl;
|
||||
__long_double_t ldbl;
|
||||
}
|
||||
fpnum;
|
||||
int int_format;
|
||||
int print_curr_symbol;
|
||||
int left_prec;
|
||||
int left_pad;
|
||||
int right_prec;
|
||||
int group;
|
||||
char pad;
|
||||
int is_long_double;
|
||||
int p_sign_posn;
|
||||
int n_sign_posn;
|
||||
int sign_posn;
|
||||
int other_sign_posn;
|
||||
int left;
|
||||
int is_negative;
|
||||
int sep_by_space;
|
||||
int other_sep_by_space;
|
||||
int cs_precedes;
|
||||
int other_cs_precedes;
|
||||
const char *sign_string;
|
||||
const char *other_sign_string;
|
||||
int done;
|
||||
const char *currency_symbol;
|
||||
size_t currency_symbol_len;
|
||||
int width;
|
||||
char *startp;
|
||||
const void *ptr;
|
||||
char space_char;
|
||||
|
||||
/* Process all character which do not introduce a format
|
||||
specification. */
|
||||
if (*fmt != '%')
|
||||
{
|
||||
out_char (*fmt++);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "%%" means a single '%' character. */
|
||||
if (fmt[1] == '%')
|
||||
{
|
||||
out_char (*++fmt);
|
||||
++fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Defaults for formatting. */
|
||||
int_format = 0; /* Use international curr. symbol */
|
||||
print_curr_symbol = 1; /* Print the currency symbol. */
|
||||
left_prec = -1; /* No left precision specified. */
|
||||
right_prec = -1; /* No right precision specified. */
|
||||
group = 1; /* Print digits grouped. */
|
||||
pad = ' '; /* Fill character is <SP>. */
|
||||
is_long_double = 0; /* Double argument by default. */
|
||||
p_sign_posn = -1; /* This indicates whether the */
|
||||
n_sign_posn = -1; /* '(' flag is given. */
|
||||
width = -1; /* No width specified so far. */
|
||||
left = 0; /* Right justified by default. */
|
||||
|
||||
/* Parse group characters. */
|
||||
while (1)
|
||||
{
|
||||
switch (*++fmt)
|
||||
{
|
||||
case '=': /* Set fill character. */
|
||||
pad = *++fmt;
|
||||
if (pad == '\0')
|
||||
{
|
||||
/* Premature EOS. */
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
case '^': /* Don't group digits. */
|
||||
group = 0;
|
||||
continue;
|
||||
case '+': /* Use +/- for sign of number. */
|
||||
if (n_sign_posn != -1)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
p_sign_posn = *_NL_CURRENT (LC_MONETARY, P_SIGN_POSN);
|
||||
n_sign_posn = *_NL_CURRENT (LC_MONETARY, N_SIGN_POSN);
|
||||
continue;
|
||||
case '(': /* Use ( ) for negative sign. */
|
||||
if (n_sign_posn != -1)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
p_sign_posn = 0;
|
||||
n_sign_posn = 0;
|
||||
continue;
|
||||
case '!': /* Don't print the currency symbol. */
|
||||
print_curr_symbol = 0;
|
||||
continue;
|
||||
case '-': /* Print left justified. */
|
||||
left = 1;
|
||||
continue;
|
||||
default:
|
||||
/* Will stop the loop. */;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (isdigit (*fmt))
|
||||
{
|
||||
/* Parse field width. */
|
||||
width = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
width *= 10;
|
||||
width += to_digit (*fmt);
|
||||
}
|
||||
|
||||
/* If we don't have enough room for the demanded width we
|
||||
can stop now and return an error. */
|
||||
if (dest + width >= s + maxsize)
|
||||
{
|
||||
__set_errno (E2BIG);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Recognize left precision. */
|
||||
if (*fmt == '#')
|
||||
{
|
||||
if (!isdigit (*++fmt))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
left_prec = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
left_prec *= 10;
|
||||
left_prec += to_digit (*fmt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recognize right precision. */
|
||||
if (*fmt == '.')
|
||||
{
|
||||
if (!isdigit (*++fmt))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
right_prec = to_digit (*fmt);
|
||||
|
||||
while (isdigit (*++fmt))
|
||||
{
|
||||
right_prec *= 10;
|
||||
right_prec += to_digit (*fmt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle modifier. This is an extension. */
|
||||
if (*fmt == 'L')
|
||||
{
|
||||
++fmt;
|
||||
is_long_double = 1;
|
||||
}
|
||||
|
||||
/* Handle format specifier. */
|
||||
char int_symbol[4];
|
||||
switch (*fmt++)
|
||||
{
|
||||
case 'i': { /* Use international currency symbol. */
|
||||
const char *int_curr_symbol;
|
||||
|
||||
int_curr_symbol = _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL);
|
||||
strncpy(int_symbol, int_curr_symbol, 3);
|
||||
int_symbol[3] = '\0';
|
||||
|
||||
currency_symbol_len = 3;
|
||||
currency_symbol = &int_symbol[0];
|
||||
space_char = int_curr_symbol[3];
|
||||
int_format = 1;
|
||||
break;
|
||||
}
|
||||
case 'n': /* Use national currency symbol. */
|
||||
currency_symbol = _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL);
|
||||
currency_symbol_len = strlen (currency_symbol);
|
||||
space_char = ' ';
|
||||
int_format = 0;
|
||||
break;
|
||||
default: /* Any unrecognized format is an error. */
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If not specified by the format string now find the values for
|
||||
the format specification. */
|
||||
if (p_sign_posn == -1)
|
||||
p_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SIGN_POSN : P_SIGN_POSN);
|
||||
if (n_sign_posn == -1)
|
||||
n_sign_posn = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SIGN_POSN : N_SIGN_POSN);
|
||||
|
||||
if (right_prec == -1)
|
||||
{
|
||||
right_prec = *_NL_CURRENT (LC_MONETARY, int_format ? INT_FRAC_DIGITS : FRAC_DIGITS);
|
||||
|
||||
if (right_prec == CHAR_MAX)
|
||||
right_prec = 2;
|
||||
}
|
||||
|
||||
/* If we have to print the digits grouped determine how many
|
||||
extra characters this means. */
|
||||
if (group && left_prec != -1)
|
||||
left_prec += __guess_grouping (left_prec,
|
||||
_NL_CURRENT (LC_MONETARY, MON_GROUPING),
|
||||
*_NL_CURRENT (LC_MONETARY,
|
||||
MON_THOUSANDS_SEP));
|
||||
|
||||
/* Now it's time to get the value. */
|
||||
if (is_long_double == 1)
|
||||
{
|
||||
fpnum.ldbl = va_arg (ap, long double);
|
||||
is_negative = fpnum.ldbl < 0;
|
||||
if (is_negative)
|
||||
fpnum.ldbl = -fpnum.ldbl;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpnum.dbl = va_arg (ap, double);
|
||||
is_negative = fpnum.dbl < 0;
|
||||
if (is_negative)
|
||||
fpnum.dbl = -fpnum.dbl;
|
||||
}
|
||||
|
||||
/* We now know the sign of the value and can determine the format. */
|
||||
if (is_negative)
|
||||
{
|
||||
sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
|
||||
/* If the locale does not specify a character for the
|
||||
negative sign we use a '-'. */
|
||||
if (*sign_string == '\0')
|
||||
sign_string = (const char *) "-";
|
||||
cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
|
||||
sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
|
||||
sign_posn = n_sign_posn;
|
||||
|
||||
other_sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
|
||||
other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
|
||||
other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
|
||||
other_sign_posn = p_sign_posn;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign_string = _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN);
|
||||
cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_CS_PRECEDES : P_CS_PRECEDES);
|
||||
sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_P_SEP_BY_SPACE : P_SEP_BY_SPACE);
|
||||
sign_posn = p_sign_posn;
|
||||
|
||||
other_sign_string = _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN);
|
||||
if (*other_sign_string == '\0')
|
||||
other_sign_string = (const char *) "-";
|
||||
other_cs_precedes = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_CS_PRECEDES : N_CS_PRECEDES);
|
||||
other_sep_by_space = *_NL_CURRENT (LC_MONETARY, int_format ? INT_N_SEP_BY_SPACE : N_SEP_BY_SPACE);
|
||||
other_sign_posn = n_sign_posn;
|
||||
}
|
||||
|
||||
/* Set default values for unspecified information. */
|
||||
if (cs_precedes != 0)
|
||||
cs_precedes = 1;
|
||||
if (other_cs_precedes != 0)
|
||||
other_cs_precedes = 1;
|
||||
if (sep_by_space == CHAR_MAX)
|
||||
sep_by_space = 0;
|
||||
if (other_sep_by_space == CHAR_MAX)
|
||||
other_sep_by_space = 0;
|
||||
if (sign_posn == CHAR_MAX)
|
||||
sign_posn = 1;
|
||||
if (other_sign_posn == CHAR_MAX)
|
||||
other_sign_posn = 1;
|
||||
|
||||
/* Check for degenerate cases */
|
||||
if (sep_by_space == 2)
|
||||
{
|
||||
if (sign_posn == 0 ||
|
||||
(sign_posn == 1 && !cs_precedes) ||
|
||||
(sign_posn == 2 && cs_precedes))
|
||||
/* sign and symbol are not adjacent, so no separator */
|
||||
sep_by_space = 0;
|
||||
}
|
||||
if (other_sep_by_space == 2)
|
||||
{
|
||||
if (other_sign_posn == 0 ||
|
||||
(other_sign_posn == 1 && !other_cs_precedes) ||
|
||||
(other_sign_posn == 2 && other_cs_precedes))
|
||||
/* sign and symbol are not adjacent, so no separator */
|
||||
other_sep_by_space = 0;
|
||||
}
|
||||
|
||||
/* Set the left precision and padding needed for alignment */
|
||||
if (left_prec == -1)
|
||||
{
|
||||
left_prec = 0;
|
||||
left_pad = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set left_pad to number of spaces needed to align positive
|
||||
and negative formats */
|
||||
|
||||
int left_bytes = 0;
|
||||
int other_left_bytes = 0;
|
||||
|
||||
/* Work out number of bytes for currency string and separator
|
||||
preceding the value */
|
||||
if (cs_precedes)
|
||||
{
|
||||
left_bytes += currency_symbol_len;
|
||||
if (sep_by_space != 0)
|
||||
++left_bytes;
|
||||
}
|
||||
|
||||
if (other_cs_precedes)
|
||||
{
|
||||
other_left_bytes += currency_symbol_len;
|
||||
if (other_sep_by_space != 0)
|
||||
++other_left_bytes;
|
||||
}
|
||||
|
||||
/* Work out number of bytes for the sign (or left parenthesis)
|
||||
preceding the value */
|
||||
if (sign_posn == 0 && is_negative)
|
||||
++left_bytes;
|
||||
else if (sign_posn == 1)
|
||||
left_bytes += strlen (sign_string);
|
||||
else if (cs_precedes && (sign_posn == 3 || sign_posn == 4))
|
||||
left_bytes += strlen (sign_string);
|
||||
|
||||
if (other_sign_posn == 0 && !is_negative)
|
||||
++other_left_bytes;
|
||||
else if (other_sign_posn == 1)
|
||||
other_left_bytes += strlen (other_sign_string);
|
||||
else if (other_cs_precedes &&
|
||||
(other_sign_posn == 3 || other_sign_posn == 4))
|
||||
other_left_bytes += strlen (other_sign_string);
|
||||
|
||||
/* Compare the number of bytes preceding the value for
|
||||
each format, and set the padding accordingly */
|
||||
if (other_left_bytes > left_bytes)
|
||||
left_pad = other_left_bytes - left_bytes;
|
||||
else
|
||||
left_pad = 0;
|
||||
}
|
||||
|
||||
/* Perhaps we'll someday make these things configurable so
|
||||
better start using symbolic names now. */
|
||||
#define left_paren '('
|
||||
#define right_paren ')'
|
||||
|
||||
startp = dest; /* Remember start so we can compute length. */
|
||||
|
||||
while (left_pad-- > 0)
|
||||
out_char (' ');
|
||||
|
||||
if (sign_posn == 0 && is_negative)
|
||||
out_char (left_paren);
|
||||
|
||||
if (cs_precedes)
|
||||
{
|
||||
if (sign_posn != 0 && sign_posn != 2 && sign_posn != 4
|
||||
&& sign_posn != 5)
|
||||
{
|
||||
out_string (sign_string);
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
}
|
||||
|
||||
if (print_curr_symbol)
|
||||
{
|
||||
out_string (currency_symbol);
|
||||
|
||||
if (sign_posn == 4)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (space_char);
|
||||
out_string (sign_string);
|
||||
if (sep_by_space == 1)
|
||||
/* POSIX.2 and SUS are not clear on this case, but C99
|
||||
says a space follows the adjacent-symbol-and-sign */
|
||||
out_char (' ');
|
||||
}
|
||||
else
|
||||
if (sep_by_space == 1)
|
||||
out_char (space_char);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (sign_posn != 0 && sign_posn != 2 && sign_posn != 3
|
||||
&& sign_posn != 4 && sign_posn != 5)
|
||||
out_string (sign_string);
|
||||
|
||||
/* Print the number. */
|
||||
#ifdef USE_IN_LIBIO
|
||||
# ifdef _IO_MTSAFE_IO
|
||||
f._sbf._f._lock = &lock;
|
||||
# endif
|
||||
INTUSE(_IO_init) ((_IO_FILE *) &f, 0);
|
||||
_IO_JUMPS ((struct _IO_FILE_plus *) &f) = &_IO_str_jumps;
|
||||
INTUSE(_IO_str_init_static) ((_IO_strfile *) &f, dest,
|
||||
(s + maxsize) - dest, dest);
|
||||
#else
|
||||
memset ((void *) &f, 0, sizeof (f));
|
||||
f.__magic = _IOMAGIC;
|
||||
f.__mode.__write = 1;
|
||||
/* The buffer size is one less than MAXLEN
|
||||
so we have space for the null terminator. */
|
||||
f.__bufp = f.__buffer = (char *) dest;
|
||||
f.__bufsize = (s + maxsize) - dest;
|
||||
f.__put_limit = f.__buffer + f.__bufsize;
|
||||
f.__get_limit = f.__buffer;
|
||||
/* After the buffer is full (MAXLEN characters have been written),
|
||||
any more characters written will go to the bit bucket. */
|
||||
f.__room_funcs = __default_room_functions;
|
||||
f.__io_funcs.__write = NULL;
|
||||
f.__seen = 1;
|
||||
#endif
|
||||
/* We clear the last available byte so we can find out whether
|
||||
the numeric representation is too long. */
|
||||
s[maxsize - 1] = '\0';
|
||||
|
||||
info.prec = right_prec;
|
||||
info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
|
||||
info.spec = 'f';
|
||||
info.is_long_double = is_long_double;
|
||||
info.is_short = 0;
|
||||
info.is_long = 0;
|
||||
info.alt = 0;
|
||||
info.space = 0;
|
||||
info.left = 0;
|
||||
info.showsign = 0;
|
||||
info.group = group;
|
||||
info.pad = pad;
|
||||
info.extra = 1; /* This means use values from LC_MONETARY. */
|
||||
info.wide = 0;
|
||||
|
||||
ptr = &fpnum;
|
||||
done = __printf_fp ((FILE *) &f, &info, &ptr);
|
||||
if (done < 0)
|
||||
return -1;
|
||||
|
||||
if (s[maxsize - 1] != '\0')
|
||||
{
|
||||
__set_errno (E2BIG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest += done;
|
||||
|
||||
if (!cs_precedes)
|
||||
{
|
||||
if (sign_posn == 3)
|
||||
{
|
||||
if (sep_by_space == 1)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
|
||||
if (print_curr_symbol)
|
||||
{
|
||||
if ((sign_posn == 3 && sep_by_space == 2)
|
||||
|| (sign_posn == 4 && sep_by_space == 1)
|
||||
|| (sign_posn == 2 && sep_by_space == 1)
|
||||
|| (sign_posn == 1 && sep_by_space == 1)
|
||||
|| (sign_posn == 0 && sep_by_space == 1))
|
||||
out_char (space_char);
|
||||
out_nstring (currency_symbol, currency_symbol_len);
|
||||
if (sign_posn == 4)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sign_posn == 2)
|
||||
{
|
||||
if (sep_by_space == 2)
|
||||
out_char (' ');
|
||||
out_string (sign_string);
|
||||
}
|
||||
|
||||
if (sign_posn == 0 && is_negative)
|
||||
out_char (right_paren);
|
||||
|
||||
/* Now test whether the output width is filled. */
|
||||
if (dest - startp < width)
|
||||
{
|
||||
if (left)
|
||||
/* We simply have to fill using spaces. */
|
||||
do
|
||||
out_char (' ');
|
||||
while (dest - startp < width);
|
||||
else
|
||||
{
|
||||
int dist = width - (dest - startp);
|
||||
char *cp;
|
||||
for (cp = dest - 1; cp >= startp; --cp)
|
||||
cp[dist] = cp[0];
|
||||
|
||||
dest += dist;
|
||||
|
||||
do
|
||||
startp[--dist] = ' ';
|
||||
while (dist > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the string. */
|
||||
*dest = '\0';
|
||||
|
||||
return dest - s;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
__strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
ssize_t res = __vstrfmon_l (s, maxsize, loc, format, ap);
|
||||
|
||||
va_end (ap);
|
||||
|
||||
return res;
|
||||
}
|
||||
weak_alias (__strfmon_l, strfmon_l)
|
||||
|
1554
stdlib/strtod.c
1554
stdlib/strtod.c
File diff suppressed because it is too large
Load Diff
1551
stdlib/strtod_l.c
1551
stdlib/strtod_l.c
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,35 @@
|
||||
/* Read decimal floating point numbers.
|
||||
This file is part of the GNU C Library.
|
||||
Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* The actual implementation for all floating point sizes is in strtod.c.
|
||||
These macros tell it to produce the `float' version, `strtof'. */
|
||||
|
||||
#define FLOAT float
|
||||
#define FLT FLT
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRTOF __strtof_l
|
||||
#ifdef USE_WIDE_CHAR
|
||||
#define STRTOF wcstof
|
||||
#define STRTOF_L __wcstof_l
|
||||
#else
|
||||
# define STRTOF strtof
|
||||
# define STRTOF_L __strtof_l
|
||||
#endif
|
||||
#define MPN2FLOAT __mpn_construct_float
|
||||
#define FLOAT_HUGE_VAL HUGE_VALF
|
||||
#define SET_MANTISSA(flt, mant) \
|
||||
do { union ieee754_float u; \
|
||||
u.f = (flt); \
|
||||
if ((mant & 0x7fffff) == 0) \
|
||||
mant = 0x400000; \
|
||||
u.ieee.mantissa = (mant) & 0x7fffff; \
|
||||
(flt) = u.f; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#include "strtod.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to float value, using given locale.
|
||||
Copyright (C) 1997,98,2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,14 +18,30 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
#include <xlocale.h>
|
||||
|
||||
extern float ____strtof_l_internal (const char *, char **, int, __locale_t);
|
||||
extern unsigned long long int ____strtoull_l_internal (const char *, char **,
|
||||
int, int, __locale_t);
|
||||
|
||||
#include <strtof.c>
|
||||
#define FLOAT float
|
||||
#define FLT FLT
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# define STRTOF wcstof_l
|
||||
# define __STRTOF __wcstof_l
|
||||
#else
|
||||
# define STRTOF strtof_l
|
||||
# define __STRTOF __strtof_l
|
||||
#endif
|
||||
#define MPN2FLOAT __mpn_construct_float
|
||||
#define FLOAT_HUGE_VAL HUGE_VALF
|
||||
#define SET_MANTISSA(flt, mant) \
|
||||
do { union ieee754_float u; \
|
||||
u.f = (flt); \
|
||||
if ((mant & 0x7fffff) == 0) \
|
||||
mant = 0x400000; \
|
||||
u.ieee.mantissa = (mant) & 0x7fffff; \
|
||||
(flt) = u.f; \
|
||||
} while (0)
|
||||
|
||||
weak_alias (__strtof_l, strtof_l)
|
||||
#include "strtod_l.c"
|
||||
|
35
stdlib/strtold.c
Normal file
35
stdlib/strtold.c
Normal file
@ -0,0 +1,35 @@
|
||||
/* Read decimal floating point numbers.
|
||||
This file is part of the GNU C Library.
|
||||
Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* The actual implementation for all floating point sizes is in strtod.c.
|
||||
These macros tell it to produce the `float' version, `strtof'. */
|
||||
|
||||
#define FLOAT long double
|
||||
#define FLT LDBL
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# define STRTOF wcstold
|
||||
# define STRTOF_L __wcstold_l
|
||||
#else
|
||||
# define STRTOF strtold
|
||||
# define STRTOF_L __strtold_l
|
||||
#endif
|
||||
|
||||
|
||||
#include "strtod.c"
|
@ -1,53 +0,0 @@
|
||||
/* Convert string representing a number to float value, using given locale.
|
||||
Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <math.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#ifndef __NO_LONG_DOUBLE_MATH
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
extern long double ____strtold_l_internal (const char *, char **, int,
|
||||
__locale_t);
|
||||
extern unsigned long long int ____strtoull_l_internal (const char *, char **,
|
||||
int, int, __locale_t);
|
||||
|
||||
# include <strtold.c>
|
||||
|
||||
#else
|
||||
/* There is no `long double' type, use the `double' implementations. */
|
||||
extern double ____strtod_l_internal (const char *, char **, int,
|
||||
__locale_t);
|
||||
long double
|
||||
____strtold_l_internal (const char *nptr, char **endptr, int group,
|
||||
__locale_t loc)
|
||||
{
|
||||
return ____strtod_l_internal (nptr, endptr, group, loc);
|
||||
}
|
||||
|
||||
long double
|
||||
__strtold_l (const char *nptr, char **endptr, __locale_t loc)
|
||||
{
|
||||
return ____strtod_l_internal (nptr, endptr, 0, loc);
|
||||
}
|
||||
#endif
|
||||
|
||||
weak_alias (__strtold_l, strtold_l)
|
526
string/strcoll.c
526
string/strcoll.c
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
|
||||
@ -17,540 +17,24 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STRING_TYPE
|
||||
# define STRING_TYPE char
|
||||
# define USTRING_TYPE unsigned char
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRCOLL __strcoll_l
|
||||
# else
|
||||
# define STRCOLL strcoll
|
||||
# define STRCOLL_L __strcoll_l
|
||||
#endif
|
||||
# define STRCMP strcmp
|
||||
# define STRLEN strlen
|
||||
# define WEIGHT_H "../locale/weight.h"
|
||||
# define SUFFIX MB
|
||||
# define L(arg) arg
|
||||
#endif
|
||||
|
||||
#define CONCAT(a,b) CONCAT1(a,b)
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
|
||||
#ifndef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
|
||||
int
|
||||
STRCOLL (s1, s2)
|
||||
const STRING_TYPE *s1;
|
||||
const STRING_TYPE *s2;
|
||||
#else
|
||||
int
|
||||
STRCOLL (s1, s2, l)
|
||||
const STRING_TYPE *s1;
|
||||
const STRING_TYPE *s2;
|
||||
__locale_t l;
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
struct locale_data *current = l->__locales[LC_COLLATE];
|
||||
uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
|
||||
#else
|
||||
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
|
||||
#endif
|
||||
/* We don't assign the following values right away since it might be
|
||||
unnecessary in case there are no rules. */
|
||||
const unsigned char *rulesets;
|
||||
const int32_t *table;
|
||||
const USTRING_TYPE *weights;
|
||||
const USTRING_TYPE *extra;
|
||||
const int32_t *indirect;
|
||||
uint_fast32_t pass;
|
||||
int result = 0;
|
||||
const USTRING_TYPE *us1;
|
||||
const USTRING_TYPE *us2;
|
||||
size_t s1len;
|
||||
size_t s2len;
|
||||
int32_t *idx1arr;
|
||||
int32_t *idx2arr;
|
||||
unsigned char *rule1arr;
|
||||
unsigned char *rule2arr;
|
||||
size_t idx1max;
|
||||
size_t idx2max;
|
||||
size_t idx1cnt;
|
||||
size_t idx2cnt;
|
||||
size_t idx1now;
|
||||
size_t idx2now;
|
||||
size_t backw1_stop;
|
||||
size_t backw2_stop;
|
||||
size_t backw1;
|
||||
size_t backw2;
|
||||
int val1;
|
||||
int val2;
|
||||
int position;
|
||||
int seq1len;
|
||||
int seq2len;
|
||||
int use_malloc;
|
||||
|
||||
#include WEIGHT_H
|
||||
|
||||
if (nrules == 0)
|
||||
return STRCMP (s1, s2);
|
||||
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
rulesets = (const unsigned char *)
|
||||
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
|
||||
table = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
|
||||
weights = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
|
||||
extra = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
|
||||
indirect = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
|
||||
#else
|
||||
rulesets = (const unsigned char *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_RULESETS);
|
||||
table = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_TABLE,SUFFIX));
|
||||
weights = (const USTRING_TYPE *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_WEIGHT,SUFFIX));
|
||||
extra = (const USTRING_TYPE *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_EXTRA,SUFFIX));
|
||||
indirect = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_INDIRECT,SUFFIX));
|
||||
#endif
|
||||
use_malloc = 0;
|
||||
|
||||
assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
|
||||
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
|
||||
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
|
||||
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
|
||||
|
||||
/* We need this a few times. */
|
||||
s1len = STRLEN (s1);
|
||||
s2len = STRLEN (s2);
|
||||
|
||||
/* Catch empty strings. */
|
||||
if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
|
||||
return (s1len != 0) - (s2len != 0);
|
||||
|
||||
/* We need the elements of the strings as unsigned values since they
|
||||
are used as indeces. */
|
||||
us1 = (const USTRING_TYPE *) s1;
|
||||
us2 = (const USTRING_TYPE *) s2;
|
||||
|
||||
/* Perform the first pass over the string and while doing this find
|
||||
and store the weights for each character. Since we want this to
|
||||
be as fast as possible we are using `alloca' to store the temporary
|
||||
values. But since there is no limit on the length of the string
|
||||
we have to use `malloc' if the string is too long. We should be
|
||||
very conservative here.
|
||||
|
||||
Please note that the localedef programs makes sure that `position'
|
||||
is not used at the first level. */
|
||||
if (! __libc_use_alloca (s1len + s2len))
|
||||
{
|
||||
idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
|
||||
idx2arr = &idx1arr[s1len];
|
||||
rule1arr = (unsigned char *) &idx2arr[s2len];
|
||||
rule2arr = &rule1arr[s1len];
|
||||
|
||||
if (idx1arr == NULL)
|
||||
/* No memory. Well, go with the stack then.
|
||||
|
||||
XXX Once this implementation is stable we will handle this
|
||||
differently. Instead of precomputing the indeces we will
|
||||
do this in time. This means, though, that this happens for
|
||||
every pass again. */
|
||||
goto try_stack;
|
||||
use_malloc = 1;
|
||||
return STRCOLL_L (s1, s2, _NL_CURRENT_LOCALE);
|
||||
}
|
||||
else
|
||||
{
|
||||
try_stack:
|
||||
idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
|
||||
idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
|
||||
rule1arr = (unsigned char *) alloca (s1len);
|
||||
rule2arr = (unsigned char *) alloca (s2len);
|
||||
}
|
||||
|
||||
idx1cnt = 0;
|
||||
idx2cnt = 0;
|
||||
idx1max = 0;
|
||||
idx2max = 0;
|
||||
idx1now = 0;
|
||||
idx2now = 0;
|
||||
backw1_stop = ~0ul;
|
||||
backw2_stop = ~0ul;
|
||||
backw1 = ~0ul;
|
||||
backw2 = ~0ul;
|
||||
seq1len = 0;
|
||||
seq2len = 0;
|
||||
position = rulesets[0] & sort_position;
|
||||
while (1)
|
||||
{
|
||||
val1 = 0;
|
||||
val2 = 0;
|
||||
|
||||
/* Get the next non-IGNOREd element for string `s1'. */
|
||||
if (seq1len == 0)
|
||||
do
|
||||
{
|
||||
++val1;
|
||||
|
||||
if (backw1_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw1 == backw1_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx1cnt < idx1max)
|
||||
idx1now = idx1cnt;
|
||||
else
|
||||
/* Nothing anymore. The backward sequence ended with
|
||||
the last sequence in the string. Note that seq1len
|
||||
is still zero. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
idx1now = --backw1;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw1_stop = idx1max;
|
||||
|
||||
while (*us1 != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us1);
|
||||
rule1arr[idx1max] = tmp >> 24;
|
||||
idx1arr[idx1max] = tmp & 0xffffff;
|
||||
idx1cnt = idx1max++;
|
||||
|
||||
if ((rulesets[rule1arr[idx1cnt] * nrules]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx1cnt;
|
||||
}
|
||||
|
||||
if (backw1_stop >= idx1cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx1cnt == idx1max || backw1_stop > idx1cnt)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw1_stop = ~0ul;
|
||||
idx1now = idx1cnt;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx1now = backw1 = idx1cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
|
||||
|
||||
/* And the same for string `s2'. */
|
||||
if (seq2len == 0)
|
||||
do
|
||||
{
|
||||
++val2;
|
||||
|
||||
if (backw2_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw2 == backw2_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx2cnt < idx2max)
|
||||
idx2now = idx2cnt;
|
||||
else
|
||||
/* Nothing anymore. The backward sequence ended with
|
||||
the last sequence in the string. Note that seq2len
|
||||
is still zero. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
idx2now = --backw2;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw2_stop = idx2max;
|
||||
|
||||
while (*us2 != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us2);
|
||||
rule2arr[idx2max] = tmp >> 24;
|
||||
idx2arr[idx2max] = tmp & 0xffffff;
|
||||
idx2cnt = idx2max++;
|
||||
|
||||
if ((rulesets[rule2arr[idx2cnt] * nrules]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx2cnt;
|
||||
}
|
||||
|
||||
if (backw2_stop >= idx2cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx2cnt == idx2max || backw2_stop > idx2cnt)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw2_stop = ~0ul;
|
||||
idx2now = idx2cnt;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx2now = backw2 = idx2cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
|
||||
|
||||
/* See whether any or both strings are empty. */
|
||||
if (seq1len == 0 || seq2len == 0)
|
||||
{
|
||||
if (seq1len == seq2len)
|
||||
/* Both ended. So far so good, both strings are equal at the
|
||||
first level. */
|
||||
break;
|
||||
|
||||
/* This means one string is shorter than the other. Find out
|
||||
which one and return an appropriate value. */
|
||||
result = seq1len == 0 ? -1 : 1;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Test for position if necessary. */
|
||||
if (position && val1 != val2)
|
||||
{
|
||||
result = val1 - val2;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Compare the two sequences. */
|
||||
do
|
||||
{
|
||||
if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
|
||||
{
|
||||
/* The sequences differ. */
|
||||
result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Increment the offsets. */
|
||||
++idx1arr[idx1now];
|
||||
++idx2arr[idx2now];
|
||||
|
||||
--seq1len;
|
||||
--seq2len;
|
||||
}
|
||||
while (seq1len > 0 && seq2len > 0);
|
||||
|
||||
if (position && seq1len != seq2len)
|
||||
{
|
||||
result = seq1len - seq2len;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the remaining passes over the weights. We now use the
|
||||
indeces we found before. */
|
||||
for (pass = 1; pass < nrules; ++pass)
|
||||
{
|
||||
/* We assume that if a rule has defined `position' in one section
|
||||
this is true for all of them. */
|
||||
idx1cnt = 0;
|
||||
idx2cnt = 0;
|
||||
backw1_stop = ~0ul;
|
||||
backw2_stop = ~0ul;
|
||||
backw1 = ~0ul;
|
||||
backw2 = ~0ul;
|
||||
position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
|
||||
|
||||
while (1)
|
||||
{
|
||||
val1 = 0;
|
||||
val2 = 0;
|
||||
|
||||
/* Get the next non-IGNOREd element for string `s1'. */
|
||||
if (seq1len == 0)
|
||||
do
|
||||
{
|
||||
++val1;
|
||||
|
||||
if (backw1_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw1 == backw1_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx1cnt < idx1max)
|
||||
idx1now = idx1cnt;
|
||||
else
|
||||
{
|
||||
/* Nothing anymore. The backward sequence
|
||||
ended with the last sequence in the string. */
|
||||
idx1now = ~0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
idx1now = --backw1;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw1_stop = idx1cnt;
|
||||
|
||||
while (idx1cnt < idx1max)
|
||||
{
|
||||
if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx1cnt;
|
||||
}
|
||||
|
||||
if (backw1_stop == idx1cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx1cnt == idx1max)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw1_stop = ~0ul;
|
||||
idx1now = idx1cnt++;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx1now = backw1 = idx1cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
|
||||
|
||||
/* And the same for string `s2'. */
|
||||
if (seq2len == 0)
|
||||
do
|
||||
{
|
||||
++val2;
|
||||
|
||||
if (backw2_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw2 == backw2_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx2cnt < idx2max)
|
||||
idx2now = idx2cnt;
|
||||
else
|
||||
{
|
||||
/* Nothing anymore. The backward sequence
|
||||
ended with the last sequence in the string. */
|
||||
idx2now = ~0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
idx2now = --backw2;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw2_stop = idx2cnt;
|
||||
|
||||
while (idx2cnt < idx2max)
|
||||
{
|
||||
if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx2cnt;
|
||||
}
|
||||
|
||||
if (backw2_stop == idx2cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx2cnt == idx2max)
|
||||
/* Note that seq2len is still zero. */
|
||||
break;
|
||||
|
||||
backw2_stop = ~0ul;
|
||||
idx2now = idx2cnt++;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx2now = backw2 = idx2cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
|
||||
|
||||
/* See whether any or both strings are empty. */
|
||||
if (seq1len == 0 || seq2len == 0)
|
||||
{
|
||||
if (seq1len == seq2len)
|
||||
/* Both ended. So far so good, both strings are equal
|
||||
at this level. */
|
||||
break;
|
||||
|
||||
/* This means one string is shorter than the other. Find out
|
||||
which one and return an appropriate value. */
|
||||
result = seq1len == 0 ? -1 : 1;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Test for position if necessary. */
|
||||
if (position && val1 != val2)
|
||||
{
|
||||
result = val1 - val2;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Compare the two sequences. */
|
||||
do
|
||||
{
|
||||
if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
|
||||
{
|
||||
/* The sequences differ. */
|
||||
result = (weights[idx1arr[idx1now]]
|
||||
- weights[idx2arr[idx2now]]);
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Increment the offsets. */
|
||||
++idx1arr[idx1now];
|
||||
++idx2arr[idx2now];
|
||||
|
||||
--seq1len;
|
||||
--seq2len;
|
||||
}
|
||||
while (seq1len > 0 && seq2len > 0);
|
||||
|
||||
if (position && seq1len != seq2len)
|
||||
{
|
||||
result = seq1len - seq2len;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory if needed. */
|
||||
free_and_return:
|
||||
if (use_malloc)
|
||||
free (idx1arr);
|
||||
|
||||
return result;
|
||||
}
|
||||
#if !defined WIDE_CHAR_VERSION && !defined USE_IN_EXTENDED_LOCALE_MODEL
|
||||
#if !defined WIDE_CHAR_VERSION
|
||||
libc_hidden_def (strcoll)
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1995,96,97,2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,96,97,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||
|
||||
@ -17,7 +17,515 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <strcoll.c>
|
||||
|
||||
#include <assert.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STRING_TYPE
|
||||
# define STRING_TYPE char
|
||||
# define USTRING_TYPE unsigned char
|
||||
# define STRCOLL __strcoll_l
|
||||
# define STRCMP strcmp
|
||||
# define STRLEN strlen
|
||||
# define WEIGHT_H "../locale/weight.h"
|
||||
# define SUFFIX MB
|
||||
# define L(arg) arg
|
||||
#endif
|
||||
|
||||
#define CONCAT(a,b) CONCAT1(a,b)
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
|
||||
int
|
||||
STRCOLL (s1, s2, l)
|
||||
const STRING_TYPE *s1;
|
||||
const STRING_TYPE *s2;
|
||||
__locale_t l;
|
||||
{
|
||||
struct locale_data *current = l->__locales[LC_COLLATE];
|
||||
uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
|
||||
/* We don't assign the following values right away since it might be
|
||||
unnecessary in case there are no rules. */
|
||||
const unsigned char *rulesets;
|
||||
const int32_t *table;
|
||||
const USTRING_TYPE *weights;
|
||||
const USTRING_TYPE *extra;
|
||||
const int32_t *indirect;
|
||||
uint_fast32_t pass;
|
||||
int result = 0;
|
||||
const USTRING_TYPE *us1;
|
||||
const USTRING_TYPE *us2;
|
||||
size_t s1len;
|
||||
size_t s2len;
|
||||
int32_t *idx1arr;
|
||||
int32_t *idx2arr;
|
||||
unsigned char *rule1arr;
|
||||
unsigned char *rule2arr;
|
||||
size_t idx1max;
|
||||
size_t idx2max;
|
||||
size_t idx1cnt;
|
||||
size_t idx2cnt;
|
||||
size_t idx1now;
|
||||
size_t idx2now;
|
||||
size_t backw1_stop;
|
||||
size_t backw2_stop;
|
||||
size_t backw1;
|
||||
size_t backw2;
|
||||
int val1;
|
||||
int val2;
|
||||
int position;
|
||||
int seq1len;
|
||||
int seq2len;
|
||||
int use_malloc;
|
||||
|
||||
#include WEIGHT_H
|
||||
|
||||
if (nrules == 0)
|
||||
return STRCMP (s1, s2);
|
||||
|
||||
rulesets = (const unsigned char *)
|
||||
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
|
||||
table = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
|
||||
weights = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
|
||||
extra = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
|
||||
indirect = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
|
||||
use_malloc = 0;
|
||||
|
||||
assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
|
||||
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
|
||||
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
|
||||
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
|
||||
|
||||
/* We need this a few times. */
|
||||
s1len = STRLEN (s1);
|
||||
s2len = STRLEN (s2);
|
||||
|
||||
/* Catch empty strings. */
|
||||
if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
|
||||
return (s1len != 0) - (s2len != 0);
|
||||
|
||||
/* We need the elements of the strings as unsigned values since they
|
||||
are used as indeces. */
|
||||
us1 = (const USTRING_TYPE *) s1;
|
||||
us2 = (const USTRING_TYPE *) s2;
|
||||
|
||||
/* Perform the first pass over the string and while doing this find
|
||||
and store the weights for each character. Since we want this to
|
||||
be as fast as possible we are using `alloca' to store the temporary
|
||||
values. But since there is no limit on the length of the string
|
||||
we have to use `malloc' if the string is too long. We should be
|
||||
very conservative here.
|
||||
|
||||
Please note that the localedef programs makes sure that `position'
|
||||
is not used at the first level. */
|
||||
if (! __libc_use_alloca (s1len + s2len))
|
||||
{
|
||||
idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
|
||||
idx2arr = &idx1arr[s1len];
|
||||
rule1arr = (unsigned char *) &idx2arr[s2len];
|
||||
rule2arr = &rule1arr[s1len];
|
||||
|
||||
if (idx1arr == NULL)
|
||||
/* No memory. Well, go with the stack then.
|
||||
|
||||
XXX Once this implementation is stable we will handle this
|
||||
differently. Instead of precomputing the indeces we will
|
||||
do this in time. This means, though, that this happens for
|
||||
every pass again. */
|
||||
goto try_stack;
|
||||
use_malloc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try_stack:
|
||||
idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
|
||||
idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
|
||||
rule1arr = (unsigned char *) alloca (s1len);
|
||||
rule2arr = (unsigned char *) alloca (s2len);
|
||||
}
|
||||
|
||||
idx1cnt = 0;
|
||||
idx2cnt = 0;
|
||||
idx1max = 0;
|
||||
idx2max = 0;
|
||||
idx1now = 0;
|
||||
idx2now = 0;
|
||||
backw1_stop = ~0ul;
|
||||
backw2_stop = ~0ul;
|
||||
backw1 = ~0ul;
|
||||
backw2 = ~0ul;
|
||||
seq1len = 0;
|
||||
seq2len = 0;
|
||||
position = rulesets[0] & sort_position;
|
||||
while (1)
|
||||
{
|
||||
val1 = 0;
|
||||
val2 = 0;
|
||||
|
||||
/* Get the next non-IGNOREd element for string `s1'. */
|
||||
if (seq1len == 0)
|
||||
do
|
||||
{
|
||||
++val1;
|
||||
|
||||
if (backw1_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw1 == backw1_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx1cnt < idx1max)
|
||||
idx1now = idx1cnt;
|
||||
else
|
||||
/* Nothing anymore. The backward sequence ended with
|
||||
the last sequence in the string. Note that seq1len
|
||||
is still zero. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
idx1now = --backw1;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw1_stop = idx1max;
|
||||
|
||||
while (*us1 != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us1);
|
||||
rule1arr[idx1max] = tmp >> 24;
|
||||
idx1arr[idx1max] = tmp & 0xffffff;
|
||||
idx1cnt = idx1max++;
|
||||
|
||||
if ((rulesets[rule1arr[idx1cnt] * nrules]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx1cnt;
|
||||
}
|
||||
|
||||
if (backw1_stop >= idx1cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx1cnt == idx1max || backw1_stop > idx1cnt)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw1_stop = ~0ul;
|
||||
idx1now = idx1cnt;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx1now = backw1 = idx1cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
|
||||
|
||||
/* And the same for string `s2'. */
|
||||
if (seq2len == 0)
|
||||
do
|
||||
{
|
||||
++val2;
|
||||
|
||||
if (backw2_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw2 == backw2_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx2cnt < idx2max)
|
||||
idx2now = idx2cnt;
|
||||
else
|
||||
/* Nothing anymore. The backward sequence ended with
|
||||
the last sequence in the string. Note that seq2len
|
||||
is still zero. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
idx2now = --backw2;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw2_stop = idx2max;
|
||||
|
||||
while (*us2 != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us2);
|
||||
rule2arr[idx2max] = tmp >> 24;
|
||||
idx2arr[idx2max] = tmp & 0xffffff;
|
||||
idx2cnt = idx2max++;
|
||||
|
||||
if ((rulesets[rule2arr[idx2cnt] * nrules]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx2cnt;
|
||||
}
|
||||
|
||||
if (backw2_stop >= idx2cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx2cnt == idx2max || backw2_stop > idx2cnt)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw2_stop = ~0ul;
|
||||
idx2now = idx2cnt;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx2now = backw2 = idx2cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
|
||||
|
||||
/* See whether any or both strings are empty. */
|
||||
if (seq1len == 0 || seq2len == 0)
|
||||
{
|
||||
if (seq1len == seq2len)
|
||||
/* Both ended. So far so good, both strings are equal at the
|
||||
first level. */
|
||||
break;
|
||||
|
||||
/* This means one string is shorter than the other. Find out
|
||||
which one and return an appropriate value. */
|
||||
result = seq1len == 0 ? -1 : 1;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Test for position if necessary. */
|
||||
if (position && val1 != val2)
|
||||
{
|
||||
result = val1 - val2;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Compare the two sequences. */
|
||||
do
|
||||
{
|
||||
if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
|
||||
{
|
||||
/* The sequences differ. */
|
||||
result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Increment the offsets. */
|
||||
++idx1arr[idx1now];
|
||||
++idx2arr[idx2now];
|
||||
|
||||
--seq1len;
|
||||
--seq2len;
|
||||
}
|
||||
while (seq1len > 0 && seq2len > 0);
|
||||
|
||||
if (position && seq1len != seq2len)
|
||||
{
|
||||
result = seq1len - seq2len;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the remaining passes over the weights. We now use the
|
||||
indeces we found before. */
|
||||
for (pass = 1; pass < nrules; ++pass)
|
||||
{
|
||||
/* We assume that if a rule has defined `position' in one section
|
||||
this is true for all of them. */
|
||||
idx1cnt = 0;
|
||||
idx2cnt = 0;
|
||||
backw1_stop = ~0ul;
|
||||
backw2_stop = ~0ul;
|
||||
backw1 = ~0ul;
|
||||
backw2 = ~0ul;
|
||||
position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
|
||||
|
||||
while (1)
|
||||
{
|
||||
val1 = 0;
|
||||
val2 = 0;
|
||||
|
||||
/* Get the next non-IGNOREd element for string `s1'. */
|
||||
if (seq1len == 0)
|
||||
do
|
||||
{
|
||||
++val1;
|
||||
|
||||
if (backw1_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw1 == backw1_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx1cnt < idx1max)
|
||||
idx1now = idx1cnt;
|
||||
else
|
||||
{
|
||||
/* Nothing anymore. The backward sequence
|
||||
ended with the last sequence in the string. */
|
||||
idx1now = ~0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
idx1now = --backw1;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw1_stop = idx1cnt;
|
||||
|
||||
while (idx1cnt < idx1max)
|
||||
{
|
||||
if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx1cnt;
|
||||
}
|
||||
|
||||
if (backw1_stop == idx1cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx1cnt == idx1max)
|
||||
/* Note that seq1len is still zero. */
|
||||
break;
|
||||
|
||||
backw1_stop = ~0ul;
|
||||
idx1now = idx1cnt++;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx1now = backw1 = idx1cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
|
||||
|
||||
/* And the same for string `s2'. */
|
||||
if (seq2len == 0)
|
||||
do
|
||||
{
|
||||
++val2;
|
||||
|
||||
if (backw2_stop != ~0ul)
|
||||
{
|
||||
/* The is something pushed. */
|
||||
if (backw2 == backw2_stop)
|
||||
{
|
||||
/* The last pushed character was handled. Continue
|
||||
with forward characters. */
|
||||
if (idx2cnt < idx2max)
|
||||
idx2now = idx2cnt;
|
||||
else
|
||||
{
|
||||
/* Nothing anymore. The backward sequence
|
||||
ended with the last sequence in the string. */
|
||||
idx2now = ~0ul;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
idx2now = --backw2;
|
||||
}
|
||||
else
|
||||
{
|
||||
backw2_stop = idx2cnt;
|
||||
|
||||
while (idx2cnt < idx2max)
|
||||
{
|
||||
if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
|
||||
& sort_backward) == 0)
|
||||
/* No more backward characters to push. */
|
||||
break;
|
||||
++idx2cnt;
|
||||
}
|
||||
|
||||
if (backw2_stop == idx2cnt)
|
||||
{
|
||||
/* No sequence at all or just one. */
|
||||
if (idx2cnt == idx2max)
|
||||
/* Note that seq2len is still zero. */
|
||||
break;
|
||||
|
||||
backw2_stop = ~0ul;
|
||||
idx2now = idx2cnt++;
|
||||
}
|
||||
else
|
||||
/* We pushed backward sequences. */
|
||||
idx2now = backw2 = idx2cnt - 1;
|
||||
}
|
||||
}
|
||||
while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
|
||||
|
||||
/* See whether any or both strings are empty. */
|
||||
if (seq1len == 0 || seq2len == 0)
|
||||
{
|
||||
if (seq1len == seq2len)
|
||||
/* Both ended. So far so good, both strings are equal
|
||||
at this level. */
|
||||
break;
|
||||
|
||||
/* This means one string is shorter than the other. Find out
|
||||
which one and return an appropriate value. */
|
||||
result = seq1len == 0 ? -1 : 1;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Test for position if necessary. */
|
||||
if (position && val1 != val2)
|
||||
{
|
||||
result = val1 - val2;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Compare the two sequences. */
|
||||
do
|
||||
{
|
||||
if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
|
||||
{
|
||||
/* The sequences differ. */
|
||||
result = (weights[idx1arr[idx1now]]
|
||||
- weights[idx2arr[idx2now]]);
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Increment the offsets. */
|
||||
++idx1arr[idx1now];
|
||||
++idx2arr[idx2now];
|
||||
|
||||
--seq1len;
|
||||
--seq2len;
|
||||
}
|
||||
while (seq1len > 0 && seq2len > 0);
|
||||
|
||||
if (position && seq1len != seq2len)
|
||||
{
|
||||
result = seq1len - seq2len;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory if needed. */
|
||||
free_and_return:
|
||||
if (use_malloc)
|
||||
free (idx1arr);
|
||||
|
||||
return result;
|
||||
}
|
||||
libc_hidden_def (STRCOLL)
|
||||
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
weak_alias (__strcoll_l, strcoll_l)
|
||||
#endif
|
||||
|
442
string/strxfrm.c
442
string/strxfrm.c
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1995-1999,2000,2001,2002,2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-1999,2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
|
||||
@ -17,451 +17,17 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <locale/localeinfo.h>
|
||||
|
||||
#ifndef STRING_TYPE
|
||||
# define STRING_TYPE char
|
||||
# define USTRING_TYPE unsigned char
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRXFRM __strxfrm_l
|
||||
# else
|
||||
# define STRXFRM strxfrm
|
||||
# endif
|
||||
# define STRCMP strcmp
|
||||
# define STRLEN strlen
|
||||
# define STPNCPY __stpncpy
|
||||
# define WEIGHT_H "../locale/weight.h"
|
||||
# define SUFFIX MB
|
||||
# define L(arg) arg
|
||||
# define STRXFRM_L __strxfrm_l
|
||||
#endif
|
||||
|
||||
#define CONCAT(a,b) CONCAT1(a,b)
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
|
||||
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
|
||||
/* We need UTF-8 encoding of numbers. */
|
||||
static int
|
||||
utf8_encode (char *buf, int val)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (val < 0x80)
|
||||
{
|
||||
*buf++ = (char) val;
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int step;
|
||||
|
||||
for (step = 2; step < 6; ++step)
|
||||
if ((val & (~(uint32_t)0 << (5 * step + 1))) == 0)
|
||||
break;
|
||||
retval = step;
|
||||
|
||||
*buf = (unsigned char) (~0xff >> step);
|
||||
--step;
|
||||
do
|
||||
{
|
||||
buf[step] = 0x80 | (val & 0x3f);
|
||||
val >>= 6;
|
||||
}
|
||||
while (--step > 0);
|
||||
*buf |= val;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
size_t
|
||||
STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n)
|
||||
#else
|
||||
size_t
|
||||
STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
|
||||
#endif
|
||||
{
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
struct locale_data *current = l->__locales[LC_COLLATE];
|
||||
uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
|
||||
#else
|
||||
uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
|
||||
#endif
|
||||
/* We don't assign the following values right away since it might be
|
||||
unnecessary in case there are no rules. */
|
||||
const unsigned char *rulesets;
|
||||
const int32_t *table;
|
||||
const USTRING_TYPE *weights;
|
||||
const USTRING_TYPE *extra;
|
||||
const int32_t *indirect;
|
||||
uint_fast32_t pass;
|
||||
size_t needed;
|
||||
const USTRING_TYPE *usrc;
|
||||
size_t srclen = STRLEN (src);
|
||||
int32_t *idxarr;
|
||||
unsigned char *rulearr;
|
||||
size_t idxmax;
|
||||
size_t idxcnt;
|
||||
int use_malloc;
|
||||
|
||||
#include WEIGHT_H
|
||||
|
||||
if (nrules == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
STPNCPY (dest, src, MIN (srclen + 1, n));
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
rulesets = (const unsigned char *)
|
||||
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
|
||||
table = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
|
||||
weights = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
|
||||
extra = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
|
||||
indirect = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
|
||||
#else
|
||||
rulesets = (const unsigned char *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_RULESETS);
|
||||
table = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_TABLE,SUFFIX));
|
||||
weights = (const USTRING_TYPE *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_WEIGHT,SUFFIX));
|
||||
extra = (const USTRING_TYPE *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_EXTRA,SUFFIX));
|
||||
indirect = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, CONCAT(_NL_COLLATE_INDIRECT,SUFFIX));
|
||||
#endif
|
||||
use_malloc = 0;
|
||||
|
||||
assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
|
||||
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
|
||||
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
|
||||
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
|
||||
|
||||
/* Handle an empty string as a special case. */
|
||||
if (srclen == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
*dest = L('\0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need the elements of the string as unsigned values since they
|
||||
are used as indeces. */
|
||||
usrc = (const USTRING_TYPE *) src;
|
||||
|
||||
/* Perform the first pass over the string and while doing this find
|
||||
and store the weights for each character. Since we want this to
|
||||
be as fast as possible we are using `alloca' to store the temporary
|
||||
values. But since there is no limit on the length of the string
|
||||
we have to use `malloc' if the string is too long. We should be
|
||||
very conservative here. */
|
||||
if (! __libc_use_alloca (srclen))
|
||||
{
|
||||
idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1));
|
||||
rulearr = (unsigned char *) &idxarr[srclen];
|
||||
|
||||
if (idxarr == NULL)
|
||||
/* No memory. Well, go with the stack then.
|
||||
|
||||
XXX Once this implementation is stable we will handle this
|
||||
differently. Instead of precomputing the indeces we will
|
||||
do this in time. This means, though, that this happens for
|
||||
every pass again. */
|
||||
goto try_stack;
|
||||
use_malloc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try_stack:
|
||||
idxarr = (int32_t *) alloca (srclen * sizeof (int32_t));
|
||||
rulearr = (unsigned char *) alloca (srclen + 1);
|
||||
}
|
||||
|
||||
idxmax = 0;
|
||||
do
|
||||
{
|
||||
int32_t tmp = findidx (&usrc);
|
||||
rulearr[idxmax] = tmp >> 24;
|
||||
idxarr[idxmax] = tmp & 0xffffff;
|
||||
|
||||
++idxmax;
|
||||
}
|
||||
while (*usrc != L('\0'));
|
||||
|
||||
/* This element is only read, the value never used but to determine
|
||||
another value which then is ignored. */
|
||||
rulearr[idxmax] = '\0';
|
||||
|
||||
/* Now the passes over the weights. We now use the indeces we found
|
||||
before. */
|
||||
needed = 0;
|
||||
for (pass = 0; pass < nrules; ++pass)
|
||||
{
|
||||
size_t backw_stop = ~0ul;
|
||||
int rule = rulesets[rulearr[0] * nrules + pass];
|
||||
/* We assume that if a rule has defined `position' in one section
|
||||
this is true for all of them. */
|
||||
int position = rule & sort_position;
|
||||
|
||||
if (position == 0)
|
||||
{
|
||||
for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
|
||||
{
|
||||
if ((rule & sort_forward) != 0)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
for (backw = idxcnt - 1; backw >= backw_stop; --backw)
|
||||
{
|
||||
len = weights[idxarr[backw]++];
|
||||
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[backw]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[backw] += len;
|
||||
}
|
||||
}
|
||||
|
||||
backw_stop = ~0ul;
|
||||
}
|
||||
|
||||
/* Now handle the forward element. */
|
||||
len = weights[idxarr[idxcnt]++];
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[idxcnt]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[idxcnt] += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember where the backwards series started. */
|
||||
if (backw_stop == ~0ul)
|
||||
backw_stop = idxcnt;
|
||||
}
|
||||
|
||||
rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
|
||||
}
|
||||
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
backw = idxcnt;
|
||||
while (backw > backw_stop)
|
||||
{
|
||||
size_t len = weights[idxarr[--backw]++];
|
||||
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[backw]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[backw] += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int val = 1;
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
char buf[7];
|
||||
size_t buflen;
|
||||
#endif
|
||||
size_t i;
|
||||
|
||||
for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
|
||||
{
|
||||
if ((rule & sort_forward) != 0)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
for (backw = idxcnt - 1; backw >= backw_stop; --backw)
|
||||
{
|
||||
len = weights[idxarr[backw]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1 + len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[backw] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
++val;
|
||||
}
|
||||
|
||||
backw_stop = ~0ul;
|
||||
}
|
||||
|
||||
/* Now handle the forward element. */
|
||||
len = weights[idxarr[idxcnt]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1+ len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[idxcnt] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[idxcnt] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[idxcnt] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
/* Note that we don't have to increment `idxarr[idxcnt]'
|
||||
since the length is zero. */
|
||||
++val;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember where the backwards series started. */
|
||||
if (backw_stop == ~0ul)
|
||||
backw_stop = idxcnt;
|
||||
}
|
||||
|
||||
rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
|
||||
}
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
backw = idxmax - 1;
|
||||
while (backw > backw_stop)
|
||||
{
|
||||
size_t len = weights[idxarr[--backw]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1 + len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[backw] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
++val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally store the byte to separate the passes or terminate
|
||||
the string. */
|
||||
if (needed < n)
|
||||
dest[needed] = pass + 1 < nrules ? L('\1') : L('\0');
|
||||
++needed;
|
||||
}
|
||||
|
||||
/* This is a little optimization: many collation specifications have
|
||||
a `position' rule at the end and if no non-ignored character
|
||||
is found the last \1 byte is immediately followed by a \0 byte
|
||||
signalling this. We can avoid the \1 byte(s). */
|
||||
if (needed <= n && needed > 2 && dest[needed - 2] == L('\1'))
|
||||
{
|
||||
/* Remove the \1 byte. */
|
||||
--needed;
|
||||
dest[needed - 1] = L('\0');
|
||||
}
|
||||
|
||||
/* Free the memory if needed. */
|
||||
if (use_malloc)
|
||||
free (idxarr);
|
||||
|
||||
/* Return the number of bytes/words we need, but don't count the NUL
|
||||
byte/word at the end. */
|
||||
return needed - 1;
|
||||
return STRXFRM_L (dest, src, n, _NL_CURRENT_LOCALE);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1995,96,97,2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,96,97,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||
|
||||
@ -17,7 +17,430 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <strxfrm.c>
|
||||
#include <assert.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef STRING_TYPE
|
||||
# define STRING_TYPE char
|
||||
# define USTRING_TYPE unsigned char
|
||||
# define STRXFRM __strxfrm_l
|
||||
# define STRCMP strcmp
|
||||
# define STRLEN strlen
|
||||
# define STPNCPY __stpncpy
|
||||
# define WEIGHT_H "../locale/weight.h"
|
||||
# define SUFFIX MB
|
||||
# define L(arg) arg
|
||||
#endif
|
||||
|
||||
#define CONCAT(a,b) CONCAT1(a,b)
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
|
||||
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
|
||||
/* We need UTF-8 encoding of numbers. */
|
||||
static int
|
||||
utf8_encode (char *buf, int val)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (val < 0x80)
|
||||
{
|
||||
*buf++ = (char) val;
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int step;
|
||||
|
||||
for (step = 2; step < 6; ++step)
|
||||
if ((val & (~(uint32_t)0 << (5 * step + 1))) == 0)
|
||||
break;
|
||||
retval = step;
|
||||
|
||||
*buf = (unsigned char) (~0xff >> step);
|
||||
--step;
|
||||
do
|
||||
{
|
||||
buf[step] = 0x80 | (val & 0x3f);
|
||||
val >>= 6;
|
||||
}
|
||||
while (--step > 0);
|
||||
*buf |= val;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
size_t
|
||||
STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
|
||||
{
|
||||
struct locale_data *current = l->__locales[LC_COLLATE];
|
||||
uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
|
||||
/* We don't assign the following values right away since it might be
|
||||
unnecessary in case there are no rules. */
|
||||
const unsigned char *rulesets;
|
||||
const int32_t *table;
|
||||
const USTRING_TYPE *weights;
|
||||
const USTRING_TYPE *extra;
|
||||
const int32_t *indirect;
|
||||
uint_fast32_t pass;
|
||||
size_t needed;
|
||||
const USTRING_TYPE *usrc;
|
||||
size_t srclen = STRLEN (src);
|
||||
int32_t *idxarr;
|
||||
unsigned char *rulearr;
|
||||
size_t idxmax;
|
||||
size_t idxcnt;
|
||||
int use_malloc;
|
||||
|
||||
#include WEIGHT_H
|
||||
|
||||
if (nrules == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
STPNCPY (dest, src, MIN (srclen + 1, n));
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
rulesets = (const unsigned char *)
|
||||
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
|
||||
table = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
|
||||
weights = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
|
||||
extra = (const USTRING_TYPE *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
|
||||
indirect = (const int32_t *)
|
||||
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
|
||||
use_malloc = 0;
|
||||
|
||||
assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
|
||||
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
|
||||
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
|
||||
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
|
||||
|
||||
/* Handle an empty string as a special case. */
|
||||
if (srclen == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
*dest = L('\0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need the elements of the string as unsigned values since they
|
||||
are used as indeces. */
|
||||
usrc = (const USTRING_TYPE *) src;
|
||||
|
||||
/* Perform the first pass over the string and while doing this find
|
||||
and store the weights for each character. Since we want this to
|
||||
be as fast as possible we are using `alloca' to store the temporary
|
||||
values. But since there is no limit on the length of the string
|
||||
we have to use `malloc' if the string is too long. We should be
|
||||
very conservative here. */
|
||||
if (! __libc_use_alloca (srclen))
|
||||
{
|
||||
idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1));
|
||||
rulearr = (unsigned char *) &idxarr[srclen];
|
||||
|
||||
if (idxarr == NULL)
|
||||
/* No memory. Well, go with the stack then.
|
||||
|
||||
XXX Once this implementation is stable we will handle this
|
||||
differently. Instead of precomputing the indeces we will
|
||||
do this in time. This means, though, that this happens for
|
||||
every pass again. */
|
||||
goto try_stack;
|
||||
use_malloc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try_stack:
|
||||
idxarr = (int32_t *) alloca (srclen * sizeof (int32_t));
|
||||
rulearr = (unsigned char *) alloca (srclen + 1);
|
||||
}
|
||||
|
||||
idxmax = 0;
|
||||
do
|
||||
{
|
||||
int32_t tmp = findidx (&usrc);
|
||||
rulearr[idxmax] = tmp >> 24;
|
||||
idxarr[idxmax] = tmp & 0xffffff;
|
||||
|
||||
++idxmax;
|
||||
}
|
||||
while (*usrc != L('\0'));
|
||||
|
||||
/* This element is only read, the value never used but to determine
|
||||
another value which then is ignored. */
|
||||
rulearr[idxmax] = '\0';
|
||||
|
||||
/* Now the passes over the weights. We now use the indeces we found
|
||||
before. */
|
||||
needed = 0;
|
||||
for (pass = 0; pass < nrules; ++pass)
|
||||
{
|
||||
size_t backw_stop = ~0ul;
|
||||
int rule = rulesets[rulearr[0] * nrules + pass];
|
||||
/* We assume that if a rule has defined `position' in one section
|
||||
this is true for all of them. */
|
||||
int position = rule & sort_position;
|
||||
|
||||
if (position == 0)
|
||||
{
|
||||
for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
|
||||
{
|
||||
if ((rule & sort_forward) != 0)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
for (backw = idxcnt - 1; backw >= backw_stop; --backw)
|
||||
{
|
||||
len = weights[idxarr[backw]++];
|
||||
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[backw]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[backw] += len;
|
||||
}
|
||||
}
|
||||
|
||||
backw_stop = ~0ul;
|
||||
}
|
||||
|
||||
/* Now handle the forward element. */
|
||||
len = weights[idxarr[idxcnt]++];
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[idxcnt]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[idxcnt] += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember where the backwards series started. */
|
||||
if (backw_stop == ~0ul)
|
||||
backw_stop = idxcnt;
|
||||
}
|
||||
|
||||
rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
|
||||
}
|
||||
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
backw = idxcnt;
|
||||
while (backw > backw_stop)
|
||||
{
|
||||
size_t len = weights[idxarr[--backw]++];
|
||||
|
||||
if (needed + len < n)
|
||||
while (len-- > 0)
|
||||
dest[needed++] = weights[idxarr[backw]++];
|
||||
else
|
||||
{
|
||||
/* No more characters fit into the buffer. */
|
||||
needed += len;
|
||||
idxarr[backw] += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int val = 1;
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
char buf[7];
|
||||
size_t buflen;
|
||||
#endif
|
||||
size_t i;
|
||||
|
||||
for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
|
||||
{
|
||||
if ((rule & sort_forward) != 0)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
for (backw = idxcnt - 1; backw >= backw_stop; --backw)
|
||||
{
|
||||
len = weights[idxarr[backw]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1 + len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[backw] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
++val;
|
||||
}
|
||||
|
||||
backw_stop = ~0ul;
|
||||
}
|
||||
|
||||
/* Now handle the forward element. */
|
||||
len = weights[idxarr[idxcnt]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1+ len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[idxcnt] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[idxcnt] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[idxcnt] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
/* Note that we don't have to increment `idxarr[idxcnt]'
|
||||
since the length is zero. */
|
||||
++val;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember where the backwards series started. */
|
||||
if (backw_stop == ~0ul)
|
||||
backw_stop = idxcnt;
|
||||
}
|
||||
|
||||
rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
|
||||
}
|
||||
|
||||
if (backw_stop != ~0ul)
|
||||
{
|
||||
/* Handle the pushed elements now. */
|
||||
size_t backw;
|
||||
|
||||
backw = idxmax - 1;
|
||||
while (backw > backw_stop)
|
||||
{
|
||||
size_t len = weights[idxarr[--backw]++];
|
||||
if (len != 0)
|
||||
{
|
||||
#ifdef WIDE_CHAR_VERSION
|
||||
if (needed + 1 + len < n)
|
||||
{
|
||||
dest[needed] = val;
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + 1 + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += 1 + len;
|
||||
#else
|
||||
buflen = utf8_encode (buf, val);
|
||||
if (needed + buflen + len < n)
|
||||
{
|
||||
for (i = 0; i < buflen; ++i)
|
||||
dest[needed + i] = buf[i];
|
||||
for (i = 0; i < len; ++i)
|
||||
dest[needed + buflen + i] =
|
||||
weights[idxarr[backw] + i];
|
||||
}
|
||||
needed += buflen + len;
|
||||
#endif
|
||||
idxarr[backw] += len;
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
++val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally store the byte to separate the passes or terminate
|
||||
the string. */
|
||||
if (needed < n)
|
||||
dest[needed] = pass + 1 < nrules ? L('\1') : L('\0');
|
||||
++needed;
|
||||
}
|
||||
|
||||
/* This is a little optimization: many collation specifications have
|
||||
a `position' rule at the end and if no non-ignored character
|
||||
is found the last \1 byte is immediately followed by a \0 byte
|
||||
signalling this. We can avoid the \1 byte(s). */
|
||||
if (needed <= n && needed > 2 && dest[needed - 2] == L('\1'))
|
||||
{
|
||||
/* Remove the \1 byte. */
|
||||
--needed;
|
||||
dest[needed - 1] = L('\0');
|
||||
}
|
||||
|
||||
/* Free the memory if needed. */
|
||||
if (use_malloc)
|
||||
free (idxarr);
|
||||
|
||||
/* Return the number of bytes/words we need, but don't count the NUL
|
||||
byte/word at the end. */
|
||||
return needed - 1;
|
||||
}
|
||||
libc_hidden_def (STRXFRM)
|
||||
|
||||
#ifndef WIDE_CHAR_VERSION
|
||||
weak_alias (__strxfrm_l, strxfrm_l)
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representation of a number into an integer value.
|
||||
Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003
|
||||
Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003,2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@ -18,46 +18,10 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define USE_NUMBER_GROUPING
|
||||
# define STDC_HEADERS
|
||||
# define HAVE_LIMITS_H
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
#ifndef __set_errno
|
||||
# define __set_errno(Val) errno = (Val)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <locale.h>
|
||||
#else
|
||||
# ifndef NULL
|
||||
# define NULL 0
|
||||
# endif
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#include <locale/localeinfo.h>
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# include "../locale/localeinfo.h"
|
||||
#endif
|
||||
|
||||
/* Nonzero if we are defining `strtoul' or `strtoull', operating on
|
||||
unsigned integers. */
|
||||
#ifndef UNSIGNED
|
||||
# define UNSIGNED 0
|
||||
# define INT LONG int
|
||||
@ -65,508 +29,83 @@ extern int errno;
|
||||
# define INT unsigned LONG int
|
||||
#endif
|
||||
|
||||
/* Determine the name. */
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# if UNSIGNED
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol __wcstoull_l
|
||||
# else
|
||||
# define strtol __wcstoul_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol __strtoull_l
|
||||
# else
|
||||
# define strtol __strtoul_l
|
||||
# endif
|
||||
# endif
|
||||
# else
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol __wcstoll_l
|
||||
# else
|
||||
# define strtol __wcstol_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol __strtoll_l
|
||||
# else
|
||||
# define strtol __strtol_l
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#if UNSIGNED
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol wcstoull
|
||||
# define __strtol_l __wcstoull_l
|
||||
# else
|
||||
# define strtol wcstoul
|
||||
# define __strtol_l __wcstoul_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol strtoull
|
||||
# define __strtol_l __strtoull_l
|
||||
# else
|
||||
# define strtol strtoul
|
||||
# define __strtol_l __strtoul_l
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol wcstoll
|
||||
# define __strtol_l __wcstoll_l
|
||||
# else
|
||||
# define strtol wcstol
|
||||
# define __strtol_l __wcstol_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol strtoll
|
||||
# define __strtol_l __strtoll_l
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* If QUAD is defined, we are defining `strtoll' or `strtoull',
|
||||
operating on `long long int's. */
|
||||
#ifdef QUAD
|
||||
# define LONG long long
|
||||
# define STRTOL_LONG_MIN LONG_LONG_MIN
|
||||
# define STRTOL_LONG_MAX LONG_LONG_MAX
|
||||
# define STRTOL_ULONG_MAX ULONG_LONG_MAX
|
||||
# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
|
||||
/* Work around gcc bug with using this constant. */
|
||||
static const unsigned long long int maxquad = ULONG_LONG_MAX;
|
||||
# undef STRTOL_ULONG_MAX
|
||||
# define STRTOL_ULONG_MAX maxquad
|
||||
# endif
|
||||
#else
|
||||
# define LONG long
|
||||
|
||||
# ifndef ULONG_MAX
|
||||
# define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
|
||||
# endif
|
||||
# ifndef LONG_MAX
|
||||
# define LONG_MAX ((long int) (ULONG_MAX >> 1))
|
||||
# endif
|
||||
# define STRTOL_LONG_MIN LONG_MIN
|
||||
# define STRTOL_LONG_MAX LONG_MAX
|
||||
# define STRTOL_ULONG_MAX ULONG_MAX
|
||||
#endif
|
||||
|
||||
|
||||
/* We use this code also for the extended locale handling where the
|
||||
function gets as an additional argument the locale which has to be
|
||||
used. To access the values we have to redefine the _NL_CURRENT
|
||||
macro. */
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# undef _NL_CURRENT
|
||||
# define _NL_CURRENT(category, item) \
|
||||
(current->values[_NL_ITEM_INDEX (item)].string)
|
||||
# define LOCALE_PARAM , loc
|
||||
# define LOCALE_PARAM_DECL __locale_t loc;
|
||||
#else
|
||||
# define LOCALE_PARAM
|
||||
# define LOCALE_PARAM_DECL
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || defined HAVE_WCHAR_H
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# include <wctype.h>
|
||||
# define L_(Ch) L##Ch
|
||||
# define UCHAR_TYPE wint_t
|
||||
# define STRING_TYPE wchar_t
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
|
||||
# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
|
||||
# define TOUPPER(Ch) __towupper_l ((Ch), loc)
|
||||
#else
|
||||
# define ISSPACE(Ch) iswspace (Ch)
|
||||
# define ISALPHA(Ch) iswalpha (Ch)
|
||||
# define TOUPPER(Ch) towupper (Ch)
|
||||
# endif
|
||||
# else
|
||||
# if defined _LIBC \
|
||||
|| defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
# else
|
||||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
# endif
|
||||
# define L_(Ch) Ch
|
||||
# define UCHAR_TYPE unsigned char
|
||||
# define STRING_TYPE char
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define ISSPACE(Ch) __isspace_l ((Ch), loc)
|
||||
# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
|
||||
# define TOUPPER(Ch) __toupper_l ((Ch), loc)
|
||||
# else
|
||||
# define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
|
||||
# define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
|
||||
# define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
|
||||
#define INTERNAL(X) INTERNAL1(X)
|
||||
#define INTERNAL1(X) __##X##_internal
|
||||
# define WEAKNAME(X) WEAKNAME1(X)
|
||||
#else
|
||||
# define INTERNAL(X) __/**/X/**/_internal
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
/* This file defines a function to check for correct grouping. */
|
||||
# include "grouping.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern INT INTERNAL (__strtol_l) (const STRING_TYPE *, STRING_TYPE **, int,
|
||||
int, __locale_t);
|
||||
|
||||
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
|
||||
If BASE is 0 the base is determined by the presence of a leading
|
||||
zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
|
||||
If BASE is < 2 or > 36, it is reset to 10.
|
||||
If ENDPTR is not NULL, a pointer to the character after the last
|
||||
one converted is stored in *ENDPTR. */
|
||||
|
||||
INT
|
||||
INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
|
||||
INTERNAL (strtol) (nptr, endptr, base, group)
|
||||
const STRING_TYPE *nptr;
|
||||
STRING_TYPE **endptr;
|
||||
int base;
|
||||
int group;
|
||||
LOCALE_PARAM_DECL
|
||||
{
|
||||
int negative;
|
||||
register unsigned LONG int cutoff;
|
||||
register unsigned int cutlim;
|
||||
register unsigned LONG int i;
|
||||
register const STRING_TYPE *s;
|
||||
register UCHAR_TYPE c;
|
||||
const STRING_TYPE *save, *end;
|
||||
int overflow;
|
||||
#ifndef USE_WIDE_CHAR
|
||||
size_t cnt;
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
||||
# endif
|
||||
/* The thousands character of the current locale. */
|
||||
# ifdef USE_WIDE_CHAR
|
||||
wchar_t thousands = L'\0';
|
||||
# else
|
||||
const char *thousands = NULL;
|
||||
size_t thousands_len = 0;
|
||||
# endif
|
||||
/* The numeric grouping specification of the current locale,
|
||||
in the format described in <locale.h>. */
|
||||
const char *grouping;
|
||||
|
||||
if (__builtin_expect (group, 0))
|
||||
{
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping <= 0 || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
else
|
||||
{
|
||||
/* Figure out the thousands separator character. */
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef _LIBC
|
||||
thousands = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
# endif
|
||||
if (thousands == L'\0')
|
||||
grouping = NULL;
|
||||
# else
|
||||
# ifdef _LIBC
|
||||
thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
# endif
|
||||
if (*thousands == '\0')
|
||||
{
|
||||
thousands = NULL;
|
||||
grouping = NULL;
|
||||
return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
grouping = NULL;
|
||||
#endif
|
||||
|
||||
if (base < 0 || base == 1 || base > 36)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
save = s = nptr;
|
||||
|
||||
/* Skip white space. */
|
||||
while (ISSPACE (*s))
|
||||
++s;
|
||||
if (__builtin_expect (*s == L_('\0'), 0))
|
||||
goto noconv;
|
||||
|
||||
/* Check for a sign. */
|
||||
negative = 0;
|
||||
if (*s == L_('-'))
|
||||
{
|
||||
negative = 1;
|
||||
++s;
|
||||
}
|
||||
else if (*s == L_('+'))
|
||||
++s;
|
||||
|
||||
/* Recognize number prefix and if BASE is zero, figure it out ourselves. */
|
||||
if (*s == L_('0'))
|
||||
{
|
||||
if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
|
||||
{
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
else if (base == 0)
|
||||
base = 8;
|
||||
}
|
||||
else if (base == 0)
|
||||
base = 10;
|
||||
|
||||
/* Save the pointer so we can check later if anything happened. */
|
||||
save = s;
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
if (base != 10)
|
||||
grouping = NULL;
|
||||
|
||||
if (__builtin_expect (grouping != NULL, 0))
|
||||
{
|
||||
# ifndef USE_WIDE_CHAR
|
||||
thousands_len = strlen (thousands);
|
||||
# endif
|
||||
|
||||
/* Find the end of the digit string and check its grouping. */
|
||||
end = s;
|
||||
if (
|
||||
# ifdef USE_WIDE_CHAR
|
||||
*s != thousands
|
||||
# else
|
||||
({ for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != end[cnt])
|
||||
break;
|
||||
cnt < thousands_len; })
|
||||
# endif
|
||||
)
|
||||
{
|
||||
for (c = *end; c != L_('\0'); c = *++end)
|
||||
if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
|
||||
# ifdef USE_WIDE_CHAR
|
||||
&& (wchar_t) c != thousands
|
||||
# else
|
||||
&& ({ for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != end[cnt])
|
||||
break;
|
||||
cnt < thousands_len; })
|
||||
# endif
|
||||
&& (!ISALPHA (c)
|
||||
|| (int) (TOUPPER (c) - L_('A') + 10) >= base))
|
||||
break;
|
||||
|
||||
# ifdef USE_WIDE_CHAR
|
||||
end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
|
||||
# else
|
||||
end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
end = NULL;
|
||||
|
||||
cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
|
||||
cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
|
||||
|
||||
overflow = 0;
|
||||
i = 0;
|
||||
c = *s;
|
||||
if (sizeof (long int) != sizeof (LONG int))
|
||||
{
|
||||
unsigned long int j = 0;
|
||||
unsigned long int jmax = ULONG_MAX / base;
|
||||
|
||||
for (;c != L_('\0'); c = *++s)
|
||||
{
|
||||
if (s == end)
|
||||
break;
|
||||
if (c >= L_('0') && c <= L_('9'))
|
||||
c -= L_('0');
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# ifdef USE_WIDE_CHAR
|
||||
else if (grouping && (wchar_t) c == thousands)
|
||||
continue;
|
||||
# else
|
||||
else if (thousands_len)
|
||||
{
|
||||
for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != s[cnt])
|
||||
break;
|
||||
if (cnt == thousands_len)
|
||||
{
|
||||
s += thousands_len - 1;
|
||||
continue;
|
||||
}
|
||||
if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
else if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
if ((int) c >= base)
|
||||
break;
|
||||
/* Note that we never can have an overflow. */
|
||||
else if (j >= jmax)
|
||||
{
|
||||
/* We have an overflow. Now use the long representation. */
|
||||
i = (unsigned LONG int) j;
|
||||
goto use_long;
|
||||
}
|
||||
else
|
||||
j = j * (unsigned long int) base + c;
|
||||
}
|
||||
|
||||
i = (unsigned LONG int) j;
|
||||
}
|
||||
else
|
||||
for (;c != L_('\0'); c = *++s)
|
||||
{
|
||||
if (s == end)
|
||||
break;
|
||||
if (c >= L_('0') && c <= L_('9'))
|
||||
c -= L_('0');
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# ifdef USE_WIDE_CHAR
|
||||
else if (grouping && (wchar_t) c == thousands)
|
||||
continue;
|
||||
# else
|
||||
else if (thousands_len)
|
||||
{
|
||||
for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != s[cnt])
|
||||
break;
|
||||
if (cnt == thousands_len)
|
||||
{
|
||||
s += thousands_len - 1;
|
||||
continue;
|
||||
}
|
||||
if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
else if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
if ((int) c >= base)
|
||||
break;
|
||||
/* Check for overflow. */
|
||||
if (i > cutoff || (i == cutoff && c > cutlim))
|
||||
overflow = 1;
|
||||
else
|
||||
{
|
||||
use_long:
|
||||
i *= (unsigned LONG int) base;
|
||||
i += c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if anything actually happened. */
|
||||
if (s == save)
|
||||
goto noconv;
|
||||
|
||||
/* Store in ENDPTR the address of one character
|
||||
past the last character we converted. */
|
||||
if (endptr != NULL)
|
||||
*endptr = (STRING_TYPE *) s;
|
||||
|
||||
#if !UNSIGNED
|
||||
/* Check for a value that is within the range of
|
||||
`unsigned LONG int', but outside the range of `LONG int'. */
|
||||
if (overflow == 0
|
||||
&& i > (negative
|
||||
? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
|
||||
: (unsigned LONG int) STRTOL_LONG_MAX))
|
||||
overflow = 1;
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (overflow, 0))
|
||||
{
|
||||
__set_errno (ERANGE);
|
||||
#if UNSIGNED
|
||||
return STRTOL_ULONG_MAX;
|
||||
#else
|
||||
return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the result of the appropriate sign. */
|
||||
return negative ? -i : i;
|
||||
|
||||
noconv:
|
||||
/* We must handle a special case here: the base is 0 or 16 and the
|
||||
first two characters are '0' and 'x', but the rest are no
|
||||
hexadecimal digits. This is no error case. We return 0 and
|
||||
ENDPTR points to the `x`. */
|
||||
if (endptr != NULL)
|
||||
{
|
||||
if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
|
||||
&& save[-2] == L_('0'))
|
||||
*endptr = (STRING_TYPE *) &save[-1];
|
||||
else
|
||||
/* There was no number to convert. */
|
||||
*endptr = (STRING_TYPE *) nptr;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
#if defined _LIBC \
|
||||
&& !(defined USE_IN_EXTENDED_LOCALE_MODEL && defined USE_WIDE_CHAR)
|
||||
libc_hidden_def (INTERNAL (strtol))
|
||||
#endif
|
||||
|
||||
/* External user entry point. */
|
||||
|
||||
#if _LIBC - 0 == 0
|
||||
# undef PARAMS
|
||||
# if defined (__STDC__) && __STDC__
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
|
||||
/* Prototype. */
|
||||
INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
|
||||
#endif
|
||||
|
||||
|
||||
INT
|
||||
#ifdef weak_function
|
||||
weak_function
|
||||
#endif
|
||||
strtol (nptr, endptr, base LOCALE_PARAM)
|
||||
strtol (nptr, endptr, base)
|
||||
const STRING_TYPE *nptr;
|
||||
STRING_TYPE **endptr;
|
||||
int base;
|
||||
LOCALE_PARAM_DECL
|
||||
{
|
||||
return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
|
||||
return INTERNAL (__strtol_l) (nptr, endptr, base, 0, _NL_CURRENT_LOCALE);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,13 +18,496 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define USE_NUMBER_GROUPING
|
||||
# define STDC_HEADERS
|
||||
# define HAVE_LIMITS_H
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifndef __set_errno
|
||||
# define __set_errno(Val) errno = (Val)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
extern long int ____strtol_l_internal (const char *, char **, int, int,
|
||||
__locale_t);
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# include "../locale/localeinfo.h"
|
||||
#endif
|
||||
|
||||
#include "strtol.c"
|
||||
/* Nonzero if we are defining `strtoul' or `strtoull', operating on
|
||||
unsigned integers. */
|
||||
#ifndef UNSIGNED
|
||||
# define UNSIGNED 0
|
||||
# define INT LONG int
|
||||
#else
|
||||
# define INT unsigned LONG int
|
||||
#endif
|
||||
|
||||
/* Determine the name. */
|
||||
#if UNSIGNED
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol_l wcstoull_l
|
||||
# else
|
||||
# define strtol_l wcstoul_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol_l strtoull_l
|
||||
# else
|
||||
# define strtol_l strtoul_l
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef QUAD
|
||||
# define strtol_l wcstoll_l
|
||||
# else
|
||||
# define strtol_l wcstol_l
|
||||
# endif
|
||||
# else
|
||||
# ifdef QUAD
|
||||
# define strtol_l strtoll_l
|
||||
# else
|
||||
# define strtol_l strtol_l
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define __strtol_l __strtol_l2(strtol_l)
|
||||
#define __strtol_l2(name) __strtol_l3(name)
|
||||
#define __strtol_l3(name) __##name
|
||||
|
||||
|
||||
/* If QUAD is defined, we are defining `strtoll' or `strtoull',
|
||||
operating on `long long int's. */
|
||||
#ifdef QUAD
|
||||
# define LONG long long
|
||||
# define STRTOL_LONG_MIN LONG_LONG_MIN
|
||||
# define STRTOL_LONG_MAX LONG_LONG_MAX
|
||||
# define STRTOL_ULONG_MAX ULONG_LONG_MAX
|
||||
#else
|
||||
# define LONG long
|
||||
|
||||
# ifndef ULONG_MAX
|
||||
# define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
|
||||
# endif
|
||||
# ifndef LONG_MAX
|
||||
# define LONG_MAX ((long int) (ULONG_MAX >> 1))
|
||||
# endif
|
||||
# define STRTOL_LONG_MIN LONG_MIN
|
||||
# define STRTOL_LONG_MAX LONG_MAX
|
||||
# define STRTOL_ULONG_MAX ULONG_MAX
|
||||
#endif
|
||||
|
||||
|
||||
/* We use this code for the extended locale handling where the
|
||||
function gets as an additional argument the locale which has to be
|
||||
used. To access the values we have to redefine the _NL_CURRENT and
|
||||
_NL_CURRENT_WORD macros. */
|
||||
#undef _NL_CURRENT
|
||||
#define _NL_CURRENT(category, item) \
|
||||
(current->values[_NL_ITEM_INDEX (item)].string)
|
||||
#undef _NL_CURRENT_WORD
|
||||
#define _NL_CURRENT_WORD(category, item) \
|
||||
((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
|
||||
|
||||
#if defined _LIBC || defined HAVE_WCHAR_H
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# include <wctype.h>
|
||||
# define L_(Ch) L##Ch
|
||||
# define UCHAR_TYPE wint_t
|
||||
# define STRING_TYPE wchar_t
|
||||
# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
|
||||
# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
|
||||
# define TOUPPER(Ch) __towupper_l ((Ch), loc)
|
||||
#else
|
||||
# if defined _LIBC \
|
||||
|| defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
# else
|
||||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
# endif
|
||||
# define L_(Ch) Ch
|
||||
# define UCHAR_TYPE unsigned char
|
||||
# define STRING_TYPE char
|
||||
# define ISSPACE(Ch) __isspace_l ((Ch), loc)
|
||||
# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
|
||||
# define TOUPPER(Ch) __toupper_l ((Ch), loc)
|
||||
#endif
|
||||
|
||||
#define INTERNAL(X) INTERNAL1(X)
|
||||
#define INTERNAL1(X) __##X##_internal
|
||||
#define WEAKNAME(X) WEAKNAME1(X)
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
/* This file defines a function to check for correct grouping. */
|
||||
# include "grouping.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
|
||||
If BASE is 0 the base is determined by the presence of a leading
|
||||
zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
|
||||
If BASE is < 2 or > 36, it is reset to 10.
|
||||
If ENDPTR is not NULL, a pointer to the character after the last
|
||||
one converted is stored in *ENDPTR. */
|
||||
|
||||
INT
|
||||
INTERNAL (__strtol_l) (nptr, endptr, base, group, loc)
|
||||
const STRING_TYPE *nptr;
|
||||
STRING_TYPE **endptr;
|
||||
int base;
|
||||
int group;
|
||||
__locale_t loc;
|
||||
{
|
||||
int negative;
|
||||
register unsigned LONG int cutoff;
|
||||
register unsigned int cutlim;
|
||||
register unsigned LONG int i;
|
||||
register const STRING_TYPE *s;
|
||||
register UCHAR_TYPE c;
|
||||
const STRING_TYPE *save, *end;
|
||||
int overflow;
|
||||
#ifndef USE_WIDE_CHAR
|
||||
size_t cnt;
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
||||
/* The thousands character of the current locale. */
|
||||
# ifdef USE_WIDE_CHAR
|
||||
wchar_t thousands = L'\0';
|
||||
# else
|
||||
const char *thousands = NULL;
|
||||
size_t thousands_len = 0;
|
||||
# endif
|
||||
/* The numeric grouping specification of the current locale,
|
||||
in the format described in <locale.h>. */
|
||||
const char *grouping;
|
||||
|
||||
if (__builtin_expect (group, 0))
|
||||
{
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping <= 0 || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
else
|
||||
{
|
||||
/* Figure out the thousands separator character. */
|
||||
# ifdef USE_WIDE_CHAR
|
||||
# ifdef _LIBC
|
||||
thousands = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
# endif
|
||||
if (thousands == L'\0')
|
||||
grouping = NULL;
|
||||
# else
|
||||
# ifdef _LIBC
|
||||
thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
# endif
|
||||
if (*thousands == '\0')
|
||||
{
|
||||
thousands = NULL;
|
||||
grouping = NULL;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
grouping = NULL;
|
||||
#endif
|
||||
|
||||
if (base < 0 || base == 1 || base > 36)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
save = s = nptr;
|
||||
|
||||
/* Skip white space. */
|
||||
while (ISSPACE (*s))
|
||||
++s;
|
||||
if (__builtin_expect (*s == L_('\0'), 0))
|
||||
goto noconv;
|
||||
|
||||
/* Check for a sign. */
|
||||
negative = 0;
|
||||
if (*s == L_('-'))
|
||||
{
|
||||
negative = 1;
|
||||
++s;
|
||||
}
|
||||
else if (*s == L_('+'))
|
||||
++s;
|
||||
|
||||
/* Recognize number prefix and if BASE is zero, figure it out ourselves. */
|
||||
if (*s == L_('0'))
|
||||
{
|
||||
if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
|
||||
{
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
else if (base == 0)
|
||||
base = 8;
|
||||
}
|
||||
else if (base == 0)
|
||||
base = 10;
|
||||
|
||||
/* Save the pointer so we can check later if anything happened. */
|
||||
save = s;
|
||||
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
if (base != 10)
|
||||
grouping = NULL;
|
||||
|
||||
if (__builtin_expect (grouping != NULL, 0))
|
||||
{
|
||||
# ifndef USE_WIDE_CHAR
|
||||
thousands_len = strlen (thousands);
|
||||
# endif
|
||||
|
||||
/* Find the end of the digit string and check its grouping. */
|
||||
end = s;
|
||||
if (
|
||||
# ifdef USE_WIDE_CHAR
|
||||
*s != thousands
|
||||
# else
|
||||
({ for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != end[cnt])
|
||||
break;
|
||||
cnt < thousands_len; })
|
||||
# endif
|
||||
)
|
||||
{
|
||||
for (c = *end; c != L_('\0'); c = *++end)
|
||||
if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
|
||||
# ifdef USE_WIDE_CHAR
|
||||
&& (wchar_t) c != thousands
|
||||
# else
|
||||
&& ({ for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != end[cnt])
|
||||
break;
|
||||
cnt < thousands_len; })
|
||||
# endif
|
||||
&& (!ISALPHA (c)
|
||||
|| (int) (TOUPPER (c) - L_('A') + 10) >= base))
|
||||
break;
|
||||
|
||||
# ifdef USE_WIDE_CHAR
|
||||
end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
|
||||
# else
|
||||
end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
end = NULL;
|
||||
|
||||
cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
|
||||
cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
|
||||
|
||||
overflow = 0;
|
||||
i = 0;
|
||||
c = *s;
|
||||
if (sizeof (long int) != sizeof (LONG int))
|
||||
{
|
||||
unsigned long int j = 0;
|
||||
unsigned long int jmax = ULONG_MAX / base;
|
||||
|
||||
for (;c != L_('\0'); c = *++s)
|
||||
{
|
||||
if (s == end)
|
||||
break;
|
||||
if (c >= L_('0') && c <= L_('9'))
|
||||
c -= L_('0');
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# ifdef USE_WIDE_CHAR
|
||||
else if (grouping && (wchar_t) c == thousands)
|
||||
continue;
|
||||
# else
|
||||
else if (thousands_len)
|
||||
{
|
||||
for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != s[cnt])
|
||||
break;
|
||||
if (cnt == thousands_len)
|
||||
{
|
||||
s += thousands_len - 1;
|
||||
continue;
|
||||
}
|
||||
if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
else if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
if ((int) c >= base)
|
||||
break;
|
||||
/* Note that we never can have an overflow. */
|
||||
else if (j >= jmax)
|
||||
{
|
||||
/* We have an overflow. Now use the long representation. */
|
||||
i = (unsigned LONG int) j;
|
||||
goto use_long;
|
||||
}
|
||||
else
|
||||
j = j * (unsigned long int) base + c;
|
||||
}
|
||||
|
||||
i = (unsigned LONG int) j;
|
||||
}
|
||||
else
|
||||
for (;c != L_('\0'); c = *++s)
|
||||
{
|
||||
if (s == end)
|
||||
break;
|
||||
if (c >= L_('0') && c <= L_('9'))
|
||||
c -= L_('0');
|
||||
#ifdef USE_NUMBER_GROUPING
|
||||
# ifdef USE_WIDE_CHAR
|
||||
else if (grouping && (wchar_t) c == thousands)
|
||||
continue;
|
||||
# else
|
||||
else if (thousands_len)
|
||||
{
|
||||
for (cnt = 0; cnt < thousands_len; ++cnt)
|
||||
if (thousands[cnt] != s[cnt])
|
||||
break;
|
||||
if (cnt == thousands_len)
|
||||
{
|
||||
s += thousands_len - 1;
|
||||
continue;
|
||||
}
|
||||
if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
else if (ISALPHA (c))
|
||||
c = TOUPPER (c) - L_('A') + 10;
|
||||
else
|
||||
break;
|
||||
if ((int) c >= base)
|
||||
break;
|
||||
/* Check for overflow. */
|
||||
if (i > cutoff || (i == cutoff && c > cutlim))
|
||||
overflow = 1;
|
||||
else
|
||||
{
|
||||
use_long:
|
||||
i *= (unsigned LONG int) base;
|
||||
i += c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if anything actually happened. */
|
||||
if (s == save)
|
||||
goto noconv;
|
||||
|
||||
/* Store in ENDPTR the address of one character
|
||||
past the last character we converted. */
|
||||
if (endptr != NULL)
|
||||
*endptr = (STRING_TYPE *) s;
|
||||
|
||||
#if !UNSIGNED
|
||||
/* Check for a value that is within the range of
|
||||
`unsigned LONG int', but outside the range of `LONG int'. */
|
||||
if (overflow == 0
|
||||
&& i > (negative
|
||||
? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
|
||||
: (unsigned LONG int) STRTOL_LONG_MAX))
|
||||
overflow = 1;
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (overflow, 0))
|
||||
{
|
||||
__set_errno (ERANGE);
|
||||
#if UNSIGNED
|
||||
return STRTOL_ULONG_MAX;
|
||||
#else
|
||||
return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the result of the appropriate sign. */
|
||||
return negative ? -i : i;
|
||||
|
||||
noconv:
|
||||
/* We must handle a special case here: the base is 0 or 16 and the
|
||||
first two characters are '0' and 'x', but the rest are no
|
||||
hexadecimal digits. This is no error case. We return 0 and
|
||||
ENDPTR points to the `x`. */
|
||||
if (endptr != NULL)
|
||||
{
|
||||
if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
|
||||
&& save[-2] == L_('0'))
|
||||
*endptr = (STRING_TYPE *) &save[-1];
|
||||
else
|
||||
/* There was no number to convert. */
|
||||
*endptr = (STRING_TYPE *) nptr;
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
#if defined _LIBC && !defined USE_WIDE_CHAR
|
||||
libc_hidden_def (INTERNAL (__strtol_l))
|
||||
#endif
|
||||
|
||||
/* External user entry point. */
|
||||
|
||||
#if _LIBC - 0 == 0
|
||||
# undef PARAMS
|
||||
# if defined (__STDC__) && __STDC__
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
|
||||
/* Prototype. */
|
||||
extern INT __strtol_l PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
|
||||
int base));
|
||||
#endif
|
||||
|
||||
|
||||
INT
|
||||
#ifdef weak_function
|
||||
weak_function
|
||||
#endif
|
||||
__strtol_l (nptr, endptr, base, loc)
|
||||
const STRING_TYPE *nptr;
|
||||
STRING_TYPE **endptr;
|
||||
int base;
|
||||
__locale_t loc;
|
||||
{
|
||||
return INTERNAL (__strtol_l) (nptr, endptr, base, 0, loc);
|
||||
}
|
||||
weak_alias (__strtol_l, strtol_l)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1999, 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -18,17 +18,23 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
|
||||
extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
|
||||
|
||||
|
||||
/* There is no `long double' type, use the `double' implementations. */
|
||||
long double
|
||||
__strtold_internal (const char *nptr, char **endptr, int group)
|
||||
____strtold_l_internal (const char *nptr, char **endptr, int group,
|
||||
__locale_t loc)
|
||||
{
|
||||
return __strtod_internal (nptr, endptr, group);
|
||||
return ____strtod_l_internal (nptr, endptr, group, loc);
|
||||
}
|
||||
libc_hidden_def (__strtold_internal)
|
||||
|
||||
|
||||
long double
|
||||
strtold (const char *nptr, char **endptr)
|
||||
strtold (const char *nptr, char **endptr, __locale_t loc)
|
||||
{
|
||||
return __strtod_internal (nptr, endptr, 0);
|
||||
return ____strtod_l_internal (nptr, endptr, 0, loc);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,13 +18,11 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define QUAD 1
|
||||
|
||||
#include <xlocale.h>
|
||||
|
||||
extern long long int ____strtoll_l_internal (const char *, char **, int, int,
|
||||
__locale_t);
|
||||
|
||||
#include <strtoll.c>
|
||||
|
||||
weak_alias (__strtoll_l, strtoll_l)
|
||||
#include <strtol_l.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,13 +18,11 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define UNSIGNED 1
|
||||
|
||||
#include <xlocale.h>
|
||||
|
||||
extern unsigned long int ____strtoul_l_internal (const char *, char **, int,
|
||||
int, __locale_t);
|
||||
|
||||
#include "strtoul.c"
|
||||
|
||||
weak_alias (__strtoul_l, strtoul_l)
|
||||
#include "strtol_l.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,13 +18,12 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define QUAD 1
|
||||
#define UNSIGNED 1
|
||||
|
||||
#include <xlocale.h>
|
||||
|
||||
extern unsigned long long int ____strtoull_l_internal (const char *, char **,
|
||||
int, int, __locale_t);
|
||||
|
||||
#include <strtoull.c>
|
||||
|
||||
weak_alias (__strtoull_l, strtoull_l)
|
||||
#include <strtol_l.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -22,11 +22,9 @@
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define USE_WIDE_CHAR 1
|
||||
|
||||
extern long int ____wcstol_l_internal (const wchar_t *, wchar_t **, int, int,
|
||||
__locale_t);
|
||||
|
||||
#include "wcstol.c"
|
||||
|
||||
weak_alias (__wcstol_l, wcstol_l)
|
||||
#include "strtol_l.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -22,11 +22,9 @@
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define QUAD 1
|
||||
|
||||
extern long long int ____wcstoll_l_internal (const wchar_t *, wchar_t **,
|
||||
int, int, __locale_t);
|
||||
|
||||
#include <wcstoll.c>
|
||||
|
||||
weak_alias (__wcstoll_l, wcstoll_l)
|
||||
#include <wcstol_l.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -22,11 +22,9 @@
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define UNSIGNED 1
|
||||
|
||||
extern unsigned long int ____wcstoul_l_internal (const wchar_t *, wchar_t **,
|
||||
int, int, __locale_t);
|
||||
|
||||
#include <wcstoul.c>
|
||||
|
||||
weak_alias (__wcstoul_l, wcstoul_l)
|
||||
#include <wcstol_l.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -22,12 +22,10 @@
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#define UNSIGNED 1
|
||||
|
||||
extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
|
||||
wchar_t **, int, int,
|
||||
__locale_t);
|
||||
|
||||
#include <wcstoull.c>
|
||||
|
||||
weak_alias (__wcstoull_l, wcstoull_l)
|
||||
#include <wcstoll_l.c>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -23,10 +23,12 @@
|
||||
|
||||
#define FLOAT long double
|
||||
#define FLT LDBL
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRTOF __strtold_l
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# define STRTOF wcstold_l
|
||||
# define __STRTOF __wcstold_l
|
||||
#else
|
||||
# define STRTOF strtold
|
||||
# define STRTOF strtold_l
|
||||
# define __STRTOF __strtold_l
|
||||
#endif
|
||||
#define MPN2FLOAT __mpn_construct_long_double
|
||||
#define FLOAT_HUGE_VAL HUGE_VALL
|
||||
@ -40,4 +42,4 @@
|
||||
(flt) = u.d; \
|
||||
} while (0)
|
||||
|
||||
# include "strtod.c"
|
||||
#include <strtod_l.c>
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -23,10 +23,12 @@
|
||||
|
||||
#define FLOAT long double
|
||||
#define FLT LDBL
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRTOF __strtold_l
|
||||
#ifdef USE_WIDE_CHAR
|
||||
# define STRTOF wcstold_l
|
||||
# define __STRTOF __wcstold_l
|
||||
#else
|
||||
# define STRTOF strtold
|
||||
# define STRTOF strtold_l
|
||||
# define __STRTOF __strtold_l
|
||||
#endif
|
||||
#define MPN2FLOAT __mpn_construct_long_double
|
||||
#define FLOAT_HUGE_VAL HUGE_VALL
|
||||
@ -40,4 +42,4 @@
|
||||
(flt) = u.d; \
|
||||
} while (0)
|
||||
|
||||
# include "strtod.c"
|
||||
#include <strtod_l.c>
|
@ -1,2 +0,0 @@
|
||||
#define DENORM_EXP (MIN_EXP - 1)
|
||||
#include <sysdeps/ieee754/ldbl-96/strtold.c>
|
2
sysdeps/m68k/strtold_l.c
Normal file
2
sysdeps/m68k/strtold_l.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define DENORM_EXP (MIN_EXP - 1)
|
||||
#include <sysdeps/ieee754/ldbl-96/strtold_l.c>
|
1419
time/strftime.c
1419
time/strftime.c
File diff suppressed because it is too large
Load Diff
1426
time/strftime_l.c
1426
time/strftime_l.c
File diff suppressed because it is too large
Load Diff
1066
time/strptime.c
1066
time/strptime.c
File diff suppressed because it is too large
Load Diff
1052
time/strptime_l.c
1052
time/strptime_l.c
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,30 @@
|
||||
#include <wctype.h>
|
||||
/* Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <wchar.h>
|
||||
#define COMPILE_WIDE 1
|
||||
#include "strftime.c"
|
||||
#include <locale/localeinfo.h>
|
||||
|
||||
|
||||
size_t
|
||||
wcsftime (wchar_t *s, size_t maxsize, const wchar_t *format,
|
||||
const struct tm *tp)
|
||||
{
|
||||
return __wcsftime_l (s, maxsize, format, tp, _NL_CURRENT_LOCALE);
|
||||
}
|
||||
libc_hidden_def (wcsftime)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -16,7 +16,11 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <wcsftime.c>
|
||||
#define COMPILE_WIDE 1
|
||||
#include "strftime_l.c"
|
||||
|
||||
weak_alias (__wcsftime_l, wcsftime_l)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996,1997,1999,2000,2001,2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
@ -22,17 +22,8 @@
|
||||
|
||||
#define STRING_TYPE wchar_t
|
||||
#define USTRING_TYPE wint_t
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRCOLL __wcscoll_l
|
||||
#else
|
||||
#define STRCOLL __wcscoll
|
||||
#endif
|
||||
#define STRCMP wcscmp
|
||||
#define STRLEN __wcslen
|
||||
#define WEIGHT_H "../locale/weightwc.h"
|
||||
#define SUFFIX WC
|
||||
#define L(arg) L##arg
|
||||
#define WIDE_CHAR_VERSION 1
|
||||
#define STRCOLL_L __wcscoll_l
|
||||
|
||||
#include "../string/strcoll.c"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
|
||||
|
||||
@ -17,7 +17,20 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <wcscoll.c>
|
||||
|
||||
#include <wchar.h>
|
||||
#include "../locale/coll-lookup.h"
|
||||
|
||||
#define STRING_TYPE wchar_t
|
||||
#define USTRING_TYPE wint_t
|
||||
#define STRCOLL __wcscoll_l
|
||||
#define STRCMP wcscmp
|
||||
#define STRLEN __wcslen
|
||||
#define WEIGHT_H "../locale/weightwc.h"
|
||||
#define SUFFIX WC
|
||||
#define L(arg) L##arg
|
||||
#define WIDE_CHAR_VERSION 1
|
||||
|
||||
#include "../string/strcoll_l.c"
|
||||
|
||||
weak_alias (__wcscoll_l, wcscoll_l)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
|
||||
|
||||
@ -17,9 +17,13 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
/* The actual implementation for all floating point sizes is in strtod.c. */
|
||||
|
||||
#define USE_WIDE_CHAR 1
|
||||
|
||||
extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
|
||||
#include <stdlib/strtod.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,11 +18,9 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define __need_wchar_t
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
@ -30,6 +28,6 @@ extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
|
||||
wchar_t **, int, int,
|
||||
__locale_t);
|
||||
|
||||
#include <wcstod.c>
|
||||
#define USE_WIDE_CHAR 1
|
||||
|
||||
weak_alias (__wcstod_l, wcstod_l)
|
||||
#include <stdlib/strtod_l.c>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
|
||||
|
||||
@ -17,27 +17,12 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
/* The actual implementation for all floating point sizes is in strtod.c.
|
||||
These macros tell it to produce the `float' version, `wcstof'. */
|
||||
|
||||
#define FLOAT float
|
||||
#define FLT FLT
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRTOF __wcstof_l
|
||||
#else
|
||||
# define STRTOF wcstof
|
||||
#endif
|
||||
#define MPN2FLOAT __mpn_construct_float
|
||||
#define FLOAT_HUGE_VAL HUGE_VALF
|
||||
#define USE_WIDE_CHAR 1
|
||||
#define SET_MANTISSA(flt, mant) \
|
||||
do { union ieee754_float u; \
|
||||
u.f = (flt); \
|
||||
if ((mant & 0x7fffff) == 0) \
|
||||
mant = 0x400000; \
|
||||
u.ieee.mantissa = (mant) & 0x7fffff; \
|
||||
(flt) = u.f; \
|
||||
} while (0)
|
||||
|
||||
#include <stdlib/strtod.c>
|
||||
extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
|
||||
#include <stdlib/strtof.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997,98,2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,11 +18,11 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define __need_wchar_t
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
#define USE_WIDE_CHAR 1
|
||||
|
||||
extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
@ -30,6 +30,4 @@ extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
|
||||
wchar_t **, int, int,
|
||||
__locale_t);
|
||||
|
||||
#include <wcstof.c>
|
||||
|
||||
weak_alias (__wcstof_l, wcstof_l)
|
||||
#include <stdlib/strtof_l.c>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 1998, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
|
||||
|
||||
@ -17,46 +17,12 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <math.h>
|
||||
#include <wchar.h>
|
||||
#include <stddef.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#ifndef __NO_LONG_DOUBLE_MATH
|
||||
/* The actual implementation for all floating point sizes is in strtod.c.
|
||||
These macros tell it to produce the `long double' version, `wcstold'. */
|
||||
|
||||
# define FLOAT long double
|
||||
# define FLT LDBL
|
||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRTOF __wcstold_l
|
||||
# else
|
||||
# define STRTOF wcstold
|
||||
# endif
|
||||
# define MPN2FLOAT __mpn_construct_long_double
|
||||
# define FLOAT_HUGE_VAL HUGE_VALL
|
||||
#define USE_WIDE_CHAR 1
|
||||
# define SET_MANTISSA(flt, mant) \
|
||||
do { union ieee854_long_double u; \
|
||||
u.d = (flt); \
|
||||
if ((mant & 0x7fffffffffffffffULL) == 0) \
|
||||
mant = 0x4000000000000000ULL; \
|
||||
u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \
|
||||
u.ieee.mantissa1 = (mant) & 0xffffffff; \
|
||||
(flt) = u.d; \
|
||||
} while (0)
|
||||
|
||||
# include <stdlib/strtod.c>
|
||||
#else
|
||||
/* There is no `long double' type, use the `double' implementations. */
|
||||
long double
|
||||
__wcstold_internal (const wchar_t *nptr, wchar_t **endptr, int group)
|
||||
{
|
||||
return __wcstod_internal (nptr, endptr, group);
|
||||
}
|
||||
libc_hidden_def (__wcstold_internal)
|
||||
extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
|
||||
long double
|
||||
wcstold (const wchar_t *nptr, wchar_t **endptr)
|
||||
{
|
||||
return __wcstod_internal (nptr, endptr, 0);
|
||||
}
|
||||
#endif
|
||||
#include <stdlib/strtold.c>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Convert string representing a number to integer value, using given locale.
|
||||
Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,98,99,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@ -18,15 +18,10 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define __need_wchar_t
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
|
||||
#ifndef __NO_LONG_DOUBLE_MATH
|
||||
#define USE_WIDE_CHAR 1
|
||||
|
||||
extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
@ -34,23 +29,4 @@ extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
|
||||
wchar_t **, int, int,
|
||||
__locale_t);
|
||||
|
||||
# include <wcstold.c>
|
||||
#else
|
||||
/* There is no `long double' type, use the `double' implementations. */
|
||||
extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int,
|
||||
__locale_t);
|
||||
long double
|
||||
____wcstold_l_internal (const wchar_t *nptr, wchar_t **endptr, int group,
|
||||
__locale_t loc)
|
||||
{
|
||||
return ____wcstod_l_internal (nptr, endptr, group, loc);
|
||||
}
|
||||
|
||||
long double
|
||||
__wcstold_l (const wchar_t *nptr, wchar_t **endptr, __locale_t loc)
|
||||
{
|
||||
return ____wcstod_l_internal (nptr, endptr, 0, loc);
|
||||
}
|
||||
#endif
|
||||
|
||||
weak_alias (__wcstold_l, wcstold_l)
|
||||
#include <strtold_l.c>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2000, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
@ -21,18 +21,7 @@
|
||||
#include "../locale/coll-lookup.h"
|
||||
|
||||
#define STRING_TYPE wchar_t
|
||||
#define USTRING_TYPE wint_t
|
||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||
# define STRXFRM __wcsxfrm_l
|
||||
#else
|
||||
#define STRXFRM wcsxfrm
|
||||
#endif
|
||||
#define STRCMP wcscmp
|
||||
#define STRLEN __wcslen
|
||||
#define STPNCPY __wcpncpy
|
||||
#define WEIGHT_H "../locale/weightwc.h"
|
||||
#define SUFFIX WC
|
||||
#define L(arg) L##arg
|
||||
#define WIDE_CHAR_VERSION 1
|
||||
#define STRXFRM_L __wcsxfrm_l
|
||||
|
||||
#include "../string/strxfrm.c"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996,97,2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996,97,2002, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
|
||||
|
||||
@ -17,7 +17,20 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define USE_IN_EXTENDED_LOCALE_MODEL 1
|
||||
#include <wcsxfrm.c>
|
||||
#include <wchar.h>
|
||||
#include "../locale/coll-lookup.h"
|
||||
|
||||
#define STRING_TYPE wchar_t
|
||||
#define USTRING_TYPE wint_t
|
||||
#define STRXFRM __wcsxfrm_l
|
||||
#define STRCMP wcscmp
|
||||
#define STRLEN __wcslen
|
||||
#define STPNCPY __wcpncpy
|
||||
#define WEIGHT_H "../locale/weightwc.h"
|
||||
#define SUFFIX WC
|
||||
#define L(arg) L##arg
|
||||
#define WIDE_CHAR_VERSION 1
|
||||
|
||||
#include "../string/strxfrm_l.c"
|
||||
|
||||
weak_alias (__wcsxfrm_l, wcsxfrm_l)
|
||||
|
Loading…
Reference in New Issue
Block a user