]>
git.saurik.com Git - apple/libc.git/blob - nls/FreeBSD/msgcat.c
9b61cc9965b5be7c2f75ebae283d58e94162d4fd
1 /***********************************************************
2 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that Alfalfa's name not be used in
11 advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission.
14 ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 If you make any modifications, bugfixes or other changes to this software
23 we'd appreciate it if you could send a copy to us so we can keep things
24 up-to-date. Many thanks.
26 Alfalfa Software, Inc.
28 Cambridge, MA 02139 USA
31 ******************************************************************/
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.48 2003/10/29 10:45:01 tjr Exp $");
37 * We need a better way of handling errors than printing text. I need
38 * to add an error handling routine.
41 #include "namespace.h"
42 #include <sys/types.h>
54 #include "un-namespace.h"
57 #include "../locale/setlocale.h" /* for ENCODING_LEN */
59 #define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
64 #define NLERR ((nl_catd) -1)
65 #define NLRETERR(errc) { errno = errc; return (NLERR); }
67 static nl_catd
loadCat();
69 static void __nls_free_resources();
78 char *nlspath
, *lang
, *base
, *cptr
, *pathP
, *tmpptr
;
79 char *cptr1
, *plang
, *pter
, *pcode
;
82 if (name
== NULL
|| *name
== '\0')
85 /* is it absolute path ? if yes, load immediately */
86 if (strchr(name
, '/') != NULL
)
87 return (loadCat(name
));
89 if (type
== NL_CAT_LOCALE
)
90 lang
= setlocale(LC_MESSAGES
, NULL
);
92 lang
= getenv("LANG");
94 if (lang
== NULL
|| *lang
== '\0' || strlen(lang
) > ENCODING_LEN
||
96 (lang
[1] == '\0' || (lang
[1] == '.' && lang
[2] == '\0'))) ||
97 strchr(lang
, '/') != NULL
)
100 if ((plang
= cptr1
= strdup(lang
)) == NULL
)
102 if ((cptr
= strchr(cptr1
, '@')) != NULL
)
105 if ((cptr
= strchr(cptr1
, '_')) != NULL
) {
109 if ((cptr
= strchr(cptr1
, '.')) != NULL
) {
114 if ((nlspath
= getenv("NLSPATH")) == NULL
|| issetugid())
115 nlspath
= _DEFAULT_NLS_PATH
;
117 if ((base
= cptr
= strdup(nlspath
)) == NULL
) {
124 while ((nlspath
= strsep(&cptr
, ":")) != NULL
) {
127 for (; *nlspath
; ++nlspath
) {
128 if (*nlspath
== '%') {
129 switch (*(nlspath
+ 1)) {
143 tmpptr
= (char *)name
;
152 *(pathP
++) = *nlspath
;
157 spcleft
= sizeof(path
) -
159 if (strlcpy(pathP
, tmpptr
, spcleft
) >=
164 NLRETERR(ENAMETOOLONG
);
166 pathP
+= strlen(tmpptr
);
168 if (pathP
- path
>= sizeof(path
) - 1)
170 *(pathP
++) = *nlspath
;
174 if (stat(path
, &sbuf
) == 0) {
177 return (loadCat(path
));
180 tmpptr
= (char *)name
;
191 * We've got an odd situation here. The odds are real good that the
192 * number we are looking for is almost the same as the index. We could
193 * use the index, check the difference and do something intelligent, but
194 * I haven't quite figured out what's intelligent.
197 * Take an id N. If there are > N items in the list, then N cannot
198 * be more than N items from the start, since otherwise there would
199 * have to be duplicate items. So we can safely set the top to N+1
200 * (after taking into account that ids start at 1, and arrays at 0)
202 * Let's say we are at position P, and we are looking for N, but have
203 * V. If N > V, then the furthest away that N could be is
204 * P + (N-V). So we can safely set hi to P+(N-V)+1. For example:
205 * We are looking for 10, but have 8
211 #define LOOKUP(PARENT, CHILD, ID, NUM, SET) { \
213 if (ID - 1 < PARENT->NUM) { \
218 cur = (hi - lo) / 2; \
221 CHILD = PARENT->SET + cur; \
222 if (CHILD->ID == ID) \
224 if (CHILD->ID < ID) { \
226 if (hi > cur + (ID - CHILD->ID) + 1) \
227 hi = cur + (ID - CHILD->ID) + 1; \
238 cur += ((hi - lo) / 2) * dir; \
248 long lo
, hi
, cur
, dir
;
250 if (cat
== NULL
|| setId
<= 0)
252 LOOKUP(cat
, set
, setId
, numSets
, sets
);
253 if (set
->invalid
&& loadSet(cat
, set
) <= 0)
264 long lo
, hi
, cur
, dir
;
266 if (set
== NULL
|| set
->invalid
|| msgId
<= 0)
268 LOOKUP(set
, msg
, msgId
, numMsgs
, u
.msgs
);
273 catgets(catd
, setId
, msgId
, dflt
)
280 MCCatT
*cat
= (MCCatT
*)catd
;
283 if (catd
== NULL
|| catd
== NLERR
)
284 return ((char *)dflt
);
285 msg
= MCGetMsg(MCGetSet(cat
, setId
), msgId
);
290 return ((char *)cptr
);
297 MCCatT
*cat
= (MCCatT
*)catd
;
299 if (catd
== NULL
|| catd
== NLERR
) {
304 if (cat
->loadType
!= MCLoadAll
)
306 (void)fclose(cat
->fp
);
307 __nls_free_resources(cat
, cat
->numSets
);
316 /* Note that only malloc failures are allowed to return an error */
317 static char *_errowner
= "Message Catalog System";
319 #define CORRUPT() { \
320 (void)fclose(cat->fp); \
321 (void)fprintf(stderr, "%s: corrupt file.", _errowner); \
326 #define NOSPACE() { \
328 (void)fclose(cat->fp); \
329 (void)fprintf(stderr, "%s: no more memory.", _errowner); \
336 __nls_free_resources(cat
, i
)
343 for (j
= 0; j
< i
; j
++) {
355 __const
char *catpath
;
364 if ((cat
= (MCCatT
*)malloc(sizeof(MCCatT
))) == NULL
)
366 cat
->loadType
= MCLoadBySet
;
368 if ((cat
->fp
= fopen(catpath
, "r")) == NULL
) {
374 (void)_fcntl(fileno(cat
->fp
), F_SETFD
, FD_CLOEXEC
);
376 if (fread(&header
, sizeof(header
), 1, cat
->fp
) != 1 ||
377 strncmp(header
.magic
, MCMagic
, MCMagicLen
) != 0)
380 if (header
.majorVer
!= MCMajorVer
) {
381 (void)fclose(cat
->fp
);
383 (void)fprintf(stderr
, "%s: %s is version %ld, we need %ld.\n",
384 _errowner
, catpath
, header
.majorVer
, MCMajorVer
);
387 if (header
.numSets
<= 0) {
388 (void)fclose(cat
->fp
);
390 (void)fprintf(stderr
, "%s: %s has %ld sets!\n",
391 _errowner
, catpath
, header
.numSets
);
395 cat
->numSets
= header
.numSets
;
396 if ((cat
->sets
= (MCSetT
*)malloc(sizeof(MCSetT
) * header
.numSets
)) ==
400 nextSet
= header
.firstSet
;
401 for (i
= 0; i
< cat
->numSets
; ++i
) {
402 if (fseeko(cat
->fp
, nextSet
, SEEK_SET
) == -1) {
403 __nls_free_resources(cat
, i
);
407 /* read in the set header */
409 if (fread(set
, sizeof(*set
), 1, cat
->fp
) != 1) {
410 __nls_free_resources(cat
, i
);
414 /* if it's invalid, skip over it (and backup 'i') */
417 nextSet
= set
->nextSet
;
421 if (cat
->loadType
== MCLoadAll
) {
424 if ((res
= loadSet(cat
, set
)) <= 0) {
426 __nls_free_resources(cat
, i
);
435 nextSet
= set
->nextSet
;
438 if (cat
->loadType
== MCLoadAll
) {
439 (void)fclose(cat
->fp
);
443 return ((nl_catd
) cat
);
456 if (fseeko(cat
->fp
, set
->data
.off
, SEEK_SET
) == -1)
458 if ((set
->data
.str
= malloc(set
->dataLen
)) == NULL
)
460 if (fread(set
->data
.str
, set
->dataLen
, 1, cat
->fp
) != 1) {
467 /* Get the messages */
468 if (fseeko(cat
->fp
, set
->u
.firstMsg
, SEEK_SET
) == -1) {
474 if ((set
->u
.msgs
= (MCMsgT
*)malloc(sizeof(MCMsgT
) * set
->numMsgs
)) ==
482 for (i
= 0; i
< set
->numMsgs
; ++i
) {
483 msg
= set
->u
.msgs
+ i
;
484 if (fread(msg
, sizeof(*msg
), 1, cat
->fp
) != 1) {
495 msg
->msg
.str
= (char *)(set
->data
.str
+ msg
->msg
.off
);
497 set
->invalid
= FALSE
;