]> granicus.if.org Git - imagemagick/blob - MagickCore/configure.c
(no commit message)
[imagemagick] / MagickCore / configure.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %          CCCC   OOO   N   N  FFFFF  IIIII   GGGG  U   U  RRRR   EEEEE       %
7 %         C      O   O  NN  N  F        I    G      U   U  R   R  E           %
8 %         C      O   O  N N N  FFF      I    G GG   U   U  RRRR   EEE         %
9 %         C      O   O  N  NN  F        I    G   G  U   U  R R    E           %
10 %          CCCC   OOO   N   N  F      IIIII   GGG    UUU   R  R   EEEEE       %
11 %                                                                             %
12 %                                                                             %
13 %                      MagickCore Image Configure Methods                     %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 2003                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2014 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         (void) FormatLocaleString(path,MaxTextExtent,"%s",
756           MAGICKCORE_SHAREARCH_PATH);
757         (void) AppendValueToLinkedList(paths,ConstantString(path));
758 #endif
759         home=DestroyString(home);
760       }
761     }
762   if (*GetClientPath() != '\0')
763     {
764 #if !defined(MAGICKCORE_POSIX_SUPPORT)
765       (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
766         DirectorySeparator);
767       (void) AppendValueToLinkedList(paths,ConstantString(path));
768 #else
769       char
770         prefix[MaxTextExtent];
771
772       /*
773         Search based on executable directory if directory is known.
774       */
775       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
776       ChopPathComponents(prefix,1);
777       (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
778         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
779       (void) AppendValueToLinkedList(paths,ConstantString(path));
780       (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
781         MAGICKCORE_SHARE_RELATIVE_PATH);
782       (void) AppendValueToLinkedList(paths,ConstantString(path));
783       (void) FormatLocaleString(path,MaxTextExtent,"%s",
784         MAGICKCORE_SHAREARCH_PATH);
785       (void) AppendValueToLinkedList(paths,ConstantString(path));
786 #endif
787     }
788   /*
789     Search current directory.
790   */
791   (void) AppendValueToLinkedList(paths,ConstantString(""));
792 #endif
793   {
794     char
795       *home;
796
797     home=GetEnvironmentValue("HOME");
798     if (home == (char *) NULL)
799       home=GetEnvironmentValue("USERPROFILE");
800     if (home != (char *) NULL)
801       {
802         /*
803           Search $HOME/.magick.
804         */
805         (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s",home,
806           DirectorySeparator,DirectorySeparator);
807         (void) AppendValueToLinkedList(paths,ConstantString(path));
808         home=DestroyString(home);
809       }
810   }
811 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
812   {
813     char
814       module_path[MaxTextExtent];
815
816     if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
817         (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
818       {
819         unsigned char
820           *key_value;
821
822         /*
823           Search module path.
824         */
825         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
826           DirectorySeparator);
827         key_value=NTRegistryKeyLookup(RegistryKey);
828         if (key_value == (unsigned char *) NULL)
829           (void) AppendValueToLinkedList(paths,ConstantString(path));
830         else
831           key_value=(unsigned char *) RelinquishMagickMemory(key_value);
832       }
833     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
834       {
835         /*
836           Search PerlMagick module path.
837         */
838         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
839           DirectorySeparator);
840         (void) AppendValueToLinkedList(paths,ConstantString(path));
841         (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
842           "\\inc\\lib\\auto\\Image\\Magick\\");
843         (void) AppendValueToLinkedList(paths,ConstantString(path));
844       }
845   }
846 #endif
847   return(paths);
848 }
849 \f
850 /*
851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852 %                                                                             %
853 %                                                                             %
854 %                                                                             %
855 %   G e t C o n f i g u r e V a l u e                                         %
856 %                                                                             %
857 %                                                                             %
858 %                                                                             %
859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860 %
861 %  GetConfigureValue() returns the value associated with the configure info.
862 %
863 %  The format of the GetConfigureValue method is:
864 %
865 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
866 %
867 %  A description of each parameter follows:
868 %
869 %    o configure_info:  The configure info.
870 %
871 */
872 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
873 {
874   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
875   assert(configure_info != (ConfigureInfo *) NULL);
876   assert(configure_info->signature == MagickSignature);
877   return(configure_info->value);
878 }
879 \f
880 /*
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882 %                                                                             %
883 %                                                                             %
884 %                                                                             %
885 +   I n i t i a l i z e C o n f i g u r e L i s t                             %
886 %                                                                             %
887 %                                                                             %
888 %                                                                             %
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890 %
891 %  InitializeConfigureList() initializes the configure list.
892 %
893 %  The format of the InitializeConfigureList method is:
894 %
895 %      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
896 %
897 %  A description of each parameter follows.
898 %
899 %    o exception: return any errors or warnings in this structure.
900 %
901 */
902 static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
903 {
904   if ((configure_list == (LinkedListInfo *) NULL) &&
905       (instantiate_configure == MagickFalse))
906     {
907       if (configure_semaphore == (SemaphoreInfo *) NULL)
908         AcquireSemaphoreInfo(&configure_semaphore);
909       LockSemaphoreInfo(configure_semaphore);
910       if ((configure_list == (LinkedListInfo *) NULL) &&
911           (instantiate_configure == MagickFalse))
912         {
913           (void) LoadConfigureLists(ConfigureFilename,exception);
914           instantiate_configure=MagickTrue;
915         }
916       UnlockSemaphoreInfo(configure_semaphore);
917     }
918   return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
919 }
920 \f
921 /*
922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
923 %                                                                             %
924 %                                                                             %
925 %                                                                             %
926 %  L i s t C o n f i g u r e I n f o                                          %
927 %                                                                             %
928 %                                                                             %
929 %                                                                             %
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931 %
932 %  ListConfigureInfo() lists the configure info to a file.
933 %
934 %  The format of the ListConfigureInfo method is:
935 %
936 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
937 %
938 %  A description of each parameter follows.
939 %
940 %    o file:  An pointer to a FILE.
941 %
942 %    o exception: return any errors or warnings in this structure.
943 %
944 */
945 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
946   ExceptionInfo *exception)
947 {
948   const char
949     *name,
950     *path,
951     *value;
952
953   const ConfigureInfo
954     **configure_info;
955
956   register ssize_t
957     i;
958
959   size_t
960     number_options;
961
962   ssize_t
963     j;
964
965   if (file == (const FILE *) NULL)
966     file=stdout;
967   configure_info=GetConfigureInfoList("*",&number_options,exception);
968   if (configure_info == (const ConfigureInfo **) NULL)
969     return(MagickFalse);
970   path=(const char *) NULL;
971   for (i=0; i < (ssize_t) number_options; i++)
972   {
973     if (configure_info[i]->stealth != MagickFalse)
974       continue;
975     if ((path == (const char *) NULL) ||
976         (LocaleCompare(path,configure_info[i]->path) != 0))
977       {
978         if (configure_info[i]->path != (char *) NULL)
979           (void) FormatLocaleFile(file,"\nPath: %s\n\n",
980             configure_info[i]->path);
981         (void) FormatLocaleFile(file,"Name           Value\n");
982         (void) FormatLocaleFile(file,
983           "-------------------------------------------------"
984           "------------------------------\n");
985       }
986     path=configure_info[i]->path;
987     name="unknown";
988     if (configure_info[i]->name != (char *) NULL)
989       name=configure_info[i]->name;
990     (void) FormatLocaleFile(file,"%s",name);
991     for (j=(ssize_t) strlen(name); j <= 13; j++)
992       (void) FormatLocaleFile(file," ");
993     (void) FormatLocaleFile(file," ");
994     value="unknown";
995     if (configure_info[i]->value != (char *) NULL)
996       value=configure_info[i]->value;
997     (void) FormatLocaleFile(file,"%s",value);
998     (void) FormatLocaleFile(file,"\n");
999   }
1000   (void) fflush(file);
1001   configure_info=(const ConfigureInfo **)
1002     RelinquishMagickMemory((void *) configure_info);
1003   return(MagickTrue);
1004 }
1005 \f
1006 /*
1007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 +   L o a d C o n f i g u r e L i s t                                         %
1012 %                                                                             %
1013 %                                                                             %
1014 %                                                                             %
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 %
1017 %  LoadConfigureList() loads the configure configuration file which provides a
1018 %  mapping between configure attributes and a configure name.
1019 %
1020 %  The format of the LoadConfigureList method is:
1021 %
1022 %      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
1023 %        const size_t depth,ExceptionInfo *exception)
1024 %
1025 %  A description of each parameter follows:
1026 %
1027 %    o xml:  The configure list in XML format.
1028 %
1029 %    o filename:  The configure list filename.
1030 %
1031 %    o depth: depth of <include /> statements.
1032 %
1033 %    o exception: return any errors or warnings in this structure.
1034 %
1035 */
1036 static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
1037   const size_t depth,ExceptionInfo *exception)
1038 {
1039   char
1040     keyword[MaxTextExtent],
1041     *token;
1042
1043   ConfigureInfo
1044     *configure_info;
1045
1046   const char
1047     *q;
1048
1049   MagickBooleanType
1050     status;
1051
1052   /*
1053     Load the configure map file.
1054   */
1055   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1056     "Loading configure file \"%s\" ...",filename);
1057   if (configure_list == (LinkedListInfo *) NULL)
1058     {
1059       configure_list=NewLinkedList(0);
1060       if (configure_list == (LinkedListInfo *) NULL)
1061         {
1062           ThrowFileException(exception,ResourceLimitError,
1063             "MemoryAllocationFailed",filename);
1064           return(MagickFalse);
1065         }
1066     }
1067   status=MagickTrue;
1068   configure_info=(ConfigureInfo *) NULL;
1069   token=AcquireString((char *) xml);
1070   for (q=(char *) xml; *q != '\0'; )
1071   {
1072     /*
1073       Interpret XML.
1074     */
1075     GetMagickToken(q,&q,token);
1076     if (*token == '\0')
1077       break;
1078     (void) CopyMagickString(keyword,token,MaxTextExtent);
1079     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1080       {
1081         /*
1082           Doctype element.
1083         */
1084         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1085           GetMagickToken(q,&q,token);
1086         continue;
1087       }
1088     if (LocaleNCompare(keyword,"<!--",4) == 0)
1089       {
1090         /*
1091           Comment element.
1092         */
1093         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1094           GetMagickToken(q,&q,token);
1095         continue;
1096       }
1097     if (LocaleCompare(keyword,"<include") == 0)
1098       {
1099         /*
1100           Include element.
1101         */
1102         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1103         {
1104           (void) CopyMagickString(keyword,token,MaxTextExtent);
1105           GetMagickToken(q,&q,token);
1106           if (*token != '=')
1107             continue;
1108           GetMagickToken(q,&q,token);
1109           if (LocaleCompare(keyword,"file") == 0)
1110             {
1111               if (depth > 200)
1112                 (void) ThrowMagickException(exception,GetMagickModule(),
1113                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1114               else
1115                 {
1116                   char
1117                     path[MaxTextExtent],
1118                     *xml;
1119
1120                   GetPathComponent(filename,HeadPath,path);
1121                   if (*path != '\0')
1122                     (void) ConcatenateMagickString(path,DirectorySeparator,
1123                       MaxTextExtent);
1124                   if (*token == *DirectorySeparator)
1125                     (void) CopyMagickString(path,token,MaxTextExtent);
1126                   else
1127                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
1128                   xml=FileToString(path,~0UL,exception);
1129                   if (xml != (char *) NULL)
1130                     {
1131                       status=LoadConfigureList(xml,path,depth+1,exception);
1132                       xml=(char *) RelinquishMagickMemory(xml);
1133                     }
1134                 }
1135             }
1136         }
1137         continue;
1138       }
1139     if (LocaleCompare(keyword,"<configure") == 0)
1140       {
1141         /*
1142           Configure element.
1143         */
1144         configure_info=(ConfigureInfo *) AcquireMagickMemory(
1145           sizeof(*configure_info));
1146         if (configure_info == (ConfigureInfo *) NULL)
1147           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1148         (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1149         configure_info->path=ConstantString(filename);
1150         configure_info->exempt=MagickFalse;
1151         configure_info->signature=MagickSignature;
1152         continue;
1153       }
1154     if (configure_info == (ConfigureInfo *) NULL)
1155       continue;
1156     if (LocaleCompare(keyword,"/>") == 0)
1157       {
1158         status=AppendValueToLinkedList(configure_list,configure_info);
1159         if (status == MagickFalse)
1160           (void) ThrowMagickException(exception,GetMagickModule(),
1161             ResourceLimitError,"MemoryAllocationFailed","`%s'",
1162             configure_info->name);
1163         configure_info=(ConfigureInfo *) NULL;
1164         continue;
1165       }
1166     /*
1167       Parse configure element.
1168     */
1169     GetMagickToken(q,(const char **) NULL,token);
1170     if (*token != '=')
1171       continue;
1172     GetMagickToken(q,&q,token);
1173     GetMagickToken(q,&q,token);
1174     switch (*keyword)
1175     {
1176       case 'N':
1177       case 'n':
1178       {
1179         if (LocaleCompare((char *) keyword,"name") == 0)
1180           {
1181             configure_info->name=ConstantString(token);
1182             break;
1183           }
1184         break;
1185       }
1186       case 'S':
1187       case 's':
1188       {
1189         if (LocaleCompare((char *) keyword,"stealth") == 0)
1190           {
1191             configure_info->stealth=IsStringTrue(token);
1192             break;
1193           }
1194         break;
1195       }
1196       case 'V':
1197       case 'v':
1198       {
1199         if (LocaleCompare((char *) keyword,"value") == 0)
1200           {
1201             configure_info->value=ConstantString(token);
1202             break;
1203           }
1204         break;
1205       }
1206       default:
1207         break;
1208     }
1209   }
1210   token=(char *) RelinquishMagickMemory(token);
1211   return(status);
1212 }
1213 \f
1214 /*
1215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 %                                                                             %
1217 %                                                                             %
1218 %                                                                             %
1219 %  L o a d C o n f i g u r e L i s t s                                        %
1220 %                                                                             %
1221 %                                                                             %
1222 %                                                                             %
1223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1224 %
1225 %  LoadConfigureList() loads one or more configure configuration files which
1226 %  provides a mapping between configure attributes and a configure name.
1227 %
1228 %  The format of the LoadConfigureLists method is:
1229 %
1230 %      MagickBooleanType LoadConfigureLists(const char *filename,
1231 %        ExceptionInfo *exception)
1232 %
1233 %  A description of each parameter follows:
1234 %
1235 %    o filename: the font file name.
1236 %
1237 %    o exception: return any errors or warnings in this structure.
1238 %
1239 */
1240 static MagickBooleanType LoadConfigureLists(const char *filename,
1241   ExceptionInfo *exception)
1242 {
1243   const StringInfo
1244     *option;
1245
1246   LinkedListInfo
1247     *options;
1248
1249   MagickStatusType
1250     status;
1251
1252   register ssize_t
1253     i;
1254
1255   /*
1256     Load external configure map.
1257   */
1258   if (configure_list == (LinkedListInfo *) NULL)
1259     {
1260       configure_list=NewLinkedList(0);
1261       if (configure_list == (LinkedListInfo *) NULL)
1262         {
1263           ThrowFileException(exception,ResourceLimitError,
1264             "MemoryAllocationFailed",filename);
1265           return(MagickFalse);
1266         }
1267     }
1268   status=MagickTrue;
1269   options=GetConfigureOptions(filename,exception);
1270   option=(const StringInfo *) GetNextValueInLinkedList(options);
1271   while (option != (const StringInfo *) NULL)
1272   {
1273     status&=LoadConfigureList((const char *) GetStringInfoDatum(option),
1274       GetStringInfoPath(option),0,exception);
1275     option=(const StringInfo *) GetNextValueInLinkedList(options);
1276   }
1277   options=DestroyConfigureOptions(options);
1278   /*
1279     Load built-in configure map.
1280   */
1281   for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
1282   {
1283     ConfigureInfo
1284       *configure_info;
1285
1286     register const ConfigureMapInfo
1287       *p;
1288
1289     p=ConfigureMap+i;
1290     configure_info=(ConfigureInfo *) AcquireMagickMemory(
1291       sizeof(*configure_info));
1292     if (configure_info == (ConfigureInfo *) NULL)
1293       {
1294         (void) ThrowMagickException(exception,GetMagickModule(),
1295           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
1296         continue;
1297       }
1298     (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1299     configure_info->path=(char *) "[built-in]";
1300     configure_info->name=(char *) p->name;
1301     configure_info->value=(char *) p->value;
1302     configure_info->exempt=MagickTrue;
1303     configure_info->signature=MagickSignature;
1304     status&=AppendValueToLinkedList(configure_list,configure_info);
1305     if (status == MagickFalse)
1306       (void) ThrowMagickException(exception,GetMagickModule(),
1307         ResourceLimitError,"MemoryAllocationFailed","`%s'",
1308         configure_info->name);
1309   }
1310   return(status != 0 ? MagickTrue : MagickFalse);
1311 }