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