Home | History | Annotate | Line # | Download | only in intl
      1 /*	$NetBSD: explodename.c,v 1.1.1.1 2016/01/10 21:36:17 christos Exp $	*/
      2 
      3 /* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
      4    Contributed by Ulrich Drepper <drepper (at) gnu.ai.mit.edu>, 1995.
      5 
      6    This program is free software; you can redistribute it and/or modify it
      7    under the terms of the GNU Library General Public License as published
      8    by the Free Software Foundation; either version 2, or (at your option)
      9    any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    Library General Public License for more details.
     15 
     16    You should have received a copy of the GNU Library General Public
     17    License along with this program; if not, write to the Free Software
     18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
     19    USA.  */
     20 
     21 #ifdef HAVE_CONFIG_H
     22 # include <config.h>
     23 #endif
     24 
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <sys/types.h>
     28 
     29 #include "loadinfo.h"
     30 
     31 /* On some strange systems still no definition of NULL is found.  Sigh!  */
     32 #ifndef NULL
     33 # if defined __STDC__ && __STDC__
     34 #  define NULL ((void *) 0)
     35 # else
     36 #  define NULL 0
     37 # endif
     38 #endif
     39 
     40 /* @@ end of prolog @@ */
     41 
     42 char *
     43 _nl_find_language (name)
     44      const char *name;
     45 {
     46   while (name[0] != '\0' && name[0] != '_' && name[0] != '@'
     47 	 && name[0] != '+' && name[0] != ',')
     48     ++name;
     49 
     50   return (char *) name;
     51 }
     52 
     53 
     54 int
     55 _nl_explode_name (name, language, modifier, territory, codeset,
     56 		  normalized_codeset, special, sponsor, revision)
     57      char *name;
     58      const char **language;
     59      const char **modifier;
     60      const char **territory;
     61      const char **codeset;
     62      const char **normalized_codeset;
     63      const char **special;
     64      const char **sponsor;
     65      const char **revision;
     66 {
     67   enum { undecided, xpg, cen } syntax;
     68   char *cp;
     69   int mask;
     70 
     71   *modifier = NULL;
     72   *territory = NULL;
     73   *codeset = NULL;
     74   *normalized_codeset = NULL;
     75   *special = NULL;
     76   *sponsor = NULL;
     77   *revision = NULL;
     78 
     79   /* Now we determine the single parts of the locale name.  First
     80      look for the language.  Termination symbols are `_' and `@' if
     81      we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
     82   mask = 0;
     83   syntax = undecided;
     84   *language = cp = name;
     85   cp = _nl_find_language (*language);
     86 
     87   if (*language == cp)
     88     /* This does not make sense: language has to be specified.  Use
     89        this entry as it is without exploding.  Perhaps it is an alias.  */
     90     cp = strchr (*language, '\0');
     91   else if (cp[0] == '_')
     92     {
     93       /* Next is the territory.  */
     94       cp[0] = '\0';
     95       *territory = ++cp;
     96 
     97       while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@'
     98 	     && cp[0] != '+' && cp[0] != ',' && cp[0] != '_')
     99 	++cp;
    100 
    101       mask |= TERRITORY;
    102 
    103       if (cp[0] == '.')
    104 	{
    105 	  /* Next is the codeset.  */
    106 	  syntax = xpg;
    107 	  cp[0] = '\0';
    108 	  *codeset = ++cp;
    109 
    110 	  while (cp[0] != '\0' && cp[0] != '@')
    111 	    ++cp;
    112 
    113 	  mask |= XPG_CODESET;
    114 
    115 	  if (*codeset != cp && (*codeset)[0] != '\0')
    116 	    {
    117 	      *normalized_codeset = _nl_normalize_codeset (*codeset,
    118 							   cp - *codeset);
    119 	      if (strcmp (*codeset, *normalized_codeset) == 0)
    120 		free ((char *) *normalized_codeset);
    121 	      else
    122 		mask |= XPG_NORM_CODESET;
    123 	    }
    124 	}
    125     }
    126 
    127   if (cp[0] == '@' || (syntax != xpg && cp[0] == '+'))
    128     {
    129       /* Next is the modifier.  */
    130       syntax = cp[0] == '@' ? xpg : cen;
    131       cp[0] = '\0';
    132       *modifier = ++cp;
    133 
    134       while (syntax == cen && cp[0] != '\0' && cp[0] != '+'
    135 	     && cp[0] != ',' && cp[0] != '_')
    136 	++cp;
    137 
    138       mask |= XPG_MODIFIER | CEN_AUDIENCE;
    139     }
    140 
    141   if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_'))
    142     {
    143       syntax = cen;
    144 
    145       if (cp[0] == '+')
    146 	{
    147  	  /* Next is special application (CEN syntax).  */
    148 	  cp[0] = '\0';
    149 	  *special = ++cp;
    150 
    151 	  while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_')
    152 	    ++cp;
    153 
    154 	  mask |= CEN_SPECIAL;
    155 	}
    156 
    157       if (cp[0] == ',')
    158 	{
    159  	  /* Next is sponsor (CEN syntax).  */
    160 	  cp[0] = '\0';
    161 	  *sponsor = ++cp;
    162 
    163 	  while (cp[0] != '\0' && cp[0] != '_')
    164 	    ++cp;
    165 
    166 	  mask |= CEN_SPONSOR;
    167 	}
    168 
    169       if (cp[0] == '_')
    170 	{
    171  	  /* Next is revision (CEN syntax).  */
    172 	  cp[0] = '\0';
    173 	  *revision = ++cp;
    174 
    175 	  mask |= CEN_REVISION;
    176 	}
    177     }
    178 
    179   /* For CEN syntax values it might be important to have the
    180      separator character in the file name, not for XPG syntax.  */
    181   if (syntax == xpg)
    182     {
    183       if (*territory != NULL && (*territory)[0] == '\0')
    184 	mask &= ~TERRITORY;
    185 
    186       if (*codeset != NULL && (*codeset)[0] == '\0')
    187 	mask &= ~XPG_CODESET;
    188 
    189       if (*modifier != NULL && (*modifier)[0] == '\0')
    190 	mask &= ~XPG_MODIFIER;
    191     }
    192 
    193   return mask;
    194 }
    195