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