Blame gnulib/nl_langinfo.c

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