Blame support/localeinfo.c

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