summaryrefslogtreecommitdiff
path: root/libc/misc/locale
diff options
context:
space:
mode:
Diffstat (limited to 'libc/misc/locale')
-rw-r--r--libc/misc/locale/Makefile46
-rw-r--r--libc/misc/locale/locale.c164
2 files changed, 210 insertions, 0 deletions
diff --git a/libc/misc/locale/Makefile b/libc/misc/locale/Makefile
new file mode 100644
index 000000000..c4b62a661
--- /dev/null
+++ b/libc/misc/locale/Makefile
@@ -0,0 +1,46 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources. Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.mak
+LIBC=$(TOPDIR)libc.a
+
+MSRC=locale.c
+MOBJ= setlocale.o
+
+OBJS=$(MOBJ)
+all: $(MOBJ) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+ $(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(MOBJ): $(MSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(OBJS): Makefile
+
+clean:
+ rm -f *.[oa] *~ core
+
diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c
new file mode 100644
index 000000000..109573871
--- /dev/null
+++ b/libc/misc/locale/locale.c
@@ -0,0 +1,164 @@
+/* setlocale.c
+ * Load LC_CTYPE locale only special for uclibc
+ *
+ * Written by Vladimir Oleynik (c) vodz@usa.net
+ *
+ * This file is part of the uClibc C library and is distributed
+ * under the GNU Library General Public License.
+ * used ideas is part of the GNU C Library.
+ */
+
+/*
+ * No-locale-support setlocale() added.
+ */
+
+#include <locale.h>
+#include <stdio.h> /* NULL, fopen */
+#include <stdlib.h> /* malloc */
+#include <string.h>
+#include <limits.h> /* PATH_MAX */
+
+#include "../ctype/ctype.h"
+
+#undef TEST_LOCALE
+
+
+#ifdef L_setlocale
+
+#if __UCLIBC_HAS_LOCALE__
+
+static char C_LOCALE_NAME[]="C";
+
+#ifdef TEST_LOCALE
+static const char PATH_LOCALE[]="./";
+#else
+static const char PATH_LOCALE[]=__UCLIBC_LOCALE_DIR;
+#endif
+
+static const char LC_CTYPE_STR[]="/LC_CTYPE";
+
+struct SAV_LOADED_LOCALE {
+ char *locale;
+ const unsigned char *buf;
+ struct SAV_LOADED_LOCALE *next;
+};
+
+
+static struct SAV_LOADED_LOCALE sav_loaded_locale [1] = {
+ { C_LOCALE_NAME, _uc_ctype_b_C, 0 }
+};
+
+static struct SAV_LOADED_LOCALE * old_locale = sav_loaded_locale;
+
+static char *set_new_locale(struct SAV_LOADED_LOCALE * s_locale)
+{
+ _uc_ctype_b = s_locale->buf;
+ _uc_ctype_trans = s_locale->buf+LOCALE_BUF_SIZE/2;
+ old_locale = s_locale;
+ return s_locale->locale;
+}
+
+/* Current support only LC_CTYPE or LC_ALL category */
+
+char *setlocale(int category, const char *locale)
+{
+ FILE * fl;
+ struct SAV_LOADED_LOCALE *cur;
+ struct SAV_LOADED_LOCALE *bottom;
+ char full_path[PATH_MAX];
+ char * buf = 0;
+ int l;
+
+ if(category!=LC_CTYPE && category!=LC_ALL)
+ return NULL;
+
+ if(locale==0)
+ return set_new_locale(old_locale);
+
+ if(strcmp(locale, "POSIX")==0)
+ return set_new_locale(sav_loaded_locale);
+ else if(*locale == '\0') {
+
+ locale = getenv(LC_CTYPE_STR+1);
+ if(locale == 0 || *locale == 0)
+ locale = getenv("LANG");
+ if(locale == 0 || *locale == '\0')
+ return set_new_locale(old_locale);
+ if(strcmp(locale, "POSIX")==0)
+ return set_new_locale(sav_loaded_locale);
+ }
+
+ for(cur = sav_loaded_locale; cur; cur = cur->next)
+ if(strcmp(cur->locale, locale)==0)
+ return set_new_locale(cur);
+
+ l = strlen(locale);
+ if((l+sizeof(PATH_LOCALE)+sizeof(LC_CTYPE_STR))>=PATH_MAX)
+ return NULL;
+
+ strcpy(full_path, PATH_LOCALE);
+ strcat(full_path, locale);
+ strcat(full_path, LC_CTYPE_STR);
+ fl = fopen(full_path, "r");
+ if(fl==0)
+ return NULL;
+
+ cur = malloc(sizeof(struct SAV_LOADED_LOCALE)+LOCALE_BUF_SIZE+l);
+ if(cur) {
+ buf = (char *)(cur+1);
+ if(fread(buf, 1, LOCALE_BUF_SIZE+1, fl)!=(LOCALE_BUF_SIZE)) {
+ /* broken locale file */
+ free(cur);
+ buf = 0;
+#ifdef TEST_LOCALE
+ fprintf(stderr, "\nbroken locale file\n");
+#endif
+ }
+ }
+
+ fclose(fl);
+ if(cur==0) /* not enough memory */
+ return NULL;
+ if(buf==0) /* broken locale file, set to "C" */
+ return set_new_locale(sav_loaded_locale);
+
+ cur->next = 0;
+ strcpy(buf+LOCALE_BUF_SIZE, locale);
+
+ bottom = sav_loaded_locale;
+ while(bottom->next!=0)
+ bottom = bottom->next;
+ bottom->next = cur;
+
+ /* next two line only pedantic */
+ cur->buf = buf;
+ cur->locale = buf+LOCALE_BUF_SIZE;
+
+ return set_new_locale(cur);
+}
+
+#else /* no locale support */
+
+char *setlocale(int category, const char *locale)
+{
+ /* Allow locales "C" and "" (native). Both are "C" for our purposes. */
+ if (locale) {
+ if (*locale == 'C') {
+ ++locale;
+ }
+ if (*locale) { /* locale wasn't "C" or ""!! */
+ return NULL;
+ }
+ }
+
+ /* Allow any legal category for "C" or "" (native) locale. */
+ if((category < LC_CTYPE) || (category > LC_ALL)) { /* Illegal category! */
+ return NULL;
+ }
+
+ return "C";
+}
+
+#endif
+
+#endif /* L_setlocale */