00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _GNU_SOURCE
00023 # define _GNU_SOURCE 1
00024 #endif
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <sys/types.h>
00033
00034 #ifdef __GNUC__
00035 # define alloca __builtin_alloca
00036 # define HAVE_ALLOCA 1
00037 #else
00038 # if defined HAVE_ALLOCA_H || defined _LIBC
00039 # include <alloca.h>
00040 # else
00041 # ifdef _AIX
00042 #pragma alloca
00043 # else
00044 # ifndef alloca
00045 char *alloca ();
00046 # endif
00047 # endif
00048 # endif
00049 #endif
00050
00051 #include <stdlib.h>
00052
00053 #include <string.h>
00054 #if !HAVE_STRCHR && !defined _LIBC
00055 # ifndef strchr
00056 # define strchr index
00057 # endif
00058 #endif
00059
00060 #ifdef STRING_WITH_STRINGS
00061 #include <strings.h>
00062 #endif
00063
00064 #include "gettextP.h"
00065
00066
00067
00068 #ifdef _LIBC
00069
00070
00071
00072 # define strcasecmp __strcasecmp
00073
00074 # ifndef mempcpy
00075 # define mempcpy __mempcpy
00076 # endif
00077 # define HAVE_MEMPCPY 1
00078
00079
00080 # include <bits/libc-lock.h>
00081
00082 __libc_lock_define_initialized (static, lock);
00083 #endif
00084
00085 #ifndef internal_function
00086 # define internal_function
00087 #endif
00088
00089
00090
00091 #ifdef HAVE_ALLOCA
00092 # define freea(p)
00093 #else
00094 # define alloca(n) malloc (n)
00095 # define freea(p) free (p)
00096 #endif
00097
00098 #if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
00099 # undef fgets
00100 # define fgets(buf, len, s) fgets_unlocked (buf, len, s)
00101 #endif
00102 #if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
00103 # undef feof
00104 # define feof(s) feof_unlocked (s)
00105 #endif
00106
00107
00108 struct alias_map
00109 {
00110 const char *alias;
00111 const char *value;
00112 };
00113
00114
00115 static char *string_space;
00116 static size_t string_space_act;
00117 static size_t string_space_max;
00118 static struct alias_map *map;
00119 static size_t nmap;
00120 static size_t maxmap;
00121
00122
00123
00124 static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
00125 internal_function;
00126 static int extend_alias_table PARAMS ((void));
00127 static int alias_compare PARAMS ((const struct alias_map *map1,
00128 const struct alias_map *map2));
00129
00130
00131 const char *
00132 _nl_expand_alias (name)
00133 const char *name;
00134 {
00135 static const char *locale_alias_path = LOCALE_ALIAS_PATH;
00136 struct alias_map *retval;
00137 const char *result = NULL;
00138 size_t added;
00139
00140 #ifdef _LIBC
00141 __libc_lock_lock (lock);
00142 #endif
00143
00144 do
00145 {
00146 struct alias_map item;
00147
00148 item.alias = name;
00149
00150 if (nmap > 0)
00151 retval = (struct alias_map *) bsearch (&item, map, nmap,
00152 sizeof (struct alias_map),
00153 (int (*) PARAMS ((const void *,
00154 const void *))
00155 ) alias_compare);
00156 else
00157 retval = NULL;
00158
00159
00160 if (retval != NULL)
00161 {
00162 result = retval->value;
00163 break;
00164 }
00165
00166
00167 added = 0;
00168 while (added == 0 && locale_alias_path[0] != '\0')
00169 {
00170 const char *start;
00171
00172 while (locale_alias_path[0] == PATH_SEPARATOR)
00173 ++locale_alias_path;
00174 start = locale_alias_path;
00175
00176 while (locale_alias_path[0] != '\0'
00177 && locale_alias_path[0] != PATH_SEPARATOR)
00178 ++locale_alias_path;
00179
00180 if (start < locale_alias_path)
00181 added = read_alias_file (start, locale_alias_path - start);
00182 }
00183 }
00184 while (added != 0);
00185
00186 #ifdef _LIBC
00187 __libc_lock_unlock (lock);
00188 #endif
00189
00190 return result;
00191 }
00192
00193
00194 static size_t
00195 internal_function
00196 read_alias_file (fname, fname_len)
00197 const char *fname;
00198 int fname_len;
00199 {
00200 FILE *fp;
00201 char *full_fname;
00202 size_t added;
00203 static const char aliasfile[] = "/locale.alias";
00204
00205 full_fname = (char *) alloca (fname_len + sizeof aliasfile);
00206 #ifdef HAVE_MEMPCPY
00207 mempcpy (mempcpy (full_fname, fname, fname_len),
00208 aliasfile, sizeof aliasfile);
00209 #else
00210 memcpy (full_fname, fname, fname_len);
00211 memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
00212 #endif
00213
00214 fp = fopen (full_fname, "r");
00215 freea (full_fname);
00216 if (fp == NULL)
00217 return 0;
00218
00219 added = 0;
00220 while (!feof (fp))
00221 {
00222
00223
00224
00225
00226
00227 char buf[BUFSIZ];
00228 char *alias;
00229 char *value;
00230 char *cp;
00231
00232 if (fgets (buf, sizeof buf, fp) == NULL)
00233
00234 break;
00235
00236
00237
00238 if (strchr (buf, '\n') == NULL)
00239 {
00240 char altbuf[BUFSIZ];
00241 do
00242 if (fgets (altbuf, sizeof altbuf, fp) == NULL)
00243
00244
00245 break;
00246 while (strchr (altbuf, '\n') == NULL);
00247 }
00248
00249 cp = buf;
00250
00251 while (isspace ((unsigned char)cp[0]))
00252 ++cp;
00253
00254
00255 if (cp[0] != '\0' && cp[0] != '#')
00256 {
00257 alias = cp++;
00258 while (cp[0] != '\0' && !isspace ((unsigned char)cp[0]))
00259 ++cp;
00260
00261 if (cp[0] != '\0')
00262 *cp++ = '\0';
00263
00264
00265 while (isspace ((unsigned char)cp[0]))
00266 ++cp;
00267
00268 if (cp[0] != '\0')
00269 {
00270 size_t alias_len;
00271 size_t value_len;
00272
00273 value = cp++;
00274 while (cp[0] != '\0' && !isspace ((unsigned char)cp[0]))
00275 ++cp;
00276
00277 if (cp[0] == '\n')
00278 {
00279
00280
00281
00282 *cp++ = '\0';
00283 *cp = '\n';
00284 }
00285 else if (cp[0] != '\0')
00286 *cp++ = '\0';
00287
00288 if (nmap >= maxmap)
00289 if (__builtin_expect (extend_alias_table (), 0))
00290 return added;
00291
00292 alias_len = strlen (alias) + 1;
00293 value_len = strlen (value) + 1;
00294
00295 if (string_space_act + alias_len + value_len > string_space_max)
00296 {
00297
00298 size_t new_size = (string_space_max
00299 + (alias_len + value_len > 1024
00300 ? alias_len + value_len : 1024));
00301 char *new_pool = (char *) realloc (string_space, new_size);
00302 if (new_pool == NULL)
00303 return added;
00304
00305 if (__builtin_expect (string_space != new_pool, 0))
00306 {
00307 size_t i;
00308
00309 for (i = 0; i < nmap; i++)
00310 {
00311 map[i].alias += new_pool - string_space;
00312 map[i].value += new_pool - string_space;
00313 }
00314 }
00315
00316 string_space = new_pool;
00317 string_space_max = new_size;
00318 }
00319
00320 memcpy (&string_space[string_space_act], alias, alias_len);
00321 map[nmap].alias = &string_space[string_space_act];
00322 string_space_act += alias_len;
00323
00324 memcpy (&string_space[string_space_act], value, value_len);
00325 map[nmap].value = &string_space[string_space_act];
00326 string_space_act += value_len;
00327
00328 ++nmap;
00329 ++added;
00330 }
00331 }
00332 }
00333
00334
00335
00336 fclose (fp);
00337
00338 if (added > 0)
00339 qsort (map, nmap, sizeof (struct alias_map),
00340 (int (*) PARAMS ((const void *, const void *))) alias_compare);
00341
00342 return added;
00343 }
00344
00345
00346 static int
00347 extend_alias_table ()
00348 {
00349 size_t new_size;
00350 struct alias_map *new_map;
00351
00352 new_size = maxmap == 0 ? 100 : 2 * maxmap;
00353 new_map = (struct alias_map *) realloc (map, (new_size
00354 * sizeof (struct alias_map)));
00355 if (new_map == NULL)
00356
00357 return -1;
00358
00359 map = new_map;
00360 maxmap = new_size;
00361 return 0;
00362 }
00363
00364
00365 #ifdef _LIBC
00366 static void __attribute__ ((unused))
00367 free_mem (void)
00368 {
00369 if (string_space != NULL)
00370 free (string_space);
00371 if (map != NULL)
00372 free (map);
00373 }
00374 text_set_element (__libc_subfreeres, free_mem);
00375 #endif
00376
00377
00378 static int
00379 alias_compare (map1, map2)
00380 const struct alias_map *map1;
00381 const struct alias_map *map2;
00382 {
00383 #if defined _LIBC || defined HAVE_STRCASECMP
00384 return strcasecmp (map1->alias, map2->alias);
00385 #else
00386 const unsigned char *p1 = (const unsigned char *) map1->alias;
00387 const unsigned char *p2 = (const unsigned char *) map2->alias;
00388 unsigned char c1, c2;
00389
00390 if (p1 == p2)
00391 return 0;
00392
00393 do
00394 {
00395
00396
00397 c1 = isupper ((unsigned char)*p1) ? tolower ((unsigned char)*p1) : *p1;
00398 c2 = isupper ((unsigned char)*p2) ? tolower ((unsigned char)*p2) : *p2;
00399 if (c1 == '\0')
00400 break;
00401 ++p1;
00402 ++p2;
00403 }
00404 while (c1 == c2);
00405
00406 return c1 - c2;
00407 #endif
00408 }