Blame lib/localeinfo.c

Packit 709fb3
/* locale information
Packit 709fb3
Packit 709fb3
   Copyright 2016-2017 Free Software Foundation, Inc.
Packit 709fb3
Packit 709fb3
   This program is free software; you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3, or (at your option)
Packit 709fb3
   any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program; if not, write to the Free Software
Packit 709fb3
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
Packit 709fb3
   02110-1301, USA.  */
Packit 709fb3
Packit 709fb3
/* Written by Paul Eggert.  */
Packit 709fb3
Packit 709fb3
#include <config.h>
Packit 709fb3
Packit 709fb3
#include <localeinfo.h>
Packit 709fb3
Packit 709fb3
#include <verify.h>
Packit 709fb3
Packit 709fb3
#include <limits.h>
Packit 709fb3
#include <locale.h>
Packit 709fb3
#include <stdlib.h>
Packit 709fb3
#include <string.h>
Packit 709fb3
#include <wctype.h>
Packit 709fb3
Packit 709fb3
/* The sbclen implementation relies on this.  */
Packit 709fb3
verify (MB_LEN_MAX <= SCHAR_MAX);
Packit 709fb3
Packit 709fb3
/* Return true if the locale uses UTF-8.  */
Packit 709fb3
Packit 709fb3
static bool
Packit 709fb3
is_using_utf8 (void)
Packit 709fb3
{
Packit 709fb3
  wchar_t wc;
Packit 709fb3
  mbstate_t mbs = {0};
Packit 709fb3
  return mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100;
Packit 709fb3
}
Packit 709fb3
Packit 709fb3
/* Initialize *LOCALEINFO from the current locale.  */
Packit 709fb3
Packit 709fb3
void
Packit 709fb3
init_localeinfo (struct localeinfo *localeinfo)
Packit 709fb3
{
Packit 709fb3
  int i;
Packit 709fb3
Packit 709fb3
  localeinfo->multibyte = MB_CUR_MAX > 1;
Packit 709fb3
  localeinfo->using_utf8 = is_using_utf8 ();
Packit 709fb3
Packit 709fb3
  for (i = CHAR_MIN; i <= CHAR_MAX; i++)
Packit 709fb3
    {
Packit 709fb3
      char c = i;
Packit 709fb3
      unsigned char uc = i;
Packit 709fb3
      mbstate_t s = {0};
Packit 709fb3
      wchar_t wc;
Packit 709fb3
      size_t len = mbrtowc (&wc, &c, 1, &s);
Packit 709fb3
      localeinfo->sbclen[uc] = len <= 1 ? 1 : - (int) - len;
Packit 709fb3
      localeinfo->sbctowc[uc] = len <= 1 ? wc : WEOF;
Packit 709fb3
    }
Packit 709fb3
}
Packit 709fb3
Packit 709fb3
/* The set of wchar_t values C such that there's a useful locale
Packit 709fb3
   somewhere where C != towupper (C) && C != towlower (towupper (C)).
Packit 709fb3
   For example, 0x00B5 (U+00B5 MICRO SIGN) is in this table, because
Packit 709fb3
   towupper (0x00B5) == 0x039C (U+039C GREEK CAPITAL LETTER MU), and
Packit 709fb3
   towlower (0x039C) == 0x03BC (U+03BC GREEK SMALL LETTER MU).  */
Packit 709fb3
static short const lonesome_lower[] =
Packit 709fb3
  {
Packit 709fb3
    0x00B5, 0x0131, 0x017F, 0x01C5, 0x01C8, 0x01CB, 0x01F2, 0x0345,
Packit 709fb3
    0x03C2, 0x03D0, 0x03D1, 0x03D5, 0x03D6, 0x03F0, 0x03F1,
Packit 709fb3
Packit 709fb3
    /* U+03F2 GREEK LUNATE SIGMA SYMBOL lacks a specific uppercase
Packit 709fb3
       counterpart in locales predating Unicode 4.0.0 (April 2003).  */
Packit 709fb3
    0x03F2,
Packit 709fb3
Packit 709fb3
    0x03F5, 0x1E9B, 0x1FBE,
Packit 709fb3
  };
Packit 709fb3
Packit 709fb3
/* Verify that the worst case fits.  This is 1 for towupper, 1 for
Packit 709fb3
   towlower, and 1 for each entry in LONESOME_LOWER.  */
Packit 709fb3
verify (1 + 1 + sizeof lonesome_lower / sizeof *lonesome_lower
Packit 709fb3
        <= CASE_FOLDED_BUFSIZE);
Packit 709fb3
Packit 709fb3
/* Find the characters equal to C after case-folding, other than C
Packit 709fb3
   itself, and store them into FOLDED.  Return the number of characters
Packit 709fb3
   stored; this is zero if C is WEOF.  */
Packit 709fb3
Packit 709fb3
int
Packit 709fb3
case_folded_counterparts (wint_t c, wchar_t folded[CASE_FOLDED_BUFSIZE])
Packit 709fb3
{
Packit 709fb3
  int i;
Packit 709fb3
  int n = 0;
Packit 709fb3
  wint_t uc = towupper (c);
Packit 709fb3
  wint_t lc = towlower (uc);
Packit 709fb3
  if (uc != c)
Packit 709fb3
    folded[n++] = uc;
Packit 709fb3
  if (lc != uc && lc != c && towupper (lc) == uc)
Packit 709fb3
    folded[n++] = lc;
Packit 709fb3
  for (i = 0; i < sizeof lonesome_lower / sizeof *lonesome_lower; i++)
Packit 709fb3
    {
Packit 709fb3
      wint_t li = lonesome_lower[i];
Packit 709fb3
      if (li != lc && li != uc && li != c && towupper (li) == uc)
Packit 709fb3
        folded[n++] = li;
Packit 709fb3
    }
Packit 709fb3
  return n;
Packit 709fb3
}