chiark / gitweb /
Apply https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d506068ed11c8bfa1e1e...
[eglibc.git] / intl / explodename.c
1 /* Copyright (C) 1995-2002, 2003, 2006, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27
28 #include "loadinfo.h"
29
30 /* On some strange systems still no definition of NULL is found.  Sigh!  */
31 #ifndef NULL
32 # if defined __STDC__ && __STDC__
33 #  define NULL ((void *) 0)
34 # else
35 #  define NULL 0
36 # endif
37 #endif
38
39 /* @@ end of prolog @@ */
40
41 static char *_nl_find_language PARAMS ((const char *name));
42
43 static char *
44 _nl_find_language (name)
45      const char *name;
46 {
47   while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
48     ++name;
49
50   return (char *) name;
51 }
52
53
54 int
55 _nl_explode_name (name, language, modifier, territory, codeset,
56                   normalized_codeset)
57      char *name;
58      const char **language;
59      const char **modifier;
60      const char **territory;
61      const char **codeset;
62      const char **normalized_codeset;
63 {
64   char *cp;
65   int mask;
66
67   *modifier = NULL;
68   *territory = NULL;
69   *codeset = NULL;
70   *normalized_codeset = NULL;
71
72   /* Now we determine the single parts of the locale name.  First
73      look for the language.  Termination symbols are `_', '.', and `@'.  */
74   mask = 0;
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 = __rawmemchr (*language, '\0');
82   else if (cp[0] != '@')
83     {
84       if (cp[0] == '_')
85         {
86           /* Next is the territory.  */
87           cp[0] = '\0';
88           *territory = ++cp;
89
90           while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
91             ++cp;
92
93           mask |= XPG_TERRITORY;
94         }
95
96       if (cp[0] == '.')
97         {
98           /* Next is the codeset.  */
99           cp[0] = '\0';
100           *codeset = ++cp;
101
102           while (cp[0] != '\0' && cp[0] != '@')
103             ++cp;
104
105           mask |= XPG_CODESET;
106
107           if (*codeset != cp && (*codeset)[0] != '\0')
108             {
109               *normalized_codeset = _nl_normalize_codeset (*codeset,
110                                                            cp - *codeset);
111               if (*normalized_codeset == NULL)
112                 return -1;
113               else if (strcmp (*codeset, *normalized_codeset) == 0)
114                 free ((char *) *normalized_codeset);
115               else
116                 mask |= XPG_NORM_CODESET;
117             }
118         }
119     }
120
121   if (cp[0] == '@')
122     {
123       /* Next is the modifier.  */
124       cp[0] = '\0';
125       *modifier = ++cp;
126
127       if (cp[0] != '\0')
128         mask |= XPG_MODIFIER;
129     }
130
131   if (*territory != NULL && (*territory)[0] == '\0')
132     mask &= ~XPG_TERRITORY;
133
134   if (*codeset != NULL && (*codeset)[0] == '\0')
135     mask &= ~XPG_CODESET;
136
137   return mask;
138 }