configure.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %          CCCC   OOO   N   N  FFFFF  IIIII   GGGG  U   U  RRRR   EEEEE       %
00007 %         C      O   O  NN  N  F        I    G      U   U  R   R  E           %
00008 %         C      O   O  N N N  FFF      I    G GG   U   U  RRRR   EEE         %
00009 %         C      O   O  N  NN  F        I    G   G  U   U  R R    E           %
00010 %          CCCC   OOO   N   N  F      IIIII   GGG    UUU   R  R   EEEEE       %
00011 %                                                                             %
00012 %                                                                             %
00013 %                      MagickCore Image Configure Methods                     %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 2003                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/blob.h"
00044 #include "magick/client.h"
00045 #include "magick/configure.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/hashmap.h"
00049 #include "magick/log.h"
00050 #include "magick/memory_.h"
00051 #include "magick/semaphore.h"
00052 #include "magick/string_.h"
00053 #include "magick/token.h"
00054 #include "magick/utility.h"
00055 #include "magick/xml-tree.h"
00056 
00057 /*
00058   Define declarations.
00059 */
00060 #define ConfigureFilename  "configure.xml"
00061 
00062 /*
00063   Static declarations.
00064 */
00065 static const char
00066   *ConfigureMap = (char *)
00067     "<?xml version=\"1.0\"?>"
00068     "<configuremap>"
00069     "  <configure stealth=\"True\" />"
00070     "</configuremap>";
00071 
00072 static LinkedListInfo
00073   *configure_list = (LinkedListInfo *) NULL;
00074 
00075 static SemaphoreInfo
00076   *configure_semaphore = (SemaphoreInfo *) NULL;
00077 
00078 static volatile MagickBooleanType
00079   instantiate_configure = MagickFalse;
00080 
00081 /*
00082   Forward declarations.
00083 */
00084 static MagickBooleanType
00085   InitializeConfigureList(ExceptionInfo *),
00086   LoadConfigureLists(const char *,ExceptionInfo *);
00087 
00088 /*
00089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00090 %                                                                             %
00091 %                                                                             %
00092 %                                                                             %
00093 +   D e s t r o y C o n f i g u r e L i s t                                   %
00094 %                                                                             %
00095 %                                                                             %
00096 %                                                                             %
00097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00098 %
00099 %  DestroyConfigureList() deallocates memory associated with the configure list.
00100 %
00101 %  The format of the DestroyConfigureList method is:
00102 %
00103 %      DestroyConfigureList(void)
00104 %
00105 */
00106 
00107 static void *DestroyConfigureElement(void *configure_info)
00108 {
00109   register ConfigureInfo
00110     *p;
00111 
00112   p=(ConfigureInfo *) configure_info;
00113   if (p->path != (char *) NULL)
00114     p->path=DestroyString(p->path);
00115   if (p->name != (char *) NULL)
00116     p->name=DestroyString(p->name);
00117   if (p->value != (char *) NULL)
00118     p->value=DestroyString(p->value);
00119   p=(ConfigureInfo *) RelinquishMagickMemory(p);
00120   return((void *) NULL);
00121 }
00122 
00123 MagickExport void DestroyConfigureList(void)
00124 {
00125   AcquireSemaphoreInfo(&configure_semaphore);
00126   if (configure_list != (LinkedListInfo *) NULL)
00127     configure_list=DestroyLinkedList(configure_list,DestroyConfigureElement);
00128   configure_list=(LinkedListInfo *) NULL;
00129   instantiate_configure=MagickFalse;
00130   RelinquishSemaphoreInfo(configure_semaphore);
00131   DestroySemaphoreInfo(&configure_semaphore);
00132 }
00133 
00134 /*
00135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00136 %                                                                             %
00137 %                                                                             %
00138 %                                                                             %
00139 %   D e s t r o y C o n f i g u r e O p t i o n s                             %
00140 %                                                                             %
00141 %                                                                             %
00142 %                                                                             %
00143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00144 %
00145 %  DestroyConfigureOptions() releases memory associated with an configure
00146 %  options.
00147 %
00148 %  The format of the DestroyProfiles method is:
00149 %
00150 %      LinkedListInfo *DestroyConfigureOptions(Image *image)
00151 %
00152 %  A description of each parameter follows:
00153 %
00154 %    o image: the image.
00155 %
00156 */
00157 
00158 static void *DestroyOptions(void *option)
00159 {
00160   return(DestroyStringInfo((StringInfo *) option));
00161 }
00162 
00163 MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
00164 {
00165   assert(options != (LinkedListInfo *) NULL);
00166   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00167   return(DestroyLinkedList(options,DestroyOptions));
00168 }
00169 
00170 /*
00171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00172 %                                                                             %
00173 %                                                                             %
00174 %                                                                             %
00175 +   G e t C o n f i g u r e I n f o                                           %
00176 %                                                                             %
00177 %                                                                             %
00178 %                                                                             %
00179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00180 %
00181 %  GetConfigureInfo() searches the configure list for the specified name and if
00182 %  found returns attributes for that element.
00183 %
00184 %  The format of the GetConfigureInfo method is:
00185 %
00186 %      const ConfigureInfo *GetConfigureInfo(const char *name,
00187 %        ExceptionInfo *exception)
00188 %
00189 %  A description of each parameter follows:
00190 %
00191 %    o configure_info: GetConfigureInfo() searches the configure list for the
00192 %      specified name and if found returns attributes for that element.
00193 %
00194 %    o name: the configure name.
00195 %
00196 %    o exception: return any errors or warnings in this structure.
00197 %
00198 */
00199 MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
00200   ExceptionInfo *exception)
00201 {
00202   register const ConfigureInfo
00203     *p;
00204 
00205   assert(exception != (ExceptionInfo *) NULL);
00206   if ((configure_list == (LinkedListInfo *) NULL) ||
00207       (instantiate_configure == MagickFalse))
00208     if (InitializeConfigureList(exception) == MagickFalse)
00209       return((const ConfigureInfo *) NULL);
00210   if ((configure_list == (LinkedListInfo *) NULL) ||
00211       (IsLinkedListEmpty(configure_list) != MagickFalse))
00212     return((const ConfigureInfo *) NULL);
00213   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
00214     return((const ConfigureInfo *) GetValueFromLinkedList(configure_list,0));
00215   /*
00216     Search for configure tag.
00217   */
00218   AcquireSemaphoreInfo(&configure_semaphore);
00219   ResetLinkedListIterator(configure_list);
00220   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00221   while (p != (const ConfigureInfo *) NULL)
00222   {
00223     if (LocaleCompare(name,p->name) == 0)
00224       break;
00225     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00226   }
00227   if (p != (ConfigureInfo *) NULL)
00228     (void) InsertValueInLinkedList(configure_list,0,
00229       RemoveElementByValueFromLinkedList(configure_list,p));
00230   RelinquishSemaphoreInfo(configure_semaphore);
00231   return(p);
00232 }
00233 
00234 /*
00235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00236 %                                                                             %
00237 %                                                                             %
00238 %                                                                             %
00239 %   G e t C o n f i g u r e I n f o L i s t                                   %
00240 %                                                                             %
00241 %                                                                             %
00242 %                                                                             %
00243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00244 %
00245 %  GetConfigureInfoList() returns any configure options that match the
00246 %  specified pattern.
00247 %
00248 %  The format of the GetConfigureInfoList function is:
00249 %
00250 %      const ConfigureInfo **GetConfigureInfoList(const char *pattern,
00251 %        unsigned long *number_options,ExceptionInfo *exception)
00252 %
00253 %  A description of each parameter follows:
00254 %
00255 %    o pattern: Specifies a pointer to a text string containing a pattern.
00256 %
00257 %    o number_options:  This integer returns the number of configure options in
00258 %    the list.
00259 %
00260 %    o exception: return any errors or warnings in this structure.
00261 %
00262 */
00263 
00264 #if defined(__cplusplus) || defined(c_plusplus)
00265 extern "C" {
00266 #endif
00267 
00268 static int ConfigureInfoCompare(const void *x,const void *y)
00269 {
00270   const ConfigureInfo
00271     **p,
00272     **q;
00273 
00274   p=(const ConfigureInfo **) x,
00275   q=(const ConfigureInfo **) y;
00276   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00277     return(LocaleCompare((*p)->name,(*q)->name));
00278   return(LocaleCompare((*p)->path,(*q)->path));
00279 }
00280 
00281 #if defined(__cplusplus) || defined(c_plusplus)
00282 }
00283 #endif
00284 
00285 MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
00286   unsigned long *number_options,ExceptionInfo *exception)
00287 {
00288   const ConfigureInfo
00289     **options;
00290 
00291   register const ConfigureInfo
00292     *p;
00293 
00294   register long
00295     i;
00296 
00297   /*
00298     Allocate configure list.
00299   */
00300   assert(pattern != (char *) NULL);
00301   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00302   assert(number_options != (unsigned long *) NULL);
00303   *number_options=0;
00304   p=GetConfigureInfo("*",exception);
00305   if (p == (const ConfigureInfo *) NULL)
00306     return((const ConfigureInfo **) NULL);
00307   options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
00308     GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
00309   if (options == (const ConfigureInfo **) NULL)
00310     return((const ConfigureInfo **) NULL);
00311   /*
00312     Generate configure list.
00313   */
00314   AcquireSemaphoreInfo(&configure_semaphore);
00315   ResetLinkedListIterator(configure_list);
00316   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00317   for (i=0; p != (const ConfigureInfo *) NULL; )
00318   {
00319     if ((p->stealth == MagickFalse) &&
00320         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00321       options[i++]=p;
00322     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00323   }
00324   RelinquishSemaphoreInfo(configure_semaphore);
00325   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
00326   options[i]=(ConfigureInfo *) NULL;
00327   *number_options=(unsigned long) i;
00328   return(options);
00329 }
00330 
00331 /*
00332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00333 %                                                                             %
00334 %                                                                             %
00335 %                                                                             %
00336 %   G e t C o n f i g u r e L i s t                                           %
00337 %                                                                             %
00338 %                                                                             %
00339 %                                                                             %
00340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00341 %
00342 %  GetConfigureList() returns any configure options that match the specified
00343 %  pattern.
00344 %
00345 %  The format of the GetConfigureList function is:
00346 %
00347 %      char **GetConfigureList(const char *pattern,
00348 %        unsigned long *number_options,ExceptionInfo *exception)
00349 %
00350 %  A description of each parameter follows:
00351 %
00352 %    o pattern: Specifies a pointer to a text string containing a pattern.
00353 %
00354 %    o number_options:  This integer returns the number of options in the list.
00355 %
00356 %    o exception: return any errors or warnings in this structure.
00357 %
00358 */
00359 
00360 #if defined(__cplusplus) || defined(c_plusplus)
00361 extern "C" {
00362 #endif
00363 
00364 static int ConfigureCompare(const void *x,const void *y)
00365 {
00366   register char
00367     **p,
00368     **q;
00369 
00370   p=(char **) x;
00371   q=(char **) y;
00372   return(LocaleCompare(*p,*q));
00373 }
00374 
00375 #if defined(__cplusplus) || defined(c_plusplus)
00376 }
00377 #endif
00378 
00379 MagickExport char **GetConfigureList(const char *pattern,
00380   unsigned long *number_options,ExceptionInfo *exception)
00381 {
00382   char
00383     **options;
00384 
00385   register const ConfigureInfo
00386     *p;
00387 
00388   register long
00389     i;
00390 
00391   /*
00392     Allocate configure list.
00393   */
00394   assert(pattern != (char *) NULL);
00395   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00396   assert(number_options != (unsigned long *) NULL);
00397   *number_options=0;
00398   p=GetConfigureInfo("*",exception);
00399   if (p == (const ConfigureInfo *) NULL)
00400     return((char **) NULL);
00401   AcquireSemaphoreInfo(&configure_semaphore);
00402   RelinquishSemaphoreInfo(configure_semaphore);
00403   options=(char **) AcquireQuantumMemory((size_t)
00404     GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
00405   if (options == (char **) NULL)
00406     return((char **) NULL);
00407   AcquireSemaphoreInfo(&configure_semaphore);
00408   ResetLinkedListIterator(configure_list);
00409   p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00410   for (i=0; p != (const ConfigureInfo *) NULL; )
00411   {
00412     if ((p->stealth == MagickFalse) &&
00413         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00414       options[i++]=ConstantString(p->name);
00415     p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
00416   }
00417   RelinquishSemaphoreInfo(configure_semaphore);
00418   qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
00419   options[i]=(char *) NULL;
00420   *number_options=(unsigned long) i;
00421   return(options);
00422 }
00423 
00424 /*
00425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00426 %                                                                             %
00427 %                                                                             %
00428 %                                                                             %
00429 %   G e t C o n f i g u r e O p t i o n                                       %
00430 %                                                                             %
00431 %                                                                             %
00432 %                                                                             %
00433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00434 %
00435 %  GetConfigureOption() returns the value associated with the configure option.
00436 %
00437 %  The format of the GetConfigureOption method is:
00438 %
00439 %      char *GetConfigureOption(const char *option)
00440 %
00441 %  A description of each parameter follows:
00442 %
00443 %    o configure_info:  The configure info.
00444 %
00445 */
00446 MagickExport char *GetConfigureOption(const char *option)
00447 {
00448   const char
00449     *value;
00450 
00451   const ConfigureInfo
00452     *configure_info;
00453 
00454   ExceptionInfo
00455     *exception;
00456 
00457   assert(option != (const char *) NULL);
00458   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
00459   exception=AcquireExceptionInfo();
00460   configure_info=GetConfigureInfo(option,exception);
00461   exception=DestroyExceptionInfo(exception);
00462   if (configure_info == (ConfigureInfo *) NULL)
00463     return((char *) NULL);
00464   value=GetConfigureValue(configure_info);
00465   if ((value == (const char *) NULL) || (*value == '\0'))
00466     return((char *) NULL);
00467   return(ConstantString(value));
00468 }
00469 
00470 /*
00471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00472 %                                                                             %
00473 %                                                                             %
00474 %                                                                             %
00475 %  G e t C o n f i g u r e O p t i o n s                                      %
00476 %                                                                             %
00477 %                                                                             %
00478 %                                                                             %
00479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00480 %
00481 %  GetConfigureOptions() returns any Magick configuration options associated
00482 %  with the specified filename.
00483 %
00484 %  The format of the GetConfigureOptions method is:
00485 %
00486 %      LinkedListInfo *GetConfigureOptions(const char *filename,
00487 %        ExceptionInfo *exception)
00488 %
00489 %  A description of each parameter follows:
00490 %
00491 %    o filename: the configure file name.
00492 %
00493 %    o exception: return any errors or warnings in this structure.
00494 %
00495 */
00496 MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
00497   ExceptionInfo *exception)
00498 {
00499   char
00500     path[MaxTextExtent];
00501 
00502   const char
00503     *element;
00504 
00505   LinkedListInfo
00506     *options,
00507     *paths;
00508 
00509   StringInfo
00510     *xml;
00511 
00512   assert(filename != (const char *) NULL);
00513   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00514   assert(exception != (ExceptionInfo *) NULL);
00515   (void) CopyMagickString(path,filename,MaxTextExtent);
00516   /*
00517     Load XML from configuration files to linked-list.
00518   */
00519   options=NewLinkedList(0);
00520   paths=GetConfigurePaths(filename,exception);
00521   if (paths != (LinkedListInfo *) NULL)
00522     {
00523       ResetLinkedListIterator(paths);
00524       element=(const char *) GetNextValueInLinkedList(paths);
00525       while (element != (const char *) NULL)
00526       {
00527         (void) FormatMagickString(path,MaxTextExtent,"%s%s",element,filename);
00528         (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00529           "Searching for configure file: \"%s\"",path);
00530         xml=ConfigureFileToStringInfo(path);
00531         if (xml != (StringInfo *) NULL)
00532           (void) AppendValueToLinkedList(options,xml);
00533         element=(const char *) GetNextValueInLinkedList(paths);
00534       }
00535       paths=DestroyLinkedList(paths,RelinquishMagickMemory);
00536     }
00537 #if defined(__WINDOWS__)
00538   {
00539     char
00540       *blob;
00541 
00542     blob=(char *) NTResourceToBlob(filename);
00543     if (blob != (char *) NULL)
00544       {
00545         xml=StringToStringInfo(blob);
00546         SetStringInfoPath(xml,filename);
00547         (void) AppendValueToLinkedList(options,xml);
00548         blob=DestroyString(blob);
00549       }
00550   }
00551 #endif
00552   if (GetNumberOfElementsInLinkedList(options) == 0)
00553     (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
00554       "UnableToOpenConfigureFile","`%s'",filename);
00555   ResetLinkedListIterator(options);
00556   return(options);
00557 }
00558 
00559 /*
00560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00561 %                                                                             %
00562 %                                                                             %
00563 %                                                                             %
00564 %  G e t C o n f i g u r e P a t h s                                          %
00565 %                                                                             %
00566 %                                                                             %
00567 %                                                                             %
00568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00569 %
00570 %  GetConfigurePaths() returns any Magick configuration paths associated
00571 %  with the specified filename.
00572 %
00573 %  The format of the GetConfigurePaths method is:
00574 %
00575 %      LinkedListInfo *GetConfigurePaths(const char *filename,
00576 %        ExceptionInfo *exception)
00577 %
00578 %  A description of each parameter follows:
00579 %
00580 %    o filename: the configure file name.
00581 %
00582 %    o exception: return any errors or warnings in this structure.
00583 %
00584 */
00585 MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
00586   ExceptionInfo *exception)
00587 {
00588   char
00589     path[MaxTextExtent];
00590 
00591   LinkedListInfo
00592     *paths;
00593 
00594   assert(filename != (const char *) NULL);
00595   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00596   assert(exception != (ExceptionInfo *) NULL);
00597   (void) CopyMagickString(path,filename,MaxTextExtent);
00598   paths=NewLinkedList(0);
00599   {
00600     char
00601       *configure_path;
00602 
00603     /*
00604       Search $MAGICK_CONFIGURE_PATH.
00605     */
00606     configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
00607     if (configure_path != (char *) NULL)
00608       {
00609         register char
00610           *p,
00611           *q;
00612 
00613         for (p=configure_path-1; p != (char *) NULL; )
00614         {
00615           (void) CopyMagickString(path,p+1,MaxTextExtent);
00616           q=strchr(path,DirectoryListSeparator);
00617           if (q != (char *) NULL)
00618             *q='\0';
00619           q=path+strlen(path)-1;
00620           if ((q >= path) && (*q != *DirectorySeparator))
00621             (void) ConcatenateMagickString(path,DirectorySeparator,
00622               MaxTextExtent);
00623           (void) AppendValueToLinkedList(paths,ConstantString(path));
00624           p=strchr(p+1,DirectoryListSeparator);
00625         }
00626         configure_path=DestroyString(configure_path);
00627       }
00628   }
00629 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
00630 #if defined(MAGICKCORE_SHARE_CONFIGURE_PATH)
00631   (void) AppendValueToLinkedList(paths,ConstantString(
00632     MAGICKCORE_SHARE_CONFIGURE_PATH));
00633 #endif
00634 #if defined(MAGICKCORE_CONFIGURE_PATH)
00635   (void) AppendValueToLinkedList(paths,ConstantString(
00636     MAGICKCORE_CONFIGURE_PATH));
00637 #endif
00638 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
00639   (void) AppendValueToLinkedList(paths,ConstantString(
00640     MAGICKCORE_DOCUMENTATION_PATH));
00641 #endif
00642 #if defined(MAGICKCORE_SHARE_PATH)
00643   (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
00644 #endif
00645 #if defined(__WINDOWS__) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_CONFIGURE_PATH))
00646   {
00647     char
00648       *registry_key;
00649 
00650     unsigned char
00651       *key_value;
00652 
00653     /*
00654       Locate file via registry key.
00655     */
00656     registry_key="ConfigurePath";
00657     key_value=NTRegistryKeyLookup(registry_key);
00658     if (key_value == (unsigned char *) NULL)
00659       ThrowMagickException(exception,GetMagickModule(),ConfigureError,
00660         "RegistryKeyLookupFailed","`%s'",registry_key);
00661     else
00662       {
00663         (void) FormatMagickString(path,MaxTextExtent,"%s%s",(char *) key_value,
00664           DirectorySeparator);
00665         (void) AppendValueToLinkedList(paths,ConstantString(path));
00666         key_value=(unsigned char *) RelinquishMagickMemory(key_value);
00667       }
00668   }
00669 #endif
00670 #else
00671   {
00672     char
00673       *home;
00674 
00675     /*
00676       Search under MAGICK_HOME.
00677     */
00678     home=GetEnvironmentValue("MAGICK_HOME");
00679     if (home != (char *) NULL)
00680       {
00681 #if !defined(MAGICKCORE_POSIX_SUPPORT)
00682         (void) FormatMagickString(path,MaxTextExtent,"%s%s",home,
00683           DirectorySeparator);
00684         (void) AppendValueToLinkedList(paths,ConstantString(path));
00685 #else
00686         (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",home,
00687           MAGICKCORE_CONFIGURE_RELATIVE_PATH);
00688         (void) AppendValueToLinkedList(paths,ConstantString(path));
00689         (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",home,
00690           MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
00691         (void) AppendValueToLinkedList(paths,ConstantString(path));
00692 #endif
00693         home=DestroyString(home);
00694       }
00695     }
00696   if (*GetClientPath() != '\0')
00697     {
00698 #if !defined(MAGICKCORE_POSIX_SUPPORT)
00699       (void) FormatMagickString(path,MaxTextExtent,"%s%s",GetClientPath(),
00700         DirectorySeparator);
00701       (void) AppendValueToLinkedList(paths,ConstantString(path));
00702 #else
00703       char
00704         prefix[MaxTextExtent];
00705 
00706       /*
00707         Search based on executable directory if directory is known.
00708       */
00709       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
00710       ChopPathComponents(prefix,1);
00711       (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",prefix,
00712         MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
00713       (void) AppendValueToLinkedList(paths,ConstantString(path));
00714       (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",prefix,
00715         MAGICKCORE_CONFIGURE_RELATIVE_PATH);
00716       (void) AppendValueToLinkedList(paths,ConstantString(path));
00717 #endif
00718     }
00719 #endif
00720   {
00721     char
00722       *home;
00723 
00724     home=GetEnvironmentValue("HOME");
00725     if (home == (char *) NULL)
00726       home=GetEnvironmentValue("USERPROFILE");
00727     if (home != (char *) NULL)
00728       {
00729         /*
00730           Search $HOME/.magick.
00731         */
00732         (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s",home,
00733           DirectorySeparator,DirectorySeparator);
00734         (void) AppendValueToLinkedList(paths,ConstantString(path));
00735         home=DestroyString(home);
00736       }
00737   }
00738 #if defined(__WINDOWS__)
00739   {
00740     char
00741       module_path[MaxTextExtent];
00742 
00743     if (NTGetModulePath("CORE_RL_magick_.dll",module_path) != MagickFalse)
00744       {
00745         char
00746           *element;
00747 
00748         /*
00749           Search module path.
00750         */
00751         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
00752           DirectorySeparator);
00753         element=(char *) RemoveElementByValueFromLinkedList(paths,path);
00754         if (element != (char *) NULL)
00755           element=DestroyString(element);
00756         (void) AppendValueToLinkedList(paths,ConstantString(path));
00757       }
00758     if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
00759       {
00760         /*
00761           Search PerlMagick module path.
00762         */
00763         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
00764           DirectorySeparator);
00765         (void) AppendValueToLinkedList(paths,ConstantString(path));
00766         (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
00767           "\\inc\\lib\\auto\\Image\\Magick\\");
00768         (void) AppendValueToLinkedList(paths,ConstantString(path));
00769       }
00770   }
00771 #endif
00772   /*
00773     Search current directory.
00774   */
00775   (void) AppendValueToLinkedList(paths,ConstantString(""));
00776   return(paths);
00777 }
00778 
00779 /*
00780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00781 %                                                                             %
00782 %                                                                             %
00783 %                                                                             %
00784 %   G e t C o n f i g u r e V a l u e                                         %
00785 %                                                                             %
00786 %                                                                             %
00787 %                                                                             %
00788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00789 %
00790 %  GetConfigureValue() returns the value associated with the configure info.
00791 %
00792 %  The format of the GetConfigureValue method is:
00793 %
00794 %      const char *GetConfigureValue(const ConfigureInfo *configure_info)
00795 %
00796 %  A description of each parameter follows:
00797 %
00798 %    o configure_info:  The configure info.
00799 %
00800 */
00801 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
00802 {
00803   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00804   assert(configure_info != (ConfigureInfo *) NULL);
00805   assert(configure_info->signature == MagickSignature);
00806   return(configure_info->value);
00807 }
00808 
00809 /*
00810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00811 %                                                                             %
00812 %                                                                             %
00813 %                                                                             %
00814 +   I n i t i a l i z e C o n f i g u r e L i s t                             %
00815 %                                                                             %
00816 %                                                                             %
00817 %                                                                             %
00818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00819 %
00820 %  InitializeConfigureList() initializes the configure list.
00821 %
00822 %  The format of the InitializeConfigureList method is:
00823 %
00824 %      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
00825 %
00826 %  A description of each parameter follows.
00827 %
00828 %    o exception: return any errors or warnings in this structure.
00829 %
00830 */
00831 static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
00832 {
00833   if ((configure_list == (LinkedListInfo *) NULL) &&
00834       (instantiate_configure == MagickFalse))
00835     {
00836       AcquireSemaphoreInfo(&configure_semaphore);
00837       if ((configure_list == (LinkedListInfo *) NULL) &&
00838           (instantiate_configure == MagickFalse))
00839         {
00840           (void) LoadConfigureLists(ConfigureFilename,exception);
00841           instantiate_configure=MagickTrue;
00842         }
00843       RelinquishSemaphoreInfo(configure_semaphore);
00844     }
00845   return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
00846 }
00847 
00848 /*
00849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00850 %                                                                             %
00851 %                                                                             %
00852 %                                                                             %
00853 %  L i s t C o n f i g u r e I n f o                                          %
00854 %                                                                             %
00855 %                                                                             %
00856 %                                                                             %
00857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00858 %
00859 %  ListConfigureInfo() lists the configure info to a file.
00860 %
00861 %  The format of the ListConfigureInfo method is:
00862 %
00863 %      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
00864 %
00865 %  A description of each parameter follows.
00866 %
00867 %    o file:  An pointer to a FILE.
00868 %
00869 %    o exception: return any errors or warnings in this structure.
00870 %
00871 */
00872 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
00873   ExceptionInfo *exception)
00874 {
00875   const char
00876     *name,
00877     *path,
00878     *value;
00879 
00880   const ConfigureInfo
00881     **configure_info;
00882 
00883   long
00884     j;
00885 
00886   register long
00887     i;
00888 
00889   unsigned long
00890     number_options;
00891 
00892   if (file == (const FILE *) NULL)
00893     file=stdout;
00894   configure_info=GetConfigureInfoList("*",&number_options,exception);
00895   if (configure_info == (const ConfigureInfo **) NULL)
00896     return(MagickFalse);
00897   path=(const char *) NULL;
00898   for (i=0; i < (long) number_options; i++)
00899   {
00900     if (configure_info[i]->stealth != MagickFalse)
00901       continue;
00902     if ((path == (const char *) NULL) ||
00903         (LocaleCompare(path,configure_info[i]->path) != 0))
00904       {
00905         if (configure_info[i]->path != (char *) NULL)
00906           (void) fprintf(file,"\nPath: %s\n\n",configure_info[i]->path);
00907         (void) fprintf(file,"Name          Value\n");
00908         (void) fprintf(file,"-------------------------------------------------"
00909           "------------------------------\n");
00910       }
00911     path=configure_info[i]->path;
00912     name="unknown";
00913     if (configure_info[i]->name != (char *) NULL)
00914       name=configure_info[i]->name;
00915     (void) fprintf(file,"%s",name);
00916     for (j=(long) strlen(name); j <= 12; j++)
00917       (void) fprintf(file," ");
00918     (void) fprintf(file," ");
00919     value="unknown";
00920     if (configure_info[i]->value != (char *) NULL)
00921       value=configure_info[i]->value;
00922     (void) fprintf(file,"%s",value);
00923     (void) fprintf(file,"\n");
00924   }
00925   (void) fflush(file);
00926   configure_info=(const ConfigureInfo **)
00927     RelinquishMagickMemory((void *) configure_info);
00928   return(MagickTrue);
00929 }
00930 
00931 /*
00932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00933 %                                                                             %
00934 %                                                                             %
00935 %                                                                             %
00936 +   L o a d C o n f i g u r e L i s t                                         %
00937 %                                                                             %
00938 %                                                                             %
00939 %                                                                             %
00940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00941 %
00942 %  LoadConfigureList() loads the configure configuration file which provides a
00943 %  mapping between configure attributes and a configure name.
00944 %
00945 %  The format of the LoadConfigureList method is:
00946 %
00947 %      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
00948 %        const unsigned long depth,ExceptionInfo *exception)
00949 %
00950 %  A description of each parameter follows:
00951 %
00952 %    o xml:  The configure list in XML format.
00953 %
00954 %    o filename:  The configure list filename.
00955 %
00956 %    o depth: depth of <include /> statements.
00957 %
00958 %    o exception: return any errors or warnings in this structure.
00959 %
00960 */
00961 static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
00962   const unsigned long depth,ExceptionInfo *exception)
00963 {
00964   char
00965     keyword[MaxTextExtent],
00966     *token;
00967 
00968   ConfigureInfo
00969     *configure_info;
00970 
00971   const char
00972     *q;
00973 
00974   MagickBooleanType
00975     status;
00976 
00977   /*
00978     Load the configure map file.
00979   */
00980   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00981     "Loading configure file \"%s\" ...",filename);
00982   if (configure_list == (LinkedListInfo *) NULL)
00983     {
00984       configure_list=NewLinkedList(0);
00985       if (configure_list == (LinkedListInfo *) NULL)
00986         {
00987           ThrowFileException(exception,ResourceLimitError,
00988             "MemoryAllocationFailed",filename);
00989           return(MagickFalse);
00990         }
00991     }
00992   status=MagickTrue;
00993   configure_info=(ConfigureInfo *) NULL;
00994   if (xml == (char *) NULL)
00995     token=AcquireString(ConfigureMap);
00996   else
00997     token=AcquireString((char *) xml);
00998   for (q=(char *) xml; *q != '\0'; )
00999   {
01000     /*
01001       Interpret XML.
01002     */
01003     GetMagickToken(q,&q,token);
01004     if (*token == '\0')
01005       break;
01006     (void) CopyMagickString(keyword,token,MaxTextExtent);
01007     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
01008       {
01009         /*
01010           Doctype element.
01011         */
01012         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
01013           GetMagickToken(q,&q,token);
01014         continue;
01015       }
01016     if (LocaleNCompare(keyword,"<!--",4) == 0)
01017       {
01018         /*
01019           Comment element.
01020         */
01021         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
01022           GetMagickToken(q,&q,token);
01023         continue;
01024       }
01025     if (LocaleCompare(keyword,"<include") == 0)
01026       {
01027         /*
01028           Include element.
01029         */
01030         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
01031         {
01032           (void) CopyMagickString(keyword,token,MaxTextExtent);
01033           GetMagickToken(q,&q,token);
01034           if (*token != '=')
01035             continue;
01036           GetMagickToken(q,&q,token);
01037           if (LocaleCompare(keyword,"file") == 0)
01038             {
01039               if (depth > 200)
01040                 (void) ThrowMagickException(exception,GetMagickModule(),
01041                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
01042               else
01043                 {
01044                   char
01045                     path[MaxTextExtent],
01046                     *xml;
01047 
01048                   GetPathComponent(filename,HeadPath,path);
01049                   if (*path != '\0')
01050                     (void) ConcatenateMagickString(path,DirectorySeparator,
01051                       MaxTextExtent);
01052                   (void) ConcatenateMagickString(path,token,MaxTextExtent);
01053                   xml=FileToString(path,~0,exception);
01054