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