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