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