Ejemplo n.º 1
0
char *
_setlocale_r (struct _reent *p,
       int category,
       const char *locale)
{
#ifndef _MB_CAPABLE
  if (locale)
    { 
      if (strcmp (locale, "POSIX") && strcmp (locale, "C")
	  && strcmp (locale, ""))
        return NULL;
    }
  return "C";
#else /* _MB_CAPABLE */
  static char new_categories[_LC_LAST][ENCODING_LEN + 1];
  static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
  int i, j, len, saverr;
  const char *env, *r;

  if (category < LC_ALL || category >= _LC_LAST)
    {
      p->_errno = EINVAL;
      return NULL;
    }

  if (locale == NULL)
    return category != LC_ALL ? __get_global_locale ()->categories[category]
			      : currentlocale();

  /*
   * Default to the current locale for everything.
   */
  for (i = 1; i < _LC_LAST; ++i)
    strcpy (new_categories[i], __get_global_locale ()->categories[i]);

  /*
   * Now go fill up new_categories from the locale argument
   */
  if (!*locale)
    {
      if (category == LC_ALL)
	{
	  for (i = 1; i < _LC_LAST; ++i)
	    {
	      env = __get_locale_env (p, i);
	      if (strlen (env) > ENCODING_LEN)
		{
		  p->_errno = EINVAL;
		  return NULL;
		}
	      strcpy (new_categories[i], env);
	    }
	}
      else
	{
	  env = __get_locale_env (p, category);
	  if (strlen (env) > ENCODING_LEN)
	    {
	      p->_errno = EINVAL;
	      return NULL;
	    }
	  strcpy (new_categories[category], env);
	}
    }
  else if (category != LC_ALL)
    {
      if (strlen (locale) > ENCODING_LEN)
	{
	  p->_errno = EINVAL;
	  return NULL;
	}
      strcpy (new_categories[category], locale);
    }
  else
    {
      if ((r = strchr (locale, '/')) == NULL)
	{
	  if (strlen (locale) > ENCODING_LEN)
	    {
	      p->_errno = EINVAL;
	      return NULL;
	    }
	  for (i = 1; i < _LC_LAST; ++i)
	    strcpy (new_categories[i], locale);
	}
      else
	{
	  for (i = 1; r[1] == '/'; ++r)
	    ;
	  if (!r[1])
	    {
	      p->_errno = EINVAL;
	      return NULL;  /* Hmm, just slashes... */
	    }
	  do
	    {
	      if (i == _LC_LAST)
		break;  /* Too many slashes... */
	      if ((len = r - locale) > ENCODING_LEN)
		{
		  p->_errno = EINVAL;
		  return NULL;
		}
	      strlcpy (new_categories[i], locale, len + 1);
	      i++;
	      while (*r == '/')
		r++;
	      locale = r;
	      while (*r && *r != '/')
		r++;
	    }
	  while (*locale);
	  while (i < _LC_LAST)
	    {
	      strcpy (new_categories[i], new_categories[i-1]);
	      i++;
	    }
	}
    }

  if (category != LC_ALL)
    return __loadlocale (__get_global_locale (), category,
			 new_categories[category]);

  for (i = 1; i < _LC_LAST; ++i)
    {
      strcpy (saved_categories[i], __get_global_locale ()->categories[i]);
      if (__loadlocale (__get_global_locale (), i, new_categories[i]) == NULL)
	{
	  saverr = p->_errno;
	  for (j = 1; j < i; j++)
	    {
	      strcpy (new_categories[j], saved_categories[j]);
	      if (__loadlocale (__get_global_locale (), j, new_categories[j])
		  == NULL)
		{
		  strcpy (new_categories[j], "C");
		  __loadlocale (__get_global_locale (), j, new_categories[j]);
		}
	    }
	  p->_errno = saverr;
	  return NULL;
	}
    }
  return currentlocale ();
#endif /* _MB_CAPABLE */
}
Ejemplo n.º 2
0
struct __locale_t *
_newlocale_r (struct _reent *p, int category_mask, const char *locale,
	      struct __locale_t *base)
{
#ifndef _MB_CAPABLE
  return __get_C_locale ();
#else /* _MB_CAPABLE */
  char new_categories[_LC_LAST][ENCODING_LEN + 1];
  struct __locale_t tmp_locale, *new_locale;
  int i;

  /* Convert LC_ALL_MASK to a mask containing all valid MASK values.
     This simplifies the code below. */
  if (category_mask & LC_ALL_MASK)
    {
      category_mask &= ~LC_ALL_MASK;
      category_mask |= LC_VALID_MASK;
    }
  /* Check for invalid mask values and valid locale ptr. */
  if ((category_mask & ~LC_VALID_MASK) || !locale)
    {
      p->_errno = EINVAL;
      return NULL;
    }
  /* If the new locale is supposed to be all default locale, just return
     a pointer to the default locale. */
  if ((!base && category_mask == 0)
      || (category_mask == LC_VALID_MASK
	  && (!strcmp (locale, "C") || !strcmp (locale, "POSIX"))))
    return __get_C_locale ();
  /* Start with setting all values to the default locale values. */
  tmp_locale = *__get_C_locale ();
  /* Fill out new category strings. */
  for (i = 1; i < _LC_LAST; ++i)
    {
      if (((1 << i) & category_mask) != 0)
	{
	  /* If locale is "", fetch from environment.  Otherwise use locale
	     name verbatim. */
	  const char *cat = (locale[0] == '\0') ? __get_locale_env (p, i)
						: locale;
	  if (strlen (cat) > ENCODING_LEN)
	    {
	      p->_errno = EINVAL;
	      return NULL;
	    }
	  strcpy (new_categories[i], cat);
	}
      else
	strcpy (new_categories[i], base ? base->categories[i] : "C");
    }
  /* Now go over all categories and set them. */
  for (i = 1; i < _LC_LAST; ++i)
    {
      /* If we have a base locale, and the category is not in category_mask
	 or the new category is the base categroy, just copy over. */
      if (base && (((1 << i) & category_mask) == 0
		   || !strcmp (base->categories[i], new_categories[i])))
	{
	  strcpy (tmp_locale.categories[i], new_categories[i]);
	  if (i == LC_CTYPE)
	    {
	      tmp_locale.wctomb = base->wctomb;
	      tmp_locale.mbtowc = base->mbtowc;
	      tmp_locale.cjk_lang = base->cjk_lang;
	      tmp_locale.ctype_ptr = base->ctype_ptr;
	    }
#ifdef __HAVE_LOCALE_INFO__
	  /* Mark the values as "has still to be copied".  We do this in
	     two steps to simplify freeing new locale types in case of a
	     subsequent error. */
	  tmp_locale.lc_cat[i].ptr = base->lc_cat[i].ptr;
	  tmp_locale.lc_cat[i].buf = (void *) -1;
#else /* !__HAVE_LOCALE_INFO__ */
	  if (i == LC_CTYPE)
	    strcpy (tmp_locale.ctype_codeset, base->ctype_codeset);
	  else if (i == LC_MESSAGES)
	    strcpy (tmp_locale.message_codeset, base->message_codeset);
#endif /* !__HAVE_LOCALE_INFO__ */
	}
      /* Otherwise, if the category is in category_mask, create entry. */
      else if (((1 << i) & category_mask) != 0)
	{
	  /* Nothing to do for "C"/"POSIX" locale. */
	  if (!strcmp (new_categories[i], "C")
	      || !strcmp (new_categories[i], "POSIX"))
	    continue;
	  /* Otherwise load locale data. */
	  else if (!__loadlocale (&tmp_locale, i, new_categories[i]))
	    goto error;
	}
    }
  /* Allocate new locale_t. */
  new_locale = (struct __locale_t *) _calloc_r (p, 1, sizeof *new_locale);
  if (!new_locale)
    goto error;
  if (base)
    {
#ifdef __HAVE_LOCALE_INFO__
      /* Step 2 of copying over..  Make sure to invalidate the copied buffer
	 pointers in base, so the subsequent _freelocale_r (base) doesn't free
	 the buffers now used in the new locale. */
      for (i = 1; i < _LC_LAST; ++i)
	if (tmp_locale.lc_cat[i].buf == (const void *) -1)
	  {
	    tmp_locale.lc_cat[i].buf = base->lc_cat[i].buf;
	    base->lc_cat[i].ptr = base->lc_cat[i].buf = NULL;
	  }
#endif /* __HAVE_LOCALE_INFO__ */
      _freelocale_r (p, base);
    }

  *new_locale = tmp_locale;
  return new_locale;

error:
  /* An error occured while we had already (potentially) allocated memory.
     Free memory and return NULL.  errno is supposed to be set already. */
#ifdef __HAVE_LOCALE_INFO__
  for (i = 1; i < _LC_LAST; ++i)
    if (((1 << i) & category_mask) != 0
	&& tmp_locale.lc_cat[i].buf
	&& tmp_locale.lc_cat[i].buf != (const void *) -1)
      {
	_free_r (p, (void *) tmp_locale.lc_cat[i].ptr);
	_free_r (p, tmp_locale.lc_cat[i].buf);
      }
#endif /* __HAVE_LOCALE_INFO__ */

  return NULL;
#endif /* _MB_CAPABLE */
}
Ejemplo n.º 3
0
#define NSTRINGS \
	(offsetof(_MonetaryLocale, int_frac_digits)/sizeof(const char **))
#define NCHARS \
	(offsetof(_MonetaryLocale, int_n_sign_posn) - \
	 offsetof(_MonetaryLocale, int_frac_digits) + 1)

static int
_localeio_LC_MONETARY_create_impl(const char * __restrict root,
    const char * __restrict name, _MonetaryLocale ** __restrict pdata)
{
	char path[PATH_MAX + 1];
	int ret;

        _DIAGASSERT(root != NULL);
        _DIAGASSERT(name != NULL);
        _DIAGASSERT(pdata != NULL);

	snprintf(path, sizeof(path),
            "%s/%s/LC_MONETARY", root, name);
	ret = __loadlocale(path, NSTRINGS, NCHARS, sizeof(_MonetaryLocale),
	    (void *)pdata);
	if (!ret) {
		(*pdata)->mon_grouping =
		   __fix_locale_grouping_str((*pdata)->mon_grouping);
	}
	return ret;
}

#include "nb_lc_template.h"
_LOCALE_CATEGORY_ENTRY(_localeio_LC_MONETARY_);