/src/imagemagick/MagickCore/locale.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % L OOO CCCC AAA L EEEEE % |
7 | | % L O O C A A L E % |
8 | | % L O O C AAAAA L EEE % |
9 | | % L O O C A A L E % |
10 | | % LLLLL OOO CCCC A A LLLLL EEEEE % |
11 | | % % |
12 | | % % |
13 | | % MagickCore Image Locale Methods % |
14 | | % % |
15 | | % Software Design % |
16 | | % Cristy % |
17 | | % July 2003 % |
18 | | % % |
19 | | % % |
20 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
21 | | % dedicated to making software imaging solutions freely available. % |
22 | | % % |
23 | | % You may not use this file except in compliance with the License. You may % |
24 | | % obtain a copy of the License at % |
25 | | % % |
26 | | % https://imagemagick.org/license/ % |
27 | | % % |
28 | | % Unless required by applicable law or agreed to in writing, software % |
29 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
30 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
31 | | % See the License for the specific language governing permissions and % |
32 | | % limitations under the License. % |
33 | | % % |
34 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
35 | | % |
36 | | % |
37 | | */ |
38 | | |
39 | | /* |
40 | | Include declarations. |
41 | | */ |
42 | | #include "MagickCore/studio.h" |
43 | | #include "MagickCore/blob.h" |
44 | | #include "MagickCore/client.h" |
45 | | #include "MagickCore/configure.h" |
46 | | #include "MagickCore/exception.h" |
47 | | #include "MagickCore/exception-private.h" |
48 | | #include "MagickCore/image-private.h" |
49 | | #include "MagickCore/linked-list.h" |
50 | | #include "MagickCore/locale_.h" |
51 | | #include "MagickCore/locale-private.h" |
52 | | #include "MagickCore/log.h" |
53 | | #include "MagickCore/memory_.h" |
54 | | #include "MagickCore/memory-private.h" |
55 | | #include "MagickCore/nt-base-private.h" |
56 | | #include "MagickCore/semaphore.h" |
57 | | #include "MagickCore/splay-tree.h" |
58 | | #include "MagickCore/string_.h" |
59 | | #include "MagickCore/string-private.h" |
60 | | #include "MagickCore/token.h" |
61 | | #include "MagickCore/utility.h" |
62 | | #include "MagickCore/utility-private.h" |
63 | | #include "MagickCore/xml-tree.h" |
64 | | #include "MagickCore/xml-tree-private.h" |
65 | | |
66 | | /* |
67 | | Define declarations. |
68 | | */ |
69 | | #if (defined(MAGICKCORE_HAVE_NEWLOCALE) || defined(MAGICKCORE_WINDOWS_SUPPORT)) && !defined(__MINGW32__) |
70 | | # define MAGICKCORE_LOCALE_SUPPORT |
71 | | #endif |
72 | | |
73 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
74 | | # if !defined(locale_t) |
75 | | # define locale_t _locale_t |
76 | | # endif |
77 | | #endif |
78 | | |
79 | 295 | #define LocaleFilename "locale.xml" |
80 | | |
81 | | /* |
82 | | Static declarations. |
83 | | */ |
84 | | static const char |
85 | | *LocaleMap = |
86 | | "<?xml version=\"1.0\"?>" |
87 | | "<localemap>" |
88 | | " <locale name=\"C\">" |
89 | | " <Exception>" |
90 | | " <Message name=\"\">" |
91 | | " </Message>" |
92 | | " </Exception>" |
93 | | " </locale>" |
94 | | "</localemap>"; |
95 | | |
96 | | static SemaphoreInfo |
97 | | *locale_semaphore = (SemaphoreInfo *) NULL; |
98 | | |
99 | | static SplayTreeInfo |
100 | | *locale_cache = (SplayTreeInfo *) NULL; |
101 | | |
102 | | #if defined(MAGICKCORE_LOCALE_SUPPORT) |
103 | | static volatile locale_t |
104 | | c_locale = (locale_t) NULL; |
105 | | #endif |
106 | | |
107 | | /* |
108 | | Forward declarations. |
109 | | */ |
110 | | static MagickBooleanType |
111 | | IsLocaleTreeInstantiated(ExceptionInfo *), |
112 | | LoadLocaleCache(SplayTreeInfo *,const char *,const char *,const char *, |
113 | | const size_t,ExceptionInfo *); |
114 | | |
115 | | #if defined(MAGICKCORE_LOCALE_SUPPORT) |
116 | | /* |
117 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
118 | | % % |
119 | | % % |
120 | | % % |
121 | | + A c q u i r e C L o c a l e % |
122 | | % % |
123 | | % % |
124 | | % % |
125 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
126 | | % |
127 | | % AcquireCLocale() allocates the C locale object, or (locale_t) 0 with |
128 | | % errno set if it cannot be acquired. |
129 | | % |
130 | | % The format of the AcquireCLocale method is: |
131 | | % |
132 | | % locale_t AcquireCLocale(void) |
133 | | % |
134 | | */ |
135 | | static locale_t AcquireCLocale(void) |
136 | 168M | { |
137 | 168M | #if defined(MAGICKCORE_HAVE_NEWLOCALE) |
138 | 168M | if (c_locale == (locale_t) NULL) |
139 | 295 | c_locale=newlocale(LC_ALL_MASK,"C",(locale_t) 0); |
140 | | #elif defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) |
141 | | if (c_locale == (locale_t) NULL) |
142 | | c_locale=_create_locale(LC_ALL,"C"); |
143 | | #endif |
144 | 168M | return(c_locale); |
145 | 168M | } |
146 | | #endif |
147 | | |
148 | | /* |
149 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
150 | | % % |
151 | | % % |
152 | | % % |
153 | | % A c q u i r e L o c a l e S p l a y T r e e % |
154 | | % % |
155 | | % % |
156 | | % % |
157 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
158 | | % |
159 | | % AcquireLocaleSplayTree() caches one or more locale configurations which |
160 | | % provides a mapping between locale attributes and a locale tag. |
161 | | % |
162 | | % The format of the AcquireLocaleSplayTree method is: |
163 | | % |
164 | | % SplayTreeInfo *AcquireLocaleSplayTree(const char *filename, |
165 | | % ExceptionInfo *exception) |
166 | | % |
167 | | % A description of each parameter follows: |
168 | | % |
169 | | % o filename: the font file tag. |
170 | | % |
171 | | % o locale: the actual locale. |
172 | | % |
173 | | % o exception: return any errors or warnings in this structure. |
174 | | % |
175 | | */ |
176 | | |
177 | | static void *DestroyLocaleNode(void *locale_info) |
178 | 0 | { |
179 | 0 | LocaleInfo |
180 | 0 | *p; |
181 | |
|
182 | 0 | p=(LocaleInfo *) locale_info; |
183 | 0 | if (p->path != (char *) NULL) |
184 | 0 | p->path=DestroyString(p->path); |
185 | 0 | if (p->tag != (char *) NULL) |
186 | 0 | p->tag=DestroyString(p->tag); |
187 | 0 | if (p->message != (char *) NULL) |
188 | 0 | p->message=DestroyString(p->message); |
189 | 0 | return(RelinquishMagickMemory(p)); |
190 | 0 | } |
191 | | |
192 | | static SplayTreeInfo *AcquireLocaleSplayTree(const char *filename, |
193 | | const char *locale,ExceptionInfo *exception) |
194 | 295 | { |
195 | 295 | SplayTreeInfo |
196 | 295 | *cache; |
197 | | |
198 | 295 | cache=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL, |
199 | 295 | DestroyLocaleNode); |
200 | 295 | #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT |
201 | 295 | { |
202 | 295 | const StringInfo |
203 | 295 | *option; |
204 | | |
205 | 295 | LinkedListInfo |
206 | 295 | *options; |
207 | | |
208 | 295 | options=GetLocaleOptions(filename,exception); |
209 | 295 | option=(const StringInfo *) GetNextValueInLinkedList(options); |
210 | 295 | while (option != (const StringInfo *) NULL) |
211 | 0 | { |
212 | 0 | (void) LoadLocaleCache(cache,(const char *) |
213 | 0 | GetStringInfoDatum(option),GetStringInfoPath(option),locale,0, |
214 | 0 | exception); |
215 | 0 | option=(const StringInfo *) GetNextValueInLinkedList(options); |
216 | 0 | } |
217 | 295 | options=DestroyLocaleOptions(options); |
218 | 295 | if (GetNumberOfNodesInSplayTree(cache) == 0) |
219 | 295 | { |
220 | 295 | options=GetLocaleOptions("english.xml",exception); |
221 | 295 | option=(const StringInfo *) GetNextValueInLinkedList(options); |
222 | 295 | while (option != (const StringInfo *) NULL) |
223 | 0 | { |
224 | 0 | (void) LoadLocaleCache(cache,(const char *) |
225 | 0 | GetStringInfoDatum(option),GetStringInfoPath(option),locale,0, |
226 | 0 | exception); |
227 | 0 | option=(const StringInfo *) GetNextValueInLinkedList(options); |
228 | 0 | } |
229 | 295 | options=DestroyLocaleOptions(options); |
230 | 295 | } |
231 | 295 | } |
232 | | #else |
233 | | magick_unreferenced(filename); |
234 | | #endif |
235 | 295 | if (GetNumberOfNodesInSplayTree(cache) == 0) |
236 | 295 | (void) LoadLocaleCache(cache,LocaleMap,"built-in",locale,0, |
237 | 295 | exception); |
238 | 295 | return(cache); |
239 | 295 | } |
240 | | |
241 | | #if defined(MAGICKCORE_LOCALE_SUPPORT) |
242 | | /* |
243 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
244 | | % % |
245 | | % % |
246 | | % % |
247 | | + D e s t r o y C L o c a l e % |
248 | | % % |
249 | | % % |
250 | | % % |
251 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
252 | | % |
253 | | % DestroyCLocale() releases the resources allocated for a locale object |
254 | | % returned by a call to the AcquireCLocale() method. |
255 | | % |
256 | | % The format of the DestroyCLocale method is: |
257 | | % |
258 | | % void DestroyCLocale(void) |
259 | | % |
260 | | */ |
261 | | static void DestroyCLocale(void) |
262 | 0 | { |
263 | 0 | if (c_locale != (locale_t) NULL) |
264 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
265 | | _free_locale(c_locale); |
266 | | #else |
267 | 0 | freelocale(c_locale); |
268 | 0 | #endif |
269 | 0 | c_locale=(locale_t) NULL; |
270 | 0 | } |
271 | | #endif |
272 | | |
273 | | /* |
274 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
275 | | % % |
276 | | % % |
277 | | % % |
278 | | % D e s t r o y L o c a l e O p t i o n s % |
279 | | % % |
280 | | % % |
281 | | % % |
282 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
283 | | % |
284 | | % DestroyLocaleOptions() releases memory associated with an locale |
285 | | % messages. |
286 | | % |
287 | | % The format of the DestroyProfiles method is: |
288 | | % |
289 | | % LinkedListInfo *DestroyLocaleOptions(Image *image) |
290 | | % |
291 | | % A description of each parameter follows: |
292 | | % |
293 | | % o image: the image. |
294 | | % |
295 | | */ |
296 | | |
297 | | static void *DestroyOptions(void *message) |
298 | 0 | { |
299 | 0 | return(DestroyStringInfo((StringInfo *) message)); |
300 | 0 | } |
301 | | |
302 | | MagickExport LinkedListInfo *DestroyLocaleOptions(LinkedListInfo *messages) |
303 | 590 | { |
304 | 590 | assert(messages != (LinkedListInfo *) NULL); |
305 | 590 | if (IsEventLogging() != MagickFalse) |
306 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); |
307 | 590 | return(DestroyLinkedList(messages,DestroyOptions)); |
308 | 590 | } |
309 | | |
310 | | /* |
311 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
312 | | % % |
313 | | % % |
314 | | % % |
315 | | + F o r m a t L o c a l e F i l e % |
316 | | % % |
317 | | % % |
318 | | % % |
319 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
320 | | % |
321 | | % FormatLocaleFile() prints formatted output of a variable argument list to a |
322 | | % file in the "C" locale. |
323 | | % |
324 | | % The format of the FormatLocaleFile method is: |
325 | | % |
326 | | % ssize_t FormatLocaleFile(FILE *file,const char *format,...) |
327 | | % |
328 | | % A description of each parameter follows. |
329 | | % |
330 | | % o file: the file. |
331 | | % |
332 | | % o format: A file describing the format to use to write the remaining |
333 | | % arguments. |
334 | | % |
335 | | */ |
336 | | |
337 | | MagickPrivate ssize_t FormatLocaleFileList(FILE *file, |
338 | | const char *magick_restrict format,va_list operands) |
339 | 235k | { |
340 | 235k | ssize_t |
341 | 235k | n; |
342 | | |
343 | | #if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_VFPRINTF_L) |
344 | | { |
345 | | locale_t |
346 | | locale; |
347 | | |
348 | | locale=AcquireCLocale(); |
349 | | if (locale == (locale_t) NULL) |
350 | | n=(ssize_t) vfprintf(file,format,operands); |
351 | | else |
352 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
353 | | n=(ssize_t) _vfprintf_l(file,format,locale,operands); |
354 | | #else |
355 | | n=(ssize_t) vfprintf_l(file,locale,format,operands); |
356 | | #endif |
357 | | } |
358 | | #else |
359 | 235k | #if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_USELOCALE) |
360 | 235k | { |
361 | 235k | locale_t |
362 | 235k | locale, |
363 | 235k | previous_locale; |
364 | | |
365 | 235k | locale=AcquireCLocale(); |
366 | 235k | if (locale == (locale_t) NULL) |
367 | 0 | n=(ssize_t) vfprintf(file,format,operands); |
368 | 235k | else |
369 | 235k | { |
370 | 235k | previous_locale=uselocale(locale); |
371 | 235k | n=(ssize_t) vfprintf(file,format,operands); |
372 | 235k | uselocale(previous_locale); |
373 | 235k | } |
374 | 235k | } |
375 | | #else |
376 | | n=(ssize_t) vfprintf(file,format,operands); |
377 | | #endif |
378 | 235k | #endif |
379 | 235k | return(n); |
380 | 235k | } |
381 | | |
382 | | MagickExport ssize_t FormatLocaleFile(FILE *file, |
383 | | const char *magick_restrict format,...) |
384 | 235k | { |
385 | 235k | ssize_t |
386 | 235k | n; |
387 | | |
388 | 235k | va_list |
389 | 235k | operands; |
390 | | |
391 | 235k | va_start(operands,format); |
392 | 235k | n=FormatLocaleFileList(file,format,operands); |
393 | 235k | va_end(operands); |
394 | 235k | return(n); |
395 | 235k | } |
396 | | |
397 | | /* |
398 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
399 | | % % |
400 | | % % |
401 | | % % |
402 | | + F o r m a t L o c a l e S t r i n g % |
403 | | % % |
404 | | % % |
405 | | % % |
406 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
407 | | % |
408 | | % FormatLocaleString() prints formatted output of a variable argument list to |
409 | | % a string buffer in the "C" locale. |
410 | | % |
411 | | % The format of the FormatLocaleString method is: |
412 | | % |
413 | | % ssize_t FormatLocaleString(char *string,const size_t length, |
414 | | % const char *format,...) |
415 | | % |
416 | | % A description of each parameter follows. |
417 | | % |
418 | | % o string: FormatLocaleString() returns the formatted string in this |
419 | | % character buffer. |
420 | | % |
421 | | % o length: the maximum length of the string. |
422 | | % |
423 | | % o format: A string describing the format to use to write the remaining |
424 | | % arguments. |
425 | | % |
426 | | */ |
427 | | |
428 | | MagickPrivate ssize_t FormatLocaleStringList(char *magick_restrict string, |
429 | | const size_t length,const char *magick_restrict format,va_list operands) |
430 | 86.4M | { |
431 | 86.4M | ssize_t |
432 | 86.4M | n; |
433 | | |
434 | | #if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_VSNPRINTF_L) |
435 | | { |
436 | | locale_t |
437 | | locale; |
438 | | |
439 | | locale=AcquireCLocale(); |
440 | | if (locale == (locale_t) NULL) |
441 | | n=(ssize_t) vsnprintf(string,length,format,operands); |
442 | | else |
443 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
444 | | #if _MSC_VER |
445 | | #pragma warning(push) |
446 | | #pragma warning(disable:4996) |
447 | | #endif |
448 | | n=(ssize_t) _vsnprintf_l(string,length,format,locale,operands); |
449 | | #if _MSC_VER |
450 | | #pragma warning(pop) |
451 | | #endif |
452 | | #else |
453 | | n=(ssize_t) vsnprintf_l(string,length,locale,format,operands); |
454 | | #endif |
455 | | } |
456 | | #elif defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_USELOCALE) |
457 | | { |
458 | 86.4M | locale_t |
459 | 86.4M | locale, |
460 | 86.4M | previous_locale; |
461 | | |
462 | 86.4M | locale=AcquireCLocale(); |
463 | 86.4M | if (locale == (locale_t) NULL) |
464 | 0 | n=(ssize_t) vsnprintf(string,length,format,operands); |
465 | 86.4M | else |
466 | 86.4M | { |
467 | 86.4M | previous_locale=uselocale(locale); |
468 | 86.4M | n=(ssize_t) vsnprintf(string,length,format,operands); |
469 | 86.4M | uselocale(previous_locale); |
470 | 86.4M | } |
471 | 86.4M | } |
472 | | #else |
473 | | n=(ssize_t) vsnprintf(string,length,format,operands); |
474 | | #endif |
475 | 86.4M | if (n < 0) |
476 | 0 | string[length-1]='\0'; |
477 | 86.4M | return(n); |
478 | 86.4M | } |
479 | | |
480 | | MagickExport ssize_t FormatLocaleString(char *magick_restrict string, |
481 | | const size_t length,const char *magick_restrict format,...) |
482 | 86.2M | { |
483 | 86.2M | ssize_t |
484 | 86.2M | n; |
485 | | |
486 | 86.2M | va_list |
487 | 86.2M | operands; |
488 | | |
489 | 86.2M | va_start(operands,format); |
490 | 86.2M | n=FormatLocaleStringList(string,length,format,operands); |
491 | 86.2M | va_end(operands); |
492 | 86.2M | return(n); |
493 | 86.2M | } |
494 | | |
495 | | /* |
496 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
497 | | % % |
498 | | % % |
499 | | % % |
500 | | + G e t L o c a l e I n f o _ % |
501 | | % % |
502 | | % % |
503 | | % % |
504 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
505 | | % |
506 | | % GetLocaleInfo_() searches the locale list for the specified tag and if |
507 | | % found returns attributes for that element. |
508 | | % |
509 | | % The format of the GetLocaleInfo method is: |
510 | | % |
511 | | % const LocaleInfo *GetLocaleInfo_(const char *tag, |
512 | | % ExceptionInfo *exception) |
513 | | % |
514 | | % A description of each parameter follows: |
515 | | % |
516 | | % o tag: the locale tag. |
517 | | % |
518 | | % o exception: return any errors or warnings in this structure. |
519 | | % |
520 | | */ |
521 | | MagickExport const LocaleInfo *GetLocaleInfo_(const char *tag, |
522 | | ExceptionInfo *exception) |
523 | 23.6M | { |
524 | 23.6M | const LocaleInfo |
525 | 23.6M | *locale_info; |
526 | | |
527 | 23.6M | assert(exception != (ExceptionInfo *) NULL); |
528 | 23.6M | if (IsLocaleTreeInstantiated(exception) == MagickFalse) |
529 | 0 | return((const LocaleInfo *) NULL); |
530 | 23.6M | LockSemaphoreInfo(locale_semaphore); |
531 | 23.6M | if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0)) |
532 | 0 | { |
533 | 0 | ResetSplayTreeIterator(locale_cache); |
534 | 0 | locale_info=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache); |
535 | 0 | UnlockSemaphoreInfo(locale_semaphore); |
536 | 0 | return(locale_info); |
537 | 0 | } |
538 | 23.6M | locale_info=(const LocaleInfo *) GetValueFromSplayTree(locale_cache,tag); |
539 | 23.6M | UnlockSemaphoreInfo(locale_semaphore); |
540 | 23.6M | return(locale_info); |
541 | 23.6M | } |
542 | | |
543 | | /* |
544 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
545 | | % % |
546 | | % % |
547 | | % % |
548 | | % G e t L o c a l e I n f o L i s t % |
549 | | % % |
550 | | % % |
551 | | % % |
552 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
553 | | % |
554 | | % GetLocaleInfoList() returns any locale messages that match the |
555 | | % specified pattern. |
556 | | % |
557 | | % The format of the GetLocaleInfoList function is: |
558 | | % |
559 | | % const LocaleInfo **GetLocaleInfoList(const char *pattern, |
560 | | % size_t *number_messages,ExceptionInfo *exception) |
561 | | % |
562 | | % A description of each parameter follows: |
563 | | % |
564 | | % o pattern: Specifies a pointer to a text string containing a pattern. |
565 | | % |
566 | | % o number_messages: This integer returns the number of locale messages in |
567 | | % the list. |
568 | | % |
569 | | % o exception: return any errors or warnings in this structure. |
570 | | % |
571 | | */ |
572 | | |
573 | | #if defined(__cplusplus) || defined(c_plusplus) |
574 | | extern "C" { |
575 | | #endif |
576 | | |
577 | | static int LocaleInfoCompare(const void *x,const void *y) |
578 | 0 | { |
579 | 0 | const LocaleInfo |
580 | 0 | **p, |
581 | 0 | **q; |
582 | |
|
583 | 0 | p=(const LocaleInfo **) x, |
584 | 0 | q=(const LocaleInfo **) y; |
585 | 0 | if (LocaleCompare((*p)->path,(*q)->path) == 0) |
586 | 0 | return(LocaleCompare((*p)->tag,(*q)->tag)); |
587 | 0 | return(LocaleCompare((*p)->path,(*q)->path)); |
588 | 0 | } |
589 | | |
590 | | #if defined(__cplusplus) || defined(c_plusplus) |
591 | | } |
592 | | #endif |
593 | | |
594 | | MagickExport const LocaleInfo **GetLocaleInfoList(const char *pattern, |
595 | | size_t *number_messages,ExceptionInfo *exception) |
596 | 0 | { |
597 | 0 | const LocaleInfo |
598 | 0 | **messages; |
599 | |
|
600 | 0 | const LocaleInfo |
601 | 0 | *p; |
602 | |
|
603 | 0 | ssize_t |
604 | 0 | i; |
605 | | |
606 | | /* |
607 | | Allocate locale list. |
608 | | */ |
609 | 0 | assert(pattern != (char *) NULL); |
610 | 0 | assert(number_messages != (size_t *) NULL); |
611 | 0 | if (IsEventLogging() != MagickFalse) |
612 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); |
613 | 0 | *number_messages=0; |
614 | 0 | p=GetLocaleInfo_("*",exception); |
615 | 0 | if (p == (const LocaleInfo *) NULL) |
616 | 0 | return((const LocaleInfo **) NULL); |
617 | 0 | messages=(const LocaleInfo **) AcquireQuantumMemory((size_t) |
618 | 0 | GetNumberOfNodesInSplayTree(locale_cache)+1UL,sizeof(*messages)); |
619 | 0 | if (messages == (const LocaleInfo **) NULL) |
620 | 0 | return((const LocaleInfo **) NULL); |
621 | | /* |
622 | | Generate locale list. |
623 | | */ |
624 | 0 | LockSemaphoreInfo(locale_semaphore); |
625 | 0 | ResetSplayTreeIterator(locale_cache); |
626 | 0 | p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache); |
627 | 0 | for (i=0; p != (const LocaleInfo *) NULL; ) |
628 | 0 | { |
629 | 0 | if ((p->stealth == MagickFalse) && |
630 | 0 | (GlobExpression(p->tag,pattern,MagickTrue) != MagickFalse)) |
631 | 0 | messages[i++]=p; |
632 | 0 | p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache); |
633 | 0 | } |
634 | 0 | UnlockSemaphoreInfo(locale_semaphore); |
635 | 0 | qsort((void *) messages,(size_t) i,sizeof(*messages),LocaleInfoCompare); |
636 | 0 | messages[i]=(LocaleInfo *) NULL; |
637 | 0 | *number_messages=(size_t) i; |
638 | 0 | return(messages); |
639 | 0 | } |
640 | | |
641 | | /* |
642 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
643 | | % % |
644 | | % % |
645 | | % % |
646 | | % G e t L o c a l e L i s t % |
647 | | % % |
648 | | % % |
649 | | % % |
650 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
651 | | % |
652 | | % GetLocaleList() returns any locale messages that match the specified |
653 | | % pattern. |
654 | | % |
655 | | % The format of the GetLocaleList function is: |
656 | | % |
657 | | % char **GetLocaleList(const char *pattern,size_t *number_messages, |
658 | | % Exceptioninfo *exception) |
659 | | % |
660 | | % A description of each parameter follows: |
661 | | % |
662 | | % o pattern: Specifies a pointer to a text string containing a pattern. |
663 | | % |
664 | | % o number_messages: This integer returns the number of messages in the |
665 | | % list. |
666 | | % |
667 | | % o exception: return any errors or warnings in this structure. |
668 | | % |
669 | | */ |
670 | | |
671 | | #if defined(__cplusplus) || defined(c_plusplus) |
672 | | extern "C" { |
673 | | #endif |
674 | | |
675 | | static int LocaleTagCompare(const void *x,const void *y) |
676 | 0 | { |
677 | 0 | char |
678 | 0 | **p, |
679 | 0 | **q; |
680 | |
|
681 | 0 | p=(char **) x; |
682 | 0 | q=(char **) y; |
683 | 0 | return(LocaleCompare(*p,*q)); |
684 | 0 | } |
685 | | |
686 | | #if defined(__cplusplus) || defined(c_plusplus) |
687 | | } |
688 | | #endif |
689 | | |
690 | | MagickExport char **GetLocaleList(const char *pattern,size_t *number_messages, |
691 | | ExceptionInfo *exception) |
692 | 0 | { |
693 | 0 | char |
694 | 0 | **messages; |
695 | |
|
696 | 0 | const LocaleInfo |
697 | 0 | *p; |
698 | |
|
699 | 0 | ssize_t |
700 | 0 | i; |
701 | | |
702 | | /* |
703 | | Allocate locale list. |
704 | | */ |
705 | 0 | assert(pattern != (char *) NULL); |
706 | 0 | assert(number_messages != (size_t *) NULL); |
707 | 0 | if (IsEventLogging() != MagickFalse) |
708 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); |
709 | 0 | *number_messages=0; |
710 | 0 | p=GetLocaleInfo_("*",exception); |
711 | 0 | if (p == (const LocaleInfo *) NULL) |
712 | 0 | return((char **) NULL); |
713 | 0 | messages=(char **) AcquireQuantumMemory((size_t) |
714 | 0 | GetNumberOfNodesInSplayTree(locale_cache)+1UL,sizeof(*messages)); |
715 | 0 | if (messages == (char **) NULL) |
716 | 0 | return((char **) NULL); |
717 | 0 | LockSemaphoreInfo(locale_semaphore); |
718 | 0 | p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache); |
719 | 0 | for (i=0; p != (const LocaleInfo *) NULL; ) |
720 | 0 | { |
721 | 0 | if ((p->stealth == MagickFalse) && |
722 | 0 | (GlobExpression(p->tag,pattern,MagickTrue) != MagickFalse)) |
723 | 0 | messages[i++]=ConstantString(p->tag); |
724 | 0 | p=(const LocaleInfo *) GetNextValueInSplayTree(locale_cache); |
725 | 0 | } |
726 | 0 | UnlockSemaphoreInfo(locale_semaphore); |
727 | 0 | qsort((void *) messages,(size_t) i,sizeof(*messages),LocaleTagCompare); |
728 | 0 | messages[i]=(char *) NULL; |
729 | 0 | *number_messages=(size_t) i; |
730 | 0 | return(messages); |
731 | 0 | } |
732 | | |
733 | | /* |
734 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
735 | | % % |
736 | | % % |
737 | | % % |
738 | | % G e t L o c a l e M e s s a g e % |
739 | | % % |
740 | | % % |
741 | | % % |
742 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
743 | | % |
744 | | % GetLocaleMessage() returns a message in the current locale that matches the |
745 | | % supplied tag. |
746 | | % |
747 | | % The format of the GetLocaleMessage method is: |
748 | | % |
749 | | % const char *GetLocaleMessage(const char *tag) |
750 | | % |
751 | | % A description of each parameter follows: |
752 | | % |
753 | | % o tag: Return a message that matches this tag in the current locale. |
754 | | % |
755 | | */ |
756 | | MagickExport const char *GetLocaleMessage(const char *tag) |
757 | 23.6M | { |
758 | 23.6M | char |
759 | 23.6M | name[MagickLocaleExtent]; |
760 | | |
761 | 23.6M | const LocaleInfo |
762 | 23.6M | *locale_info; |
763 | | |
764 | 23.6M | ExceptionInfo |
765 | 23.6M | *exception; |
766 | | |
767 | 23.6M | if ((tag == (const char *) NULL) || (*tag == '\0')) |
768 | 0 | return(tag); |
769 | 23.6M | exception=AcquireExceptionInfo(); |
770 | 23.6M | (void) FormatLocaleString(name,MagickLocaleExtent,"%s/",tag); |
771 | 23.6M | locale_info=GetLocaleInfo_(name,exception); |
772 | 23.6M | exception=DestroyExceptionInfo(exception); |
773 | 23.6M | if (locale_info != (const LocaleInfo *) NULL) |
774 | 0 | return(locale_info->message); |
775 | 23.6M | return(tag); |
776 | 23.6M | } |
777 | | |
778 | | /* |
779 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
780 | | % % |
781 | | % % |
782 | | % % |
783 | | % G e t L o c a l e O p t i o n s % |
784 | | % % |
785 | | % % |
786 | | % % |
787 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
788 | | % |
789 | | % GetLocaleOptions() returns any Magick configuration messages associated |
790 | | % with the specified filename. |
791 | | % |
792 | | % The format of the GetLocaleOptions method is: |
793 | | % |
794 | | % LinkedListInfo *GetLocaleOptions(const char *filename, |
795 | | % ExceptionInfo *exception) |
796 | | % |
797 | | % A description of each parameter follows: |
798 | | % |
799 | | % o filename: the locale file tag. |
800 | | % |
801 | | % o exception: return any errors or warnings in this structure. |
802 | | % |
803 | | */ |
804 | | MagickExport LinkedListInfo *GetLocaleOptions(const char *filename, |
805 | | ExceptionInfo *exception) |
806 | 590 | { |
807 | 590 | char |
808 | 590 | path[MagickPathExtent]; |
809 | | |
810 | 590 | const char |
811 | 590 | *element; |
812 | | |
813 | 590 | LinkedListInfo |
814 | 590 | *messages, |
815 | 590 | *paths; |
816 | | |
817 | 590 | StringInfo |
818 | 590 | *xml; |
819 | | |
820 | 590 | assert(filename != (const char *) NULL); |
821 | 590 | assert(exception != (ExceptionInfo *) NULL); |
822 | 590 | if (IsEventLogging() != MagickFalse) |
823 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); |
824 | 590 | (void) CopyMagickString(path,filename,MagickPathExtent); |
825 | | /* |
826 | | Load XML from configuration files to linked-list. |
827 | | */ |
828 | 590 | messages=NewLinkedList(0); |
829 | 590 | paths=GetConfigurePaths(filename,exception); |
830 | 590 | if (paths != (LinkedListInfo *) NULL) |
831 | 590 | { |
832 | 590 | ResetLinkedListIterator(paths); |
833 | 590 | element=(const char *) GetNextValueInLinkedList(paths); |
834 | 3.54k | while (element != (const char *) NULL) |
835 | 2.95k | { |
836 | 2.95k | (void) FormatLocaleString(path,MagickPathExtent,"%s%s",element, |
837 | 2.95k | filename); |
838 | 2.95k | (void) LogMagickEvent(LocaleEvent,GetMagickModule(), |
839 | 2.95k | "Searching for locale file: \"%s\"",path); |
840 | 2.95k | xml=ConfigureFileToStringInfo(path); |
841 | 2.95k | if (xml != (StringInfo *) NULL) |
842 | 0 | (void) AppendValueToLinkedList(messages,xml); |
843 | 2.95k | element=(const char *) GetNextValueInLinkedList(paths); |
844 | 2.95k | } |
845 | 590 | paths=DestroyLinkedList(paths,RelinquishMagickMemory); |
846 | 590 | } |
847 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
848 | | { |
849 | | char |
850 | | *blob; |
851 | | |
852 | | blob=(char *) NTResourceToBlob(filename); |
853 | | if (blob != (char *) NULL) |
854 | | { |
855 | | xml=AcquireStringInfo(0); |
856 | | SetStringInfoLength(xml,strlen(blob)+1); |
857 | | SetStringInfoDatum(xml,(const unsigned char *) blob); |
858 | | blob=(char *) RelinquishMagickMemory(blob); |
859 | | SetStringInfoPath(xml,filename); |
860 | | (void) AppendValueToLinkedList(messages,xml); |
861 | | } |
862 | | } |
863 | | #endif |
864 | 590 | ResetLinkedListIterator(messages); |
865 | 590 | return(messages); |
866 | 590 | } |
867 | | |
868 | | /* |
869 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
870 | | % % |
871 | | % % |
872 | | % % |
873 | | % G e t L o c a l e V a l u e % |
874 | | % % |
875 | | % % |
876 | | % % |
877 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
878 | | % |
879 | | % GetLocaleValue() returns the message associated with the locale info. |
880 | | % |
881 | | % The format of the GetLocaleValue method is: |
882 | | % |
883 | | % const char *GetLocaleValue(const LocaleInfo *locale_info) |
884 | | % |
885 | | % A description of each parameter follows: |
886 | | % |
887 | | % o locale_info: The locale info. |
888 | | % |
889 | | */ |
890 | | MagickExport const char *GetLocaleValue(const LocaleInfo *locale_info) |
891 | 0 | { |
892 | 0 | if (IsEventLogging() != MagickFalse) |
893 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); |
894 | 0 | assert(locale_info != (LocaleInfo *) NULL); |
895 | 0 | assert(locale_info->signature == MagickCoreSignature); |
896 | 0 | return(locale_info->message); |
897 | 0 | } |
898 | | |
899 | | /* |
900 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
901 | | % % |
902 | | % % |
903 | | % % |
904 | | + I s L o c a l e T r e e I n s t a n t i a t e d % |
905 | | % % |
906 | | % % |
907 | | % % |
908 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
909 | | % |
910 | | % IsLocaleTreeInstantiated() determines if the locale tree is instantiated. |
911 | | % If not, it instantiates the tree and returns it. |
912 | | % |
913 | | % The format of the IsLocaleInstantiated method is: |
914 | | % |
915 | | % MagickBooleanType IsLocaleTreeInstantiated(ExceptionInfo *exception) |
916 | | % |
917 | | % A description of each parameter follows. |
918 | | % |
919 | | % o exception: return any errors or warnings in this structure. |
920 | | % |
921 | | */ |
922 | | static MagickBooleanType IsLocaleTreeInstantiated(ExceptionInfo *exception) |
923 | 23.6M | { |
924 | 23.6M | if (locale_cache == (SplayTreeInfo *) NULL) |
925 | 295 | { |
926 | 295 | if (locale_semaphore == (SemaphoreInfo *) NULL) |
927 | 295 | ActivateSemaphoreInfo(&locale_semaphore); |
928 | 295 | LockSemaphoreInfo(locale_semaphore); |
929 | 295 | if (locale_cache == (SplayTreeInfo *) NULL) |
930 | 295 | { |
931 | 295 | char |
932 | 295 | *locale; |
933 | | |
934 | 295 | const char |
935 | 295 | *p; |
936 | | |
937 | 295 | locale=(char *) NULL; |
938 | 295 | p=setlocale(LC_CTYPE,(const char *) NULL); |
939 | 295 | if (p != (const char *) NULL) |
940 | 295 | locale=ConstantString(p); |
941 | 295 | if (locale == (char *) NULL) |
942 | 0 | locale=GetEnvironmentValue("LC_ALL"); |
943 | 295 | if (locale == (char *) NULL) |
944 | 0 | locale=GetEnvironmentValue("LC_MESSAGES"); |
945 | 295 | if (locale == (char *) NULL) |
946 | 0 | locale=GetEnvironmentValue("LC_CTYPE"); |
947 | 295 | if (locale == (char *) NULL) |
948 | 0 | locale=GetEnvironmentValue("LANG"); |
949 | 295 | if (locale == (char *) NULL) |
950 | 0 | locale=ConstantString("C"); |
951 | 295 | locale_cache=AcquireLocaleSplayTree(LocaleFilename,locale,exception); |
952 | 295 | locale=DestroyString(locale); |
953 | 295 | } |
954 | 295 | UnlockSemaphoreInfo(locale_semaphore); |
955 | 295 | } |
956 | 23.6M | return(locale_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse); |
957 | 23.6M | } |
958 | | |
959 | | /* |
960 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
961 | | % % |
962 | | % % |
963 | | % % |
964 | | + I n t e r p r e t L o c a l e V a l u e % |
965 | | % % |
966 | | % % |
967 | | % % |
968 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
969 | | % |
970 | | % InterpretLocaleValue() interprets the string as a floating point number in |
971 | | % the "C" locale and returns its value as a double. If sentinel is not a null |
972 | | % pointer, the method also sets the value pointed by sentinel to point to the |
973 | | % first character after the number. |
974 | | % |
975 | | % The format of the InterpretLocaleValue method is: |
976 | | % |
977 | | % double InterpretLocaleValue(const char *value,char **sentinel) |
978 | | % |
979 | | % A description of each parameter follows: |
980 | | % |
981 | | % o value: the string value. |
982 | | % |
983 | | % o sentinel: if sentinel is not NULL, a pointer to the character after the |
984 | | % last character used in the conversion is stored in the location |
985 | | % referenced by sentinel. |
986 | | % |
987 | | */ |
988 | | MagickExport double InterpretLocaleValue(const char *magick_restrict string, |
989 | | char *magick_restrict *sentinel) |
990 | 81.4M | { |
991 | 81.4M | char |
992 | 81.4M | *q; |
993 | | |
994 | 81.4M | double |
995 | 81.4M | value; |
996 | | |
997 | 81.4M | if ((*string == '0') && ((string[1] | 0x20)=='x')) |
998 | 56.8k | value=(double) strtoul(string,&q,16); |
999 | 81.3M | else |
1000 | 81.3M | { |
1001 | 81.3M | #if defined(MAGICKCORE_LOCALE_SUPPORT) && defined(MAGICKCORE_HAVE_STRTOD_L) |
1002 | 81.3M | locale_t |
1003 | 81.3M | locale; |
1004 | | |
1005 | 81.3M | locale=AcquireCLocale(); |
1006 | 81.3M | if (locale == (locale_t) NULL) |
1007 | 0 | value=strtod(string,&q); |
1008 | 81.3M | else |
1009 | | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
1010 | | value=_strtod_l(string,&q,locale); |
1011 | | #else |
1012 | 81.3M | value=strtod_l(string,&q,locale); |
1013 | 81.3M | #endif |
1014 | | #else |
1015 | | value=strtod(string,&q); |
1016 | | #endif |
1017 | 81.3M | } |
1018 | 81.4M | if (sentinel != (char **) NULL) |
1019 | 81.4M | *sentinel=q; |
1020 | 81.4M | return(value); |
1021 | 81.4M | } |
1022 | | |
1023 | | /* |
1024 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1025 | | % % |
1026 | | % % |
1027 | | % % |
1028 | | % L i s t L o c a l e I n f o % |
1029 | | % % |
1030 | | % % |
1031 | | % % |
1032 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1033 | | % |
1034 | | % ListLocaleInfo() lists the locale info to a file. |
1035 | | % |
1036 | | % The format of the ListLocaleInfo method is: |
1037 | | % |
1038 | | % MagickBooleanType ListLocaleInfo(FILE *file,ExceptionInfo *exception) |
1039 | | % |
1040 | | % A description of each parameter follows. |
1041 | | % |
1042 | | % o file: An pointer to a FILE. |
1043 | | % |
1044 | | % o exception: return any errors or warnings in this structure. |
1045 | | % |
1046 | | */ |
1047 | | MagickExport MagickBooleanType ListLocaleInfo(FILE *file, |
1048 | | ExceptionInfo *exception) |
1049 | 0 | { |
1050 | 0 | const char |
1051 | 0 | *path; |
1052 | |
|
1053 | 0 | const LocaleInfo |
1054 | 0 | **locale_info; |
1055 | |
|
1056 | 0 | ssize_t |
1057 | 0 | i; |
1058 | |
|
1059 | 0 | size_t |
1060 | 0 | number_messages; |
1061 | |
|
1062 | 0 | if (file == (const FILE *) NULL) |
1063 | 0 | file=stdout; |
1064 | 0 | number_messages=0; |
1065 | 0 | locale_info=GetLocaleInfoList("*",&number_messages,exception); |
1066 | 0 | if (locale_info == (const LocaleInfo **) NULL) |
1067 | 0 | return(MagickFalse); |
1068 | 0 | path=(const char *) NULL; |
1069 | 0 | for (i=0; i < (ssize_t) number_messages; i++) |
1070 | 0 | { |
1071 | 0 | if (locale_info[i]->stealth != MagickFalse) |
1072 | 0 | continue; |
1073 | 0 | if ((path == (const char *) NULL) || |
1074 | 0 | (LocaleCompare(path,locale_info[i]->path) != 0)) |
1075 | 0 | { |
1076 | 0 | if (locale_info[i]->path != (char *) NULL) |
1077 | 0 | (void) FormatLocaleFile(file,"\nPath: %s\n\n",locale_info[i]->path); |
1078 | 0 | (void) FormatLocaleFile(file,"Tag/Message\n"); |
1079 | 0 | (void) FormatLocaleFile(file, |
1080 | 0 | "-------------------------------------------------" |
1081 | 0 | "------------------------------\n"); |
1082 | 0 | } |
1083 | 0 | path=locale_info[i]->path; |
1084 | 0 | (void) FormatLocaleFile(file,"%s\n",locale_info[i]->tag); |
1085 | 0 | if (locale_info[i]->message != (char *) NULL) |
1086 | 0 | (void) FormatLocaleFile(file," %s",locale_info[i]->message); |
1087 | 0 | (void) FormatLocaleFile(file,"\n"); |
1088 | 0 | } |
1089 | 0 | (void) fflush(file); |
1090 | 0 | locale_info=(const LocaleInfo **) |
1091 | 0 | RelinquishMagickMemory((void *) locale_info); |
1092 | 0 | return(MagickTrue); |
1093 | 0 | } |
1094 | | |
1095 | | /* |
1096 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1097 | | % % |
1098 | | % % |
1099 | | % % |
1100 | | + L o a d L o c a l e C a c h e % |
1101 | | % % |
1102 | | % % |
1103 | | % % |
1104 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1105 | | % |
1106 | | % LoadLocaleCache() loads the locale configurations which provides a mapping |
1107 | | % between locale attributes and a locale name. |
1108 | | % |
1109 | | % The format of the LoadLocaleCache method is: |
1110 | | % |
1111 | | % MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml, |
1112 | | % const char *filename,const size_t depth,ExceptionInfo *exception) |
1113 | | % |
1114 | | % A description of each parameter follows: |
1115 | | % |
1116 | | % o xml: The locale list in XML format. |
1117 | | % |
1118 | | % o filename: The locale list filename. |
1119 | | % |
1120 | | % o depth: depth of <include /> statements. |
1121 | | % |
1122 | | % o exception: return any errors or warnings in this structure. |
1123 | | % |
1124 | | */ |
1125 | | |
1126 | | static void ChopLocaleComponents(char *path,const size_t components) |
1127 | 885 | { |
1128 | 885 | char |
1129 | 885 | *p; |
1130 | | |
1131 | 885 | ssize_t |
1132 | 885 | count; |
1133 | | |
1134 | 885 | if (*path == '\0') |
1135 | 295 | return; |
1136 | 590 | p=path+strlen(path)-1; |
1137 | 590 | if (*p == '/') |
1138 | 295 | *p='\0'; |
1139 | 4.13k | for (count=0; (count < (ssize_t) components) && (p > path); p--) |
1140 | 3.54k | if (*p == '/') |
1141 | 590 | { |
1142 | 590 | *p='\0'; |
1143 | 590 | count++; |
1144 | 590 | } |
1145 | 590 | if (count < (ssize_t) components) |
1146 | 295 | *path='\0'; |
1147 | 590 | } |
1148 | | |
1149 | | |
1150 | | static void LocaleFatalErrorHandler(const ExceptionType severity, |
1151 | | const char *reason,const char *description) magick_attribute((__noreturn__)); |
1152 | | |
1153 | | static void LocaleFatalErrorHandler( |
1154 | | const ExceptionType magick_unused(severity), |
1155 | | const char *reason,const char *description) |
1156 | 0 | { |
1157 | 0 | magick_unreferenced(severity); |
1158 | |
|
1159 | 0 | (void) FormatLocaleFile(stderr,"%s: ",GetClientName()); |
1160 | 0 | if (reason != (char *) NULL) |
1161 | 0 | (void) FormatLocaleFile(stderr," %s",reason); |
1162 | 0 | if (description != (char *) NULL) |
1163 | 0 | (void) FormatLocaleFile(stderr," (%s)",description); |
1164 | 0 | (void) FormatLocaleFile(stderr,".\n"); |
1165 | 0 | (void) fflush(stderr); |
1166 | 0 | exit(1); |
1167 | 0 | } |
1168 | | |
1169 | | static MagickBooleanType LoadLocaleCache(SplayTreeInfo *cache,const char *xml, |
1170 | | const char *filename,const char *locale,const size_t depth,ExceptionInfo *exception) |
1171 | 295 | { |
1172 | 295 | char |
1173 | 295 | keyword[MagickLocaleExtent], |
1174 | 295 | message[MagickLocaleExtent], |
1175 | 295 | tag[MagickLocaleExtent], |
1176 | 295 | *token; |
1177 | | |
1178 | 295 | const char |
1179 | 295 | *q; |
1180 | | |
1181 | 295 | FatalErrorHandler |
1182 | 295 | fatal_handler; |
1183 | | |
1184 | 295 | LocaleInfo |
1185 | 295 | *locale_info; |
1186 | | |
1187 | 295 | MagickStatusType |
1188 | 295 | status; |
1189 | | |
1190 | 295 | char |
1191 | 295 | *p; |
1192 | | |
1193 | 295 | size_t |
1194 | 295 | extent; |
1195 | | |
1196 | | /* |
1197 | | Read the locale configure file. |
1198 | | */ |
1199 | 295 | (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), |
1200 | 295 | "Loading locale configure file \"%s\" ...",filename); |
1201 | 295 | if (xml == (const char *) NULL) |
1202 | 0 | return(MagickFalse); |
1203 | 295 | status=MagickTrue; |
1204 | 295 | locale_info=(LocaleInfo *) NULL; |
1205 | 295 | *tag='\0'; |
1206 | 295 | *message='\0'; |
1207 | 295 | *keyword='\0'; |
1208 | 295 | fatal_handler=SetFatalErrorHandler(LocaleFatalErrorHandler); |
1209 | 295 | token=AcquireString(xml); |
1210 | 295 | extent=strlen(token)+MagickPathExtent; |
1211 | 6.19k | for (q=(char *) xml; *q != '\0'; ) |
1212 | 5.90k | { |
1213 | | /* |
1214 | | Interpret XML. |
1215 | | */ |
1216 | 5.90k | (void) GetNextToken(q,&q,extent,token); |
1217 | 5.90k | if (*token == '\0') |
1218 | 0 | break; |
1219 | 5.90k | (void) CopyMagickString(keyword,token,MagickLocaleExtent); |
1220 | 5.90k | if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) |
1221 | 0 | { |
1222 | | /* |
1223 | | Doctype element. |
1224 | | */ |
1225 | 0 | while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) |
1226 | 0 | { |
1227 | 0 | (void) GetNextToken(q,&q,extent,token); |
1228 | 0 | while (isspace((int) ((unsigned char) *q)) != 0) |
1229 | 0 | q++; |
1230 | 0 | } |
1231 | 0 | continue; |
1232 | 0 | } |
1233 | 5.90k | if (LocaleNCompare(keyword,"<!--",4) == 0) |
1234 | 0 | { |
1235 | | /* |
1236 | | Comment element. |
1237 | | */ |
1238 | 0 | while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) |
1239 | 0 | { |
1240 | 0 | (void) GetNextToken(q,&q,extent,token); |
1241 | 0 | while (isspace((int) ((unsigned char) *q)) != 0) |
1242 | 0 | q++; |
1243 | 0 | } |
1244 | 0 | continue; |
1245 | 0 | } |
1246 | 5.90k | if (LocaleCompare(keyword,"<include") == 0) |
1247 | 0 | { |
1248 | | /* |
1249 | | Include element. |
1250 | | */ |
1251 | 0 | while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) |
1252 | 0 | { |
1253 | 0 | (void) CopyMagickString(keyword,token,MagickLocaleExtent); |
1254 | 0 | (void) GetNextToken(q,&q,extent,token); |
1255 | 0 | if (*token != '=') |
1256 | 0 | continue; |
1257 | 0 | (void) GetNextToken(q,&q,extent,token); |
1258 | 0 | if (LocaleCompare(keyword,"locale") == 0) |
1259 | 0 | { |
1260 | 0 | if (LocaleCompare(locale,token) != 0) |
1261 | 0 | break; |
1262 | 0 | continue; |
1263 | 0 | } |
1264 | 0 | if (LocaleCompare(keyword,"file") == 0) |
1265 | 0 | { |
1266 | 0 | if (depth > MagickMaxRecursionDepth) |
1267 | 0 | (void) ThrowMagickException(exception,GetMagickModule(), |
1268 | 0 | ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token); |
1269 | 0 | else |
1270 | 0 | { |
1271 | 0 | char |
1272 | 0 | path[MagickPathExtent], |
1273 | 0 | *file_xml; |
1274 | |
|
1275 | 0 | *path='\0'; |
1276 | 0 | GetPathComponent(filename,HeadPath,path); |
1277 | 0 | if (*path != '\0') |
1278 | 0 | (void) ConcatenateMagickString(path,DirectorySeparator, |
1279 | 0 | MagickPathExtent); |
1280 | 0 | if (*token == *DirectorySeparator) |
1281 | 0 | (void) CopyMagickString(path,token,MagickPathExtent); |
1282 | 0 | else |
1283 | 0 | (void) ConcatenateMagickString(path,token,MagickPathExtent); |
1284 | 0 | file_xml=FileToXML(path,~0UL); |
1285 | 0 | if (file_xml != (char *) NULL) |
1286 | 0 | { |
1287 | 0 | status&=(MagickStatusType) LoadLocaleCache(cache,file_xml, |
1288 | 0 | path,locale,depth+1,exception); |
1289 | 0 | file_xml=DestroyString(file_xml); |
1290 | 0 | } |
1291 | 0 | } |
1292 | 0 | } |
1293 | 0 | } |
1294 | 0 | continue; |
1295 | 0 | } |
1296 | 5.90k | if (LocaleCompare(keyword,"<locale") == 0) |
1297 | 295 | { |
1298 | | /* |
1299 | | Locale element. |
1300 | | */ |
1301 | 1.18k | while ((*token != '>') && (*q != '\0')) |
1302 | 885 | { |
1303 | 885 | (void) CopyMagickString(keyword,token,MagickLocaleExtent); |
1304 | 885 | (void) GetNextToken(q,&q,extent,token); |
1305 | 885 | if (*token != '=') |
1306 | 590 | continue; |
1307 | 295 | (void) GetNextToken(q,&q,extent,token); |
1308 | 295 | } |
1309 | 295 | continue; |
1310 | 295 | } |
1311 | 5.60k | if (LocaleCompare(keyword,"</locale>") == 0) |
1312 | 295 | { |
1313 | 295 | ChopLocaleComponents(tag,1); |
1314 | 295 | (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent); |
1315 | 295 | continue; |
1316 | 295 | } |
1317 | 5.31k | if (LocaleCompare(keyword,"<localemap>") == 0) |
1318 | 295 | continue; |
1319 | 5.01k | if (LocaleCompare(keyword,"</localemap>") == 0) |
1320 | 295 | continue; |
1321 | 4.72k | if (LocaleCompare(keyword,"<message") == 0) |
1322 | 295 | { |
1323 | | /* |
1324 | | Message element. |
1325 | | */ |
1326 | 1.18k | while ((*token != '>') && (*q != '\0')) |
1327 | 885 | { |
1328 | 885 | (void) CopyMagickString(keyword,token,MagickLocaleExtent); |
1329 | 885 | (void) GetNextToken(q,&q,extent,token); |
1330 | 885 | if (*token != '=') |
1331 | 590 | continue; |
1332 | 295 | (void) GetNextToken(q,&q,extent,token); |
1333 | 295 | if (LocaleCompare(keyword,"name") == 0) |
1334 | 295 | { |
1335 | 295 | (void) ConcatenateMagickString(tag,token,MagickLocaleExtent); |
1336 | 295 | (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent); |
1337 | 295 | } |
1338 | 295 | } |
1339 | 295 | for (p=(char *) q; (*q != '<') && (*q != '\0'); q++) ; |
1340 | 295 | while (isspace((int) ((unsigned char) *p)) != 0) |
1341 | 0 | p++; |
1342 | 295 | q--; |
1343 | 295 | while ((isspace((int) ((unsigned char) *q)) != 0) && (q > p)) |
1344 | 0 | q--; |
1345 | 295 | (void) CopyMagickString(message,p,MagickMin((size_t) (q-p+2), |
1346 | 295 | MagickLocaleExtent)); |
1347 | 295 | locale_info=(LocaleInfo *) AcquireCriticalMemory(sizeof(*locale_info)); |
1348 | 295 | (void) memset(locale_info,0,sizeof(*locale_info)); |
1349 | 295 | locale_info->path=ConstantString(filename); |
1350 | 295 | locale_info->tag=ConstantString(tag); |
1351 | 295 | locale_info->message=ConstantString(message); |
1352 | 295 | locale_info->signature=MagickCoreSignature; |
1353 | 295 | status=AddValueToSplayTree(cache,locale_info->tag,locale_info); |
1354 | 295 | if (status == MagickFalse) |
1355 | 0 | (void) ThrowMagickException(exception,GetMagickModule(), |
1356 | 0 | ResourceLimitError,"MemoryAllocationFailed","`%s'", |
1357 | 0 | locale_info->tag); |
1358 | 295 | (void) ConcatenateMagickString(tag,message,MagickLocaleExtent); |
1359 | 295 | (void) ConcatenateMagickString(tag,"\n",MagickLocaleExtent); |
1360 | 295 | q++; |
1361 | 295 | continue; |
1362 | 295 | } |
1363 | 4.42k | if (LocaleCompare(keyword,"</message>") == 0) |
1364 | 295 | { |
1365 | 295 | ChopLocaleComponents(tag,2); |
1366 | 295 | (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent); |
1367 | 295 | continue; |
1368 | 295 | } |
1369 | 4.13k | if (*keyword == '<') |
1370 | 885 | { |
1371 | | /* |
1372 | | Subpath element. |
1373 | | */ |
1374 | 885 | if (*(keyword+1) == '?') |
1375 | 295 | continue; |
1376 | 590 | if (*(keyword+1) == '/') |
1377 | 295 | { |
1378 | 295 | ChopLocaleComponents(tag,1); |
1379 | 295 | if (*tag != '\0') |
1380 | 0 | (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent); |
1381 | 295 | continue; |
1382 | 295 | } |
1383 | 295 | token[strlen(token)-1]='\0'; |
1384 | 295 | (void) CopyMagickString(token,token+1,MagickLocaleExtent); |
1385 | 295 | (void) ConcatenateMagickString(tag,token,MagickLocaleExtent); |
1386 | 295 | (void) ConcatenateMagickString(tag,"/",MagickLocaleExtent); |
1387 | 295 | continue; |
1388 | 590 | } |
1389 | 3.24k | (void) GetNextToken(q,(const char **) NULL,extent,token); |
1390 | 3.24k | if (*token != '=') |
1391 | 2.95k | continue; |
1392 | 3.24k | } |
1393 | 295 | token=(char *) RelinquishMagickMemory(token); |
1394 | 295 | (void) SetFatalErrorHandler(fatal_handler); |
1395 | 295 | return(status != 0 ? MagickTrue : MagickFalse); |
1396 | 295 | } |
1397 | | |
1398 | | /* |
1399 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1400 | | % % |
1401 | | % % |
1402 | | % % |
1403 | | % L o c a l e C o m p a r e % |
1404 | | % % |
1405 | | % % |
1406 | | % % |
1407 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1408 | | % |
1409 | | % LocaleCompare() performs a case-insensitive comparison of two strings |
1410 | | % byte-by-byte, according to the ordering of the current locale encoding. |
1411 | | % LocaleCompare returns an integer greater than, equal to, or less than 0, |
1412 | | % if the string pointed to by p is greater than, equal to, or less than the |
1413 | | % string pointed to by q respectively. The sign of a non-zero return value |
1414 | | % is determined by the sign of the difference between the values of the first |
1415 | | % pair of bytes that differ in the strings being compared. |
1416 | | % |
1417 | | % The format of the LocaleCompare method is: |
1418 | | % |
1419 | | % int LocaleCompare(const char *p,const char *q) |
1420 | | % |
1421 | | % A description of each parameter follows: |
1422 | | % |
1423 | | % o p: A pointer to a character string. |
1424 | | % |
1425 | | % o q: A pointer to a character string to compare to p. |
1426 | | % |
1427 | | */ |
1428 | | MagickExport int LocaleCompare(const char *p,const char *q) |
1429 | 387M | { |
1430 | 387M | if (p == (char *) NULL) |
1431 | 1.59M | { |
1432 | 1.59M | if (q == (char *) NULL) |
1433 | 1.44M | return(0); |
1434 | 149k | return(-1); |
1435 | 1.59M | } |
1436 | 386M | if (q == (char *) NULL) |
1437 | 4.78k | return(1); |
1438 | 386M | { |
1439 | 386M | const unsigned char |
1440 | 386M | *r = (const unsigned char *) p, |
1441 | 386M | *s = (const unsigned char *) q; |
1442 | | |
1443 | 1.71G | for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || |
1444 | 1.32G | (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++); |
1445 | 386M | return(LocaleToLowercase((int) *r)-LocaleToLowercase((int) *s)); |
1446 | 386M | } |
1447 | 386M | } |
1448 | | |
1449 | | /* |
1450 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1451 | | % % |
1452 | | % % |
1453 | | % % |
1454 | | % L o c a l e L o w e r % |
1455 | | % % |
1456 | | % % |
1457 | | % % |
1458 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1459 | | % |
1460 | | % LocaleLower() transforms all of the characters in the supplied |
1461 | | % null-terminated string, changing all uppercase letters to lowercase. |
1462 | | % |
1463 | | % The format of the LocaleLower method is: |
1464 | | % |
1465 | | % void LocaleLower(char *string) |
1466 | | % |
1467 | | % A description of each parameter follows: |
1468 | | % |
1469 | | % o string: A pointer to the string to convert to lower-case Locale. |
1470 | | % |
1471 | | */ |
1472 | | MagickExport void LocaleLower(char *string) |
1473 | 320k | { |
1474 | 320k | char |
1475 | 320k | *q; |
1476 | | |
1477 | 320k | assert(string != (char *) NULL); |
1478 | 1.88M | for (q=string; *q != '\0'; q++) |
1479 | 1.56M | *q=(char) LocaleToLowercase((int) *q); |
1480 | 320k | } |
1481 | | |
1482 | | /* |
1483 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1484 | | % % |
1485 | | % % |
1486 | | % % |
1487 | | % L o c a l e L o w e r c a s e % |
1488 | | % % |
1489 | | % % |
1490 | | % % |
1491 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1492 | | % |
1493 | | % LocaleLowercase() converts the character to lowercase. |
1494 | | % |
1495 | | % The format of the LocaleLowercase method is: |
1496 | | % |
1497 | | % void LocaleLowercase(const int c) |
1498 | | % |
1499 | | % A description of each parameter follows: |
1500 | | % |
1501 | | % o If c is a uppercase letter, return its lowercase equivalent. |
1502 | | % |
1503 | | */ |
1504 | | MagickExport int LocaleLowercase(const int c) |
1505 | 0 | { |
1506 | 0 | return(LocaleToLowercase(c)); |
1507 | 0 | } |
1508 | | |
1509 | | /* |
1510 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1511 | | % % |
1512 | | % % |
1513 | | % % |
1514 | | % L o c a l e N C o m p a r e % |
1515 | | % % |
1516 | | % % |
1517 | | % % |
1518 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1519 | | % |
1520 | | % LocaleNCompare() performs a case-insensitive comparison of two strings |
1521 | | % byte-by-byte, according to the ordering of the current locale encoding. |
1522 | | % |
1523 | | % LocaleNCompare returns an integer greater than, equal to, or less than 0, |
1524 | | % if the string pointed to by p is greater than, equal to, or less than the |
1525 | | % string pointed to by q respectively. The sign of a non-zero return value |
1526 | | % is determined by the sign of the difference between the values of the first |
1527 | | % pair of bytes that differ in the strings being compared. |
1528 | | % |
1529 | | % The LocaleNCompare method makes the same comparison as LocaleCompare but |
1530 | | % looks at a maximum of n bytes. Bytes following a null byte are not |
1531 | | % compared. |
1532 | | % |
1533 | | % The format of the LocaleNCompare method is: |
1534 | | % |
1535 | | % int LocaleNCompare(const char *p,const char *q,const size_t n) |
1536 | | % |
1537 | | % A description of each parameter follows: |
1538 | | % |
1539 | | % o p: A pointer to a character string. |
1540 | | % |
1541 | | % o q: A pointer to a character string to compare to p. |
1542 | | % |
1543 | | % o length: the number of characters to compare in strings p and q. |
1544 | | % |
1545 | | */ |
1546 | | MagickExport int LocaleNCompare(const char *p,const char *q,const size_t length) |
1547 | 98.5M | { |
1548 | 98.5M | if (p == (char *) NULL) |
1549 | 0 | { |
1550 | 0 | if (q == (char *) NULL) |
1551 | 0 | return(0); |
1552 | 0 | return(-1); |
1553 | 0 | } |
1554 | 98.5M | if (q == (char *) NULL) |
1555 | 0 | return(1); |
1556 | 98.5M | if (length == 0) |
1557 | 0 | return(0); |
1558 | 98.5M | { |
1559 | 98.5M | const unsigned char |
1560 | 98.5M | *s = (const unsigned char *) p, |
1561 | 98.5M | *t = (const unsigned char *) q; |
1562 | | |
1563 | 98.5M | size_t |
1564 | 98.5M | n = length; |
1565 | | |
1566 | 114M | for (n--; (*s != '\0') && (*t != '\0') && (n != 0) && ((*s == *t) || |
1567 | 94.6M | (LocaleToLowercase((int) *s) == LocaleToLowercase((int) *t))); s++, t++, n--); |
1568 | 98.5M | return(LocaleToLowercase((int) *s)-LocaleToLowercase((int) *t)); |
1569 | 98.5M | } |
1570 | 98.5M | } |
1571 | | |
1572 | | /* |
1573 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1574 | | % % |
1575 | | % % |
1576 | | % % |
1577 | | % L o c a l e U p p e r % |
1578 | | % % |
1579 | | % % |
1580 | | % % |
1581 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1582 | | % |
1583 | | % LocaleUpper() transforms all of the characters in the supplied |
1584 | | % null-terminated string, changing all lowercase letters to uppercase. |
1585 | | % |
1586 | | % The format of the LocaleUpper method is: |
1587 | | % |
1588 | | % void LocaleUpper(char *string) |
1589 | | % |
1590 | | % A description of each parameter follows: |
1591 | | % |
1592 | | % o string: A pointer to the string to convert to upper-case Locale. |
1593 | | % |
1594 | | */ |
1595 | | MagickExport void LocaleUpper(char *string) |
1596 | 1.66M | { |
1597 | 1.66M | char |
1598 | 1.66M | *q; |
1599 | | |
1600 | 1.66M | assert(string != (char *) NULL); |
1601 | 11.9M | for (q=string; *q != '\0'; q++) |
1602 | 10.2M | *q=(char) LocaleToUppercase((int) *q); |
1603 | 1.66M | } |
1604 | | |
1605 | | /* |
1606 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1607 | | % % |
1608 | | % % |
1609 | | % % |
1610 | | % L o c a l e U p p e r c a s e % |
1611 | | % % |
1612 | | % % |
1613 | | % % |
1614 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1615 | | % |
1616 | | % LocaleUppercase() converts the character to uppercase. |
1617 | | % |
1618 | | % The format of the LocaleUppercase method is: |
1619 | | % |
1620 | | % void LocaleUppercase(const int c) |
1621 | | % |
1622 | | % A description of each parameter follows: |
1623 | | % |
1624 | | % o If c is a lowercase letter, return its uppercase equivalent. |
1625 | | % |
1626 | | */ |
1627 | | MagickExport int LocaleUppercase(const int c) |
1628 | 0 | { |
1629 | 0 | return(LocaleToUppercase(c)); |
1630 | 0 | } |
1631 | | |
1632 | | /* |
1633 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1634 | | % % |
1635 | | % % |
1636 | | % % |
1637 | | + L o c a l e C o m p o n e n t G e n e s i s % |
1638 | | % % |
1639 | | % % |
1640 | | % % |
1641 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1642 | | % |
1643 | | % LocaleComponentGenesis() instantiates the locale component. |
1644 | | % |
1645 | | % The format of the LocaleComponentGenesis method is: |
1646 | | % |
1647 | | % MagickBooleanType LocaleComponentGenesis(void) |
1648 | | % |
1649 | | */ |
1650 | | MagickPrivate MagickBooleanType LocaleComponentGenesis(void) |
1651 | 295 | { |
1652 | 295 | if (locale_semaphore == (SemaphoreInfo *) NULL) |
1653 | 0 | locale_semaphore=AcquireSemaphoreInfo(); |
1654 | 295 | #if defined(MAGICKCORE_LOCALE_SUPPORT) |
1655 | 295 | (void) AcquireCLocale(); |
1656 | 295 | #endif |
1657 | 295 | return(MagickTrue); |
1658 | 295 | } |
1659 | | |
1660 | | /* |
1661 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1662 | | % % |
1663 | | % % |
1664 | | % % |
1665 | | + L o c a l e C o m p o n e n t T e r m i n u s % |
1666 | | % % |
1667 | | % % |
1668 | | % % |
1669 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1670 | | % |
1671 | | % LocaleComponentTerminus() destroys the locale component. |
1672 | | % |
1673 | | % The format of the LocaleComponentTerminus method is: |
1674 | | % |
1675 | | % LocaleComponentTerminus(void) |
1676 | | % |
1677 | | */ |
1678 | | MagickPrivate void LocaleComponentTerminus(void) |
1679 | 0 | { |
1680 | 0 | if (locale_semaphore == (SemaphoreInfo *) NULL) |
1681 | 0 | ActivateSemaphoreInfo(&locale_semaphore); |
1682 | 0 | LockSemaphoreInfo(locale_semaphore); |
1683 | 0 | if (locale_cache != (SplayTreeInfo *) NULL) |
1684 | 0 | locale_cache=DestroySplayTree(locale_cache); |
1685 | 0 | #if defined(MAGICKCORE_LOCALE_SUPPORT) |
1686 | 0 | DestroyCLocale(); |
1687 | 0 | #endif |
1688 | 0 | UnlockSemaphoreInfo(locale_semaphore); |
1689 | 0 | RelinquishSemaphoreInfo(&locale_semaphore); |
1690 | 0 | } |