// @(#)root/tmva $Id$
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : Configurable                                                          *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Joerg Stelzer   <Joerg.Stelzer@cern.ch>  - CERN, Switzerland              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 *                                                                                *
 **********************************************************************************/

//________________________________________________________________________
/* Begin_Html
Base Class for all classes that need option parsing
End_Html */
//________________________________________________________________________

#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>

#include "TROOT.h"
#include "TSystem.h"
#include "TString.h"
#include "TObjString.h"
#include "TQObject.h"
#include "TSpline.h"
#include "TMatrix.h"
#include "TMath.h"
#include "TFile.h"
#include "TKey.h"

#include "TMVA/Configurable.h"
#include "TMVA/Config.h"
#include "TMVA/Tools.h"

// don't change this flag without a good reason ! The FitterBase code won't work anymore !!!
// #define TMVA_Configurable_SanctionUnknownOption kTRUE

ClassImp(TMVA::Configurable)

#ifdef _WIN32
/*Disable warning C4355: 'this' : used in base member initializer list*/
#pragma warning ( disable : 4355 )
#endif

//_______________________________________________________________________
TMVA::Configurable::Configurable( const TString& theOption)
   : fOptions                    ( theOption ),
     fLooseOptionCheckingEnabled ( kTRUE ),
     fLastDeclaredOption         ( 0 ),
     fConfigName                 ( "Configurable" ), // must be replaced by name of class that uses the configurable
     fConfigDescription          ( "No description" ),
     fReferenceFile              ( "None" ),
     fLogger                     ( new MsgLogger(this) )
{
   // constructor
   fListOfOptions.SetOwner();

   // check if verbosity "V" set in option
   if (gTools().CheckForVerboseOption( theOption )) Log().SetMinType( kVERBOSE );
}

//_______________________________________________________________________
TMVA::Configurable::~Configurable()
{
   // default destructur
   delete fLogger;
}

//_______________________________________________________________________
void TMVA::Configurable::SplitOptions(const TString& theOpt, TList& loo) const
{
   // splits the option string at ':' and fills the list 'loo' with the primitive strings
   TString splitOpt(theOpt);
   loo.SetOwner();
   while (splitOpt.Length()>0) {
      if (!splitOpt.Contains(':')) {
         loo.Add(new TObjString(splitOpt));
         splitOpt = "";
      } 
      else {
         TString toSave = splitOpt(0,splitOpt.First(':'));
         loo.Add(new TObjString(toSave.Data()));
         splitOpt = splitOpt(splitOpt.First(':')+1,splitOpt.Length());
      }
   }
}

//_______________________________________________________________________
void TMVA::Configurable::ResetSetFlag() 
{
   // resets the IsSet falg for all declare options
   // to be called before options are read from stream

   TListIter decOptIt(&fListOfOptions); // declared options
   while (OptionBase* decOpt = (OptionBase*) decOptIt()) { // loop over declared options
      decOpt->fIsSet = kFALSE;
   }
}

//_______________________________________________________________________
void TMVA::Configurable::ParseOptions() 
{
   // options parser
   Log() << kVERBOSE << "Parsing option string: " << Endl;
   TString optionsWithoutTilde(fOptions);
   optionsWithoutTilde.ReplaceAll(TString("~"),TString(""));
   Log() << kVERBOSE << "... \"" << optionsWithoutTilde << "\"" << Endl;
   
   TList loo; // the List Of Options in the parsed string
   
   fOptions = fOptions.Strip(TString::kLeading, ':');
   
   // separate the options by the ':' marker
   SplitOptions(fOptions, loo);
   fOptions = "";

   // loop over the declared options and check for their availability
   std::map<TString, std::vector<std::pair<Int_t, TString> > > arrayTypeOptions;

   TListIter decOptIt(&fListOfOptions); // declared options
   TListIter setOptIt(&loo);   // parsed options
   while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options

      TString s = os->GetString();

      // the tilde in the beginning is an indication that the option
      // has been accepted during previous parsing
      //
      // while parsing this option string eventual appearances of the
      // tilde will be preserved, for correctly parsed options a new
      // one will be added (in the end it will be checked if all
      // options were parsed
      Bool_t preserveTilde = s.BeginsWith('~');
      s = s.Strip(TString::kLeading, '~');

      Bool_t paramParsed = kFALSE;
      if (s.Contains('=')) { // desired way of setting an option: "...:optname=optvalue:..."
         TString optname = s(0,s.First('=')); optname.ToLower(); 
         TString optval = s(s.First('=')+1,s.Length());
         Int_t idx = -1;

         // First check if the optname exists in the list of the
         // objects. This does not depend on the existence of a [] in
         // the optname. Sometimes the [] is part of the optname and
         // does not describe an array
         OptionBase* decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
         if (decOpt==0 && optname.Contains('[')) {
            // now we see if there is an [] and if the optname exists
            // after removing the [idx]
            TString st = optname(optname.First('[')+1,100);
            st.Remove(st.First(']'));
            std::stringstream str(st.Data());
            str >> idx;                              // save the array index
            optname.Remove(optname.First('['));      // and remove [idx] from the option name
            decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
         }

         TListIter optIt(&fListOfOptions);
         if (decOpt!=0) {
            if (decOpt->IsSet())
               Log() << kWARNING << "Value for option " << decOpt->GetName() 
                       << " was previously set to " << decOpt->GetValue() << Endl;

            if (!decOpt->HasPreDefinedVal() || (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(optval)) ) {
               if (decOpt->IsArrayOpt()) { // arrays
                  // if no index was found then we assume the value is to be set for the entire array
                  if (idx==-1) {
                     decOpt->SetValue(optval);
                  } 
                  else {
                     // since we don't know what else is comming we just put everthing into a map
                     if (!decOpt->SetValue(optval, idx))
                        Log() << kFATAL << "Index " << idx << " too large for option " << decOpt->TheName()
                                << ", allowed range is [0," << decOpt->GetArraySize()-1 << "]" << Endl;
                  }
               } 
               else { // no arrays
                  if (idx!=-1)
                     Log() << kFATAL << "Option " << decOpt->TheName()
                             << " is not an array, but you specified an index" << Endl;
                  decOpt->SetValue(optval);
               }
               paramParsed = kTRUE;
            }
            else Log() << kFATAL << "Option " << decOpt->TheName() 
                         << " does not have predefined value: \"" << optval << "\"" << Endl;               
         }
      }

      // boolean variables can be specified by just their name (!name), 
      // which will set the to true (false):  ...:V:...:!S:..
      Bool_t preserveNotSign = kFALSE;
      if (!paramParsed) {
         Bool_t hasNotSign = kFALSE;
         if (s.BeginsWith("!")) { s.Remove(0,1); preserveNotSign = hasNotSign = kTRUE; }
         TString optname(s); optname.ToLower();
         OptionBase* decOpt = 0;
         Bool_t optionExists = kFALSE;
         TListIter optIt(&fListOfOptions);
         while ((decOpt = (OptionBase*)optIt()) !=0) {
            TString predOptName(decOpt->GetName());
            predOptName.ToLower();
            if (predOptName == optname) optionExists = kTRUE;
            if (dynamic_cast<Option<bool>*>(decOpt)==0) continue; // not a boolean option
            if (predOptName == optname) break;
         }

         
         if (decOpt != 0) {
            decOpt->SetValue( hasNotSign ? "0" : "1" );
            paramParsed = kTRUE;
         } 
         else {
            if (optionExists && hasNotSign) {
               Log() << kFATAL << "Negating a non-boolean variable " << optname
                       << ", please check the opions for method: " << GetName() << Endl;
            }
         }
      }


      if (!paramParsed && LooseOptionCheckingEnabled()) {
         // loose options specification, loops through the possible string 
         // values any parameter can have not applicable for boolean or floats
         decOptIt.Reset();
         while (OptionBase* decOpt = (OptionBase*) decOptIt()) {
            if (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(s) ) {
               paramParsed = decOpt->SetValue(s);
               break;
            }
         }
      }
   
      if (fOptions!="") fOptions += ":";
      if (paramParsed || preserveTilde) fOptions += '~';
      if (preserveNotSign) fOptions += '!';
      fOptions += s;      
   }

   // print options summary
   PrintOptions();
   if (gConfig().WriteOptionsReference()) WriteOptionsReferenceToFile();
}

//______________________________________________________________________
void TMVA::Configurable::CheckForUnusedOptions() const 
{
   // checks for unused options in option string
   TString theOpt(fOptions);
   theOpt = theOpt.Strip(TString::kLeading, ':');
   
   // separate the options by the ':' marker
   TList loo; // the List of Options in the parsed string
   SplitOptions(theOpt, loo);

   TListIter setOptIt(&loo);   // options in a list
   TString unusedOptions("");
   while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options

      TString s = os->GetString();
      if (!s.BeginsWith('~')) {
         if (unusedOptions != "") unusedOptions += ':';
         unusedOptions += s;
      }
   }
   if (unusedOptions != "") {
      Log() << kFATAL
              << "The following options were specified, but could not be interpreted: \'"
              << unusedOptions << "\', please check!" << Endl;
   }
}

//______________________________________________________________________
void TMVA::Configurable::PrintOptions() const 
{
   // prints out the options set in the options string and the defaults

   Log() << kVERBOSE << "The following options are set:" << Endl;

   TListIter optIt( &fListOfOptions );
   Log() << kVERBOSE << "- By User:" << Endl;
   Bool_t found = kFALSE;
   while (OptionBase* opt = (OptionBase *) optIt()) {
      if (opt->IsSet()) { Log() << kVERBOSE << "    "; opt->Print(Log()); Log() << Endl; found = kTRUE; }
   }
   if (!found) Log() << kVERBOSE << "    <none>" << Endl;

   optIt.Reset();
   Log() << kVERBOSE << "- Default:" << Endl;
   found = kFALSE;
   while (OptionBase* opt = (OptionBase *) optIt()) {
      if (!opt->IsSet()) { Log() << kVERBOSE << "    "; opt->Print(Log()); Log() << Endl; found = kTRUE; }
   }
   if (!found) Log() << kVERBOSE << "    <none>" << Endl;
}

//______________________________________________________________________
void TMVA::Configurable::WriteOptionsToStream( std::ostream& o, const TString& prefix ) const 
{
   // write options to output stream (e.g. in writing the MVA weight files

   TListIter optIt( &fListOfOptions );
   o << prefix << "# Set by User:" << std::endl;
   while (OptionBase * opt = (OptionBase *) optIt()) 
      if (opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
   optIt.Reset();
   o << prefix << "# Default:" << std::endl;
   while (OptionBase * opt = (OptionBase *) optIt()) 
      if (!opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
   o << prefix << "##" << std::endl;
}

//______________________________________________________________________
void TMVA::Configurable::AddOptionsXMLTo( void* parent ) const 
{
   // write options to XML file
   if (!parent) return;
   void* opts = gTools().AddChild(parent, "Options");
   TListIter optIt( &fListOfOptions );
   while (OptionBase * opt = (OptionBase *) optIt()) {
      void* optnode = 0;
      if (opt->IsArrayOpt()) {
         std::stringstream s("");
         s.precision( 16 );
         for(Int_t i=0; i<opt->GetArraySize(); i++) {
            if(i>0) s << " ";
            s << std::scientific << opt->GetValue(i);
         }
         optnode = gTools().AddChild(opts,"Option",s.str().c_str());
      }
      else {
         optnode = gTools().AddChild(opts,"Option", opt->GetValue());
      }
      gTools().AddAttr(optnode, "name", opt->TheName());
      if (opt->IsArrayOpt()) {
         gTools().AddAttr(optnode, "size", opt->GetArraySize());
      }
      gTools().AddAttr(optnode, "modified", (opt->IsSet()?"Yes":"No") );
   }
}

//______________________________________________________________________
void TMVA::Configurable::ReadOptionsFromXML( void* node )
{
   void* opt = gTools().GetChild(node);
   TString optName, optValue;
   fOptions="";
   while (opt != 0) {
      if (fOptions.Length()!=0) fOptions += ":";
      gTools().ReadAttr(opt, "name", optName);
      optValue = TString( gTools().GetContent(opt) );
      std::stringstream s("");
      s.precision( 16 );
      if (gTools().HasAttr(opt, "size")) {
         UInt_t size;
         gTools().ReadAttr(opt, "size", size);
         std::vector<TString> values = gTools().SplitString(optValue, ' ');
         for(UInt_t i=0; i<size; i++) {
            if(i!=0) s << ":";
            s << std::scientific << optName << "[" << i << "]=" << values[i];
         }
      }
      else {
         s << std::scientific << optName << "=" << optValue;
      }
      fOptions += s.str().c_str();
      opt = gTools().GetNextChild(opt);
   }
}

//______________________________________________________________________
void TMVA::Configurable::WriteOptionsReferenceToFile()
{
   // write complete options to output stream

   TString dir = gConfig().GetIONames().fOptionsReferenceFileDir;
   gSystem->MakeDirectory( dir );
   fReferenceFile = dir + "/" + GetConfigName() + "_optionsRef.txt";
   std::ofstream o( fReferenceFile );
   if (!o.good()) { // file could not be opened --> Error
      Log() << kFATAL << "<WriteOptionsToInfoFile> Unable to open output file: " << fReferenceFile << Endl;
   }

   TListIter optIt( &fListOfOptions );   
   o << "# List of options:" << std::endl;
   o << "# Configurable: " << GetConfigName() << std::endl;
   o << "# Description: " << GetConfigDescription() << std::endl;
   while (OptionBase * opt = (OptionBase *) optIt()) {
      opt->Print( o, 1 ); 
      o << std::endl << "# ------------------------------------------------" << std::endl; 
   }

   o.close();
   Log() << kVERBOSE << "Wrote options reference file: \"" << fReferenceFile << "\"" << Endl;
}

//______________________________________________________________________
void TMVA::Configurable::ReadOptionsFromStream(std::istream& istr)
{
   // read option back from the weight file

   // first set the IsSet flag of all declared options to false
   // that is only necessary in our factory, when we test right
   // after the training
   ResetSetFlag();
   fOptions = "";
   char buf[512];
   istr.getline(buf,512);
   TString stropt, strval;
   while (istr.good() && !istr.eof() && !(buf[0]=='#' && buf[1]=='#')) { // if line starts with ## return
      char *p = buf;
      while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace
      if (*p=='#' || *p=='\0') {
         istr.getline(buf,512); // reading the next line
         continue; // if comment or empty line, read the next line
      }
      std::stringstream sstr(buf);
      sstr >> stropt >> strval;
      stropt.ReplaceAll(':','=');
      strval.ReplaceAll("\"","");
      if (fOptions.Length()!=0) fOptions += ":";
      fOptions += stropt;
      fOptions += strval;
      istr.getline(buf,512); // reading the next line
   }
}

 Configurable.cxx:1
 Configurable.cxx:2
 Configurable.cxx:3
 Configurable.cxx:4
 Configurable.cxx:5
 Configurable.cxx:6
 Configurable.cxx:7
 Configurable.cxx:8
 Configurable.cxx:9
 Configurable.cxx:10
 Configurable.cxx:11
 Configurable.cxx:12
 Configurable.cxx:13
 Configurable.cxx:14
 Configurable.cxx:15
 Configurable.cxx:16
 Configurable.cxx:17
 Configurable.cxx:18
 Configurable.cxx:19
 Configurable.cxx:20
 Configurable.cxx:21
 Configurable.cxx:22
 Configurable.cxx:23
 Configurable.cxx:24
 Configurable.cxx:25
 Configurable.cxx:26
 Configurable.cxx:27
 Configurable.cxx:28
 Configurable.cxx:29
 Configurable.cxx:30
 Configurable.cxx:31
 Configurable.cxx:32
 Configurable.cxx:33
 Configurable.cxx:34
 Configurable.cxx:35
 Configurable.cxx:36
 Configurable.cxx:37
 Configurable.cxx:38
 Configurable.cxx:39
 Configurable.cxx:40
 Configurable.cxx:41
 Configurable.cxx:42
 Configurable.cxx:43
 Configurable.cxx:44
 Configurable.cxx:45
 Configurable.cxx:46
 Configurable.cxx:47
 Configurable.cxx:48
 Configurable.cxx:49
 Configurable.cxx:50
 Configurable.cxx:51
 Configurable.cxx:52
 Configurable.cxx:53
 Configurable.cxx:54
 Configurable.cxx:55
 Configurable.cxx:56
 Configurable.cxx:57
 Configurable.cxx:58
 Configurable.cxx:59
 Configurable.cxx:60
 Configurable.cxx:61
 Configurable.cxx:62
 Configurable.cxx:63
 Configurable.cxx:64
 Configurable.cxx:65
 Configurable.cxx:66
 Configurable.cxx:67
 Configurable.cxx:68
 Configurable.cxx:69
 Configurable.cxx:70
 Configurable.cxx:71
 Configurable.cxx:72
 Configurable.cxx:73
 Configurable.cxx:74
 Configurable.cxx:75
 Configurable.cxx:76
 Configurable.cxx:77
 Configurable.cxx:78
 Configurable.cxx:79
 Configurable.cxx:80
 Configurable.cxx:81
 Configurable.cxx:82
 Configurable.cxx:83
 Configurable.cxx:84
 Configurable.cxx:85
 Configurable.cxx:86
 Configurable.cxx:87
 Configurable.cxx:88
 Configurable.cxx:89
 Configurable.cxx:90
 Configurable.cxx:91
 Configurable.cxx:92
 Configurable.cxx:93
 Configurable.cxx:94
 Configurable.cxx:95
 Configurable.cxx:96
 Configurable.cxx:97
 Configurable.cxx:98
 Configurable.cxx:99
 Configurable.cxx:100
 Configurable.cxx:101
 Configurable.cxx:102
 Configurable.cxx:103
 Configurable.cxx:104
 Configurable.cxx:105
 Configurable.cxx:106
 Configurable.cxx:107
 Configurable.cxx:108
 Configurable.cxx:109
 Configurable.cxx:110
 Configurable.cxx:111
 Configurable.cxx:112
 Configurable.cxx:113
 Configurable.cxx:114
 Configurable.cxx:115
 Configurable.cxx:116
 Configurable.cxx:117
 Configurable.cxx:118
 Configurable.cxx:119
 Configurable.cxx:120
 Configurable.cxx:121
 Configurable.cxx:122
 Configurable.cxx:123
 Configurable.cxx:124
 Configurable.cxx:125
 Configurable.cxx:126
 Configurable.cxx:127
 Configurable.cxx:128
 Configurable.cxx:129
 Configurable.cxx:130
 Configurable.cxx:131
 Configurable.cxx:132
 Configurable.cxx:133
 Configurable.cxx:134
 Configurable.cxx:135
 Configurable.cxx:136
 Configurable.cxx:137
 Configurable.cxx:138
 Configurable.cxx:139
 Configurable.cxx:140
 Configurable.cxx:141
 Configurable.cxx:142
 Configurable.cxx:143
 Configurable.cxx:144
 Configurable.cxx:145
 Configurable.cxx:146
 Configurable.cxx:147
 Configurable.cxx:148
 Configurable.cxx:149
 Configurable.cxx:150
 Configurable.cxx:151
 Configurable.cxx:152
 Configurable.cxx:153
 Configurable.cxx:154
 Configurable.cxx:155
 Configurable.cxx:156
 Configurable.cxx:157
 Configurable.cxx:158
 Configurable.cxx:159
 Configurable.cxx:160
 Configurable.cxx:161
 Configurable.cxx:162
 Configurable.cxx:163
 Configurable.cxx:164
 Configurable.cxx:165
 Configurable.cxx:166
 Configurable.cxx:167
 Configurable.cxx:168
 Configurable.cxx:169
 Configurable.cxx:170
 Configurable.cxx:171
 Configurable.cxx:172
 Configurable.cxx:173
 Configurable.cxx:174
 Configurable.cxx:175
 Configurable.cxx:176
 Configurable.cxx:177
 Configurable.cxx:178
 Configurable.cxx:179
 Configurable.cxx:180
 Configurable.cxx:181
 Configurable.cxx:182
 Configurable.cxx:183
 Configurable.cxx:184
 Configurable.cxx:185
 Configurable.cxx:186
 Configurable.cxx:187
 Configurable.cxx:188
 Configurable.cxx:189
 Configurable.cxx:190
 Configurable.cxx:191
 Configurable.cxx:192
 Configurable.cxx:193
 Configurable.cxx:194
 Configurable.cxx:195
 Configurable.cxx:196
 Configurable.cxx:197
 Configurable.cxx:198
 Configurable.cxx:199
 Configurable.cxx:200
 Configurable.cxx:201
 Configurable.cxx:202
 Configurable.cxx:203
 Configurable.cxx:204
 Configurable.cxx:205
 Configurable.cxx:206
 Configurable.cxx:207
 Configurable.cxx:208
 Configurable.cxx:209
 Configurable.cxx:210
 Configurable.cxx:211
 Configurable.cxx:212
 Configurable.cxx:213
 Configurable.cxx:214
 Configurable.cxx:215
 Configurable.cxx:216
 Configurable.cxx:217
 Configurable.cxx:218
 Configurable.cxx:219
 Configurable.cxx:220
 Configurable.cxx:221
 Configurable.cxx:222
 Configurable.cxx:223
 Configurable.cxx:224
 Configurable.cxx:225
 Configurable.cxx:226
 Configurable.cxx:227
 Configurable.cxx:228
 Configurable.cxx:229
 Configurable.cxx:230
 Configurable.cxx:231
 Configurable.cxx:232
 Configurable.cxx:233
 Configurable.cxx:234
 Configurable.cxx:235
 Configurable.cxx:236
 Configurable.cxx:237
 Configurable.cxx:238
 Configurable.cxx:239
 Configurable.cxx:240
 Configurable.cxx:241
 Configurable.cxx:242
 Configurable.cxx:243
 Configurable.cxx:244
 Configurable.cxx:245
 Configurable.cxx:246
 Configurable.cxx:247
 Configurable.cxx:248
 Configurable.cxx:249
 Configurable.cxx:250
 Configurable.cxx:251
 Configurable.cxx:252
 Configurable.cxx:253
 Configurable.cxx:254
 Configurable.cxx:255
 Configurable.cxx:256
 Configurable.cxx:257
 Configurable.cxx:258
 Configurable.cxx:259
 Configurable.cxx:260
 Configurable.cxx:261
 Configurable.cxx:262
 Configurable.cxx:263
 Configurable.cxx:264
 Configurable.cxx:265
 Configurable.cxx:266
 Configurable.cxx:267
 Configurable.cxx:268
 Configurable.cxx:269
 Configurable.cxx:270
 Configurable.cxx:271
 Configurable.cxx:272
 Configurable.cxx:273
 Configurable.cxx:274
 Configurable.cxx:275
 Configurable.cxx:276
 Configurable.cxx:277
 Configurable.cxx:278
 Configurable.cxx:279
 Configurable.cxx:280
 Configurable.cxx:281
 Configurable.cxx:282
 Configurable.cxx:283
 Configurable.cxx:284
 Configurable.cxx:285
 Configurable.cxx:286
 Configurable.cxx:287
 Configurable.cxx:288
 Configurable.cxx:289
 Configurable.cxx:290
 Configurable.cxx:291
 Configurable.cxx:292
 Configurable.cxx:293
 Configurable.cxx:294
 Configurable.cxx:295
 Configurable.cxx:296
 Configurable.cxx:297
 Configurable.cxx:298
 Configurable.cxx:299
 Configurable.cxx:300
 Configurable.cxx:301
 Configurable.cxx:302
 Configurable.cxx:303
 Configurable.cxx:304
 Configurable.cxx:305
 Configurable.cxx:306
 Configurable.cxx:307
 Configurable.cxx:308
 Configurable.cxx:309
 Configurable.cxx:310
 Configurable.cxx:311
 Configurable.cxx:312
 Configurable.cxx:313
 Configurable.cxx:314
 Configurable.cxx:315
 Configurable.cxx:316
 Configurable.cxx:317
 Configurable.cxx:318
 Configurable.cxx:319
 Configurable.cxx:320
 Configurable.cxx:321
 Configurable.cxx:322
 Configurable.cxx:323
 Configurable.cxx:324
 Configurable.cxx:325
 Configurable.cxx:326
 Configurable.cxx:327
 Configurable.cxx:328
 Configurable.cxx:329
 Configurable.cxx:330
 Configurable.cxx:331
 Configurable.cxx:332
 Configurable.cxx:333
 Configurable.cxx:334
 Configurable.cxx:335
 Configurable.cxx:336
 Configurable.cxx:337
 Configurable.cxx:338
 Configurable.cxx:339
 Configurable.cxx:340
 Configurable.cxx:341
 Configurable.cxx:342
 Configurable.cxx:343
 Configurable.cxx:344
 Configurable.cxx:345
 Configurable.cxx:346
 Configurable.cxx:347
 Configurable.cxx:348
 Configurable.cxx:349
 Configurable.cxx:350
 Configurable.cxx:351
 Configurable.cxx:352
 Configurable.cxx:353
 Configurable.cxx:354
 Configurable.cxx:355
 Configurable.cxx:356
 Configurable.cxx:357
 Configurable.cxx:358
 Configurable.cxx:359
 Configurable.cxx:360
 Configurable.cxx:361
 Configurable.cxx:362
 Configurable.cxx:363
 Configurable.cxx:364
 Configurable.cxx:365
 Configurable.cxx:366
 Configurable.cxx:367
 Configurable.cxx:368
 Configurable.cxx:369
 Configurable.cxx:370
 Configurable.cxx:371
 Configurable.cxx:372
 Configurable.cxx:373
 Configurable.cxx:374
 Configurable.cxx:375
 Configurable.cxx:376
 Configurable.cxx:377
 Configurable.cxx:378
 Configurable.cxx:379
 Configurable.cxx:380
 Configurable.cxx:381
 Configurable.cxx:382
 Configurable.cxx:383
 Configurable.cxx:384
 Configurable.cxx:385
 Configurable.cxx:386
 Configurable.cxx:387
 Configurable.cxx:388
 Configurable.cxx:389
 Configurable.cxx:390
 Configurable.cxx:391
 Configurable.cxx:392
 Configurable.cxx:393
 Configurable.cxx:394
 Configurable.cxx:395
 Configurable.cxx:396
 Configurable.cxx:397
 Configurable.cxx:398
 Configurable.cxx:399
 Configurable.cxx:400
 Configurable.cxx:401
 Configurable.cxx:402
 Configurable.cxx:403
 Configurable.cxx:404
 Configurable.cxx:405
 Configurable.cxx:406
 Configurable.cxx:407
 Configurable.cxx:408
 Configurable.cxx:409
 Configurable.cxx:410
 Configurable.cxx:411
 Configurable.cxx:412
 Configurable.cxx:413
 Configurable.cxx:414
 Configurable.cxx:415
 Configurable.cxx:416
 Configurable.cxx:417
 Configurable.cxx:418
 Configurable.cxx:419
 Configurable.cxx:420
 Configurable.cxx:421
 Configurable.cxx:422
 Configurable.cxx:423
 Configurable.cxx:424
 Configurable.cxx:425
 Configurable.cxx:426
 Configurable.cxx:427
 Configurable.cxx:428
 Configurable.cxx:429
 Configurable.cxx:430
 Configurable.cxx:431
 Configurable.cxx:432
 Configurable.cxx:433
 Configurable.cxx:434
 Configurable.cxx:435
 Configurable.cxx:436
 Configurable.cxx:437
 Configurable.cxx:438
 Configurable.cxx:439
 Configurable.cxx:440
 Configurable.cxx:441
 Configurable.cxx:442
 Configurable.cxx:443
 Configurable.cxx:444
 Configurable.cxx:445
 Configurable.cxx:446
 Configurable.cxx:447