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