]> granicus.if.org Git - imagemagick/blob - magick/configure.c
(no commit message)
[imagemagick] / magick / 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 "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/configure.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/hashmap.h"
49 #include "magick/log.h"
50 #include "magick/memory_.h"
51 #include "magick/semaphore.h"
52 #include "magick/string_.h"
53 #include "magick/token.h"
54 #include "magick/utility.h"
55 #include "magick/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) FormatMagickString(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_CONFIGURE_PATH)
667   (void) AppendValueToLinkedList(paths,ConstantString(
668     MAGICKCORE_SHARE_CONFIGURE_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_SHARE_PATH)
679   (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
680 #endif
681 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_CONFIGURE_PATH))
682   {
683     char
684       *registry_key;
685
686     unsigned char
687       *key_value;
688
689     /*
690       Locate file via registry key.
691     */
692     registry_key="ConfigurePath";
693     key_value=NTRegistryKeyLookup(registry_key);
694     if (key_value != (unsigned char *) NULL)
695       {
696         (void) FormatMagickString(path,MaxTextExtent,"%s%s",(char *) key_value,
697           DirectorySeparator);
698         (void) AppendValueToLinkedList(paths,ConstantString(path));
699         key_value=(unsigned char *) RelinquishMagickMemory(key_value);
700       }
701   }
702 #endif
703 #else
704   {
705     char
706       *home;
707
708     /*
709       Search under MAGICK_HOME.
710     */
711     home=GetEnvironmentValue("MAGICK_HOME");
712     if (home != (char *) NULL)
713       {
714 #if !defined(MAGICKCORE_POSIX_SUPPORT)
715         (void) FormatMagickString(path,MaxTextExtent,"%s%s",home,
716           DirectorySeparator);
717         (void) AppendValueToLinkedList(paths,ConstantString(path));
718 #else
719         (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",home,
720           MAGICKCORE_CONFIGURE_RELATIVE_PATH);
721         (void) AppendValueToLinkedList(paths,ConstantString(path));
722         (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",home,
723           MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
724         (void) AppendValueToLinkedList(paths,ConstantString(path));
725 #endif
726         home=DestroyString(home);
727       }
728     }
729   if (*GetClientPath() != '\0')
730     {
731 #if !defined(MAGICKCORE_POSIX_SUPPORT)
732       (void) FormatMagickString(path,MaxTextExtent,"%s%s",GetClientPath(),
733         DirectorySeparator);
734       (void) AppendValueToLinkedList(paths,ConstantString(path));
735 #else
736       char
737         prefix[MaxTextExtent];
738
739       /*
740         Search based on executable directory if directory is known.
741       */
742       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
743       ChopPathComponents(prefix,1);
744       (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",prefix,
745         MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
746       (void) AppendValueToLinkedList(paths,ConstantString(path));
747       (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",prefix,
748         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
749       (void) AppendValueToLinkedList(paths,ConstantString(path));
750 #endif
751     }
752   /*
753     Search current directory.
754   */
755   (void) AppendValueToLinkedList(paths,ConstantString(""));
756 #endif
757   {
758     char
759       *home;
760
761     home=GetEnvironmentValue("HOME");
762     if (home == (char *) NULL)
763       home=GetEnvironmentValue("USERPROFILE");
764     if (home != (char *) NULL)
765       {
766         /*
767           Search $HOME/.magick.
768         */
769         (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s",home,
770           DirectorySeparator,DirectorySeparator);
771         (void) AppendValueToLinkedList(paths,ConstantString(path));
772         home=DestroyString(home);
773       }
774   }
775 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
776   {
777     char
778       module_path[MaxTextExtent];
779
780     if ((NTGetModulePath("CORE_RL_magick_.dll",module_path) != MagickFalse) ||
781         (NTGetModulePath("CORE_DB_magick_.dll",module_path) != MagickFalse))
782       {
783         char
784           *element;
785
786         /*
787           Search module path.
788         */
789         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
790           DirectorySeparator);
791         element=(char *) RemoveElementByValueFromLinkedList(paths,path);
792         if (element != (char *) NULL)
793           element=DestroyString(element);
794         (void) AppendValueToLinkedList(paths,ConstantString(path));
795       }
796     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
797       {
798         /*
799           Search PerlMagick module path.
800         */
801         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
802           DirectorySeparator);
803         (void) AppendValueToLinkedList(paths,ConstantString(path));
804         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
805           "\\inc\\lib\\auto\\Image\\Magick\\");
806         (void) AppendValueToLinkedList(paths,ConstantString(path));
807       }
808   }
809 #endif
810   return(paths);
811 }
812 \f
813 /*
814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 %                                                                             %
816 %                                                                             %
817 %                                                                             %
818 %   G e t C o n f i g u r e V a l u e                                         %
819 %                                                                             %
820 %                                                                             %
821 %                                                                             %
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %
824 %  GetConfigureValue() returns the value associated with the configure info.
825 %
826 %  The format of the GetConfigureValue method is:
827 %
828 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
829 %
830 %  A description of each parameter follows:
831 %
832 %    o configure_info:  The configure info.
833 %
834 */
835 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
836 {
837   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
838   assert(configure_info != (ConfigureInfo *) NULL);
839   assert(configure_info->signature == MagickSignature);
840   return(configure_info->value);
841 }
842 \f
843 /*
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %                                                                             %
846 %                                                                             %
847 %                                                                             %
848 +   I n i t i a l i z e C o n f i g u r e L i s t                             %
849 %                                                                             %
850 %                                                                             %
851 %                                                                             %
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 %
854 %  InitializeConfigureList() initializes the configure list.
855 %
856 %  The format of the InitializeConfigureList method is:
857 %
858 %      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
859 %
860 %  A description of each parameter follows.
861 %
862 %    o exception: return any errors or warnings in this structure.
863 %
864 */
865 static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
866 {
867   if ((configure_list == (LinkedListInfo *) NULL) &&
868       (instantiate_configure == MagickFalse))
869     {
870       if (configure_semaphore == (SemaphoreInfo *) NULL)
871         AcquireSemaphoreInfo(&configure_semaphore);
872       LockSemaphoreInfo(configure_semaphore);
873       if ((configure_list == (LinkedListInfo *) NULL) &&
874           (instantiate_configure == MagickFalse))
875         {
876           (void) LoadConfigureLists(ConfigureFilename,exception);
877           instantiate_configure=MagickTrue;
878         }
879       UnlockSemaphoreInfo(configure_semaphore);
880     }
881   return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
882 }
883 \f
884 /*
885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 %                                                                             %
887 %                                                                             %
888 %                                                                             %
889 %  L i s t C o n f i g u r e I n f o                                          %
890 %                                                                             %
891 %                                                                             %
892 %                                                                             %
893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
894 %
895 %  ListConfigureInfo() lists the configure info to a file.
896 %
897 %  The format of the ListConfigureInfo method is:
898 %
899 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
900 %
901 %  A description of each parameter follows.
902 %
903 %    o file:  An pointer to a FILE.
904 %
905 %    o exception: return any errors or warnings in this structure.
906 %
907 */
908 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
909   ExceptionInfo *exception)
910 {
911   const char
912     *name,
913     *path,
914     *value;
915
916   const ConfigureInfo
917     **configure_info;
918
919   ssize_t
920     j;
921
922   register ssize_t
923     i;
924
925   size_t
926     number_options;
927
928   if (file == (const FILE *) NULL)
929     file=stdout;
930   configure_info=GetConfigureInfoList("*",&number_options,exception);
931   if (configure_info == (const ConfigureInfo **) NULL)
932     return(MagickFalse);
933   path=(const char *) NULL;
934   for (i=0; i < (ssize_t) number_options; i++)
935   {
936     if (configure_info[i]->stealth != MagickFalse)
937       continue;
938     if ((path == (const char *) NULL) ||
939         (LocaleCompare(path,configure_info[i]->path) != 0))
940       {
941         if (configure_info[i]->path != (char *) NULL)
942           (void) fprintf(file,"\nPath: %s\n\n",configure_info[i]->path);
943         (void) fprintf(file,"Name          Value\n");
944         (void) fprintf(file,"-------------------------------------------------"
945           "------------------------------\n");
946       }
947     path=configure_info[i]->path;
948     name="unknown";
949     if (configure_info[i]->name != (char *) NULL)
950       name=configure_info[i]->name;
951     (void) fprintf(file,"%s",name);
952     for (j=(ssize_t) strlen(name); j <= 12; j++)
953       (void) fprintf(file," ");
954     (void) fprintf(file," ");
955     value="unknown";
956     if (configure_info[i]->value != (char *) NULL)
957       value=configure_info[i]->value;
958     (void) fprintf(file,"%s",value);
959     (void) fprintf(file,"\n");
960   }
961   (void) fflush(file);
962   configure_info=(const ConfigureInfo **)
963     RelinquishMagickMemory((void *) configure_info);
964   return(MagickTrue);
965 }
966 \f
967 /*
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 %                                                                             %
970 %                                                                             %
971 %                                                                             %
972 +   L o a d C o n f i g u r e L i s t                                         %
973 %                                                                             %
974 %                                                                             %
975 %                                                                             %
976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 %
978 %  LoadConfigureList() loads the configure configuration file which provides a
979 %  mapping between configure attributes and a configure name.
980 %
981 %  The format of the LoadConfigureList method is:
982 %
983 %      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
984 %        const size_t depth,ExceptionInfo *exception)
985 %
986 %  A description of each parameter follows:
987 %
988 %    o xml:  The configure list in XML format.
989 %
990 %    o filename:  The configure list filename.
991 %
992 %    o depth: depth of <include /> statements.
993 %
994 %    o exception: return any errors or warnings in this structure.
995 %
996 */
997 static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
998   const size_t depth,ExceptionInfo *exception)
999 {
1000   char
1001     keyword[MaxTextExtent],
1002     *token;
1003
1004   ConfigureInfo
1005     *configure_info;
1006
1007   const char
1008     *q;
1009
1010   MagickBooleanType
1011     status;
1012
1013   /*
1014     Load the configure map file.
1015   */
1016   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1017     "Loading configure file \"%s\" ...",filename);
1018   if (configure_list == (LinkedListInfo *) NULL)
1019     {
1020       configure_list=NewLinkedList(0);
1021       if (configure_list == (LinkedListInfo *) NULL)
1022         {
1023           ThrowFileException(exception,ResourceLimitError,
1024             "MemoryAllocationFailed",filename);
1025           return(MagickFalse);
1026         }
1027     }
1028   status=MagickTrue;
1029   configure_info=(ConfigureInfo *) NULL;
1030   token=AcquireString((char *) xml);
1031   for (q=(char *) xml; *q != '\0'; )
1032   {
1033     /*
1034       Interpret XML.
1035     */
1036     GetMagickToken(q,&q,token);
1037     if (*token == '\0')
1038       break;
1039     (void) CopyMagickString(keyword,token,MaxTextExtent);
1040     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1041       {
1042         /*
1043           Doctype element.
1044         */
1045         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1046           GetMagickToken(q,&q,token);
1047         continue;
1048       }
1049     if (LocaleNCompare(keyword,"<!--",4) == 0)
1050       {
1051         /*
1052           Comment element.
1053         */
1054         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1055           GetMagickToken(q,&q,token);
1056         continue;
1057       }
1058     if (LocaleCompare(keyword,"<include") == 0)
1059       {
1060         /*
1061           Include element.
1062         */
1063         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1064         {
1065           (void) CopyMagickString(keyword,token,MaxTextExtent);
1066           GetMagickToken(q,&q,token);
1067           if (*token != '=')
1068             continue;
1069           GetMagickToken(q,&q,token);
1070           if (LocaleCompare(keyword,"file") == 0)
1071             {
1072               if (depth > 200)
1073                 (void) ThrowMagickException(exception,GetMagickModule(),
1074                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1075               else
1076                 {
1077                   char
1078                     path[MaxTextExtent],
1079                     *xml;
1080
1081                   GetPathComponent(filename,HeadPath,path);
1082                   if (*path != '\0')
1083                     (void) ConcatenateMagickString(path,DirectorySeparator,
1084                       MaxTextExtent);
1085                   if (*token == *DirectorySeparator)
1086                     (void) CopyMagickString(path,token,MaxTextExtent);
1087                   else
1088                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
1089                   xml=FileToString(path,~0,exception);
1090                   if (xml != (char *) NULL)
1091                     {
1092                       status=LoadConfigureList(xml,path,depth+1,exception);
1093                       xml=(char *) RelinquishMagickMemory(xml);
1094                     }
1095                 }
1096             }
1097         }
1098         continue;
1099       }
1100     if (LocaleCompare(keyword,"<configure") == 0)
1101       {
1102         /*
1103           Configure element.
1104         */
1105         configure_info=(ConfigureInfo *) AcquireMagickMemory(
1106           sizeof(*configure_info));
1107         if (configure_info == (ConfigureInfo *) NULL)
1108           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1109         (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1110         configure_info->path=ConstantString(filename);
1111         configure_info->exempt=MagickFalse;
1112         configure_info->signature=MagickSignature;
1113         continue;
1114       }
1115     if (configure_info == (ConfigureInfo *) NULL)
1116       continue;
1117     if (LocaleCompare(keyword,"/>") == 0)
1118       {
1119         status=AppendValueToLinkedList(configure_list,configure_info);
1120         if (status == MagickFalse)
1121           (void) ThrowMagickException(exception,GetMagickModule(),
1122             ResourceLimitError,"MemoryAllocationFailed","`%s'",
1123             configure_info->name);
1124         configure_info=(ConfigureInfo *) NULL;
1125       }
1126     /*
1127       Parse configure element.
1128     */
1129     GetMagickToken(q,(const char **) NULL,token);
1130     if (*token != '=')
1131       continue;
1132     GetMagickToken(q,&q,token);
1133     GetMagickToken(q,&q,token);
1134     switch (*keyword)
1135     {
1136       case 'N':
1137       case 'n':
1138       {
1139         if (LocaleCompare((char *) keyword,"name") == 0)
1140           {
1141             configure_info->name=ConstantString(token);
1142             break;
1143           }
1144         break;
1145       }
1146       case 'S':
1147       case 's':
1148       {
1149         if (LocaleCompare((char *) keyword,"stealth") == 0)
1150           {
1151             configure_info->stealth=IsMagickTrue(token);
1152             break;
1153           }
1154         break;
1155       }
1156       case 'V':
1157       case 'v':
1158       {
1159         if (LocaleCompare((char *) keyword,"value") == 0)
1160           {
1161             configure_info->value=ConstantString(token);
1162             break;
1163           }
1164         break;
1165       }
1166       default:
1167         break;
1168     }
1169   }
1170   token=(char *) RelinquishMagickMemory(token);
1171   return(status);
1172 }
1173 \f
1174 /*
1175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1176 %                                                                             %
1177 %                                                                             %
1178 %                                                                             %
1179 %  L o a d C o n f i g u r e L i s t s                                        %
1180 %                                                                             %
1181 %                                                                             %
1182 %                                                                             %
1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1184 %
1185 %  LoadConfigureList() loads one or more configure configuration files which
1186 %  provides a mapping between configure attributes and a configure name.
1187 %
1188 %  The format of the LoadConfigureLists method is:
1189 %
1190 %      MagickBooleanType LoadConfigureLists(const char *filename,
1191 %        ExceptionInfo *exception)
1192 %
1193 %  A description of each parameter follows:
1194 %
1195 %    o filename: the font file name.
1196 %
1197 %    o exception: return any errors or warnings in this structure.
1198 %
1199 */
1200 static MagickBooleanType LoadConfigureLists(const char *filename,
1201   ExceptionInfo *exception)
1202 {
1203   const StringInfo
1204     *option;
1205
1206   LinkedListInfo
1207     *options;
1208
1209   MagickStatusType
1210     status;
1211
1212   register ssize_t
1213     i;
1214
1215   /*
1216     Load built-in configure map.
1217   */
1218   status=MagickFalse;
1219   if (configure_list == (LinkedListInfo *) NULL)
1220     {
1221       configure_list=NewLinkedList(0);
1222       if (configure_list == (LinkedListInfo *) NULL)
1223         {
1224           ThrowFileException(exception,ResourceLimitError,
1225             "MemoryAllocationFailed",filename);
1226           return(MagickFalse);
1227         }
1228     }
1229   for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
1230   {
1231     ConfigureInfo
1232       *configure_info;
1233
1234     register const ConfigureMapInfo
1235       *p;
1236
1237     p=ConfigureMap+i;
1238     configure_info=(ConfigureInfo *) AcquireMagickMemory(
1239       sizeof(*configure_info));
1240     if (configure_info == (ConfigureInfo *) NULL)
1241       {
1242         (void) ThrowMagickException(exception,GetMagickModule(),
1243           ResourceLimitError,"MemoryAllocationFailed","`%s'",
1244           configure_info->name);
1245         continue;
1246       }
1247     (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1248     configure_info->path=(char *) "[built-in]";
1249     configure_info->name=(char *) p->name;
1250     configure_info->value=(char *) p->value;
1251     configure_info->exempt=MagickTrue;
1252     configure_info->signature=MagickSignature;
1253     status=AppendValueToLinkedList(configure_list,configure_info);
1254     if (status == MagickFalse)
1255       (void) ThrowMagickException(exception,GetMagickModule(),
1256         ResourceLimitError,"MemoryAllocationFailed","`%s'",
1257         configure_info->name);
1258   }
1259   /*
1260     Load external configure map.
1261   */
1262   options=GetConfigureOptions(filename,exception);
1263   option=(const StringInfo *) GetNextValueInLinkedList(options);
1264   while (option != (const StringInfo *) NULL)
1265   {
1266     status|=LoadConfigureList((const char *) GetStringInfoDatum(option),
1267       GetStringInfoPath(option),0,exception);
1268     option=(const StringInfo *) GetNextValueInLinkedList(options);
1269   }
1270   options=DestroyConfigureOptions(options);
1271   return(status != 0 ? MagickTrue : MagickFalse);
1272 }