1 /* Copyright (C) 1995-1998, 2000-2001, 2003 Free Software Foundation, Inc. 2 Contributed by Ulrich Drepper <drepper (at) 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 40 char * 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 51 int 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