Blame lib/nl_langinfo.c

Packit Service fdd496
/* nl_langinfo() replacement: query locale dependent information.
Packit Service fdd496
Packit Service fdd496
   Copyright (C) 2007-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#include <config.h>
Packit Service fdd496
Packit Service fdd496
/* Specification.  */
Packit Service fdd496
#include <langinfo.h>
Packit Service fdd496
Packit Service fdd496
#include <locale.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit Service fdd496
# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
Packit Service fdd496
# include <windows.h>
Packit Service fdd496
# include <stdio.h>
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Return the codeset of the current locale, if this is easily deducible.
Packit Service fdd496
   Otherwise, return "".  */
Packit Service fdd496
static char *
Packit Service fdd496
ctype_codeset (void)
Packit Service fdd496
{
Packit Service fdd496
  static char buf[2 + 10 + 1];
Packit Service fdd496
  char const *locale = setlocale (LC_CTYPE, NULL);
Packit Service fdd496
  char *codeset = buf;
Packit Service fdd496
  size_t codesetlen;
Packit Service fdd496
  codeset[0] = '\0';
Packit Service fdd496
Packit Service fdd496
  if (locale && locale[0])
Packit Service fdd496
    {
Packit Service fdd496
      /* If the locale name contains an encoding after the dot, return it.  */
Packit Service fdd496
      char *dot = strchr (locale, '.');
Packit Service fdd496
Packit Service fdd496
      if (dot)
Packit Service fdd496
        {
Packit Service fdd496
          /* Look for the possible @... trailer and remove it, if any.  */
Packit Service fdd496
          char *codeset_start = dot + 1;
Packit Service fdd496
          char const *modifier = strchr (codeset_start, '@');
Packit Service fdd496
Packit Service fdd496
          if (! modifier)
Packit Service fdd496
            codeset = codeset_start;
Packit Service fdd496
          else
Packit Service fdd496
            {
Packit Service fdd496
              codesetlen = modifier - codeset_start;
Packit Service fdd496
              if (codesetlen < sizeof buf)
Packit Service fdd496
                {
Packit Service fdd496
                  codeset = memcpy (buf, codeset_start, codesetlen);
Packit Service fdd496
                  codeset[codesetlen] = '\0';
Packit Service fdd496
                }
Packit Service fdd496
            }
Packit Service fdd496
        }
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
Packit Service fdd496
  /* If setlocale is successful, it returns the number of the
Packit Service fdd496
     codepage, as a string.  Otherwise, fall back on Windows API
Packit Service fdd496
     GetACP, which returns the locale's codepage as a number (although
Packit Service fdd496
     this doesn't change according to what the 'setlocale' call specified).
Packit Service fdd496
     Either way, prepend "CP" to make it a valid codeset name.  */
Packit Service fdd496
  codesetlen = strlen (codeset);
Packit Service fdd496
  if (0 < codesetlen && codesetlen < sizeof buf - 2)
Packit Service fdd496
    memmove (buf + 2, codeset, codesetlen + 1);
Packit Service fdd496
  else
Packit Service fdd496
    sprintf (buf + 2, "%u", GetACP ());
Packit Service fdd496
  codeset = memcpy (buf, "CP", 2);
Packit Service fdd496
#endif
Packit Service fdd496
  return codeset;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#if REPLACE_NL_LANGINFO
Packit Service fdd496
Packit Service fdd496
/* Override nl_langinfo with support for added nl_item values.  */
Packit Service fdd496
Packit Service fdd496
# undef nl_langinfo
Packit Service fdd496
Packit Service fdd496
char *
Packit Service fdd496
rpl_nl_langinfo (nl_item item)
Packit Service fdd496
{
Packit Service fdd496
  switch (item)
Packit Service fdd496
    {
Packit Service fdd496
# if GNULIB_defined_CODESET
Packit Service fdd496
    case CODESET:
Packit Service fdd496
      return ctype_codeset ();
Packit Service fdd496
# endif
Packit Service fdd496
# if GNULIB_defined_T_FMT_AMPM
Packit Service fdd496
    case T_FMT_AMPM:
Packit Service fdd496
      return (char *) "%I:%M:%S %p";
Packit Service fdd496
# endif
Packit Service fdd496
# if GNULIB_defined_ERA
Packit Service fdd496
    case ERA:
Packit Service fdd496
      /* The format is not standardized.  In glibc it is a sequence of strings
Packit Service fdd496
         of the form "direction:offset:start_date:end_date:era_name:era_format"
Packit Service fdd496
         with an empty string at the end.  */
Packit Service fdd496
      return (char *) "";
Packit Service fdd496
    case ERA_D_FMT:
Packit Service fdd496
      /* The %Ex conversion in strftime behaves like %x if the locale does not
Packit Service fdd496
         have an alternative time format.  */
Packit Service fdd496
      item = D_FMT;
Packit Service fdd496
      break;
Packit Service fdd496
    case ERA_D_T_FMT:
Packit Service fdd496
      /* The %Ec conversion in strftime behaves like %c if the locale does not
Packit Service fdd496
         have an alternative time format.  */
Packit Service fdd496
      item = D_T_FMT;
Packit Service fdd496
      break;
Packit Service fdd496
    case ERA_T_FMT:
Packit Service fdd496
      /* The %EX conversion in strftime behaves like %X if the locale does not
Packit Service fdd496
         have an alternative time format.  */
Packit Service fdd496
      item = T_FMT;
Packit Service fdd496
      break;
Packit Service fdd496
    case ALT_DIGITS:
Packit Service fdd496
      /* The format is not standardized.  In glibc it is a sequence of 10
Packit Service fdd496
         strings, appended in memory.  */
Packit Service fdd496
      return (char *) "\0\0\0\0\0\0\0\0\0\0";
Packit Service fdd496
# endif
Packit Service fdd496
# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS
Packit Service fdd496
    case YESEXPR:
Packit Service fdd496
      return (char *) "^[yY]";
Packit Service fdd496
    case NOEXPR:
Packit Service fdd496
      return (char *) "^[nN]";
Packit Service fdd496
# endif
Packit Service fdd496
    default:
Packit Service fdd496
      break;
Packit Service fdd496
    }
Packit Service fdd496
  return nl_langinfo (item);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#else
Packit Service fdd496
Packit Service fdd496
/* Provide nl_langinfo from scratch, either for native MS-Windows, or
Packit Service fdd496
   for old Unix platforms without locales, such as Linux libc5 or
Packit Service fdd496
   BeOS.  */
Packit Service fdd496
Packit Service fdd496
# include <time.h>
Packit Service fdd496
Packit Service fdd496
char *
Packit Service fdd496
nl_langinfo (nl_item item)
Packit Service fdd496
{
Packit Service fdd496
  static char nlbuf[100];
Packit Service fdd496
  struct tm tmm = { 0 };
Packit Service fdd496
Packit Service fdd496
  switch (item)
Packit Service fdd496
    {
Packit Service fdd496
    /* nl_langinfo items of the LC_CTYPE category */
Packit Service fdd496
    case CODESET:
Packit Service fdd496
      {
Packit Service fdd496
        char *codeset = ctype_codeset ();
Packit Service fdd496
        if (*codeset)
Packit Service fdd496
          return codeset;
Packit Service fdd496
      }
Packit Service fdd496
# ifdef __BEOS__
Packit Service fdd496
      return (char *) "UTF-8";
Packit Service fdd496
# else
Packit Service fdd496
      return (char *) "ISO-8859-1";
Packit Service fdd496
# endif
Packit Service fdd496
    /* nl_langinfo items of the LC_NUMERIC category */
Packit Service fdd496
    case RADIXCHAR:
Packit Service fdd496
      return localeconv () ->decimal_point;
Packit Service fdd496
    case THOUSEP:
Packit Service fdd496
      return localeconv () ->thousands_sep;
Packit Service fdd496
    case GROUPING:
Packit Service fdd496
      return localeconv () ->grouping;
Packit Service fdd496
    /* nl_langinfo items of the LC_TIME category.
Packit Service fdd496
       TODO: Really use the locale.  */
Packit Service fdd496
    case D_T_FMT:
Packit Service fdd496
    case ERA_D_T_FMT:
Packit Service fdd496
      return (char *) "%a %b %e %H:%M:%S %Y";
Packit Service fdd496
    case D_FMT:
Packit Service fdd496
    case ERA_D_FMT:
Packit Service fdd496
      return (char *) "%m/%d/%y";
Packit Service fdd496
    case T_FMT:
Packit Service fdd496
    case ERA_T_FMT:
Packit Service fdd496
      return (char *) "%H:%M:%S";
Packit Service fdd496
    case T_FMT_AMPM:
Packit Service fdd496
      return (char *) "%I:%M:%S %p";
Packit Service fdd496
    case AM_STR:
Packit Service fdd496
      if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm))
Packit Service fdd496
        return (char *) "AM";
Packit Service fdd496
      return nlbuf;
Packit Service fdd496
    case PM_STR:
Packit Service fdd496
      tmm.tm_hour = 12;
Packit Service fdd496
      if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm))
Packit Service fdd496
        return (char *) "PM";
Packit Service fdd496
      return nlbuf;
Packit Service fdd496
    case DAY_1:
Packit Service fdd496
    case DAY_2:
Packit Service fdd496
    case DAY_3:
Packit Service fdd496
    case DAY_4:
Packit Service fdd496
    case DAY_5:
Packit Service fdd496
    case DAY_6:
Packit Service fdd496
    case DAY_7:
Packit Service fdd496
      {
Packit Service fdd496
        static char const days[][sizeof "Wednesday"] = {
Packit Service fdd496
          "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
Packit Service fdd496
          "Friday", "Saturday"
Packit Service fdd496
        };
Packit Service fdd496
        tmm.tm_wday = item - DAY_1;
Packit Service fdd496
        if (!strftime (nlbuf, sizeof nlbuf, "%A", &tmm))
Packit Service fdd496
          return (char *) days[item - DAY_1];
Packit Service fdd496
        return nlbuf;
Packit Service fdd496
      }
Packit Service fdd496
    case ABDAY_1:
Packit Service fdd496
    case ABDAY_2:
Packit Service fdd496
    case ABDAY_3:
Packit Service fdd496
    case ABDAY_4:
Packit Service fdd496
    case ABDAY_5:
Packit Service fdd496
    case ABDAY_6:
Packit Service fdd496
    case ABDAY_7:
Packit Service fdd496
      {
Packit Service fdd496
        static char const abdays[][sizeof "Sun"] = {
Packit Service fdd496
          "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
Packit Service fdd496
        };
Packit Service fdd496
        tmm.tm_wday = item - ABDAY_1;
Packit Service fdd496
        if (!strftime (nlbuf, sizeof nlbuf, "%a", &tmm))
Packit Service fdd496
          return (char *) abdays[item - ABDAY_1];
Packit Service fdd496
        return nlbuf;
Packit Service fdd496
      }
Packit Service fdd496
    case MON_1:
Packit Service fdd496
    case MON_2:
Packit Service fdd496
    case MON_3:
Packit Service fdd496
    case MON_4:
Packit Service fdd496
    case MON_5:
Packit Service fdd496
    case MON_6:
Packit Service fdd496
    case MON_7:
Packit Service fdd496
    case MON_8:
Packit Service fdd496
    case MON_9:
Packit Service fdd496
    case MON_10:
Packit Service fdd496
    case MON_11:
Packit Service fdd496
    case MON_12:
Packit Service fdd496
      {
Packit Service fdd496
        static char const months[][sizeof "September"] = {
Packit Service fdd496
          "January", "February", "March", "April", "May", "June", "July",
Packit Service fdd496
          "September", "October", "November", "December"
Packit Service fdd496
        };
Packit Service fdd496
        tmm.tm_mon = item - MON_1;
Packit Service fdd496
        if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm))
Packit Service fdd496
          return (char *) months[item - MON_1];
Packit Service fdd496
        return nlbuf;
Packit Service fdd496
      }
Packit Service fdd496
    case ABMON_1:
Packit Service fdd496
    case ABMON_2:
Packit Service fdd496
    case ABMON_3:
Packit Service fdd496
    case ABMON_4:
Packit Service fdd496
    case ABMON_5:
Packit Service fdd496
    case ABMON_6:
Packit Service fdd496
    case ABMON_7:
Packit Service fdd496
    case ABMON_8:
Packit Service fdd496
    case ABMON_9:
Packit Service fdd496
    case ABMON_10:
Packit Service fdd496
    case ABMON_11:
Packit Service fdd496
    case ABMON_12:
Packit Service fdd496
      {
Packit Service fdd496
        static char const abmonths[][sizeof "Jan"] = {
Packit Service fdd496
          "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
Packit Service fdd496
          "Sep", "Oct", "Nov", "Dec"
Packit Service fdd496
        };
Packit Service fdd496
        tmm.tm_mon = item - ABMON_1;
Packit Service fdd496
        if (!strftime (nlbuf, sizeof nlbuf, "%b", &tmm))
Packit Service fdd496
          return (char *) abmonths[item - ABMON_1];
Packit Service fdd496
        return nlbuf;
Packit Service fdd496
      }
Packit Service fdd496
    case ERA:
Packit Service fdd496
      return (char *) "";
Packit Service fdd496
    case ALT_DIGITS:
Packit Service fdd496
      return (char *) "\0\0\0\0\0\0\0\0\0\0";
Packit Service fdd496
    /* nl_langinfo items of the LC_MONETARY category.  */
Packit Service fdd496
    case CRNCYSTR:
Packit Service fdd496
      return localeconv () ->currency_symbol;
Packit Service fdd496
    case INT_CURR_SYMBOL:
Packit Service fdd496
      return localeconv () ->int_curr_symbol;
Packit Service fdd496
    case MON_DECIMAL_POINT:
Packit Service fdd496
      return localeconv () ->mon_decimal_point;
Packit Service fdd496
    case MON_THOUSANDS_SEP:
Packit Service fdd496
      return localeconv () ->mon_thousands_sep;
Packit Service fdd496
    case MON_GROUPING:
Packit Service fdd496
      return localeconv () ->mon_grouping;
Packit Service fdd496
    case POSITIVE_SIGN:
Packit Service fdd496
      return localeconv () ->positive_sign;
Packit Service fdd496
    case NEGATIVE_SIGN:
Packit Service fdd496
      return localeconv () ->negative_sign;
Packit Service fdd496
    case FRAC_DIGITS:
Packit Service fdd496
      return & localeconv () ->frac_digits;
Packit Service fdd496
    case INT_FRAC_DIGITS:
Packit Service fdd496
      return & localeconv () ->int_frac_digits;
Packit Service fdd496
    case P_CS_PRECEDES:
Packit Service fdd496
      return & localeconv () ->p_cs_precedes;
Packit Service fdd496
    case N_CS_PRECEDES:
Packit Service fdd496
      return & localeconv () ->n_cs_precedes;
Packit Service fdd496
    case P_SEP_BY_SPACE:
Packit Service fdd496
      return & localeconv () ->p_sep_by_space;
Packit Service fdd496
    case N_SEP_BY_SPACE:
Packit Service fdd496
      return & localeconv () ->n_sep_by_space;
Packit Service fdd496
    case P_SIGN_POSN:
Packit Service fdd496
      return & localeconv () ->p_sign_posn;
Packit Service fdd496
    case N_SIGN_POSN:
Packit Service fdd496
      return & localeconv () ->n_sign_posn;
Packit Service fdd496
    /* nl_langinfo items of the LC_MESSAGES category
Packit Service fdd496
       TODO: Really use the locale. */
Packit Service fdd496
    case YESEXPR:
Packit Service fdd496
      return (char *) "^[yY]";
Packit Service fdd496
    case NOEXPR:
Packit Service fdd496
      return (char *) "^[nN]";
Packit Service fdd496
    default:
Packit Service fdd496
      return (char *) "";
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#endif