Back to index

glibc  2.9
Defines | Functions | Variables
localedef.c File Reference
#include <argp.h>
#include <errno.h>
#include <fcntl.h>
#include <libintl.h>
#include <locale.h>
#include <mcheck.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <error.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "localedef.h"
#include "charmap.h"
#include "locfile.h"
#include <assert.h>

Go to the source code of this file.

Defines

#define OPT_POSIX   301
#define OPT_QUIET   302
#define OPT_OLDSTYLE   303
#define OPT_PREFIX   304
#define OPT_NO_ARCHIVE   305
#define OPT_ADD_TO_ARCHIVE   306
#define OPT_REPLACE   307
#define OPT_DELETE_FROM_ARCHIVE   308
#define OPT_LIST_ARCHIVE   309

Functions

static void print_version (FILE *stream, struct argp_state *state)
static error_t parse_opt (int key, char *arg, struct argp_state *state)
static char * more_help (int key, const char *text, void *input)
void * xmalloc (size_t __n)
static void error_print (void)
static const char * construct_output_path (char *path)
static const char * normalize_codeset (const char *codeset, size_t name_len)
int main (int argc, char *argv[])
static const char * normalize_codeset (char *codeset, size_t name_len) const
struct localedef_tadd_to_readlist (int category, const char *name, const char *repertoire_name, int generate, struct localedef_t *copy_locale)
struct localedef_tfind_locale (int category, const char *name, const char *repertoire_name, const struct charmap_t *charmap)
struct localedef_tload_locale (int category, const char *name, const char *repertoire_name, const struct charmap_t *charmap, struct localedef_t *copy_locale)
static void turn_on_mcheck (void)

Variables

struct copy_def_list_t * copy_list
int posix_conformance
int verbose
int be_quiet
int oldstyle_tables
static int force_output
const char * output_prefix
static const char * charmap_file
static const char * input_file
const char * repertoire_global
const char * alias_file
static struct localedef_tlocales
bool no_archive
static bool add_to_archive
static bool delete_from_archive
static bool replace_archive
static bool list_archive
int max_locarchive_open_retry = 10
void(* argp_program_version_hook )(FILE *, struct argp_state *) = print_version
static struct argp_option []
static const char doc [] = N_("Compile locale specification")
static const char args_doc []
static struct argp
void(* __malloc_initialize_hook )(void) = turn_on_mcheck

Define Documentation

#define OPT_ADD_TO_ARCHIVE   306

Definition at line 112 of file localedef.c.

#define OPT_DELETE_FROM_ARCHIVE   308

Definition at line 114 of file localedef.c.

#define OPT_LIST_ARCHIVE   309

Definition at line 115 of file localedef.c.

#define OPT_NO_ARCHIVE   305

Definition at line 111 of file localedef.c.

#define OPT_OLDSTYLE   303

Definition at line 109 of file localedef.c.

#define OPT_POSIX   301

Definition at line 107 of file localedef.c.

#define OPT_PREFIX   304

Definition at line 110 of file localedef.c.

#define OPT_QUIET   302

Definition at line 108 of file localedef.c.

#define OPT_REPLACE   307

Definition at line 113 of file localedef.c.


Function Documentation

struct localedef_t* add_to_readlist ( int  category,
const char *  name,
const char *  repertoire_name,
int  generate,
struct localedef_t copy_locale 
) [read]

Definition at line 534 of file localedef.c.

{
  struct localedef_t *runp = locales;

  while (runp != NULL && strcmp (name, runp->name) != 0)
    runp = runp->next;

  if (runp == NULL)
    {
      /* Add a new entry at the end.  */
      struct localedef_t *newp;

      assert (generate == 1);

      newp = xcalloc (1, sizeof (struct localedef_t));
      newp->name = name;
      newp->repertoire_name = repertoire_name;

      if (locales == NULL)
       runp = locales = newp;
      else
       {
         runp = locales;
         while (runp->next != NULL)
           runp = runp->next;
         runp = runp->next = newp;
       }
    }

  if (generate
      && (runp->needed & (1 << category)) != 0
      && (runp->avail & (1 << category)) == 0)
    WITH_CUR_LOCALE (error (5, 0, _("\
circular dependencies between locale definitions")));

  if (copy_locale != NULL)
    {
      if (runp->categories[category].generic != NULL)
       WITH_CUR_LOCALE (error (5, 0, _("\
cannot add already read locale `%s' a second time"), name));
      else
       runp->categories[category].generic =
         copy_locale->categories[category].generic;
    }

  runp->needed |= 1 << category;

  return runp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char * construct_output_path ( char *  path) [static]

Definition at line 408 of file localedef.c.

{
  const char *normal = NULL;
  char *result;
  char *endp;

  if (strchr (path, '/') == NULL)
    {
      /* This is a system path.  First examine whether the locale name
        contains a reference to the codeset.  This should be
        normalized.  */
      char *startp;
      size_t n;

      startp = path;
      /* We must be prepared for finding a CEN name or a location of
        the introducing `.' where it is not possible anymore.  */
      while (*startp != '\0' && *startp != '@' && *startp != '.')
       ++startp;
      if (*startp == '.')
       {
         /* We found a codeset specification.  Now find the end.  */
         endp = ++startp;
         while (*endp != '\0' && *endp != '@')
           ++endp;

         if (endp > startp)
           normal = normalize_codeset (startp, endp - startp);
       }
      else
       /* This is to keep gcc quiet.  */
       endp = NULL;

      /* We put an additional '\0' at the end of the string because at
        the end of the function we need another byte for the trailing
        '/'.  */
      if (normal == NULL)
       n = asprintf (&result, "%s%s/%s%c",
                    output_prefix ?: "", LOCALEDIR, path, '\0');
      else
       n = asprintf (&result, "%s%s/%.*s%s%s%c",
                    output_prefix ?: "", LOCALEDIR,
                    (int) (startp - path), path, normal, endp, '\0');

      if (n < 0)
       return NULL;

      endp = result + n - 1;
    }
  else
    {
      /* This is a user path.  Please note the additional byte in the
        memory allocation.  */
      size_t len = strlen (path) + 1;
      result = xmalloc (len + 1);
      endp = mempcpy (result, path, len) - 1;

      /* If the user specified an output path we cannot add the output
        to the archive.  */
      no_archive = true;
    }

  errno = 0;

  if (no_archive && euidaccess (result, W_OK) == -1)
    /* Perhaps the directory does not exist now.  Try to create it.  */
    if (errno == ENOENT)
      {
       errno = 0;
       if (mkdir (result, 0777) < 0)
         return NULL;
      }

  *endp++ = '/';
  *endp = '\0';

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void error_print ( void  ) [static]

Definition at line 399 of file localedef.c.

{
}

Here is the caller graph for this function:

struct localedef_t* find_locale ( int  category,
const char *  name,
const char *  repertoire_name,
const struct charmap_t charmap 
) [read]

Definition at line 587 of file localedef.c.

{
  struct localedef_t *result;

  /* Find the locale, but do not generate it since this would be a bug.  */
  result = add_to_readlist (category, name, repertoire_name, 0, NULL);

  assert (result != NULL);

  if ((result->avail & (1 << category)) == 0
      && locfile_read (result, charmap) != 0)
    WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), result->name));

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct localedef_t* load_locale ( int  category,
const char *  name,
const char *  repertoire_name,
const struct charmap_t charmap,
struct localedef_t copy_locale 
) [read]

Definition at line 607 of file localedef.c.

{
  struct localedef_t *result;

  /* Generate the locale if it does not exist.  */
  result = add_to_readlist (category, name, repertoire_name, 1, copy_locale);

  assert (result != NULL);

  if ((result->avail & (1 << category)) == 0
      && locfile_read (result, charmap) != 0)
    WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), result->name));

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char *  argv[] 
)

Definition at line 182 of file localedef.c.

{
  const char *output_path;
  int cannot_write_why;
  struct charmap_t *charmap;
  struct localedef_t global;
  int remaining;

  /* Set initial values for global variables.  */
  copy_list = NULL;
  posix_conformance = getenv ("POSIXLY_CORRECT") != NULL;
  error_print_progname = error_print;

  /* Set locale.  Do not set LC_ALL because the other categories must
     not be affected (according to POSIX.2).  */
  setlocale (LC_MESSAGES, "");
  setlocale (LC_CTYPE, "");

  /* Initialize the message catalog.  */
  textdomain (_libc_intl_domainname);

  /* Parse and process arguments.  */
  argp_err_exit_status = 4;
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);

  /* Handle a few special cases.  */
  if (list_archive)
    show_archive_content (verbose);
  if (add_to_archive)
    return add_locales_to_archive (argc - remaining, &argv[remaining],
                               replace_archive);
  if (delete_from_archive)
    return delete_locales_from_archive (argc - remaining, &argv[remaining]);

  /* POSIX.2 requires to be verbose about missing characters in the
     character map.  */
  verbose |= posix_conformance;

  if (argc - remaining != 1)
    {
      /* We need exactly one non-option parameter.  */
      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
               program_invocation_short_name);
      exit (4);
    }

  /* The parameter describes the output path of the constructed files.
     If the described files cannot be written return a NULL pointer.  */
  output_path  = construct_output_path (argv[remaining]);
  if (output_path == NULL && ! no_archive)
    error (4, errno, _("cannot create directory for output files"));
  cannot_write_why = errno;

  /* Now that the parameters are processed we have to reset the local
     ctype locale.  (P1003.2 4.35.5.2)  */
  setlocale (LC_CTYPE, "POSIX");

  /* Look whether the system really allows locale definitions.  POSIX
     defines error code 3 for this situation so I think it must be
     a fatal error (see P1003.2 4.35.8).  */
  if (sysconf (_SC_2_LOCALEDEF) < 0)
    WITH_CUR_LOCALE (error (3, 0, _("\
FATAL: system does not define `_POSIX2_LOCALEDEF'")));

  /* Process charmap file.  */
  charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);

  /* Add the first entry in the locale list.  */
  memset (&global, '\0', sizeof (struct localedef_t));
  global.name = input_file ?: "/dev/stdin";
  global.needed = ALL_LOCALES;
  locales = &global;

  /* Now read the locale file.  */
  if (locfile_read (&global, charmap) != 0)
    WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), input_file));

  /* Perhaps we saw some `copy' instructions.  */
  while (1)
    {
      struct localedef_t *runp = locales;

      while (runp != NULL && (runp->needed & runp->avail) == runp->needed)
       runp = runp->next;

      if (runp == NULL)
       /* Everything read.  */
       break;

      if (locfile_read (runp, charmap) != 0)
       WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), runp->name));
    }

  /* Check the categories we processed in source form.  */
  check_all_categories (locales, charmap);

  /* We are now able to write the data files.  If warning were given we
     do it only if it is explicitly requested (--force).  */
  if (error_message_count == 0 || force_output != 0)
    {
      if (cannot_write_why != 0)
       WITH_CUR_LOCALE (error (4, cannot_write_why, _("\
cannot write output files to `%s'"), output_path));
      else
       write_all_categories (locales, charmap, argv[remaining], output_path);
    }
  else
    WITH_CUR_LOCALE (error (4, 0, _("\
no output file produced because warnings were issued")));

  /* This exit status is prescribed by POSIX.2 4.35.7.  */
  exit (error_message_count != 0);
}

Here is the call graph for this function:

static char * more_help ( int  key,
const char *  text,
void *  input 
) [static]

Definition at line 358 of file localedef.c.

{
  char *cp;

  switch (key)
    {
    case ARGP_KEY_HELP_EXTRA:
      /* We print some extra information.  */
      if (asprintf (&cp, gettext ("\
System's directory for character maps : %s\n\
                       repertoire maps: %s\n\
                       locale path    : %s\n\
%s"),
                  CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, gettext ("\
For bug reporting instructions, please see:\n\
<http://www.gnu.org/software/libc/bugs.html>.\n")) < 0)
       return NULL;
      return cp;
    default:
      break;
    }
  return (char *) text;
}

Here is the call graph for this function:

static const char* normalize_codeset ( const char *  codeset,
size_t  name_len 
) [static]

Here is the caller graph for this function:

static const char* normalize_codeset ( char *  codeset,
size_t  name_len 
) const [static]

Definition at line 492 of file localedef.c.

{
  int len = 0;
  int only_digit = 1;
  char *retval;
  char *wp;
  size_t cnt;

  for (cnt = 0; cnt < name_len; ++cnt)
    if (isalnum (codeset[cnt]))
      {
       ++len;

       if (isalpha (codeset[cnt]))
         only_digit = 0;
      }

  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);

  if (retval != NULL)
    {
      if (only_digit)
       wp = stpcpy (retval, "iso");
      else
       wp = retval;

      for (cnt = 0; cnt < name_len; ++cnt)
       if (isalpha (codeset[cnt]))
         *wp++ = tolower (codeset[cnt]);
       else if (isdigit (codeset[cnt]))
         *wp++ = codeset[cnt];

      *wp = '\0';
    }

  return (const char *) retval;
}

Here is the call graph for this function:

static error_t parse_opt ( int  key,
char *  arg,
struct argp_state state 
) [static]

Definition at line 301 of file localedef.c.

{
  switch (key)
    {
    case OPT_QUIET:
      be_quiet = 1;
      break;
    case OPT_POSIX:
      posix_conformance = 1;
      break;
    case OPT_OLDSTYLE:
      oldstyle_tables = 1;
      break;
    case OPT_PREFIX:
      output_prefix = arg;
      break;
    case OPT_NO_ARCHIVE:
      no_archive = true;
      break;
    case OPT_ADD_TO_ARCHIVE:
      add_to_archive = true;
      break;
    case OPT_REPLACE:
      replace_archive = true;
      break;
    case OPT_DELETE_FROM_ARCHIVE:
      delete_from_archive = true;
      break;
    case OPT_LIST_ARCHIVE:
      list_archive = true;
      break;
    case 'c':
      force_output = 1;
      break;
    case 'f':
      charmap_file = arg;
      break;
    case 'A':
      alias_file = arg;
      break;
    case 'i':
      input_file = arg;
      break;
    case 'u':
      repertoire_global = arg;
      break;
    case 'v':
      verbose = 1;
      break;
    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}
static void print_version ( FILE stream,
struct argp_state state 
) [static]

Definition at line 384 of file localedef.c.

{
  fprintf (stream, "localedef (GNU %s) %s\n", PACKAGE, VERSION);
  fprintf (stream, gettext ("\
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions.  There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"), "2008");
  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}

Here is the call graph for this function:

static void turn_on_mcheck ( void  ) [static]

Definition at line 626 of file localedef.c.

{
  /* Enable `malloc' debugging.  */
  mcheck (NULL);
  /* Use the following line for a more thorough but much slower testing.  */
  /* mcheck_pedantic (NULL); */
}

Here is the call graph for this function:

void* xmalloc ( size_t  __n)

Definition at line 77 of file xmalloc.c.

{
  VOID *p;

  p = malloc (n);
  if (p == 0)
    p = fixup_null_alloc (n);
  return p;
}

Variable Documentation

Definition at line 634 of file localedef.c.

bool add_to_archive [static]

Definition at line 88 of file localedef.c.

Definition at line 79 of file localedef.c.

struct argp [static]
Initial value:

Definition at line 166 of file localedef.c.

struct argp_option[] [static]

Definition at line 118 of file localedef.c.

Definition at line 105 of file localedef.c.

const char args_doc[] [static]
Initial value:
 N_("\
NAME\n\
[--add-to-archive|--delete-from-archive] FILE...\n\
--list-archive [FILE]")

Definition at line 154 of file localedef.c.

Definition at line 57 of file localedef.c.

const char* charmap_file [static]

Definition at line 70 of file localedef.c.

struct copy_def_list_t* copy_list

Definition at line 48 of file localedef.c.

bool delete_from_archive [static]

Definition at line 91 of file localedef.c.

const char doc[] = N_("Compile locale specification") [static]

Definition at line 151 of file localedef.c.

int force_output [static]

Definition at line 64 of file localedef.c.

const char* input_file [static]

Definition at line 73 of file localedef.c.

bool list_archive [static]

Definition at line 97 of file localedef.c.

struct localedef_t* locales [static]

Definition at line 82 of file localedef.c.

Definition at line 100 of file localedef.c.

bool no_archive

Definition at line 85 of file localedef.c.

Definition at line 61 of file localedef.c.

Definition at line 67 of file localedef.c.

Definition at line 51 of file localedef.c.

Definition at line 76 of file localedef.c.

bool replace_archive [static]

Definition at line 94 of file localedef.c.

Definition at line 54 of file localedef.c.