[cfe-dev] [libc++] xlocale usage portability issues

Howard Hinnant hhinnant at apple.com
Mon Oct 10 08:07:02 PDT 2011


On Oct 10, 2011, at 9:25 AM, aep wrote:

> Hi, i'm trying to port libcxx to the musl libc [1]

Great!

> which does not offer 
> xlocale.h
> 
> Here are some concrete issues:
> 
> - strtol_l and friends do not exist. can we add a #ifdef _HAVE_XLOCALE 
> to use the standard functions where xlocale doesnt exist ?

Our experience to date is that the best way to deal with this issue is to emulate the *_l functions elsewhere.  The _WIN32 port does just this.

> - ctype_base uses the libc's macros for the character masks. I don't 
> think it has to do that at all, since it never passes the mask back to 
> the libc.

On OS X and FreeBSD libc++ uses the libc character mask table.

>   this appears to works for me, but i couldn't test it, as there are 
> other errors to fix first:

Is there a flag that can be used to identify your port instead of just putting it all under "#else"?  Your very first change:

> 
> 
> diff --git a/include/__locale b/include/__locale
> index 8aa8fc1..05cc9ac 100644
> --- a/include/__locale
> +++ b/include/__locale
> @@ -22,7 +22,7 @@
>  #if _WIN32
>  # include <support/win32/locale_win32.h>
>  #else  // _WIN32
> -# include <xlocale.h>
> +# include <locale.h>
>  #endif  // _WIN32

breaks OS X and FreeBSD.


> 
>  #pragma GCC system_header
> @@ -235,11 +235,11 @@ collate<_CharT>::do_hash(const char_type* lo, 
> const char_type* hi) const
>  {
>      size_t h = 0;
>      const size_t sr = __CHAR_BIT__ * sizeof(size_t) - 8;
> -    const size_t mask = size_t(0xF) << (sr + 4);
> +    const size_t cmask = size_t(0xF) << (sr + 4);
>      for(const char_type* p = lo; p != hi; ++p)
>      {
>          h = (h << 4) + *p;
> -        size_t g = h & mask;
> +        size_t g = h & cmask;
>          h ^= g | (g >> sr);
>      }
>      return static_cast<long>(h);

Why does mask need to be renamed to cmask?


> @@ -330,7 +330,7 @@ public:
>      static const mask punct  = _PUNCT;
>      static const mask xdigit = _HEX;
>      static const mask blank  = _BLANK;
> -#else  // __GLIBC__ || _WIN32
> +#elif (__APPLE__ || __FreeBSD__)
>  #if __APPLE__
>      typedef __uint32_t mask;
>  #elif __FreeBSD__
> @@ -346,7 +346,19 @@ public:
>      static const mask punct  = _CTYPE_P;
>      static const mask xdigit = _CTYPE_X;
>      static const mask blank  = _CTYPE_B;
> -#endif  // __GLIBC__ || _WIN32
> +#else  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__
> +    typedef unsigned long mask;
> +    static const mask space  = 1<<0;
> +    static const mask print  = 1<<1;
> +    static const mask cntrl  = 1<<2;
> +    static const mask upper  = 1<<3;
> +    static const mask lower  = 1<<4;
> +    static const mask alpha  = 1<<5;
> +    static const mask digit  = 1<<6;
> +    static const mask punct  = 1<<7;
> +    static const mask xdigit = 1<<8;
> +    static const mask blank  = 1<<9;
> +#endif  // __GLIBC__ || _WIN32 || __APPLE__ || __FreeBSD__
>      static const mask alnum  = alpha | digit;
>      static const mask graph  = alnum | punct;

This part looks ok, but we're getting enough platforms in here we should probably do away with the generic "else" branch (including for Apple and FreeBSD as you suggest above).

Thanks for working on this!

Howard




More information about the cfe-dev mailing list