File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lrzsz / intl / localealias.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Oct 24 15:49:50 2019 UTC (5 years, 5 months ago) by misho
Branches: lrzsz, MAIN
CVS tags: v0_12_20p5, HEAD
lrzsz ver 0.12.20

    1: /* Handle aliases for locale names
    2:    Copyright (C) 1995, 1996, 1997 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: 
   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: 
   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: # 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: #endif
   83: 
   84: 
   85: /* For those loosing systems which don't have `alloca' we have to add
   86:    some additional code emulating it.  */
   87: #ifdef HAVE_ALLOCA
   88: /* Nothing has to be done.  */
   89: # define ADD_BLOCK(list, address) /* nothing */
   90: # define FREE_BLOCKS(list) /* nothing */
   91: #else
   92: struct block_list
   93: {
   94:   void *address;
   95:   struct block_list *next;
   96: };
   97: # define ADD_BLOCK(list, addr)						      \
   98:   do {									      \
   99:     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
  100:     /* If we cannot get a free block we cannot add the new element to	      \
  101:        the list.  */							      \
  102:     if (newp != NULL) {							      \
  103:       newp->address = (addr);						      \
  104:       newp->next = (list);						      \
  105:       (list) = newp;							      \
  106:     }									      \
  107:   } while (0)
  108: # define FREE_BLOCKS(list)						      \
  109:   do {									      \
  110:     while (list != NULL) {						      \
  111:       struct block_list *old = list;					      \
  112:       list = list->next;						      \
  113:       free (old);							      \
  114:     }									      \
  115:   } while (0)
  116: # undef alloca
  117: # define alloca(size) (malloc (size))
  118: #endif	/* have alloca */
  119: 
  120: 
  121: struct alias_map
  122: {
  123:   const char *alias;
  124:   const char *value;
  125: };
  126: 
  127: 
  128: static struct alias_map *map;
  129: static size_t nmap = 0;
  130: static size_t maxmap = 0;
  131: 
  132: 
  133: /* Prototypes for local functions.  */
  134: static size_t read_alias_file PARAMS ((const char *fname, int fname_len));
  135: static void extend_alias_table PARAMS ((void));
  136: static int alias_compare PARAMS ((const struct alias_map *map1,
  137: 				  const struct alias_map *map2));
  138: 
  139: 
  140: const char *
  141: _nl_expand_alias (name)
  142:     const char *name;
  143: {
  144:   static const char *locale_alias_path = LOCALE_ALIAS_PATH;
  145:   struct alias_map *retval;
  146:   size_t added;
  147: 
  148:   do
  149:     {
  150:       struct alias_map item;
  151: 
  152:       item.alias = name;
  153: 
  154:       if (nmap > 0)
  155: 	retval = (struct alias_map *) bsearch (&item, map, nmap,
  156: 					       sizeof (struct alias_map),
  157: 					       (int (*) PARAMS ((const void *,
  158: 								 const void *))
  159: 						) alias_compare);
  160:       else
  161: 	retval = NULL;
  162: 
  163:       /* We really found an alias.  Return the value.  */
  164:       if (retval != NULL)
  165: 	return retval->value;
  166: 
  167:       /* Perhaps we can find another alias file.  */
  168:       added = 0;
  169:       while (added == 0 && locale_alias_path[0] != '\0')
  170: 	{
  171: 	  const char *start;
  172: 
  173: 	  while (locale_alias_path[0] == ':')
  174: 	    ++locale_alias_path;
  175: 	  start = locale_alias_path;
  176: 
  177: 	  while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
  178: 	    ++locale_alias_path;
  179: 
  180: 	  if (start < locale_alias_path)
  181: 	    added = read_alias_file (start, locale_alias_path - start);
  182: 	}
  183:     }
  184:   while (added != 0);
  185: 
  186:   return NULL;
  187: }
  188: 
  189: 
  190: static size_t
  191: read_alias_file (fname, fname_len)
  192:      const char *fname;
  193:      int fname_len;
  194: {
  195: #ifndef HAVE_ALLOCA
  196:   struct block_list *block_list = NULL;
  197: #endif
  198:   FILE *fp;
  199:   char *full_fname;
  200:   size_t added;
  201:   static const char aliasfile[] = "/locale.alias";
  202: 
  203:   full_fname = (char *) alloca (fname_len + sizeof aliasfile);
  204:   ADD_BLOCK (block_list, full_fname);
  205:   memcpy (full_fname, fname, fname_len);
  206:   memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
  207: 
  208:   fp = fopen (full_fname, "r");
  209:   if (fp == NULL)
  210:     {
  211:       FREE_BLOCKS (block_list);
  212:       return 0;
  213:     }
  214: 
  215:   added = 0;
  216:   while (!feof (fp))
  217:     {
  218:       /* It is a reasonable approach to use a fix buffer here because
  219: 	 a) we are only interested in the first two fields
  220: 	 b) these fields must be usable as file names and so must not
  221: 	    be that long
  222:        */
  223:       char buf[BUFSIZ];
  224:       char *alias;
  225:       char *value;
  226:       char *cp;
  227: 
  228:       if (fgets (buf, BUFSIZ, fp) == NULL)
  229: 	/* EOF reached.  */
  230: 	break;
  231: 
  232:       cp = buf;
  233:       /* Ignore leading white space.  */
  234:       while (isspace (cp[0]))
  235: 	++cp;
  236: 
  237:       /* A leading '#' signals a comment line.  */
  238:       if (cp[0] != '\0' && cp[0] != '#')
  239: 	{
  240: 	  alias = cp++;
  241: 	  while (cp[0] != '\0' && !isspace (cp[0]))
  242: 	    ++cp;
  243: 	  /* Terminate alias name.  */
  244: 	  if (cp[0] != '\0')
  245: 	    *cp++ = '\0';
  246: 
  247: 	  /* Now look for the beginning of the value.  */
  248: 	  while (isspace (cp[0]))
  249: 	    ++cp;
  250: 
  251: 	  if (cp[0] != '\0')
  252: 	    {
  253: 	      char *tp;
  254: 	      size_t len;
  255: 
  256: 	      value = cp++;
  257: 	      while (cp[0] != '\0' && !isspace (cp[0]))
  258: 		++cp;
  259: 	      /* Terminate value.  */
  260: 	      if (cp[0] == '\n')
  261: 		{
  262: 		  /* This has to be done to make the following test
  263: 		     for the end of line possible.  We are looking for
  264: 		     the terminating '\n' which do not overwrite here.  */
  265: 		  *cp++ = '\0';
  266: 		  *cp = '\n';
  267: 		}
  268: 	      else if (cp[0] != '\0')
  269: 		*cp++ = '\0';
  270: 
  271: 	      if (nmap >= maxmap)
  272: 		extend_alias_table ();
  273: 
  274: 	      /* We cannot depend on strdup available in the libc.  Sigh!  */
  275: 	      len = strlen (alias) + 1;
  276: 	      tp = (char *) malloc (len);
  277: 	      if (tp == NULL)
  278: 		{
  279: 		  FREE_BLOCKS (block_list);
  280: 		  return added;
  281: 		}
  282: 	      memcpy (tp, alias, len);
  283: 	      map[nmap].alias = tp;
  284: 
  285: 	      len = strlen (value) + 1;
  286: 	      tp = (char *) malloc (len);
  287: 	      if (tp == NULL)
  288: 		{
  289: 		  FREE_BLOCKS (block_list);
  290: 		  return added;
  291: 		}
  292: 	      memcpy (tp, value, len);
  293: 	      map[nmap].value = tp;
  294: 
  295: 	      ++nmap;
  296: 	      ++added;
  297: 	    }
  298: 	}
  299: 
  300:       /* Possibly not the whole line fits into the buffer.  Ignore
  301: 	 the rest of the line.  */
  302:       while (strchr (cp, '\n') == NULL)
  303: 	{
  304: 	  cp = buf;
  305: 	  if (fgets (buf, BUFSIZ, fp) == NULL)
  306: 	    /* Make sure the inner loop will be left.  The outer loop
  307: 	       will exit at the `feof' test.  */
  308: 	    *cp = '\n';
  309: 	}
  310:     }
  311: 
  312:   /* Should we test for ferror()?  I think we have to silently ignore
  313:      errors.  --drepper  */
  314:   fclose (fp);
  315: 
  316:   if (added > 0)
  317:     qsort (map, nmap, sizeof (struct alias_map),
  318: 	   (int (*) PARAMS ((const void *, const void *))) alias_compare);
  319: 
  320:   FREE_BLOCKS (block_list);
  321:   return added;
  322: }
  323: 
  324: 
  325: static void
  326: extend_alias_table ()
  327: {
  328:   size_t new_size;
  329:   struct alias_map *new_map;
  330: 
  331:   new_size = maxmap == 0 ? 100 : 2 * maxmap;
  332:   new_map = (struct alias_map *) malloc (new_size
  333: 					 * sizeof (struct alias_map));
  334:   if (new_map == NULL)
  335:     /* Simply don't extend: we don't have any more core.  */
  336:     return;
  337: 
  338:   memcpy (new_map, map, nmap * sizeof (struct alias_map));
  339: 
  340:   if (maxmap != 0)
  341:     free (map);
  342: 
  343:   map = new_map;
  344:   maxmap = new_size;
  345: }
  346: 
  347: 
  348: static int
  349: alias_compare (map1, map2)
  350:      const struct alias_map *map1;
  351:      const struct alias_map *map2;
  352: {
  353: #if defined _LIBC || defined HAVE_STRCASECMP
  354:   return strcasecmp (map1->alias, map2->alias);
  355: #else
  356:   const unsigned char *p1 = (const unsigned char *) map1->alias;
  357:   const unsigned char *p2 = (const unsigned char *) map2->alias;
  358:   unsigned char c1, c2;
  359: 
  360:   if (p1 == p2)
  361:     return 0;
  362: 
  363:   do
  364:     {
  365:       /* I know this seems to be odd but the tolower() function in
  366: 	 some systems libc cannot handle nonalpha characters.  */
  367:       c1 = isupper (*p1) ? tolower (*p1) : *p1;
  368:       c2 = isupper (*p2) ? tolower (*p2) : *p2;
  369:       if (c1 == '\0')
  370: 	break;
  371:       ++p1;
  372:       ++p2;
  373:     }
  374:   while (c1 == c2);
  375: 
  376:   return c1 - c2;
  377: #endif
  378: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>