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