(linenum→info "unix/slp.c:2238")

glibc/2.7/intl/bindtextdom.c

    1: /* Implementation of the bindtextdomain(3) function
    2:    Copyright (C) 1995-1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library 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 GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #ifdef HAVE_CONFIG_H
   21: # include <config.h>
   22: #endif
   23: 
   24: #include <stddef.h>
   25: #include <stdlib.h>
   26: #include <string.h>
   27: 
   28: #ifdef _LIBC
   29: # include <libintl.h>
   30: #else
   31: # include "libgnuintl.h"
   32: #endif
   33: #include "gettextP.h"
   34: 
   35: #ifdef _LIBC
   36: /* We have to handle multi-threaded applications.  */
   37: # include <bits/libc-lock.h>
   38: #else
   39: /* Provide dummy implementation if this is outside glibc.  */
   40: # define __libc_rwlock_define(CLASS, NAME)
   41: # define __libc_rwlock_wrlock(NAME)
   42: # define __libc_rwlock_unlock(NAME)
   43: #endif
   44: 
   45: /* The internal variables in the standalone libintl.a must have different
   46:    names than the internal variables in GNU libc, otherwise programs
   47:    using libintl.a cannot be linked statically.  */
   48: #if !defined _LIBC
   49: # define _nl_default_dirname libintl_nl_default_dirname
   50: # define _nl_domain_bindings libintl_nl_domain_bindings
   51: #endif
   52: 
   53: /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
   54: #ifndef offsetof
   55: # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
   56: #endif
   57: 
   58: /* @@ end of prolog @@ */
   59: 
   60: /* Contains the default location of the message catalogs.  */
   61: extern const char _nl_default_dirname[];
   62: #ifdef _LIBC
   63: libc_hidden_proto (_nl_default_dirname)
   64: #endif
   65: 
   66: /* List with bindings of specific domains.  */
   67: extern struct binding *_nl_domain_bindings;
   68: 
   69: /* Lock variable to protect the global data in the gettext implementation.  */
   70: __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
   71: 
   72: 
   73: /* Names for the libintl functions are a problem.  They must not clash
   74:    with existing names and they should follow ANSI C.  But this source
   75:    code is also used in GNU C Library where the names have a __
   76:    prefix.  So we have to make a difference here.  */
   77: #ifdef _LIBC
   78: # define BINDTEXTDOMAIN __bindtextdomain
   79: # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
   80: # ifndef strdup
   81: #  define strdup(str) __strdup (str)
   82: # endif
   83: #else
   84: # define BINDTEXTDOMAIN libintl_bindtextdomain
   85: # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
   86: #endif
   87: 
   88: /* Prototypes for local functions.  */
   89: static void set_binding_values PARAMS ((const char *domainname,
   90:                                         const char **dirnamep,
   91:                                         const char **codesetp));
   92: 
   93: /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
   94:    to be used for the DOMAINNAME message catalog.
   95:    If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
   96:    modified, only the current value is returned.
   97:    If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
   98:    modified nor returned.  */
   99: static void
  100: set_binding_values (domainname, dirnamep, codesetp)
  101:      const char *domainname;
  102:      const char **dirnamep;
  103:      const char **codesetp;
  104: {
  105:   struct binding *binding;
  106:   int modified;
  107: 
  108:   /* Some sanity checks.  */
  109:   if (domainname == NULL || domainname[0] == '\0')
  110:     {
  111:       if (dirnamep)
  112:         *dirnamep = NULL;
  113:       if (codesetp)
  114:         *codesetp = NULL;
  115:       return;
  116:     }
  117: 
  118:   __libc_rwlock_wrlock (_nl_state_lock);
  119: 
  120:   modified = 0;
  121: 
  122:   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
  123:     {
  124:       int compare = strcmp (domainname, binding->domainname);
  125:       if (compare == 0)
  126:         /* We found it!  */
  127:         break;
  128:       if (compare < 0)
  129:         {
  130:           /* It is not in the list.  */
  131:           binding = NULL;
  132:           break;
  133:         }
  134:     }
  135: 
  136:   if (binding != NULL)
  137:     {
  138:       if (dirnamep)
  139:         {
  140:           const char *dirname = *dirnamep;
  141: 
  142:           if (dirname == NULL)
  143:             /* The current binding has be to returned.  */
  144:             *dirnamep = binding->dirname;
  145:           else
  146:             {
  147:               /* The domain is already bound.  If the new value and the old
  148:                  one are equal we simply do nothing.  Otherwise replace the
  149:                  old binding.  */
  150:               char *result = binding->dirname;
  151:               if (strcmp (dirname, result) != 0)
  152:                 {
  153:                   if (strcmp (dirname, _nl_default_dirname) == 0)
  154:                     result = (char *) _nl_default_dirname;
  155:                   else
  156:                     {
  157: #if defined _LIBC || defined HAVE_STRDUP
  158:                       result = strdup (dirname);
  159: #else
  160:                       size_t len = strlen (dirname) + 1;
  161:                       result = (char *) malloc (len);
  162:                       if (__builtin_expect (result != NULL, 1))
  163:                         memcpy (result, dirname, len);
  164: #endif
  165:                     }
  166: 
  167:                   if (__builtin_expect (result != NULL, 1))
  168:                     {
  169:                       if (binding->dirname != _nl_default_dirname)
  170:                         free (binding->dirname);
  171: 
  172:                       binding->dirname = result;
  173:                       modified = 1;
  174:                     }
  175:                 }
  176:               *dirnamep = result;
  177:             }
  178:         }
  179: 
  180:       if (codesetp)
  181:         {
  182:           const char *codeset = *codesetp;
  183: 
  184:           if (codeset == NULL)
  185:             /* The current binding has be to returned.  */
  186:             *codesetp = binding->codeset;
  187:           else
  188:             {
  189:               /* The domain is already bound.  If the new value and the old
  190:                  one are equal we simply do nothing.  Otherwise replace the
  191:                  old binding.  */
  192:               char *result = binding->codeset;
  193:               if (result == NULL || strcmp (codeset, result) != 0)
  194:                 {
  195: #if defined _LIBC || defined HAVE_STRDUP
  196:                   result = strdup (codeset);
  197: #else
  198:                   size_t len = strlen (codeset) + 1;
  199:                   result = (char *) malloc (len);
  200:                   if (__builtin_expect (result != NULL, 1))
  201:                     memcpy (result, codeset, len);
  202: #endif
  203: 
  204:                   if (__builtin_expect (result != NULL, 1))
  205:                     {
  206:                       if (binding->codeset != NULL)
  207:                         free (binding->codeset);
  208: 
  209:                       binding->codeset = result;
  210:                       modified = 1;
  211:                     }
  212:                 }
  213:               *codesetp = result;
  214:             }
  215:         }
  216:     }
  217:   else if ((dirnamep == NULL || *dirnamep == NULL)
  218:            && (codesetp == NULL || *codesetp == NULL))
  219:     {
  220:       /* Simply return the default values.  */
  221:       if (dirnamep)
  222:         *dirnamep = _nl_default_dirname;
  223:       if (codesetp)
  224:         *codesetp = NULL;
  225:     }
  226:   else
  227:     {
  228:       /* We have to create a new binding.  */
  229:       size_t len = strlen (domainname) + 1;
  230:       struct binding *new_binding =
  231:         (struct binding *) malloc (offsetof (struct binding, domainname) + len);
  232: 
  233:       if (__builtin_expect (new_binding == NULL, 0))
  234:         goto failed;
  235: 
  236:       memcpy (new_binding->domainname, domainname, len);
  237: 
  238:       if (dirnamep)
  239:         {
  240:           const char *dirname = *dirnamep;
  241: 
  242:           if (dirname == NULL)
  243:             /* The default value.  */
  244:             dirname = _nl_default_dirname;
  245:           else
  246:             {
  247:               if (strcmp (dirname, _nl_default_dirname) == 0)
  248:                 dirname = _nl_default_dirname;
  249:               else
  250:                 {
  251:                   char *result;
  252: #if defined _LIBC || defined HAVE_STRDUP
  253:                   result = strdup (dirname);
  254:                   if (__builtin_expect (result == NULL, 0))
  255:                     goto failed_dirname;
  256: #else
  257:                   size_t len = strlen (dirname) + 1;
  258:                   result = (char *) malloc (len);
  259:                   if (__builtin_expect (result == NULL, 0))
  260:                     goto failed_dirname;
  261:                   memcpy (result, dirname, len);
  262: #endif
  263:                   dirname = result;
  264:                 }
  265:             }
  266:           *dirnamep = dirname;
  267:           new_binding->dirname = (char *) dirname;
  268:         }
  269:       else
  270:         /* The default value.  */
  271:         new_binding->dirname = (char *) _nl_default_dirname;
  272: 
  273:       if (codesetp)
  274:         {
  275:           const char *codeset = *codesetp;
  276: 
  277:           if (codeset != NULL)
  278:             {
  279:               char *result;
  280: 
  281: #if defined _LIBC || defined HAVE_STRDUP
  282:               result = strdup (codeset);
  283:               if (__builtin_expect (result == NULL, 0))
  284:                 goto failed_codeset;
  285: #else
  286:               size_t len = strlen (codeset) + 1;
  287:               result = (char *) malloc (len);
  288:               if (__builtin_expect (result == NULL, 0))
  289:                 goto failed_codeset;
  290:               memcpy (result, codeset, len);
  291: #endif
  292:               codeset = result;
  293:             }
  294:           *codesetp = codeset;
  295:           new_binding->codeset = (char *) codeset;
  296:         }
  297:       else
  298:         new_binding->codeset = NULL;
  299: 
  300:       /* Now enqueue it.  */
  301:       if (_nl_domain_bindings == NULL
  302:           || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
  303:         {
  304:           new_binding->next = _nl_domain_bindings;
  305:           _nl_domain_bindings = new_binding;
  306:         }
  307:       else
  308:         {
  309:           binding = _nl_domain_bindings;
  310:           while (binding->next != NULL
  311:                  && strcmp (domainname, binding->next->domainname) > 0)
  312:             binding = binding->next;
  313: 
  314:           new_binding->next = binding->next;
  315:           binding->next = new_binding;
  316:         }
  317: 
  318:       modified = 1;
  319: 
  320:       /* Here we deal with memory allocation failures.  */
  321:       if (0)
  322:         {
  323:         failed_codeset:
  324:           if (new_binding->dirname != _nl_default_dirname)
  325:             free (new_binding->dirname);
  326:         failed_dirname:
  327:           free (new_binding);
  328:         failed:
  329:           if (dirnamep)
  330:             *dirnamep = NULL;
  331:           if (codesetp)
  332:             *codesetp = NULL;
  333:         }
  334:     }
  335: 
  336:   /* If we modified any binding, we flush the caches.  */
  337:   if (modified)
  338:     ++_nl_msg_cat_cntr;
  339: 
  340:   __libc_rwlock_unlock (_nl_state_lock);
  341: }
  342: 
  343: /* Specify that the DOMAINNAME message catalog will be found
  344:    in DIRNAME rather than in the system locale data base.  */
  345: char *
  346: BINDTEXTDOMAIN (domainname, dirname)
  347:      const char *domainname;
  348:      const char *dirname;
  349: {
  350:   set_binding_values (domainname, &dirname, NULL);
  351:   return (char *) dirname;
  352: }
  353: 
  354: /* Specify the character encoding in which the messages from the
  355:    DOMAINNAME message catalog will be returned.  */
  356: char *
  357: BIND_TEXTDOMAIN_CODESET (domainname, codeset)
  358:      const char *domainname;
  359:      const char *codeset;
  360: {
  361:   set_binding_values (domainname, NULL, &codeset);
  362:   return (char *) codeset;
  363: }
  364: 
  365: #ifdef _LIBC
  366: /* Aliases for function names in GNU C Library.  */
  367: weak_alias (__bindtextdomain, bindtextdomain);
  368: weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
  369: #endif
Syntax (Markdown)