(file) Return to localealias.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / intl

  1 rizwank 1.1 /* Handle aliases for locale names.
  2                Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
  3                Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
  4             
  5                This program is free software; you can redistribute it and/or modify
  6                it under the terms of the GNU General Public License as published by
  7                the Free Software Foundation; either version 2, or (at your option)
  8                any later version.
  9             
 10                This program 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
 13                GNU General Public License for more details.
 14             
 15                You should have received a copy of the GNU General Public License
 16                along with this program; if not, write to the Free Software Foundation,
 17                Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 18             
 19             #ifdef HAVE_CONFIG_H
 20             # include <config.h>
 21             #endif
 22 rizwank 1.1 
 23             #include <ctype.h>
 24             #include <stdio.h>
 25             #include <sys/types.h>
 26             
 27             #ifdef __GNUC__
 28             # define alloca __builtin_alloca
 29             # define HAVE_ALLOCA 1
 30             #else
 31             # if defined HAVE_ALLOCA_H || defined _LIBC
 32             #  include <alloca.h>
 33             # else
 34             #  ifdef _AIX
 35              #pragma alloca
 36             #  else
 37             #   ifndef alloca
 38             char *alloca ();
 39             #   endif
 40             #  endif
 41             # endif
 42             #endif
 43 rizwank 1.1 
 44             #if defined STDC_HEADERS || defined _LIBC
 45             # include <stdlib.h>
 46             #else
 47             char *getenv ();
 48             # ifdef HAVE_MALLOC_H
 49             #  include <malloc.h>
 50             # else
 51             void free ();
 52             # endif
 53             #endif
 54             
 55             #if defined HAVE_STRING_H || defined _LIBC
 56             # ifndef _GNU_SOURCE
 57             #  define _GNU_SOURCE	1
 58             # endif
 59             # include <string.h>
 60             #else
 61             # include <strings.h>
 62             # ifndef memcpy
 63             #  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
 64 rizwank 1.1 # endif
 65             #endif
 66             #if !HAVE_STRCHR && !defined _LIBC
 67             # ifndef strchr
 68             #  define strchr index
 69             # endif
 70             #endif
 71             
 72             #include "gettext.h"
 73             #include "gettextP.h"
 74             
 75             /* @@ end of prolog @@ */
 76             
 77             #ifdef _LIBC
 78             /* Rename the non ANSI C functions.  This is required by the standard
 79                because some ANSI C functions will require linking with this object
 80                file and the name space must not be polluted.  */
 81             # define strcasecmp __strcasecmp
 82             
 83             # define mempcpy __mempcpy
 84             # define HAVE_MEMPCPY	1
 85 rizwank 1.1 
 86             /* We need locking here since we can be called from different places.  */
 87             # include <bits/libc-lock.h>
 88             
 89             __libc_lock_define_initialized (static, lock);
 90             #endif
 91             
 92             
 93             /* For those loosing systems which don't have `alloca' we have to add
 94                some additional code emulating it.  */
 95             #ifdef HAVE_ALLOCA
 96             /* Nothing has to be done.  */
 97             # define ADD_BLOCK(list, address) /* nothing */
 98             # define FREE_BLOCKS(list) /* nothing */
 99             #else
100             struct block_list
101             {
102               void *address;
103               struct block_list *next;
104             };
105             # define ADD_BLOCK(list, addr)						      \
106 rizwank 1.1   do {									      \
107                 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
108                 /* If we cannot get a free block we cannot add the new element to	      \
109                    the list.  */							      \
110                 if (newp != NULL) {							      \
111                   newp->address = (addr);						      \
112                   newp->next = (list);						      \
113                   (list) = newp;							      \
114                 }									      \
115               } while (0)
116             # define FREE_BLOCKS(list)						      \
117               do {									      \
118                 while (list != NULL) {						      \
119                   struct block_list *old = list;					      \
120                   list = list->next;						      \
121                   free (old);							      \
122                 }									      \
123               } while (0)
124             # undef alloca
125             # define alloca(size) (malloc (size))
126             #endif	/* have alloca */
127 rizwank 1.1 
128             
129             struct alias_map
130             {
131               const char *alias;
132               const char *value;
133             };
134             
135             
136             static char *string_space = NULL;
137             static size_t string_space_act = 0;
138             static size_t string_space_max = 0;
139             static struct alias_map *map;
140             static size_t nmap = 0;
141             static size_t maxmap = 0;
142             
143             
144             /* Prototypes for local functions.  */
145             static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
146                  internal_function;
147             static void extend_alias_table PARAMS ((void));
148 rizwank 1.1 static int alias_compare PARAMS ((const struct alias_map *map1,
149             				  const struct alias_map *map2));
150             
151             
152             const char *
153             _nl_expand_alias (name)
154                 const char *name;
155             {
156               static const char *locale_alias_path = LOCALE_ALIAS_PATH;
157               struct alias_map *retval;
158               const char *result = NULL;
159               size_t added;
160             
161             #ifdef _LIBC
162               __libc_lock_lock (lock);
163             #endif
164             
165               do
166                 {
167                   struct alias_map item;
168             
169 rizwank 1.1       item.alias = name;
170             
171                   if (nmap > 0)
172             	retval = (struct alias_map *) bsearch (&item, map, nmap,
173             					       sizeof (struct alias_map),
174             					       (int (*) PARAMS ((const void *,
175             								 const void *))
176             						) alias_compare);
177                   else
178             	retval = NULL;
179             
180                   /* We really found an alias.  Return the value.  */
181                   if (retval != NULL)
182             	{
183             	  result = retval->value;
184             	  break;
185             	}
186             
187                   /* Perhaps we can find another alias file.  */
188                   added = 0;
189                   while (added == 0 && locale_alias_path[0] != '\0')
190 rizwank 1.1 	{
191             	  const char *start;
192             
193             	  while (locale_alias_path[0] == ':')
194             	    ++locale_alias_path;
195             	  start = locale_alias_path;
196             
197             	  while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
198             	    ++locale_alias_path;
199             
200             	  if (start < locale_alias_path)
201             	    added = read_alias_file (start, locale_alias_path - start);
202             	}
203                 }
204               while (added != 0);
205             
206             #ifdef _LIBC
207               __libc_lock_unlock (lock);
208             #endif
209             
210               return result;
211 rizwank 1.1 }
212             
213             
214             static size_t
215             internal_function
216             read_alias_file (fname, fname_len)
217                  const char *fname;
218                  int fname_len;
219             {
220             #ifndef HAVE_ALLOCA
221               struct block_list *block_list = NULL;
222             #endif
223               FILE *fp;
224               char *full_fname;
225               size_t added;
226               static const char aliasfile[] = "/locale.alias";
227             
228               full_fname = (char *) alloca (fname_len + sizeof aliasfile);
229               ADD_BLOCK (block_list, full_fname);
230             #ifdef HAVE_MEMPCPY
231               mempcpy (mempcpy (full_fname, fname, fname_len),
232 rizwank 1.1 	   aliasfile, sizeof aliasfile);
233             #else
234               memcpy (full_fname, fname, fname_len);
235               memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
236             #endif
237             
238               fp = fopen (full_fname, "r");
239               if (fp == NULL)
240                 {
241                   FREE_BLOCKS (block_list);
242                   return 0;
243                 }
244             
245               added = 0;
246               while (!feof (fp))
247                 {
248                   /* It is a reasonable approach to use a fix buffer here because
249             	 a) we are only interested in the first two fields
250             	 b) these fields must be usable as file names and so must not
251             	    be that long
252                    */
253 rizwank 1.1       char buf[BUFSIZ];
254                   char *alias;
255                   char *value;
256                   unsigned char *cp;
257             
258                   if (fgets (buf, sizeof buf, fp) == NULL)
259             	/* EOF reached.  */
260             	break;
261             
262                   /* Possibly not the whole line fits into the buffer.  Ignore
263             	 the rest of the line.  */
264                   if (strchr (buf, '\n') == NULL)
265             	{
266             	  char altbuf[BUFSIZ];
267             	  do
268             	    if (fgets (altbuf, sizeof altbuf, fp) == NULL)
269             	      /* Make sure the inner loop will be left.  The outer loop
270             		 will exit at the `feof' test.  */
271             	      break;
272             	  while (strchr (altbuf, '\n') == NULL);
273             	}
274 rizwank 1.1 
275                   cp = (unsigned char *) buf;
276                   /* Ignore leading white space.  */
277                   while (isspace (cp[0]))
278             	++cp;
279             
280                   /* A leading '#' signals a comment line.  */
281                   if (cp[0] != '\0' && cp[0] != '#')
282             	{
283             	  alias = (char *) cp++;
284             	  while (cp[0] != '\0' && !isspace (cp[0]))
285             	    ++cp;
286             	  /* Terminate alias name.  */
287             	  if (cp[0] != '\0')
288             	    *cp++ = '\0';
289             
290             	  /* Now look for the beginning of the value.  */
291             	  while (isspace (cp[0]))
292             	    ++cp;
293             
294             	  if (cp[0] != '\0')
295 rizwank 1.1 	    {
296             	      size_t alias_len;
297             	      size_t value_len;
298             
299             	      value = (char *) cp++;
300             	      while (cp[0] != '\0' && !isspace (cp[0]))
301             		++cp;
302             	      /* Terminate value.  */
303             	      if (cp[0] == '\n')
304             		{
305             		  /* This has to be done to make the following test
306             		     for the end of line possible.  We are looking for
307             		     the terminating '\n' which do not overwrite here.  */
308             		  *cp++ = '\0';
309             		  *cp = '\n';
310             		}
311             	      else if (cp[0] != '\0')
312             		*cp++ = '\0';
313             
314             	      if (nmap >= maxmap)
315             		extend_alias_table ();
316 rizwank 1.1 
317             	      alias_len = strlen (alias) + 1;
318             	      value_len = strlen (value) + 1;
319             
320             	      if (string_space_act + alias_len + value_len > string_space_max)
321             		{
322             		  /* Increase size of memory pool.  */
323             		  size_t new_size = (string_space_max
324             				     + (alias_len + value_len > 1024
325             					? alias_len + value_len : 1024));
326             		  char *new_pool = (char *) realloc (string_space, new_size);
327             		  if (new_pool == NULL)
328             		    {
329             		      FREE_BLOCKS (block_list);
330             		      return added;
331             		    }
332             		  string_space = new_pool;
333             		  string_space_max = new_size;
334             		}
335             
336             	      map[nmap].alias = memcpy (&string_space[string_space_act],
337 rizwank 1.1 					alias, alias_len);
338             	      string_space_act += alias_len;
339             
340             	      map[nmap].value = memcpy (&string_space[string_space_act],
341             					value, value_len);
342             	      string_space_act += value_len;
343             
344             	      ++nmap;
345             	      ++added;
346             	    }
347             	}
348                 }
349             
350               /* Should we test for ferror()?  I think we have to silently ignore
351                  errors.  --drepper  */
352               fclose (fp);
353             
354               if (added > 0)
355                 qsort (map, nmap, sizeof (struct alias_map),
356             	   (int (*) PARAMS ((const void *, const void *))) alias_compare);
357             
358 rizwank 1.1   FREE_BLOCKS (block_list);
359               return added;
360             }
361             
362             
363             static void
364             extend_alias_table ()
365             {
366               size_t new_size;
367               struct alias_map *new_map;
368             
369               new_size = maxmap == 0 ? 100 : 2 * maxmap;
370               new_map = (struct alias_map *) realloc (map, (new_size
371             						* sizeof (struct alias_map)));
372               if (new_map == NULL)
373                 /* Simply don't extend: we don't have any more core.  */
374                 return;
375             
376               map = new_map;
377               maxmap = new_size;
378             }
379 rizwank 1.1 
380             
381             #ifdef _LIBC
382             static void __attribute__ ((unused))
383             free_mem (void)
384             {
385               if (string_space != NULL)
386                 free (string_space);
387               if (map != NULL)
388                 free (map);
389             }
390             text_set_element (__libc_subfreeres, free_mem);
391             #endif
392             
393             
394             static int
395             alias_compare (map1, map2)
396                  const struct alias_map *map1;
397                  const struct alias_map *map2;
398             {
399             #if defined _LIBC || defined HAVE_STRCASECMP
400 rizwank 1.1   return strcasecmp (map1->alias, map2->alias);
401             #else
402               const unsigned char *p1 = (const unsigned char *) map1->alias;
403               const unsigned char *p2 = (const unsigned char *) map2->alias;
404               unsigned char c1, c2;
405             
406               if (p1 == p2)
407                 return 0;
408             
409               do
410                 {
411                   /* I know this seems to be odd but the tolower() function in
412             	 some systems libc cannot handle nonalpha characters.  */
413                   c1 = isupper (*p1) ? tolower (*p1) : *p1;
414                   c2 = isupper (*p2) ? tolower (*p2) : *p2;
415                   if (c1 == '\0')
416             	break;
417                   ++p1;
418                   ++p2;
419                 }
420               while (c1 == c2);
421 rizwank 1.1 
422               return c1 - c2;
423             #endif
424             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2