1b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o/* Copyright (C) 1995-1998, 2000-2001, 2003 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.
135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore 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.  */
185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_CONFIG_H
205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <config.h>
215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
23a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <stdlib.h>
24a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <string.h>
255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <sys/types.h>
265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include "loadinfo.h"
285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* On some strange systems still no definition of NULL is found.  Sigh!  */
305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifndef NULL
315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# if defined __STDC__ && __STDC__
325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define NULL ((void *) 0)
335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# else
345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define NULL 0
355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif
365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ end of prolog @@ */
395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
40a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ochar *
41b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o_nl_find_language (const char *name)
42a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o{
43a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  while (name[0] != '\0' && name[0] != '_' && name[0] != '@'
44a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	 && name[0] != '+' && name[0] != ',')
45a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    ++name;
46a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
47a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  return (char *) name;
48a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o}
49a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
50a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oint
52b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o_nl_explode_name (char *name,
53b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o		  const char **language, const char **modifier,
54b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o		  const char **territory, const char **codeset,
55b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o		  const char **normalized_codeset, const char **special,
56b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o		  const char **sponsor, const char **revision)
575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  enum { undecided, xpg, cen } syntax;
595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  char *cp;
605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  int mask;
615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *modifier = NULL;
635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *territory = NULL;
645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *codeset = NULL;
655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *normalized_codeset = NULL;
665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *special = NULL;
675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *sponsor = NULL;
685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *revision = NULL;
695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Now we determine the single parts of the locale name.  First
715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     look for the language.  Termination symbols are `_' and `@' if
725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  mask = 0;
745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  syntax = undecided;
755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  *language = cp = name;
76a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  cp = _nl_find_language (*language);
775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (*language == cp)
795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    /* This does not make sense: language has to be specified.  Use
805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o       this entry as it is without exploding.  Perhaps it is an alias.  */
815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    cp = strchr (*language, '\0');
825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  else if (cp[0] == '_')
835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* Next is the territory.  */
855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp[0] = '\0';
865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *territory = ++cp;
875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@'
895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	     && cp[0] != '+' && cp[0] != ',' && cp[0] != '_')
905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	++cp;
915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      mask |= TERRITORY;
935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (cp[0] == '.')
955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  /* Next is the codeset.  */
975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  syntax = xpg;
985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  cp[0] = '\0';
995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *codeset = ++cp;
1005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  while (cp[0] != '\0' && cp[0] != '@')
1025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    ++cp;
1035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  mask |= XPG_CODESET;
1055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  if (*codeset != cp && (*codeset)[0] != '\0')
1075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    {
1085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	      *normalized_codeset = _nl_normalize_codeset (*codeset,
1095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o							   cp - *codeset);
1105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	      if (strcmp (*codeset, *normalized_codeset) == 0)
1115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		free ((char *) *normalized_codeset);
1125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	      else
1135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		mask |= XPG_NORM_CODESET;
1145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    }
1155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1175bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
1195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* Next is the modifier.  */
1215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      syntax = cp[0] == '@' ? xpg : cen;
1225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      cp[0] = '\0';
1235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      *modifier = ++cp;
1245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
1265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	     && cp[0] != ',' && cp[0] != '_')
1275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	++cp;
1285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      mask |= XPG_MODIFIER | CEN_AUDIENCE;
1305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
1335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      syntax = cen;
1355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (cp[0] == '+')
1375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
1385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 	  /* Next is special application (CEN syntax).  */
1395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  cp[0] = '\0';
1405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *special = ++cp;
1415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
1435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    ++cp;
1445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  mask |= CEN_SPECIAL;
1465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (cp[0] == ',')
1495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
1505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 	  /* Next is sponsor (CEN syntax).  */
1515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  cp[0] = '\0';
1525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *sponsor = ++cp;
1535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  while (cp[0] != '\0' && cp[0] != '_')
1555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    ++cp;
1565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  mask |= CEN_SPONSOR;
1585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (cp[0] == '_')
1615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
1625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 	  /* Next is revision (CEN syntax).  */
1635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  cp[0] = '\0';
1645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  *revision = ++cp;
1655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  mask |= CEN_REVISION;
1675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* For CEN syntax values it might be important to have the
1715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     separator character in the file name, not for XPG syntax.  */
1725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (syntax == xpg)
1735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (*territory != NULL && (*territory)[0] == '\0')
1755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	mask &= ~TERRITORY;
1765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (*codeset != NULL && (*codeset)[0] == '\0')
1785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	mask &= ~XPG_CODESET;
1795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (*modifier != NULL && (*modifier)[0] == '\0')
1815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	mask &= ~XPG_MODIFIER;
1825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return mask;
1855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
186