1/* Copyright (C) 1995-1998, 2000-2001, 2003 Free Software Foundation, Inc.
2   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
3
4   This program is free software; you can redistribute it and/or modify it
5   under the terms of the GNU Library General Public License as published
6   by the Free Software Foundation; either version 2, or (at your option)
7   any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Library General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17   USA.  */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <stdlib.h>
24#include <string.h>
25#include <sys/types.h>
26
27#include "loadinfo.h"
28
29/* On some strange systems still no definition of NULL is found.  Sigh!  */
30#ifndef NULL
31# if defined __STDC__ && __STDC__
32#  define NULL ((void *) 0)
33# else
34#  define NULL 0
35# endif
36#endif
37
38/* @@ end of prolog @@ */
39
40char *
41_nl_find_language (const char *name)
42{
43  while (name[0] != '\0' && name[0] != '_' && name[0] != '@'
44	 && name[0] != '+' && name[0] != ',')
45    ++name;
46
47  return (char *) name;
48}
49
50
51int
52_nl_explode_name (char *name,
53		  const char **language, const char **modifier,
54		  const char **territory, const char **codeset,
55		  const char **normalized_codeset, const char **special,
56		  const char **sponsor, const char **revision)
57{
58  enum { undecided, xpg, cen } syntax;
59  char *cp;
60  int mask;
61
62  *modifier = NULL;
63  *territory = NULL;
64  *codeset = NULL;
65  *normalized_codeset = NULL;
66  *special = NULL;
67  *sponsor = NULL;
68  *revision = NULL;
69
70  /* Now we determine the single parts of the locale name.  First
71     look for the language.  Termination symbols are `_' and `@' if
72     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
73  mask = 0;
74  syntax = undecided;
75  *language = cp = name;
76  cp = _nl_find_language (*language);
77
78  if (*language == cp)
79    /* This does not make sense: language has to be specified.  Use
80       this entry as it is without exploding.  Perhaps it is an alias.  */
81    cp = strchr (*language, '\0');
82  else if (cp[0] == '_')
83    {
84      /* Next is the territory.  */
85      cp[0] = '\0';
86      *territory = ++cp;
87
88      while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@'
89	     && cp[0] != '+' && cp[0] != ',' && cp[0] != '_')
90	++cp;
91
92      mask |= TERRITORY;
93
94      if (cp[0] == '.')
95	{
96	  /* Next is the codeset.  */
97	  syntax = xpg;
98	  cp[0] = '\0';
99	  *codeset = ++cp;
100
101	  while (cp[0] != '\0' && cp[0] != '@')
102	    ++cp;
103
104	  mask |= XPG_CODESET;
105
106	  if (*codeset != cp && (*codeset)[0] != '\0')
107	    {
108	      *normalized_codeset = _nl_normalize_codeset (*codeset,
109							   cp - *codeset);
110	      if (strcmp (*codeset, *normalized_codeset) == 0)
111		free ((char *) *normalized_codeset);
112	      else
113		mask |= XPG_NORM_CODESET;
114	    }
115	}
116    }
117
118  if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
119    {
120      /* Next is the modifier.  */
121      syntax = cp[0] == '@' ? xpg : cen;
122      cp[0] = '\0';
123      *modifier = ++cp;
124
125      while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
126	     && cp[0] != ',' && cp[0] != '_')
127	++cp;
128
129      mask |= XPG_MODIFIER | CEN_AUDIENCE;
130    }
131
132  if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
133    {
134      syntax = cen;
135
136      if (cp[0] == '+')
137	{
138 	  /* Next is special application (CEN syntax).  */
139	  cp[0] = '\0';
140	  *special = ++cp;
141
142	  while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
143	    ++cp;
144
145	  mask |= CEN_SPECIAL;
146	}
147
148      if (cp[0] == ',')
149	{
150 	  /* Next is sponsor (CEN syntax).  */
151	  cp[0] = '\0';
152	  *sponsor = ++cp;
153
154	  while (cp[0] != '\0' && cp[0] != '_')
155	    ++cp;
156
157	  mask |= CEN_SPONSOR;
158	}
159
160      if (cp[0] == '_')
161	{
162 	  /* Next is revision (CEN syntax).  */
163	  cp[0] = '\0';
164	  *revision = ++cp;
165
166	  mask |= CEN_REVISION;
167	}
168    }
169
170  /* For CEN syntax values it might be important to have the
171     separator character in the file name, not for XPG syntax.  */
172  if (syntax == xpg)
173    {
174      if (*territory != NULL && (*territory)[0] == '\0')
175	mask &= ~TERRITORY;
176
177      if (*codeset != NULL && (*codeset)[0] == '\0')
178	mask &= ~XPG_CODESET;
179
180      if (*modifier != NULL && (*modifier)[0] == '\0')
181	mask &= ~XPG_MODIFIER;
182    }
183
184  return mask;
185}
186