fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / locale / ldpart.c
bloba284b9db2eb2826d99330903ead78d8e312b3d97
1 /*
2 * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
27 #include <sys/cdefs.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/syslimits.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
37 #include "setlocale.h"
38 #include "ldpart.h"
40 static int split_lines(char *, const char *);
41 static void set_from_buf(const char *, int, const char **);
43 int
44 __part_load_locale(const char *name,
45 int *using_locale,
46 char *locale_buf,
47 const char *category_filename,
48 int locale_buf_size_max,
49 int locale_buf_size_min,
50 const char **dst_localebuf) {
52 static char locale_buf_C[] = "C";
53 static int num_lines;
55 int fd;
56 char *lbuf;
57 char *p;
58 const char *plim;
59 char filename[PATH_MAX];
60 struct stat st;
61 size_t namesize;
62 size_t bufsize;
63 int save_using_locale;
64 char *nptr;
66 save_using_locale = *using_locale;
67 *using_locale = 0;
69 if (name == NULL)
70 goto no_locale;
72 if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
73 return 0;
76 * If the locale name is the same as our cache, use the cache.
78 lbuf = locale_buf;
79 if (lbuf != NULL && strcmp(name, lbuf) == 0) {
80 set_from_buf(lbuf, num_lines, dst_localebuf);
81 *using_locale = 1;
82 return 0;
86 * Slurp the locale file into the cache.
88 namesize = strlen(name) + 1;
90 if (!_PathLocale)
91 goto no_locale;
92 /* Range checking not needed, 'name' size is limited */
93 strcpy(filename, _PathLocale);
94 strcat(filename, "/");
95 strcat(filename, name);
96 strcat(filename, "/");
97 strcat(filename, category_filename);
98 fd = open(filename, O_RDONLY);
99 if (fd < 0)
100 goto no_locale;
101 #ifdef __USE_INTERNAL_STAT64
102 if (fstat64(fd, &st) != 0)
103 #else
104 if (fstat(fd, &st) != 0)
105 #endif
106 goto bad_locale;
107 if (st.st_size <= 0)
108 goto bad_locale;
109 bufsize = namesize + st.st_size;
110 locale_buf = NULL;
112 if (lbuf == NULL || lbuf == locale_buf_C)
114 lbuf = malloc(bufsize);
116 else
118 nptr = realloc(lbuf, bufsize);
119 if (!nptr && lbuf)
120 free (lbuf);
121 lbuf = nptr;
124 if (lbuf == NULL)
125 goto bad_locale;
126 (void) strcpy(lbuf, name);
127 p = lbuf + namesize;
128 plim = p + st.st_size;
129 if (read(fd, p, (size_t) st.st_size) != st.st_size)
130 goto bad_lbuf;
131 if (close(fd) != 0)
132 goto bad_lbuf;
134 * Parse the locale file into localebuf.
136 if (plim[-1] != '\n')
137 goto bad_lbuf;
138 num_lines = split_lines(p, plim);
139 if (num_lines >= locale_buf_size_max)
140 num_lines = locale_buf_size_max;
141 else if (num_lines >= locale_buf_size_min)
142 num_lines = locale_buf_size_min;
143 else
144 goto reset_locale;
145 set_from_buf(lbuf, num_lines, dst_localebuf);
147 * Record the successful parse in the cache.
149 locale_buf = lbuf;
151 *using_locale = 1;
152 return 0;
154 reset_locale:
155 locale_buf = locale_buf_C;
156 save_using_locale = 0;
157 bad_lbuf:
158 free(lbuf);
159 bad_locale:
160 (void)close(fd);
161 no_locale:
162 *using_locale = save_using_locale;
163 return -1;
166 static int
167 split_lines(char *p, const char *plim) {
169 int i;
171 for (i = 0; p < plim; i++) {
172 p = strchr(p, '\n');
173 *p++ = '\0';
175 return i;
178 static void
179 set_from_buf(const char *p, int num_lines, const char **dst_localebuf) {
181 const char **ap;
182 int i;
184 for (ap = dst_localebuf, i = 0; i < num_lines; ++ap, ++i)
185 *ap = p += strlen(p) + 1;