File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / nls.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 01:01:01 2021 UTC (3 years, 3 months ago) by misho
Branches: readline, MAIN
CVS tags: v8_2p0, v8_1p0, HEAD
readline 8.1

    1: /* nls.c -- skeletal internationalization code. */
    2: 
    3: /* Copyright (C) 1996-2017 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.      
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #include <sys/types.h>
   29: 
   30: #include <stdio.h>
   31: 
   32: #if defined (HAVE_UNISTD_H)
   33: #  include <unistd.h>
   34: #endif /* HAVE_UNISTD_H */
   35: 
   36: #if defined (HAVE_STDLIB_H)
   37: #  include <stdlib.h>
   38: #else
   39: #  include "ansi_stdlib.h"
   40: #endif /* HAVE_STDLIB_H */
   41: 
   42: #if defined (HAVE_LOCALE_H)
   43: #  include <locale.h>
   44: #endif
   45: 
   46: #if defined (HAVE_LANGINFO_CODESET)
   47: #  include <langinfo.h>
   48: #endif
   49: 
   50: #include <ctype.h>
   51: 
   52: #include "rldefs.h"
   53: #include "readline.h"
   54: #include "rlshell.h"
   55: #include "rlprivate.h"
   56: 
   57: static int utf8locale PARAMS((char *));
   58: 
   59: #if !defined (HAVE_SETLOCALE)    
   60: /* A list of legal values for the LANG or LC_CTYPE environment variables.
   61:    If a locale name in this list is the value for the LC_ALL, LC_CTYPE,
   62:    or LANG environment variable (using the first of those with a value),
   63:    readline eight-bit mode is enabled. */
   64: static char *legal_lang_values[] =
   65: {
   66:  "iso88591",
   67:  "iso88592",
   68:  "iso88593",
   69:  "iso88594",
   70:  "iso88595",
   71:  "iso88596",
   72:  "iso88597",
   73:  "iso88598",
   74:  "iso88599",
   75:  "iso885910",
   76:  "koi8r",
   77:  "utf8",
   78:   0
   79: };
   80: 
   81: static char *normalize_codeset PARAMS((char *));
   82: #endif /* !HAVE_SETLOCALE */
   83: 
   84: static char *find_codeset PARAMS((char *, size_t *));
   85: 
   86: static char *_rl_get_locale_var PARAMS((const char *));
   87: 
   88: static char *
   89: _rl_get_locale_var (const char *v)
   90: {
   91:   char *lspec;
   92: 
   93:   lspec = sh_get_env_value ("LC_ALL");
   94:   if (lspec == 0 || *lspec == 0)
   95:     lspec = sh_get_env_value (v);
   96:   if (lspec == 0 || *lspec == 0)
   97:     lspec = sh_get_env_value ("LANG");
   98: 
   99:   return lspec;
  100: }
  101: 
  102: static int
  103: utf8locale (char *lspec)
  104: {
  105:   char *cp;
  106:   size_t len;
  107: 
  108: #if HAVE_LANGINFO_CODESET
  109:   cp = nl_langinfo (CODESET);
  110:   return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
  111: #else
  112:   cp = find_codeset (lspec, &len);
  113: 
  114:   if (cp == 0 || len < 4 || len > 5)
  115:     return 0;
  116:   return ((len == 5) ? strncmp (cp, "UTF-8", len) == 0 : strncmp (cp, "utf8", 4) == 0);
  117: #endif
  118: }
  119: 
  120: /* Query the right environment variables and call setlocale() to initialize
  121:    the C library locale settings. */
  122: char *
  123: _rl_init_locale (void)
  124: {
  125:   char *ret, *lspec;
  126: 
  127:   /* Set the LC_CTYPE locale category from environment variables. */
  128:   lspec = _rl_get_locale_var ("LC_CTYPE");
  129:   /* Since _rl_get_locale_var queries the right environment variables,
  130:      we query the current locale settings with setlocale(), and, if
  131:      that doesn't return anything, we set lspec to the empty string to
  132:      force the subsequent call to setlocale() to define the `native'
  133:      environment. */
  134:   if (lspec == 0 || *lspec == 0)
  135:     lspec = setlocale (LC_CTYPE, (char *)NULL);
  136:   if (lspec == 0)
  137:     lspec = "";
  138:   ret = setlocale (LC_CTYPE, lspec);	/* ok, since it does not change locale */
  139: 
  140:   _rl_utf8locale = (ret && *ret) ? utf8locale (ret) : 0;
  141: 
  142:   return ret;
  143: }
  144: 
  145: /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value
  146:    to decide the defaults for 8-bit character input and output.  Returns
  147:    1 if we set eight-bit mode. */
  148: int
  149: _rl_init_eightbit (void)
  150: {
  151: /* If we have setlocale(3), just check the current LC_CTYPE category
  152:    value, and go into eight-bit mode if it's not C or POSIX. */
  153: #if defined (HAVE_SETLOCALE)
  154:   char *lspec, *t;
  155: 
  156:   t = _rl_init_locale ();	/* returns static pointer */
  157: 
  158:   if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
  159:     {
  160:       _rl_meta_flag = 1;
  161:       _rl_convert_meta_chars_to_ascii = 0;
  162:       _rl_output_meta_chars = 1;
  163:       return (1);
  164:     }
  165:   else
  166:     return (0);
  167: 
  168: #else /* !HAVE_SETLOCALE */
  169:   char *lspec, *t;
  170:   int i;
  171: 
  172:   /* We don't have setlocale.  Finesse it.  Check the environment for the
  173:      appropriate variables and set eight-bit mode if they have the right
  174:      values. */
  175:   lspec = _rl_get_locale_var ("LC_CTYPE");
  176: 
  177:   if (lspec == 0 || (t = normalize_codeset (lspec)) == 0)
  178:     return (0);
  179:   for (i = 0; t && legal_lang_values[i]; i++)
  180:     if (STREQ (t, legal_lang_values[i]))
  181:       {
  182: 	_rl_meta_flag = 1;
  183: 	_rl_convert_meta_chars_to_ascii = 0;
  184: 	_rl_output_meta_chars = 1;
  185: 	break;
  186:       }
  187: 
  188:   _rl_utf8locale = *t ? STREQ (t, "utf8") : 0;
  189: 
  190:   xfree (t);
  191:   return (legal_lang_values[i] ? 1 : 0);
  192: #endif /* !HAVE_SETLOCALE */
  193: }
  194: 
  195: #if !defined (HAVE_SETLOCALE)
  196: static char *
  197: normalize_codeset (char *codeset)
  198: {
  199:   size_t namelen, i;
  200:   int len, all_digits;
  201:   char *wp, *retval;
  202: 
  203:   codeset = find_codeset (codeset, &namelen);
  204: 
  205:   if (codeset == 0)
  206:     return (codeset);
  207: 
  208:   all_digits = 1;
  209:   for (len = 0, i = 0; i < namelen; i++)
  210:     {
  211:       if (ISALNUM ((unsigned char)codeset[i]))
  212: 	{
  213: 	  len++;
  214: 	  all_digits &= _rl_digit_p (codeset[i]);
  215: 	}
  216:     }
  217: 
  218:   retval = (char *)malloc ((all_digits ? 3 : 0) + len + 1);
  219:   if (retval == 0)
  220:     return ((char *)0);
  221: 
  222:   wp = retval;
  223:   /* Add `iso' to beginning of an all-digit codeset */
  224:   if (all_digits)
  225:     {
  226:       *wp++ = 'i';
  227:       *wp++ = 's';
  228:       *wp++ = 'o';
  229:     }
  230: 
  231:   for (i = 0; i < namelen; i++)
  232:     if (ISALPHA ((unsigned char)codeset[i]))
  233:       *wp++ = _rl_to_lower (codeset[i]);
  234:     else if (_rl_digit_p (codeset[i]))
  235:       *wp++ = codeset[i];
  236:   *wp = '\0';
  237: 
  238:   return retval;
  239: }
  240: #endif /* !HAVE_SETLOCALE */
  241: 
  242: /* Isolate codeset portion of locale specification. */
  243: static char *
  244: find_codeset (char *name, size_t *lenp)
  245: {
  246:   char *cp, *language, *result;
  247: 
  248:   cp = language = name;
  249:   result = (char *)0;
  250: 
  251:   while (*cp && *cp != '_' && *cp != '@' && *cp != '+' && *cp != ',')
  252:     cp++;
  253: 
  254:   /* This does not make sense: language has to be specified.  As
  255:      an exception we allow the variable to contain only the codeset
  256:      name.  Perhaps there are funny codeset names.  */
  257:   if (language == cp) 
  258:     {
  259:       *lenp = strlen (language);
  260:       result = language;
  261:     }
  262:   else
  263:     {
  264:       /* Next is the territory. */
  265:       if (*cp == '_')
  266: 	do
  267: 	  ++cp;
  268: 	while (*cp && *cp != '.' && *cp != '@' && *cp != '+' && *cp != ',' && *cp != '_');
  269: 
  270:       /* Now, finally, is the codeset. */
  271:       result = cp;
  272:       if (*cp == '.')
  273: 	do
  274: 	  ++cp;
  275: 	while (*cp && *cp != '@');
  276: 
  277:       if (cp - result > 2)
  278: 	{
  279: 	  result++;
  280: 	  *lenp = cp - result;
  281: 	}
  282:       else
  283: 	{
  284: 	  *lenp = strlen (language);
  285: 	  result = language;
  286: 	}
  287:     }
  288: 
  289:   return result;
  290: }

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