Blame lib/nl_langinfo.c

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