1/* Fake setlocale - platform independent, for testing purposes.
2   Copyright (C) 2001-2002 Free Software Foundation, Inc.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2, or (at your option)
7   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 General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software Foundation,
16   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
22#include <stdlib.h>
23#include <locale.h>
24#include <string.h>
25
26/* Return string representation of locale CATEGORY.  */
27static const char *
28category_to_name (int category)
29{
30  const char *retval;
31
32  switch (category)
33  {
34#ifdef LC_COLLATE
35  case LC_COLLATE:
36    retval = "LC_COLLATE";
37    break;
38#endif
39#ifdef LC_CTYPE
40  case LC_CTYPE:
41    retval = "LC_CTYPE";
42    break;
43#endif
44#ifdef LC_MONETARY
45  case LC_MONETARY:
46    retval = "LC_MONETARY";
47    break;
48#endif
49#ifdef LC_NUMERIC
50  case LC_NUMERIC:
51    retval = "LC_NUMERIC";
52    break;
53#endif
54#ifdef LC_TIME
55  case LC_TIME:
56    retval = "LC_TIME";
57    break;
58#endif
59#ifdef LC_MESSAGES
60  case LC_MESSAGES:
61    retval = "LC_MESSAGES";
62    break;
63#endif
64#ifdef LC_RESPONSE
65  case LC_RESPONSE:
66    retval = "LC_RESPONSE";
67    break;
68#endif
69#ifdef LC_ALL
70  case LC_ALL:
71    /* This might not make sense but is perhaps better than any other
72       value.  */
73    retval = "LC_ALL";
74    break;
75#endif
76  default:
77    /* If you have a better idea for a default value let me know.  */
78    retval = "LC_XXX";
79  }
80
81  return retval;
82}
83
84/* An implementation of setlocale that always succeeds, but doesn't
85   actually change the behaviour of locale dependent functions.
86   Assumes setenv()/putenv() is not called.  */
87char *
88setlocale (int category, SETLOCALE_CONST char *locale)
89{
90  static char C_string[] = "C";
91  static char *current_locale = C_string;
92  struct list
93  {
94    int category;
95    char *current_locale;
96    struct list *next;
97  };
98  static struct list *facets = NULL;
99  struct list *facetp;
100  char *retval;
101
102  if (locale != NULL)
103    {
104      char *copy;
105
106      copy = (char *) malloc (strlen (locale) + 1);
107      strcpy (copy, locale);
108
109      if (category == LC_ALL)
110	{
111	  while ((facetp = facets) != NULL)
112	    {
113	      facets = facetp->next;
114	      free (facetp->current_locale);
115	      free (facetp);
116	    }
117	  if (current_locale != C_string)
118	    free (current_locale);
119	  current_locale = copy;
120	}
121      else
122	{
123	  for (facetp = facets; facetp != NULL; facetp = facetp->next)
124	    if (category == facetp->category)
125	      {
126		free (facetp->current_locale);
127		facetp->current_locale = copy;
128		break;
129	      }
130	  if (facetp == NULL)
131	    {
132	      facetp = (struct list *) malloc (sizeof (struct list));
133	      facetp->category = category;
134	      facetp->current_locale = copy;
135	      facetp->next = facets;
136	      facets = facetp;
137	    }
138	}
139    }
140
141  retval = current_locale;
142  for (facetp = facets; facetp != NULL; facetp = facetp->next)
143    if (category == facetp->category)
144      {
145	retval = facetp->current_locale;
146	break;
147      }
148
149  if (retval[0] == '\0')
150    {
151      retval = getenv ("LC_ALL");
152      if (retval == NULL || retval[0] == '\0')
153	{
154	  retval = getenv (category_to_name (category));
155	  if (retval == NULL || retval[0] == '\0')
156	    {
157	      retval = getenv ("LANG");
158	      if (retval == NULL || retval[0] == '\0')
159		retval = "C";
160	    }
161	}
162    }
163  return retval;
164}
165