l10nflist.c revision a04eba3f8868af1d9b7b504d3d430c55ed3dc777
1a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
25bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
35bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   This program is free software; you can redistribute it and/or modify it
5a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   under the terms of the GNU Library General Public License as published
6a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   by the Free Software Foundation; either version 2, or (at your option)
75bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   any later version.
85bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
95bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   This program is distributed in the hope that it will be useful,
105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   but WITHOUT ANY WARRANTY; without even the implied warranty of
11a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   Library General Public License for more details.
13a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
14a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   You should have received a copy of the GNU Library General Public
15a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   License along with this program; if not, write to the Free Software
16a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   USA.  */
18a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
19a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Tell glibc's <string.h> to provide a prototype for stpcpy().
20a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   This must come before <config.h> because <config.h> may include
21a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   <features.h>, and once <features.h> has been included, it's too late.  */
22a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifndef _GNU_SOURCE
23a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define _GNU_SOURCE	1
24a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif
255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_CONFIG_H
275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <config.h>
285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
30a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <string.h>
315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if defined _LIBC || defined HAVE_ARGZ_H
335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <argz.h>
345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <ctype.h>
365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <sys/types.h>
37a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <stdlib.h>
385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include "loadinfo.h"
405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* On some strange systems still no definition of NULL is found.  Sigh!  */
425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifndef NULL
435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# if defined __STDC__ && __STDC__
445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define NULL ((void *) 0)
455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# else
465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define NULL 0
475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif
485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ end of prolog @@ */
515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Rename the non ANSI C functions.  This is required by the standard
545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   because some ANSI C functions will require linking with this object
555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   file and the name space must not be polluted.  */
565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# ifndef stpcpy
575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define stpcpy(dest, src) __stpcpy(dest, src)
585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif
595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# ifndef HAVE_STPCPY
615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic char *stpcpy PARAMS ((char *dest, const char *src));
625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif
635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
65a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Pathname support.
66a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   ISSLASH(C)           tests whether C is a directory separator character.
67a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
68a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o                        it may be concatenated to a directory pathname.
69a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o */
70a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
71a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* Win32, OS/2, DOS */
72a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define ISSLASH(C) ((C) == '/' || (C) == '\\')
73a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define HAS_DEVICE(P) \
74a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
75a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     && (P)[1] == ':')
76a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
77a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#else
78a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* Unix */
79a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define ISSLASH(C) ((C) == '/')
80a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
81a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif
82a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Define function which are usually not available.  */
845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Returns the number of strings in ARGZ.  */
875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic size_t argz_count__ PARAMS ((const char *argz, size_t len));
885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic size_t
905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oargz_count__ (argz, len)
915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *argz;
925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     size_t len;
935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  size_t count = 0;
955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  while (len > 0)
965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      size_t part_len = strlen (argz);
985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      argz += part_len + 1;
995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      len -= part_len + 1;
1005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      count++;
1015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return count;
1035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# undef __argz_count
1055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define __argz_count(argz, len) argz_count__ (argz, len)
106a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#else
107a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# ifdef _LIBC
108a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#  define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
109a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# endif
1105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif	/* !_LIBC && !HAVE___ARGZ_COUNT */
1115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
1135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
1145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   except the last into the character SEP.  */
1155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
1165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1175bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic void
1185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oargz_stringify__ (argz, len, sep)
1195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     char *argz;
1205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     size_t len;
1215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     int sep;
1225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
1235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  while (len > 0)
1245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      size_t part_len = strlen (argz);
1265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      argz += part_len;
1275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      len -= part_len + 1;
1285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (len > 0)
1295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	*argz++ = sep;
1305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# undef __argz_stringify
1335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
134a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#else
135a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# ifdef _LIBC
136a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#  define __argz_stringify(argz, len, sep) \
137a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  INTUSE(__argz_stringify) (argz, len, sep)
138a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# endif
1395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif	/* !_LIBC && !HAVE___ARGZ_STRINGIFY */
1405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
1425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic char *argz_next__ PARAMS ((char *argz, size_t argz_len,
1435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  const char *entry));
1445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic char *
1465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oargz_next__ (argz, argz_len, entry)
1475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     char *argz;
1485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     size_t argz_len;
1495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *entry;
1505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
1515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (entry)
1525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (entry < argz + argz_len)
1545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o        entry = strchr (entry, '\0') + 1;
1555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      return entry >= argz + argz_len ? NULL : (char *) entry;
1575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  else
1595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    if (argz_len > 0)
1605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      return argz;
1615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    else
1625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      return 0;
1635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# undef __argz_next
1655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
1665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif	/* !_LIBC && !HAVE___ARGZ_NEXT */
1675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Return number of bits set in X.  */
1705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic int pop PARAMS ((int x));
1715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic inline int
1735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'opop (x)
1745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     int x;
1755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
1765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* We assume that no more than 16 bits are used.  */
1775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  x = ((x & ~0x5555) >> 1) + (x & 0x5555);
1785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  x = ((x & ~0x3333) >> 2) + (x & 0x3333);
1795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  x = ((x >> 4) + x) & 0x0f0f;
1805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  x = ((x >> 8) + x) & 0xff;
1815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return x;
1835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostruct loaded_l10nfile *
1875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
1885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		    territory, codeset, normalized_codeset, modifier, special,
1895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		    sponsor, revision, filename, do_allocate)
1905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     struct loaded_l10nfile **l10nfile_list;
1915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *dirlist;
1925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     size_t dirlist_len;
1935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     int mask;
1945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *language;
1955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *territory;
1965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *codeset;
1975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *normalized_codeset;
1985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *modifier;
1995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *special;
2005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *sponsor;
2015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *revision;
2025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *filename;
2035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     int do_allocate;
2045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
2055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  char *abs_filename;
206a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  struct loaded_l10nfile **lastp;
2075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  struct loaded_l10nfile *retval;
2085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  char *cp;
209a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  size_t dirlist_count;
2105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  size_t entries;
2115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  int cnt;
2125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
213a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* If LANGUAGE contains an absolute directory specification, we ignore
214a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     DIRLIST.  */
215a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  if (IS_ABSOLUTE_PATH (language))
216a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    dirlist_len = 0;
217a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
2185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Allocate room for the full file name.  */
2195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  abs_filename = (char *) malloc (dirlist_len
2205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + strlen (language)
2215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + ((mask & TERRITORY) != 0
2225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? strlen (territory) + 1 : 0)
2235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + ((mask & XPG_CODESET) != 0
2245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? strlen (codeset) + 1 : 0)
2255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + ((mask & XPG_NORM_CODESET) != 0
2265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? strlen (normalized_codeset) + 1 : 0)
2275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + (((mask & XPG_MODIFIER) != 0
2285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				      || (mask & CEN_AUDIENCE) != 0)
2295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? strlen (modifier) + 1 : 0)
2305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + ((mask & CEN_SPECIAL) != 0
2315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? strlen (special) + 1 : 0)
2325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + (((mask & CEN_SPONSOR) != 0
2335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				      || (mask & CEN_REVISION) != 0)
2345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				     ? (1 + ((mask & CEN_SPONSOR) != 0
235a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o					     ? strlen (sponsor) : 0)
2365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o					+ ((mask & CEN_REVISION) != 0
2375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o					   ? strlen (revision) + 1 : 0)) : 0)
2385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  + 1 + strlen (filename) + 1);
2395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
2405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (abs_filename == NULL)
2415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    return NULL;
2425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
2435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Construct file name.  */
244a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  cp = abs_filename;
245a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  if (dirlist_len > 0)
246a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    {
247a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      memcpy (cp, dirlist, dirlist_len);
248a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
249a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      cp += dirlist_len;
250a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      cp[-1] = '/';
251a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    }
252a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
2535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  cp = stpcpy (cp, language);
2545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
2555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & TERRITORY) != 0)
2565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = '_';
2585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp = stpcpy (cp, territory);
2595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & XPG_CODESET) != 0)
2615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = '.';
2635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp = stpcpy (cp, codeset);
2645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & XPG_NORM_CODESET) != 0)
2665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = '.';
2685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp = stpcpy (cp, normalized_codeset);
2695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
2715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* This component can be part of both syntaces but has different
2735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	 leading characters.  For CEN we use `+', else `@'.  */
2745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
2755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp = stpcpy (cp, modifier);
2765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & CEN_SPECIAL) != 0)
2785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = '+';
2805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp = stpcpy (cp, special);
2815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
2835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
2845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *cp++ = ',';
2855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if ((mask & CEN_SPONSOR) != 0)
2865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	cp = stpcpy (cp, sponsor);
2875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if ((mask & CEN_REVISION) != 0)
2885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
2895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *cp++ = '_';
2905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  cp = stpcpy (cp, revision);
2915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
2925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
2935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
2945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *cp++ = '/';
2955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  stpcpy (cp, filename);
2965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
2975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Look in list of already loaded domains whether it is already
2985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     available.  */
299a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  lastp = l10nfile_list;
3005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
3015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    if (retval->filename != NULL)
3025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      {
3035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	int compare = strcmp (retval->filename, abs_filename);
3045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	if (compare == 0)
3055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  /* We found it!  */
3065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  break;
3075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	if (compare < 0)
3085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  {
3095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    /* It's not in the list.  */
3105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    retval = NULL;
3115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    break;
3125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  }
3135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
314a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	lastp = &retval->next;
3155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      }
3165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
3175bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval != NULL || do_allocate == 0)
3185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
3195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      free (abs_filename);
3205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      return retval;
3215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
3225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
323a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
324a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
325a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* Allocate a new loaded_l10nfile.  */
326a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  retval =
327a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    (struct loaded_l10nfile *)
328a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    malloc (sizeof (*retval)
329a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
330a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	       * sizeof (struct loaded_l10nfile *)));
3315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval == NULL)
3325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    return NULL;
3335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
3345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval->filename = abs_filename;
335a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
336a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* We set retval->data to NULL here; it is filled in later.
337a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     Setting retval->decided to 1 here means that retval does not
338a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     correspond to a real file (dirlist_count > 1) or is not worth
339a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     looking up (if an unnormalized codeset was specified).  */
340a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  retval->decided = (dirlist_count > 1
3415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		     || ((mask & XPG_CODESET) != 0
3425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			 && (mask & XPG_NORM_CODESET) != 0));
3435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval->data = NULL;
3445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
345a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  retval->next = *lastp;
346a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  *lastp = retval;
3475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
3485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  entries = 0;
349a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* Recurse to fill the inheritance list of RETVAL.
350a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
351a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     entry does not correspond to a real file; retval->filename contains
352a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     colons.  In this case we loop across all elements of DIRLIST and
353a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     across all bit patterns dominated by MASK.
354a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     If the DIRLIST is a single directory or entirely redundant (i.e.
355a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
356a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     MASK, excluding MASK itself.
357a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     In either case, we loop down from MASK to 0.  This has the effect
358a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     that the extra bits in the locale name are dropped in this order:
359a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     first the modifier, then the territory, then the codeset, then the
360a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     normalized_codeset.  */
361a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
3625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    if ((cnt & ~mask) == 0
3635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	&& ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
3645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	&& ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
3655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      {
366a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	if (dirlist_count > 1)
367a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	  {
368a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    /* Iterate over all elements of the DIRLIST.  */
369a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    char *dir = NULL;
370a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
371a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
372a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o		   != NULL)
373a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	      retval->successor[entries++]
374a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o		= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1,
375a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o				      cnt, language, territory, codeset,
376a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o				      normalized_codeset, modifier, special,
377a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o				      sponsor, revision, filename, 1);
378a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	  }
379a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	else
3805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  retval->successor[entries++]
381a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
382a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o				  cnt, language, territory, codeset,
3835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  normalized_codeset, modifier, special,
3845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o				  sponsor, revision, filename, 1);
3855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      }
3865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval->successor[entries] = NULL;
3875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
3885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return retval;
3895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
3905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
3915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Normalize codeset name.  There is no standard for the codeset
3925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   names.  Normalization allows the user to use any of the common
393a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   names.  The return value is dynamically allocated and has to be
394a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   freed by the caller.  */
3955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oconst char *
3965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o_nl_normalize_codeset (codeset, name_len)
397a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     const char *codeset;
3985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     size_t name_len;
3995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
4005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  int len = 0;
4015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  int only_digit = 1;
4025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  char *retval;
4035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  char *wp;
4045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  size_t cnt;
4055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  for (cnt = 0; cnt < name_len; ++cnt)
407a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    if (isalnum ((unsigned char) codeset[cnt]))
4085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      {
4095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	++len;
4105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
411a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	if (isalpha ((unsigned char) codeset[cnt]))
4125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  only_digit = 0;
4135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      }
4145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
4165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4175bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval != NULL)
4185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
4195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (only_digit)
4205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	wp = stpcpy (retval, "iso");
4215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      else
4225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	wp = retval;
4235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      for (cnt = 0; cnt < name_len; ++cnt)
425a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	if (isalpha ((unsigned char) codeset[cnt]))
426a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	  *wp++ = tolower ((unsigned char) codeset[cnt]);
427a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	else if (isdigit ((unsigned char) codeset[cnt]))
4285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *wp++ = codeset[cnt];
4295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *wp = '\0';
4315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
4325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return (const char *) retval;
4345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
4355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ begin of epilog @@ */
4385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
4395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* We don't want libintl.a to depend on any other library.  So we
4405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   avoid the non-standard function stpcpy.  In GNU C Library this
4415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   function is available, though.  Also allow the symbol HAVE_STPCPY
4425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   to be defined.  */
4435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if !_LIBC && !HAVE_STPCPY
4445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic char *
4455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostpcpy (dest, src)
4465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     char *dest;
4475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     const char *src;
4485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
4495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  while ((*dest++ = *src++) != '\0')
4505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    /* Do nothing. */ ;
4515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return dest - 1;
4525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
4535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
454