]> granicus.if.org Git - imagemagick/blob - MagickCore/configure.c
(no commit message)
[imagemagick] / MagickCore / configure.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %          CCCC   OOO   N   N  FFFFF  IIIII   GGGG  U   U  RRRR   EEEEE       %
7 %         C      O   O  NN  N  F        I    G      U   U  R   R  E           %
8 %         C      O   O  N N N  FFF      I    G GG   U   U  RRRR   EEE         %
9 %         C      O   O  N  NN  F        I    G   G  U   U  R R    E           %
10 %          CCCC   OOO   N   N  F      IIIII   GGG    UUU   R  R   EEEEE       %
11 %                                                                             %
12 %                                                                             %
13 %                      MagickCore Image Configure Methods                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 2003                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 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 %    http://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 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/hashmap.h"
49 #include "MagickCore/log.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/semaphore.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/token.h"
54 #include "MagickCore/utility.h"
55 #include "MagickCore/xml-tree.h"
56 \f
57 /*
58   Define declarations.
59 */
60 #define ConfigureFilename  "configure.xml"
61 \f
62 /*
63   Typedef declarations.
64 */
65 typedef struct _ConfigureMapInfo
66 {
67   const char
68     *name,
69     *value;
70 } ConfigureMapInfo;
71 \f
72 /*
73   Static declarations.
74 */
75 static const ConfigureMapInfo
76   ConfigureMap[] =
77   {
78     { "NAME", "ImageMagick" }
79   };
80
81 static LinkedListInfo
82   *configure_list = (LinkedListInfo *) NULL;
83
84 static SemaphoreInfo
85   *configure_semaphore = (SemaphoreInfo *) NULL;
86
87 static volatile MagickBooleanType
88   instantiate_configure = MagickFalse;
89 \f
90 /*
91   Forward declarations.
92 */
93 static MagickBooleanType
94   InitializeConfigureList(ExceptionInfo *),
95   LoadConfigureLists(const char *,ExceptionInfo *);
96 \f
97 /*
98 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99 %                                                                             %
100 %                                                                             %
101 %                                                                             %
102 +   C o n f i g u r e C o m p o n e n t G e n e s i s                         %
103 %                                                                             %
104 %                                                                             %
105 %                                                                             %
106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 %
108 %  ConfigureComponentGenesis() instantiates the configure component.
109 %
110 %  The format of the ConfigureComponentGenesis method is:
111 %
112 %      MagickBooleanType ConfigureComponentGenesis(void)
113 %
114 */
115 MagickExport MagickBooleanType ConfigureComponentGenesis(void)
116 {
117   AcquireSemaphoreInfo(&configure_semaphore);
118   return(MagickTrue);
119 }
120 \f
121 /*
122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 %                                                                             %
124 %                                                                             %
125 %                                                                             %
126 +   C o n f i g u r e C o m p o n e n t T e r m i n u s                       %
127 %                                                                             %
128 %                                                                             %
129 %                                                                             %
130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 %
132 %  ConfigureComponentTerminus() destroys the configure component.
133 %
134 %  The format of the ConfigureComponentTerminus method is:
135 %
136 %      ConfigureComponentTerminus(void)
137 %
138 */
139
140 static void *DestroyConfigureElement(void *configure_info)
141 {
142   register ConfigureInfo
143     *p;
144
145   p=(ConfigureInfo *) configure_info;
146   if (p->exempt == MagickFalse)
147     {
148       if (p->value != (char *) NULL)
149         p->value=DestroyString(p->value);
150       if (p->name != (char *) NULL)
151         p->name=DestroyString(p->name);
152       if (p->path != (char *) NULL)
153         p->path=DestroyString(p->path);
154     }
155   p=(ConfigureInfo *) RelinquishMagickMemory(p);
156   return((void *) NULL);
157 }
158
159 MagickExport void ConfigureComponentTerminus(void)
160 {
161   if (configure_semaphore == (SemaphoreInfo *) NULL)
162     AcquireSemaphoreInfo(&configure_semaphore);
163   LockSemaphoreInfo(configure_semaphore);
164   if (configure_list != (LinkedListInfo *) NULL)
165     configure_list=DestroyLinkedList(configure_list,DestroyConfigureElement);
166   configure_list=(LinkedListInfo *) NULL;
167   instantiate_configure=MagickFalse;
168   UnlockSemaphoreInfo(configure_semaphore);
169   DestroySemaphoreInfo(&configure_semaphore);
170 }
171 \f
172 /*
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 %                                                                             %
175 %                                                                             %
176 %                                                                             %
177 %   D e s t r o y C o n f i g u r e O p t i o n s                             %
178 %                                                                             %
179 %                                                                             %
180 %                                                                             %
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182 %
183 %  DestroyConfigureOptions() releases memory associated with an configure
184 %  options.
185 %
186 %  The format of the DestroyProfiles method is:
187 %
188 %      LinkedListInfo *DestroyConfigureOptions(Image *image)
189 %
190 %  A description of each parameter follows:
191 %
192 %    o image: the image.
193 %
194 */
195
196 static void *DestroyOptions(void *option)
197 {
198   return(DestroyStringInfo((StringInfo *) option));
199 }
200
201 MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
202 {
203   assert(options != (LinkedListInfo *) NULL);
204   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
205   return(DestroyLinkedList(options,DestroyOptions));
206 }
207 \f
208 /*
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 %                                                                             %
211 %                                                                             %
212 %                                                                             %
213 +   G e t C o n f i g u r e I n f o                                           %
214 %                                                                             %
215 %                                                                             %
216 %                                                                             %
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 %
219 %  GetConfigureInfo() searches the configure list for the specified name and if
220 %  found returns attributes for that element.
221 %
222 %  The format of the GetConfigureInfo method is:
223 %
224 %      const ConfigureInfo *GetConfigureInfo(const char *name,
225 %        ExceptionInfo *exception)
226 %
227 %  A description of each parameter follows:
228 %
229 %    o configure_info: GetConfigureInfo() searches the configure list for the
230 %      specified name and if found returns attributes for that element.
231 %
232 %    o name: the configure name.
233 %
234 %    o exception: return any errors or warnings in this structure.
235 %
236 */
237 MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
238   ExceptionInfo *exception)
239 {
240   register const ConfigureInfo
241     *p;
242
243   assert(exception != (ExceptionInfo *) NULL);
244   if ((configure_list == (LinkedListInfo *) NULL) ||
245       (instantiate_configure == MagickFalse))
246     if (InitializeConfigureList(exception) == MagickFalse)
247       return((const ConfigureInfo *) NULL);
248   if ((configure_list == (LinkedListInfo *) NULL) ||
249       (IsLinkedListEmpty(configure_list) != MagickFalse))
250     return((const ConfigureInfo *) NULL);
251   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
252     return((const ConfigureInfo *) GetValueFromLinkedList(configure_list,0));
253   /*
254     Search for configure tag.
255   */
256   LockSemaphoreInfo(configure_semaphore);
257   ResetLinkedListIterator(configure_list);
258   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
259   while (p != (const ConfigureInfo *) NULL)
260   {
261     if (LocaleCompare(name,p->name) == 0)
262       break;
263     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
264   }
265   if (p != (ConfigureInfo *) NULL)
266     (void) InsertValueInLinkedList(configure_list,0,
267       RemoveElementByValueFromLinkedList(configure_list,p));
268   UnlockSemaphoreInfo(configure_semaphore);
269   return(p);
270 }
271 \f
272 /*
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 %                                                                             %
275 %                                                                             %
276 %                                                                             %
277 %   G e t C o n f i g u r e I n f o L i s t                                   %
278 %                                                                             %
279 %                                                                             %
280 %                                                                             %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %
283 %  GetConfigureInfoList() returns any configure options that match the
284 %  specified pattern.
285 %
286 %  The format of the GetConfigureInfoList function is:
287 %
288 %      const ConfigureInfo **GetConfigureInfoList(const char *pattern,
289 %        size_t *number_options,ExceptionInfo *exception)
290 %
291 %  A description of each parameter follows:
292 %
293 %    o pattern: Specifies a pointer to a text string containing a pattern.
294 %
295 %    o number_options:  This integer returns the number of configure options in
296 %    the list.
297 %
298 %    o exception: return any errors or warnings in this structure.
299 %
300 */
301
302 #if defined(__cplusplus) || defined(c_plusplus)
303 extern "C" {
304 #endif
305
306 static int ConfigureInfoCompare(const void *x,const void *y)
307 {
308   const ConfigureInfo
309     **p,
310     **q;
311
312   p=(const ConfigureInfo **) x,
313   q=(const ConfigureInfo **) y;
314   if (LocaleCompare((*p)->path,(*q)->path) == 0)
315     return(LocaleCompare((*p)->name,(*q)->name));
316   return(LocaleCompare((*p)->path,(*q)->path));
317 }
318
319 #if defined(__cplusplus) || defined(c_plusplus)
320 }
321 #endif
322
323 MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
324   size_t *number_options,ExceptionInfo *exception)
325 {
326   const ConfigureInfo
327     **options;
328
329   register const ConfigureInfo
330     *p;
331
332   register ssize_t
333     i;
334
335   /*
336     Allocate configure list.
337   */
338   assert(pattern != (char *) NULL);
339   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
340   assert(number_options != (size_t *) NULL);
341   *number_options=0;
342   p=GetConfigureInfo("*",exception);
343   if (p == (const ConfigureInfo *) NULL)
344     return((const ConfigureInfo **) NULL);
345   options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
346     GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
347   if (options == (const ConfigureInfo **) NULL)
348     return((const ConfigureInfo **) NULL);
349   /*
350     Generate configure list.
351   */
352   LockSemaphoreInfo(configure_semaphore);
353   ResetLinkedListIterator(configure_list);
354   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
355   for (i=0; p != (const ConfigureInfo *) NULL; )
356   {
357     if ((p->stealth == MagickFalse) &&
358         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
359       options[i++]=p;
360     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
361   }
362   UnlockSemaphoreInfo(configure_semaphore);
363   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
364   options[i]=(ConfigureInfo *) NULL;
365   *number_options=(size_t) i;
366   return(options);
367 }
368 \f
369 /*
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 %                                                                             %
372 %                                                                             %
373 %                                                                             %
374 %   G e t C o n f i g u r e L i s t                                           %
375 %                                                                             %
376 %                                                                             %
377 %                                                                             %
378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 %
380 %  GetConfigureList() returns any configure options that match the specified
381 %  pattern.
382 %
383 %  The format of the GetConfigureList function is:
384 %
385 %      char **GetConfigureList(const char *pattern,
386 %        size_t *number_options,ExceptionInfo *exception)
387 %
388 %  A description of each parameter follows:
389 %
390 %    o pattern: Specifies a pointer to a text string containing a pattern.
391 %
392 %    o number_options:  This integer returns the number of options in the list.
393 %
394 %    o exception: return any errors or warnings in this structure.
395 %
396 */
397
398 #if defined(__cplusplus) || defined(c_plusplus)
399 extern "C" {
400 #endif
401
402 static int ConfigureCompare(const void *x,const void *y)
403 {
404   register char
405     **p,
406     **q;
407
408   p=(char **) x;
409   q=(char **) y;
410   return(LocaleCompare(*p,*q));
411 }
412
413 #if defined(__cplusplus) || defined(c_plusplus)
414 }
415 #endif
416
417 MagickExport char **GetConfigureList(const char *pattern,
418   size_t *number_options,ExceptionInfo *exception)
419 {
420   char
421     **options;
422
423   register const ConfigureInfo
424     *p;
425
426   register ssize_t
427     i;
428
429   /*
430     Allocate configure list.
431   */
432   assert(pattern != (char *) NULL);
433   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
434   assert(number_options != (size_t *) NULL);
435   *number_options=0;
436   p=GetConfigureInfo("*",exception);
437   if (p == (const ConfigureInfo *) NULL)
438     return((char **) NULL);
439   options=(char **) AcquireQuantumMemory((size_t)
440     GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
441   if (options == (char **) NULL)
442     return((char **) NULL);
443   LockSemaphoreInfo(configure_semaphore);
444   ResetLinkedListIterator(configure_list);
445   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
446   for (i=0; p != (const ConfigureInfo *) NULL; )
447   {
448     if ((p->stealth == MagickFalse) &&
449         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
450       options[i++]=ConstantString(p->name);
451     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
452   }
453   UnlockSemaphoreInfo(configure_semaphore);
454   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
455   options[i]=(char *) NULL;
456   *number_options=(size_t) i;
457   return(options);
458 }
459 \f
460 /*
461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 %                                                                             %
463 %                                                                             %
464 %                                                                             %
465 %   G e t C o n f i g u r e O p t i o n                                       %
466 %                                                                             %
467 %                                                                             %
468 %                                                                             %
469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 %
471 %  GetConfigureOption() returns the value associated with the configure option.
472 %
473 %  The format of the GetConfigureOption method is:
474 %
475 %      char *GetConfigureOption(const char *option)
476 %
477 %  A description of each parameter follows:
478 %
479 %    o configure_info:  The configure info.
480 %
481 */
482 MagickExport char *GetConfigureOption(const char *option)
483 {
484   const char
485     *value;
486
487   const ConfigureInfo
488     *configure_info;
489
490   ExceptionInfo
491     *exception;
492
493   assert(option != (const char *) NULL);
494   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
495   exception=AcquireExceptionInfo();
496   configure_info=GetConfigureInfo(option,exception);
497   exception=DestroyExceptionInfo(exception);
498   if (configure_info == (ConfigureInfo *) NULL)
499     return((char *) NULL);
500   value=GetConfigureValue(configure_info);
501   if ((value == (const char *) NULL) || (*value == '\0'))
502     return((char *) NULL);
503   return(ConstantString(value));
504 }
505 \f
506 /*
507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 %                                                                             %
509 %                                                                             %
510 %                                                                             %
511 %  G e t C o n f i g u r e O p t i o n s                                      %
512 %                                                                             %
513 %                                                                             %
514 %                                                                             %
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516 %
517 %  GetConfigureOptions() returns any Magick configuration options associated
518 %  with the specified filename.
519 %
520 %  The format of the GetConfigureOptions method is:
521 %
522 %      LinkedListInfo *GetConfigureOptions(const char *filename,
523 %        ExceptionInfo *exception)
524 %
525 %  A description of each parameter follows:
526 %
527 %    o filename: the configure file name.
528 %
529 %    o exception: return any errors or warnings in this structure.
530 %
531 */
532 MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
533   ExceptionInfo *exception)
534 {
535   char
536     path[MaxTextExtent];
537
538   const char
539     *element;
540
541   LinkedListInfo
542     *options,
543     *paths;
544
545   StringInfo
546     *xml;
547
548   assert(filename != (const char *) NULL);
549   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
550   assert(exception != (ExceptionInfo *) NULL);
551   (void) CopyMagickString(path,filename,MaxTextExtent);
552   /*
553     Load XML from configuration files to linked-list.
554   */
555   options=NewLinkedList(0);
556   paths=GetConfigurePaths(filename,exception);
557   if (paths != (LinkedListInfo *) NULL)
558     {
559       ResetLinkedListIterator(paths);
560       element=(const char *) GetNextValueInLinkedList(paths);
561       while (element != (const char *) NULL)
562       {
563         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",element,filename);
564         (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
565           "Searching for configure file: \"%s\"",path);
566         xml=ConfigureFileToStringInfo(path);
567         if (xml != (StringInfo *) NULL)
568           (void) AppendValueToLinkedList(options,xml);
569         element=(const char *) GetNextValueInLinkedList(paths);
570       }
571       paths=DestroyLinkedList(paths,RelinquishMagickMemory);
572     }
573 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
574   {
575     char
576       *blob;
577
578     blob=(char *) NTResourceToBlob(filename);
579     if (blob != (char *) NULL)
580       {
581         xml=StringToStringInfo(blob);
582         SetStringInfoPath(xml,filename);
583         (void) AppendValueToLinkedList(options,xml);
584         blob=DestroyString(blob);
585       }
586   }
587 #endif
588   if (GetNumberOfElementsInLinkedList(options) == 0)
589     (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
590       "UnableToOpenConfigureFile","`%s'",filename);
591   ResetLinkedListIterator(options);
592   return(options);
593 }
594 \f
595 /*
596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 %                                                                             %
598 %                                                                             %
599 %                                                                             %
600 %  G e t C o n f i g u r e P a t h s                                          %
601 %                                                                             %
602 %                                                                             %
603 %                                                                             %
604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
605 %
606 %  GetConfigurePaths() returns any Magick configuration paths associated
607 %  with the specified filename.
608 %
609 %  The format of the GetConfigurePaths method is:
610 %
611 %      LinkedListInfo *GetConfigurePaths(const char *filename,
612 %        ExceptionInfo *exception)
613 %
614 %  A description of each parameter follows:
615 %
616 %    o filename: the configure file name.
617 %
618 %    o exception: return any errors or warnings in this structure.
619 %
620 */
621 MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
622   ExceptionInfo *exception)
623 {
624   char
625     path[MaxTextExtent];
626
627   LinkedListInfo
628     *paths;
629
630   assert(filename != (const char *) NULL);
631   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
632   assert(exception != (ExceptionInfo *) NULL);
633   (void) CopyMagickString(path,filename,MaxTextExtent);
634   paths=NewLinkedList(0);
635   {
636     char
637       *configure_path;
638
639     /*
640       Search $MAGICK_CONFIGURE_PATH.
641     */
642     configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
643     if (configure_path != (char *) NULL)
644       {
645         register char
646           *p,
647           *q;
648
649         for (p=configure_path-1; p != (char *) NULL; )
650         {
651           (void) CopyMagickString(path,p+1,MaxTextExtent);
652           q=strchr(path,DirectoryListSeparator);
653           if (q != (char *) NULL)
654             *q='\0';
655           q=path+strlen(path)-1;
656           if ((q >= path) && (*q != *DirectorySeparator))
657             (void) ConcatenateMagickString(path,DirectorySeparator,
658               MaxTextExtent);
659           (void) AppendValueToLinkedList(paths,ConstantString(path));
660           p=strchr(p+1,DirectoryListSeparator);
661         }
662         configure_path=DestroyString(configure_path);
663       }
664   }
665 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
666 #if defined(MAGICKCORE_SHARE_PATH)
667   (void) AppendValueToLinkedList(paths,ConstantString(
668     MAGICKCORE_SHARE_PATH));
669 #endif
670 #if defined(MAGICKCORE_CONFIGURE_PATH)
671   (void) AppendValueToLinkedList(paths,ConstantString(
672     MAGICKCORE_CONFIGURE_PATH));
673 #endif
674 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
675   (void) AppendValueToLinkedList(paths,ConstantString(
676     MAGICKCORE_DOCUMENTATION_PATH));
677 #endif
678 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
679   {
680     char
681       *registry_key;
682
683     unsigned char
684       *key_value;
685
686     /*
687       Locate file via registry key.
688     */
689     registry_key="ConfigurePath";
690     key_value=NTRegistryKeyLookup(registry_key);
691     if (key_value != (unsigned char *) NULL)
692       {
693         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",(char *) key_value,
694           DirectorySeparator);
695         (void) AppendValueToLinkedList(paths,ConstantString(path));
696         key_value=(unsigned char *) RelinquishMagickMemory(key_value);
697       }
698   }
699 #endif
700 #else
701   {
702     char
703       *home;
704
705     /*
706       Search under MAGICK_HOME.
707     */
708     home=GetEnvironmentValue("MAGICK_HOME");
709     if (home != (char *) NULL)
710       {
711 #if !defined(MAGICKCORE_POSIX_SUPPORT)
712         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",home,
713           DirectorySeparator);
714         (void) AppendValueToLinkedList(paths,ConstantString(path));
715 #else
716         (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",home,
717           MAGICKCORE_CONFIGURE_RELATIVE_PATH);
718         (void) AppendValueToLinkedList(paths,ConstantString(path));
719         (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",home,
720           MAGICKCORE_SHARE_RELATIVE_PATH);
721         (void) AppendValueToLinkedList(paths,ConstantString(path));
722 #endif
723         home=DestroyString(home);
724       }
725     }
726   if (*GetClientPath() != '\0')
727     {
728 #if !defined(MAGICKCORE_POSIX_SUPPORT)
729       (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
730         DirectorySeparator);
731       (void) AppendValueToLinkedList(paths,ConstantString(path));
732 #else
733       char
734         prefix[MaxTextExtent];
735
736       /*
737         Search based on executable directory if directory is known.
738       */
739       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
740       ChopPathComponents(prefix,1);
741       (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
742         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
743       (void) AppendValueToLinkedList(paths,ConstantString(path));
744       (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
745         MAGICKCORE_SHARE_RELATIVE_PATH);
746       (void) AppendValueToLinkedList(paths,ConstantString(path));
747 #endif
748     }
749   /*
750     Search current directory.
751   */
752   (void) AppendValueToLinkedList(paths,ConstantString(""));
753 #endif
754   {
755     char
756       *home;
757
758     home=GetEnvironmentValue("HOME");
759     if (home == (char *) NULL)
760       home=GetEnvironmentValue("USERPROFILE");
761     if (home != (char *) NULL)
762       {
763         /*
764           Search $HOME/.magick.
765         */
766         (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s",home,
767           DirectorySeparator,DirectorySeparator);
768         (void) AppendValueToLinkedList(paths,ConstantString(path));
769         home=DestroyString(home);
770       }
771   }
772 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
773   {
774     char
775       module_path[MaxTextExtent];
776
777     if ((NTGetModulePath("CORE_RL_magick_.dll",module_path) != MagickFalse) ||
778         (NTGetModulePath("CORE_DB_magick_.dll",module_path) != MagickFalse))
779       {
780         char
781           *element;
782
783         /*
784           Search module path.
785         */
786         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
787           DirectorySeparator);
788         element=(char *) RemoveElementByValueFromLinkedList(paths,path);
789         if (element != (char *) NULL)
790           element=DestroyString(element);
791         (void) AppendValueToLinkedList(paths,ConstantString(path));
792       }
793     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
794       {
795         /*
796           Search PerlMagick module path.
797         */
798         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
799           DirectorySeparator);
800         (void) AppendValueToLinkedList(paths,ConstantString(path));
801         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
802           "\\inc\\lib\\auto\\Image\\Magick\\");
803         (void) AppendValueToLinkedList(paths,ConstantString(path));
804       }
805   }
806 #endif
807   return(paths);
808 }
809 \f
810 /*
811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812 %                                                                             %
813 %                                                                             %
814 %                                                                             %
815 %   G e t C o n f i g u r e V a l u e                                         %
816 %                                                                             %
817 %                                                                             %
818 %                                                                             %
819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820 %
821 %  GetConfigureValue() returns the value associated with the configure info.
822 %
823 %  The format of the GetConfigureValue method is:
824 %
825 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
826 %
827 %  A description of each parameter follows:
828 %
829 %    o configure_info:  The configure info.
830 %
831 */
832 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
833 {
834   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
835   assert(configure_info != (ConfigureInfo *) NULL);
836   assert(configure_info->signature == MagickSignature);
837   return(configure_info->value);
838 }
839 \f
840 /*
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %                                                                             %
843 %                                                                             %
844 %                                                                             %
845 +   I n i t i a l i z e C o n f i g u r e L i s t                             %
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 %
851 %  InitializeConfigureList() initializes the configure list.
852 %
853 %  The format of the InitializeConfigureList method is:
854 %
855 %      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
856 %
857 %  A description of each parameter follows.
858 %
859 %    o exception: return any errors or warnings in this structure.
860 %
861 */
862 static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
863 {
864   if ((configure_list == (LinkedListInfo *) NULL) &&
865       (instantiate_configure == MagickFalse))
866     {
867       if (configure_semaphore == (SemaphoreInfo *) NULL)
868         AcquireSemaphoreInfo(&configure_semaphore);
869       LockSemaphoreInfo(configure_semaphore);
870       if ((configure_list == (LinkedListInfo *) NULL) &&
871           (instantiate_configure == MagickFalse))
872         {
873           (void) LoadConfigureLists(ConfigureFilename,exception);
874           instantiate_configure=MagickTrue;
875         }
876       UnlockSemaphoreInfo(configure_semaphore);
877     }
878   return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
879 }
880 \f
881 /*
882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883 %                                                                             %
884 %                                                                             %
885 %                                                                             %
886 %  L i s t C o n f i g u r e I n f o                                          %
887 %                                                                             %
888 %                                                                             %
889 %                                                                             %
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 %
892 %  ListConfigureInfo() lists the configure info to a file.
893 %
894 %  The format of the ListConfigureInfo method is:
895 %
896 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
897 %
898 %  A description of each parameter follows.
899 %
900 %    o file:  An pointer to a FILE.
901 %
902 %    o exception: return any errors or warnings in this structure.
903 %
904 */
905 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
906   ExceptionInfo *exception)
907 {
908   const char
909     *name,
910     *path,
911     *value;
912
913   const ConfigureInfo
914     **configure_info;
915
916   register ssize_t
917     i;
918
919   size_t
920     number_options;
921
922   ssize_t
923     j;
924
925   if (file == (const FILE *) NULL)
926     file=stdout;
927   configure_info=GetConfigureInfoList("*",&number_options,exception);
928   if (configure_info == (const ConfigureInfo **) NULL)
929     return(MagickFalse);
930   path=(const char *) NULL;
931   for (i=0; i < (ssize_t) number_options; i++)
932   {
933     if (configure_info[i]->stealth != MagickFalse)
934       continue;
935     if ((path == (const char *) NULL) ||
936         (LocaleCompare(path,configure_info[i]->path) != 0))
937       {
938         if (configure_info[i]->path != (char *) NULL)
939           (void) FormatLocaleFile(file,"\nPath: %s\n\n",
940             configure_info[i]->path);
941         (void) FormatLocaleFile(file,"Name          Value\n");
942         (void) FormatLocaleFile(file,
943           "-------------------------------------------------"
944           "------------------------------\n");
945       }
946     path=configure_info[i]->path;
947     name="unknown";
948     if (configure_info[i]->name != (char *) NULL)
949       name=configure_info[i]->name;
950     (void) FormatLocaleFile(file,"%s",name);
951     for (j=(ssize_t) strlen(name); j <= 12; j++)
952       (void) FormatLocaleFile(file," ");
953     (void) FormatLocaleFile(file," ");
954     value="unknown";
955     if (configure_info[i]->value != (char *) NULL)
956       value=configure_info[i]->value;
957     (void) FormatLocaleFile(file,"%s",value);
958     (void) FormatLocaleFile(file,"\n");
959   }
960   (void) fflush(file);
961   configure_info=(const ConfigureInfo **)
962     RelinquishMagickMemory((void *) configure_info);
963   return(MagickTrue);
964 }
965 \f
966 /*
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %                                                                             %
969 %                                                                             %
970 %                                                                             %
971 +   L o a d C o n f i g u r e L i s t                                         %
972 %                                                                             %
973 %                                                                             %
974 %                                                                             %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 %
977 %  LoadConfigureList() loads the configure configuration file which provides a
978 %  mapping between configure attributes and a configure name.
979 %
980 %  The format of the LoadConfigureList method is:
981 %
982 %      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
983 %        const size_t depth,ExceptionInfo *exception)
984 %
985 %  A description of each parameter follows:
986 %
987 %    o xml:  The configure list in XML format.
988 %
989 %    o filename:  The configure list filename.
990 %
991 %    o depth: depth of <include /> statements.
992 %
993 %    o exception: return any errors or warnings in this structure.
994 %
995 */
996 static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
997   const size_t depth,ExceptionInfo *exception)
998 {
999   char
1000     keyword[MaxTextExtent],
1001     *token;
1002
1003   ConfigureInfo
1004     *configure_info;
1005
1006   const char
1007     *q;
1008
1009   MagickBooleanType
1010     status;
1011
1012   /*
1013     Load the configure map file.
1014   */
1015   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1016     "Loading configure file \"%s\" ...",filename);
1017   if (configure_list == (LinkedListInfo *) NULL)
1018     {
1019       configure_list=NewLinkedList(0);
1020       if (configure_list == (LinkedListInfo *) NULL)
1021         {
1022           ThrowFileException(exception,ResourceLimitError,
1023             "MemoryAllocationFailed",filename);
1024           return(MagickFalse);
1025         }
1026     }
1027   status=MagickTrue;
1028   configure_info=(ConfigureInfo *) NULL;
1029   token=AcquireString((char *) xml);
1030   for (q=(char *) xml; *q != '\0'; )
1031   {
1032     /*
1033       Interpret XML.
1034     */
1035     GetMagickToken(q,&q,token);
1036     if (*token == '\0')
1037       break;
1038     (void) CopyMagickString(keyword,token,MaxTextExtent);
1039     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1040       {
1041         /*
1042           Doctype element.
1043         */
1044         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1045           GetMagickToken(q,&q,token);
1046         continue;
1047       }
1048     if (LocaleNCompare(keyword,"<!--",4) == 0)
1049       {
1050         /*
1051           Comment element.
1052         */
1053         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1054           GetMagickToken(q,&q,token);
1055         continue;
1056       }
1057     if (LocaleCompare(keyword,"<include") == 0)
1058       {
1059         /*
1060           Include element.
1061         */
1062         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1063         {
1064           (void) CopyMagickString(keyword,token,MaxTextExtent);
1065           GetMagickToken(q,&q,token);
1066           if (*token != '=')
1067             continue;
1068           GetMagickToken(q,&q,token);
1069           if (LocaleCompare(keyword,"file") == 0)
1070             {
1071               if (depth > 200)
1072                 (void) ThrowMagickException(exception,GetMagickModule(),
1073                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1074               else
1075                 {
1076                   char
1077                     path[MaxTextExtent],
1078                     *xml;
1079
1080                   GetPathComponent(filename,HeadPath,path);
1081                   if (*path != '\0')
1082                     (void) ConcatenateMagickString(path,DirectorySeparator,
1083                       MaxTextExtent);
1084                   if (*token == *DirectorySeparator)
1085                     (void) CopyMagickString(path,token,MaxTextExtent);
1086                   else
1087                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
1088                   xml=FileToString(path,~0,exception);
1089                   if (xml != (char *) NULL)
1090                     {
1091                       status=LoadConfigureList(xml,path,depth+1,exception);
1092                       xml=(char *) RelinquishMagickMemory(xml);
1093                     }
1094                 }
1095             }
1096         }
1097         continue;
1098       }
1099     if (LocaleCompare(keyword,"<configure") == 0)
1100       {
1101         /*
1102           Configure element.
1103         */
1104         configure_info=(ConfigureInfo *) AcquireMagickMemory(
1105           sizeof(*configure_info));
1106         if (configure_info == (ConfigureInfo *) NULL)
1107           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1108         (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1109         configure_info->path=ConstantString(filename);
1110         configure_info->exempt=MagickFalse;
1111         configure_info->signature=MagickSignature;
1112         continue;
1113       }
1114     if (configure_info == (ConfigureInfo *) NULL)
1115       continue;
1116     if (LocaleCompare(keyword,"/>") == 0)
1117       {
1118         status=AppendValueToLinkedList(configure_list,configure_info);
1119         if (status == MagickFalse)
1120           (void) ThrowMagickException(exception,GetMagickModule(),
1121             ResourceLimitError,"MemoryAllocationFailed","`%s'",
1122             configure_info->name);
1123         configure_info=(ConfigureInfo *) NULL;
1124       }
1125     /*
1126       Parse configure element.
1127     */
1128     GetMagickToken(q,(const char **) NULL,token);
1129     if (*token != '=')
1130       continue;
1131     GetMagickToken(q,&q,token);
1132     GetMagickToken(q,&q,token);
1133     switch (*keyword)
1134     {
1135       case 'N':
1136       case 'n':
1137       {
1138         if (LocaleCompare((char *) keyword,"name") == 0)
1139           {
1140             configure_info->name=ConstantString(token);
1141             break;
1142           }
1143         break;
1144       }
1145       case 'S':
1146       case 's':
1147       {
1148         if (LocaleCompare((char *) keyword,"stealth") == 0)
1149           {
1150             configure_info->stealth=IsMagickTrue(token);
1151             break;
1152           }
1153         break;
1154       }
1155       case 'V':
1156       case 'v':
1157       {
1158         if (LocaleCompare((char *) keyword,"value") == 0)
1159           {
1160             configure_info->value=ConstantString(token);
1161             break;
1162           }
1163         break;
1164       }
1165       default:
1166         break;
1167     }
1168   }
1169   token=(char *) RelinquishMagickMemory(token);
1170   return(status);
1171 }
1172 \f
1173 /*
1174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 %                                                                             %
1176 %                                                                             %
1177 %                                                                             %
1178 %  L o a d C o n f i g u r e L i s t s                                        %
1179 %                                                                             %
1180 %                                                                             %
1181 %                                                                             %
1182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 %
1184 %  LoadConfigureList() loads one or more configure configuration files which
1185 %  provides a mapping between configure attributes and a configure name.
1186 %
1187 %  The format of the LoadConfigureLists method is:
1188 %
1189 %      MagickBooleanType LoadConfigureLists(const char *filename,
1190 %        ExceptionInfo *exception)
1191 %
1192 %  A description of each parameter follows:
1193 %
1194 %    o filename: the font file name.
1195 %
1196 %    o exception: return any errors or warnings in this structure.
1197 %
1198 */
1199 static MagickBooleanType LoadConfigureLists(const char *filename,
1200   ExceptionInfo *exception)
1201 {
1202   const StringInfo
1203     *option;
1204
1205   LinkedListInfo
1206     *options;
1207
1208   MagickStatusType
1209     status;
1210
1211   register ssize_t
1212     i;
1213
1214   /*
1215     Load built-in configure map.
1216   */
1217   status=MagickFalse;
1218   if (configure_list == (LinkedListInfo *) NULL)
1219     {
1220       configure_list=NewLinkedList(0);
1221       if (configure_list == (LinkedListInfo *) NULL)
1222         {
1223           ThrowFileException(exception,ResourceLimitError,
1224             "MemoryAllocationFailed",filename);
1225           return(MagickFalse);
1226         }
1227     }
1228   for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
1229   {
1230     ConfigureInfo
1231       *configure_info;
1232
1233     register const ConfigureMapInfo
1234       *p;
1235
1236     p=ConfigureMap+i;
1237     configure_info=(ConfigureInfo *) AcquireMagickMemory(
1238       sizeof(*configure_info));
1239     if (configure_info == (ConfigureInfo *) NULL)
1240       {
1241         (void) ThrowMagickException(exception,GetMagickModule(),
1242           ResourceLimitError,"MemoryAllocationFailed","`%s'",
1243           configure_info->name);
1244         continue;
1245       }
1246     (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1247     configure_info->path=(char *) "[built-in]";
1248     configure_info->name=(char *) p->name;
1249     configure_info->value=(char *) p->value;
1250     configure_info->exempt=MagickTrue;
1251     configure_info->signature=MagickSignature;
1252     status=AppendValueToLinkedList(configure_list,configure_info);
1253     if (status == MagickFalse)
1254       (void) ThrowMagickException(exception,GetMagickModule(),
1255         ResourceLimitError,"MemoryAllocationFailed","`%s'",
1256         configure_info->name);
1257   }
1258   /*
1259     Load external configure map.
1260   */
1261   options=GetConfigureOptions(filename,exception);
1262   option=(const StringInfo *) GetNextValueInLinkedList(options);
1263   while (option != (const StringInfo *) NULL)
1264   {
1265     status|=LoadConfigureList((const char *) GetStringInfoDatum(option),
1266       GetStringInfoPath(option),0,exception);
1267     option=(const StringInfo *) GetNextValueInLinkedList(options);
1268   }
1269   options=DestroyConfigureOptions(options);
1270   return(status != 0 ? MagickTrue : MagickFalse);
1271 }