(root)/
glibc-2.38/
intl/
explodename.c
       1  /* Copyright (C) 1995-2023 Free Software Foundation, Inc.
       2     Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as published by
       6     the Free Software Foundation; either version 2.1 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #ifdef HAVE_CONFIG_H
      18  # include <config.h>
      19  #endif
      20  
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <sys/types.h>
      24  
      25  #include "loadinfo.h"
      26  
      27  /* On some strange systems still no definition of NULL is found.  Sigh!  */
      28  #ifndef NULL
      29  # if defined __STDC__ && __STDC__
      30  #  define NULL ((void *) 0)
      31  # else
      32  #  define NULL 0
      33  # endif
      34  #endif
      35  
      36  /* @@ end of prolog @@ */
      37  
      38  /* Split a locale name NAME into a leading language part and all the
      39     rest.  Return a pointer to the first character after the language,
      40     i.e. to the first byte of the rest.  */
      41  static char *_nl_find_language (const char *name);
      42  
      43  static char *
      44  _nl_find_language (const char *name)
      45  {
      46    while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
      47      ++name;
      48  
      49    return (char *) name;
      50  }
      51  
      52  
      53  int
      54  _nl_explode_name (char *name,
      55  		  const char **language, const char **modifier,
      56  		  const char **territory, const char **codeset,
      57  		  const char **normalized_codeset)
      58  {
      59    char *cp;
      60    int mask;
      61  
      62    *modifier = NULL;
      63    *territory = NULL;
      64    *codeset = NULL;
      65    *normalized_codeset = NULL;
      66  
      67    /* Now we determine the single parts of the locale name.  First
      68       look for the language.  Termination symbols are `_', '.', and `@'.  */
      69    mask = 0;
      70    *language = cp = name;
      71    cp = _nl_find_language (*language);
      72  
      73    if (*language == cp)
      74      /* This does not make sense: language has to be specified.  Use
      75         this entry as it is without exploding.  Perhaps it is an alias.  */
      76      cp = strchr (*language, '\0');
      77    else
      78      {
      79        if (cp[0] == '_')
      80  	{
      81  	  /* Next is the territory.  */
      82  	  cp[0] = '\0';
      83  	  *territory = ++cp;
      84  
      85  	  while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
      86  	    ++cp;
      87  
      88  	  mask |= XPG_TERRITORY;
      89  	}
      90  
      91        if (cp[0] == '.')
      92  	{
      93  	  /* Next is the codeset.  */
      94  	  cp[0] = '\0';
      95  	  *codeset = ++cp;
      96  
      97  	  while (cp[0] != '\0' && cp[0] != '@')
      98  	    ++cp;
      99  
     100  	  mask |= XPG_CODESET;
     101  
     102  	  if (*codeset != cp && (*codeset)[0] != '\0')
     103  	    {
     104  	      *normalized_codeset = _nl_normalize_codeset (*codeset,
     105  							   cp - *codeset);
     106  	      if (*normalized_codeset == NULL)
     107  		return -1;
     108  	      else if (strcmp (*codeset, *normalized_codeset) == 0)
     109  		free ((char *) *normalized_codeset);
     110  	      else
     111  		mask |= XPG_NORM_CODESET;
     112  	    }
     113  	}
     114      }
     115  
     116    if (cp[0] == '@')
     117      {
     118        /* Next is the modifier.  */
     119        cp[0] = '\0';
     120        *modifier = ++cp;
     121  
     122        if (cp[0] != '\0')
     123  	mask |= XPG_MODIFIER;
     124      }
     125  
     126    if (*territory != NULL && (*territory)[0] == '\0')
     127      mask &= ~XPG_TERRITORY;
     128  
     129    if (*codeset != NULL && (*codeset)[0] == '\0')
     130      mask &= ~XPG_CODESET;
     131  
     132    return mask;
     133  }