GetPot.h

Go to the documentation of this file.
00001 
00002 
00003 //
00008 
00009 //  -*- c++ -*-  vim: set syntax=cpp:
00010 //  GetPot Version $$Version$$                                    $$Date$$
00011 //
00012 //  WEBSITE: http://getpot.sourceforge.net
00013 //
00014 //  NOTE: The LPGL License for this library is only valid in case that 
00015 //        it is not used for the production or development of applications
00016 //        dedicated to military industry. This is what the author calls
00017 //        the 'unofficial peace version of the LPGL'.
00018 //
00019 //  This library is  free software; you can redistribute  it and/or modify
00020 //  it  under  the terms  of  the GNU  Lesser  General  Public License  as
00021 //  published by the  Free Software Foundation; either version  2.1 of the
00022 //  License, or (at your option) any later version.
00023 //
00024 //  This library  is distributed in the  hope that it will  be useful, but
00025 //  WITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of
00026 //  MERCHANTABILITY  or FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
00027 //  Lesser General Public License for more details.
00028 //
00029 //  You  should have  received a  copy of  the GNU  Lesser  General Public
00030 //  License along  with this library; if  not, write to  the Free Software
00031 //  Foundation, Inc.,  59 Temple Place,  Suite 330, Boston,  MA 02111-1307
00032 //  USA
00033 //
00034 //  (C) 2001-2007 Frank R. Schaefer <fschaef@users.sf.net>
00035 //==========================================================================
00036 
00037 #ifndef __include_guard_GETPOT_H__
00038 #define __include_guard_GETPOT_H__
00039 
00040 #if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC)
00041 #define strtok_r(a, b, c) strtok(a, b)
00042 #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
00043 
00044 extern "C" {
00045 //   leave the 'extern C' to make it 100% sure to work -
00046 //   expecially with older distributions of header files.
00047 #ifndef WIN32
00048 // this is necessary (depending on OS)
00049 #include <ctype.h>
00050 #endif
00051 #include <stdio.h>
00052 #include <stdarg.h>
00053 #include <assert.h>
00054 #include <string.h>
00055 }
00056 #include <cmath>
00057 #include <string>
00058 #include <vector>
00059 #include <algorithm>
00060 
00061 #include <fstream>
00062 #include <iostream> // not every compiler distribution includes <iostream> 
00063 //                  // with <fstream>
00064 
00065 typedef  std::vector<std::string>  STRING_VECTOR;
00066 
00067 #define victorate(TYPE, VARIABLE, ITERATOR)                        \
00068   std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin(); \
00069   for(; (ITERATOR) != (VARIABLE).end(); (ITERATOR)++)
00070 
00071 
00073 //
00074 
00075 class GetPot {
00076     //--------
00077     inline void __basic_initialization();
00078 public:
00079     // (*) constructors, destructor, assignment operator -----------------------
00080     inline GetPot();
00081     inline GetPot(const GetPot&);
00082     inline GetPot(const int argc_, char** argv_, 
00083                   const char* FieldSeparator=0x0);
00084     inline GetPot(const char* FileName, 
00085                   const char* CommentStart=0x0, const char* CommentEnd=0x0,
00086                   const char* FieldSeparator=0x0);
00087     inline ~GetPot();
00088     inline GetPot& operator=(const GetPot&);
00089 
00090 
00091     // (*) absorbing contents of another GetPot object
00092     inline void            absorb(const GetPot& That);
00093     //     -- for ufo detection: recording requested arguments, options etc.
00094     inline void            clear_requests();
00095     inline void            disable_request_recording() { __request_recording_f = false; }
00096     inline void            enable_request_recording()  { __request_recording_f = true; }
00097 
00098     // (*) direct access to command line arguments -----------------------------
00099     inline const std::string    operator[](unsigned Idx) const;
00100     inline int                  get(unsigned Idx, int           Default) const;
00101     inline double               get(unsigned Idx, const double& Default) const;
00102     inline const std::string    get(unsigned Idx, const char*   Default) const;
00103     inline unsigned             size() const;
00104 
00105     // (*) flags ---------------------------------------------------------------
00106     inline bool            options_contain(const char* FlagList) const;
00107     inline bool            argument_contains(unsigned Idx, const char* FlagList) const;
00108 
00109     // (*) variables -----------------------------------------------------------
00110     //     -- scalar values
00111     inline int                operator()(const char* VarName, int           Default) const;
00112     inline double             operator()(const char* VarName, const double& Default) const;
00113     inline const std::string  operator()(const char* VarName, const char*   Default) const;
00114     //     -- vectors
00115     inline int                operator()(const char* VarName, int Default, unsigned Idx) const;
00116     inline double             operator()(const char* VarName, const double& Default, unsigned Idx) const;
00117     inline const std::string  operator()(const char* VarName, const char* Default, unsigned Idx) const;
00118 
00119     //     -- setting variables
00120     //                  i) from outside of GetPot (considering prefix etc.)
00121     //                  ii) from inside, use '__set_variable()' below
00122     inline void            set(const char* VarName, const char* Value, const bool Requested = true);
00123     inline void            set(const char* VarName, const double& Value, const bool Requested = true);
00124     inline void            set(const char* VarName, const int Value, const bool Requested = true);
00125     
00126     inline unsigned        vector_variable_size(const char* VarName) const;
00127     inline STRING_VECTOR   get_variable_names() const;
00128     inline STRING_VECTOR   get_section_names() const;
00129     
00130 
00131     // (*) cursor oriented functions -------------------------------------------
00132     inline void            set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
00133     inline bool            search_failed() const { return search_failed_f; }
00134 
00135     //     -- enable/disable search for an option in loop
00136     inline void            disable_loop() { search_loop_f = false; }
00137     inline void            enable_loop()  { search_loop_f = true; }
00138 
00139     //     -- reset cursor to position '1'
00140     inline void            reset_cursor();
00141     inline void            init_multiple_occurrence();
00142 
00143     //     -- search for a certain option and set cursor to position
00144     inline bool            search(const char* option);
00145     inline bool            search(unsigned No, const char* P, ...);
00146     //     -- get argument at cursor++
00147     inline int                next(int           Default);
00148     inline double             next(const double& Default);
00149     inline const std::string  next(const char*   Default);
00150     //     -- search for option and get argument at cursor++
00151     inline int                follow(int           Default, const char* Option);
00152     inline double             follow(const double& Default, const char* Option);
00153     inline const std::string  follow(const char*   Default, const char* Option);
00154     //     -- search for one of the given options and get argument that follows it
00155     inline int                follow(int           Default, unsigned No, const char* Option, ...);
00156     inline double             follow(const double& Default, unsigned No, const char* Option, ...);
00157     inline const std::string  follow(const char*   Default, unsigned No, const char* Option, ...);
00158     //     -- lists of nominuses following an option
00159     inline std::vector<std::string> nominus_followers(const char* Option);
00160     inline std::vector<std::string> nominus_followers(unsigned No, ...);
00161 
00162     //     -- directly followed arguments
00163     inline int                direct_follow(int           Default, const char* Option);
00164     inline double             direct_follow(const double& Default, const char* Option);
00165     inline const std::string  direct_follow(const char*   Default, const char* Option);
00166 
00167     inline std::vector<std::string>  string_tails(const char* StartString);
00168     inline std::vector<int>          int_tails(const char* StartString, const int Default = 1);
00169     inline std::vector<double>       double_tails(const char* StartString, const double Default = 1.0);
00170 
00171     // (*) nominus arguments ---------------------------------------------------
00172     inline STRING_VECTOR   nominus_vector() const;
00173     inline unsigned        nominus_size() const  { return static_cast<unsigned int>(idx_nominus.size()); }
00174     inline std::string     next_nominus();
00175 
00176     // (*) unidentified flying objects -----------------------------------------
00177     inline STRING_VECTOR   unidentified_arguments(unsigned Number, const char* Known, ...) const;
00178     inline STRING_VECTOR   unidentified_arguments(const STRING_VECTOR& Knowns) const;
00179     inline STRING_VECTOR   unidentified_arguments() const;
00180 
00181     inline STRING_VECTOR   unidentified_options(unsigned Number, const char* Known, ...) const;
00182     inline STRING_VECTOR   unidentified_options(const STRING_VECTOR& Knowns) const;
00183     inline STRING_VECTOR   unidentified_options() const;
00184 
00185     inline std::string     unidentified_flags(const char* Known,
00186                                              int ArgumentNumber /* =-1 */) const;
00187 
00188     inline STRING_VECTOR   unidentified_variables(unsigned Number, const char* Known, ...) const;
00189     inline STRING_VECTOR   unidentified_variables(const STRING_VECTOR& Knowns) const;
00190     inline STRING_VECTOR   unidentified_variables() const;
00191 
00192     inline STRING_VECTOR   unidentified_sections(unsigned Number, const char* Known, ...) const;
00193     inline STRING_VECTOR   unidentified_sections(const STRING_VECTOR& Knowns) const;
00194     inline STRING_VECTOR   unidentified_sections() const;
00195 
00196     inline STRING_VECTOR   unidentified_nominuses(unsigned Number, const char* Known, ...) const;
00197     inline STRING_VECTOR   unidentified_nominuses(const STRING_VECTOR& Knowns) const;
00198     inline STRING_VECTOR   unidentified_nominuses() const;
00199 
00200     // (*) output --------------------------------------------------------------
00201     inline int print() const;
00202 
00203 private:
00204     // (*) Type Declaration ----------------------------------------------------
00205     struct variable {
00206         //-----------
00207         // Variable to be specified on the command line or in input files.
00208         // (i.e. of the form var='12 312 341')
00209 
00210         // -- constructors, destructors, assignment operator
00211         variable();
00212         variable(const variable&);
00213         variable(const char* Name, const char* Value, const char* FieldSeparator);
00214         ~variable();
00215         variable& operator=(const variable& That);
00216 
00217         void      take(const char* Value, const char* FieldSeparator);
00218 
00219         // -- get a specific element in the string vector
00220         //    (return 0 if not present)
00221         const std::string*  get_element(unsigned Idx) const;
00222 
00223         // -- data memebers
00224         std::string       name;      // identifier of variable
00225         STRING_VECTOR     value;     // value of variable stored in vector
00226         std::string       original;  // value of variable as given on command line
00227     };
00228 
00229     // (*) member variables --------------------------------------------------------------
00230     std::string           prefix;          // prefix automatically added in queries
00231     std::string           section;         // (for dollar bracket parsing)
00232     STRING_VECTOR         section_list;    // list of all parsed sections
00233     //     -- argument vector
00234     STRING_VECTOR         argv;            // vector of command line arguments stored as strings
00235     unsigned              cursor;          // cursor for argv
00236     bool                  search_loop_f;   // shall search start at beginning after
00237     //                                     // reaching end of arg array ?
00238     bool                  search_failed_f; // flag indicating a failed search() operation
00239     //                                     // (e.g. next() functions react with 'missed')
00240 
00241     //     --  nominus vector
00242     int                   nominus_cursor;  // cursor for nominus_pointers
00243     std::vector<unsigned> idx_nominus;     // indecies of 'no minus' arguments
00244 
00245     //     -- variables
00246     //       (arguments of the form "variable=value")
00247     std::vector<variable> variables;
00248     
00249     //     -- comment delimiters
00250     std::string           _comment_start;
00251     std::string           _comment_end;
00252 
00253     //     -- field separator (separating elements of a vector)
00254     std::string           _field_separator;
00255 
00256     //     -- some functions return a char pointer to a temporarily existing string
00257     //        this container makes them 'available' until the getpot object is destroyed.
00258     std::vector<char*>    __internal_string_container;
00259 
00260     //     -- keeping track about arguments that are requested, so that the UFO detection
00261     //        can be simplified
00262     STRING_VECTOR   _requested_arguments;
00263     STRING_VECTOR   _requested_variables;
00264     STRING_VECTOR   _requested_sections;
00265 
00266     bool            __request_recording_f;   // speed: request recording can be turned off
00267 
00268     //     -- if an argument is requested record it and the 'tag' the section branch to which 
00269     //        it belongs. Caution: both functions mark the sections as 'tagged'.
00270     void                      __record_argument_request(const std::string& Arg);
00271     void                      __record_variable_request(const std::string& Arg);
00272 
00273     // (*) helper functions ----------------------------------------------------
00274     //                  set variable from inside GetPot (no prefix considered)
00275     inline void               __set_variable(const char* VarName, const char* Value);
00276 
00277     //     -- produce three basic data vectors:
00278     //          - argument vector
00279     //          - nominus vector
00280     //          - variable dictionary
00281     inline void               __parse_argument_vector(const STRING_VECTOR& ARGV);
00282 
00283     //     -- helpers for argument list processing
00284     //        * search for a variable in 'variables' array
00285     inline const variable*    __find_variable(const char*) const;
00286     //        * support finding directly followed arguments
00287     inline const char*        __match_starting_string(const char* StartString);
00288     //        * support search for flags in a specific argument
00289     inline bool               __check_flags(const std::string& Str, const char* FlagList) const;
00290     //        * type conversion if possible
00291     inline int                __convert_to_type(const std::string& String, int Default) const;
00292     inline double             __convert_to_type(const std::string& String, double Default) const;
00293     //        * prefix extraction
00294     const std::string         __get_remaining_string(const std::string& String, 
00295                                                      const std::string& Start) const;
00296     //        * search for a specific string
00297     inline bool               __search_string_vector(const STRING_VECTOR& Vec,
00298                                                      const std::string& Str) const;
00299 
00300     //     -- helpers to parse input file
00301     //        create an argument vector based on data found in an input file, i.e.:
00302     //           1) delete comments (in between '_comment_start' '_comment_end')
00303     //           2) contract assignment expressions, such as
00304     //                   my-variable   =    '007 J. B.'
00305     //             into
00306     //                   my-variable='007 J. B.'
00307     //           3) interprete sections like '[../my-section]' etc.
00308     inline void               __skip_whitespace(std::istream& istr);
00309     inline const std::string  __get_next_token(std::istream& istr);
00310     inline const std::string  __get_string(std::istream& istr);
00311     inline const std::string  __get_until_closing_bracket(std::istream& istr);
00312 
00313     inline STRING_VECTOR      __read_in_stream(std::istream& istr);
00314     inline STRING_VECTOR      __read_in_file(const char* FileName);
00315     inline std::string        __process_section_label(const std::string& Section,
00316                                                       STRING_VECTOR& section_stack);
00317 
00318     //      -- dollar bracket expressions
00319     std::string               __DBE_expand_string(const std::string str);
00320     std::string               __DBE_expand(const std::string str);
00321     const GetPot::variable*   __DBE_get_variable(const std::string str);
00322     STRING_VECTOR             __DBE_get_expr_list(const std::string str, const unsigned ExpectedNumber);
00323 
00324     std::string  __double2string(const double& Value) const {
00325         // -- converts a double integer into a string
00326         char* tmp = new char[128];
00327 #ifndef WIN32
00328         snprintf(tmp, (int)sizeof(char)*128, "%e", Value);
00329 #else
00330         _snprintf(tmp, sizeof(char)*128, "%e", Value);
00331 #endif
00332         std::string result(tmp);
00333         delete [] tmp;
00334         return result;
00335     }
00336 
00337     std::string  __int2string(const int& Value) const {
00338         // -- converts an integer into a string
00339         char* tmp = new char[128];
00340 #ifndef WIN32
00341         snprintf(tmp, (int)sizeof(char)*128, "%i", Value);
00342 #else
00343         _snprintf(tmp, sizeof(char)*128, "%i", Value);
00344 #endif
00345         std::string result(tmp);
00346         delete [] tmp;
00347         return result;
00348     }
00349 
00350     STRING_VECTOR __get_section_tree(const std::string& FullPath) {
00351         // -- cuts a variable name into a tree of sub-sections. this is requested for recording
00352         //    requested sections when dealing with 'ufo' detection.
00353         STRING_VECTOR   result;
00354         const char* Start = FullPath.c_str();
00355 
00356         for(char *p = (char*)Start; *p ; p++) {
00357             if( *p == '/' ) { 
00358                 *p = '\0';  // set terminating zero for convinience
00359                 const std::string Section = Start;
00360                 *p = '/';   // reset slash at place
00361                 result.push_back(Section);
00362             }
00363         }
00364 
00365         return result;
00366     }
00367 };
00368 
00369 
00371 // (*) constructors, destructor, assignment operator
00372 //.............................................................................
00373 //
00374 inline void
00375 GetPot::__basic_initialization()
00376 {
00377     cursor = 0;              nominus_cursor = -1;
00378     search_failed_f = true;  search_loop_f = true;
00379     prefix = "";             section = "";
00380     
00381     // automatic request recording for later ufo detection
00382     __request_recording_f = true;
00383 
00384     // comment start and end strings
00385     _comment_start = std::string("#");
00386     _comment_end   = std::string("\n");
00387 
00388     // default: separate vector elements by whitespaces
00389     _field_separator = " \t\n";
00390 }
00391 
00392 inline
00393 GetPot::GetPot() 
00394 { 
00395     __basic_initialization(); 
00396 
00397     STRING_VECTOR _apriori_argv;
00398     _apriori_argv.push_back(std::string("Empty"));
00399     __parse_argument_vector(_apriori_argv);
00400 }
00401 
00402 inline
00403 GetPot::GetPot(const int argc_, char ** argv_, 
00404                const char* FieldSeparator /* =0x0 */)     
00405     // leave 'char**' non-const to honor less capable compilers ... 
00406 {
00407     // TODO: Ponder over the problem when the argument list is of size = 0.
00408     //       This is 'sabotage', but it can still occur if the user specifies
00409     //       it himself.
00410     assert(argc_ >= 1);
00411     __basic_initialization();
00412 
00413     // if specified -> overwrite default string
00414     if( FieldSeparator ) _field_separator = std::string(FieldSeparator);
00415 
00416     // -- make an internal copy of the argument list:
00417     STRING_VECTOR _apriori_argv;
00418     // -- for the sake of clarity: we do want to include the first argument in the argument vector !
00419     //    it will not be a nominus argument, though. This gives us a minimun vector size of one
00420     //    which facilitates error checking in many functions. Also the user will be able to
00421     //    retrieve the name of his application by "get[0]"
00422     _apriori_argv.push_back(std::string(argv_[0]));
00423     int i=1;
00424     for(; i<argc_; ++i) {
00425         std::string tmp(argv_[i]);   // recall the problem with temporaries,
00426         _apriori_argv.push_back(tmp);       // reference counting in arguement lists ...
00427     }
00428     __parse_argument_vector(_apriori_argv);
00429 }
00430 
00431 
00432 inline
00433 GetPot::GetPot(const char* FileName,
00434                const char* CommentStart  /* = 0x0 */, const char* CommentEnd /* = 0x0 */,
00435                const char* FieldSeparator/* = 0x0 */)     
00436 {
00437     __basic_initialization();
00438 
00439     // if specified -> overwrite default strings
00440     if( CommentStart )   _comment_start = std::string(CommentStart);
00441     if( CommentEnd )     _comment_end   = std::string(CommentEnd);
00442     if( FieldSeparator ) _field_separator = FieldSeparator;
00443     
00444     STRING_VECTOR _apriori_argv;
00445     // -- file name is element of argument vector, however, it is not parsed for
00446     //    variable assignments or nominuses.
00447     _apriori_argv.push_back(std::string(FileName));
00448 
00449     STRING_VECTOR args = __read_in_file(FileName);
00450     _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end());
00451     __parse_argument_vector(_apriori_argv);
00452 }
00453 
00454 inline
00455 GetPot::GetPot(const GetPot& That)
00456 { GetPot::operator=(That); }
00457 
00458 inline
00459 GetPot::~GetPot()
00460 { 
00461     // may be some return strings had to be created, delete now !
00462     victorate(char*, __internal_string_container, it)
00463         delete [] *it;  
00464 }
00465 
00466 inline GetPot&
00467 GetPot::operator=(const GetPot& That)
00468 {
00469     if (&That == this) return *this;
00470 
00471     _comment_start  = That._comment_start;
00472     _comment_end    = That._comment_end;
00473     argv            = That.argv;
00474     variables       = That.variables;
00475     prefix          = That.prefix;
00476 
00477     cursor          = That.cursor;
00478     nominus_cursor  = That.nominus_cursor;
00479     search_failed_f = That.search_failed_f;
00480 
00481     idx_nominus     = That.idx_nominus;
00482     search_loop_f   = That.search_loop_f;
00483 
00484     return *this;
00485 }
00486 
00487 
00488 inline void
00489 GetPot::absorb(const GetPot& That)
00490 {
00491     if (&That == this) return;
00492 
00493     STRING_VECTOR  __tmp(That.argv);
00494 
00495     __tmp.erase(__tmp.begin());
00496 
00497     __parse_argument_vector(__tmp);
00498 }
00499 
00500 inline void    
00501 GetPot::clear_requests()
00502 {
00503     _requested_arguments.erase(_requested_arguments.begin(), _requested_arguments.end());
00504     _requested_variables.erase(_requested_variables.begin(), _requested_variables.end());
00505     _requested_sections.erase(_requested_sections.begin(), _requested_sections.end());
00506 }
00507 
00508 inline void
00509 GetPot::__parse_argument_vector(const STRING_VECTOR& ARGV)
00510 {
00511     if( ARGV.size() == 0 ) return;
00512 
00513     // build internal databases:
00514     //   1) array with no-minus arguments (usually used as filenames)
00515     //   2) variable assignments:
00516     //             'variable name' '=' number | string
00517     STRING_VECTOR                 section_stack;
00518     STRING_VECTOR::const_iterator it = ARGV.begin();
00519 
00520 
00521     section = "";
00522 
00523     // -- do not parse the first argument, so that it is not interpreted a s a nominus or so.
00524     argv.push_back(*it);
00525     ++it;
00526 
00527     // -- loop over remaining arguments
00528     unsigned i=1;
00529     for(; it != ARGV.end(); ++it, ++i) {
00530         std::string arg = *it;
00531 
00532         if( arg.length() == 0 ) continue;
00533 
00534         // -- [section] labels
00535         if( arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']' ) {
00536 
00537             // (*) sections are considered 'requested arguments'
00538             if( __request_recording_f ) _requested_arguments.push_back(arg);
00539             
00540             const std::string Name = __DBE_expand_string(arg.substr(1, arg.length()-2));
00541             section = __process_section_label(Name, section_stack);
00542             // new section --> append to list of sections
00543             if( find(section_list.begin(), section_list.end(), section) == section_list.end() )
00544                 if( section.length() != 0 ) section_list.push_back(section);
00545             argv.push_back(arg);
00546         }
00547         else {
00548             arg = section + __DBE_expand_string(arg);
00549             argv.push_back(arg);
00550         }
00551 
00552         // -- separate array for nominus arguments
00553         if( arg[0] != '-' ) idx_nominus.push_back(unsigned(i));
00554 
00555         // -- variables: does arg contain a '=' operator ?
00556         const char* p = arg.c_str();
00557         for(; *p ; p++) {
00558             if( *p == '=' ) {
00559                 // (*) record for later ufo detection
00560                 //     arguments carriying variables are always treated as 'requested' arguments. 
00561                 //     as a whole! That is 'x=4712' is  considered a requested argument.
00562                 //
00563                 //     unrequested variables have to be detected with the ufo-variable
00564                 //     detection routine.
00565                 if( __request_recording_f ) _requested_arguments.push_back(arg);
00566 
00567                 // set terminating 'zero' to treat first part as single string
00568                 // => arg (from start to 'p') = Name of variable
00569                 //    p+1     (until terminating zero) = value of variable
00570                 char* o = (char*)p++;
00571                 *o = '\0';                       // set temporary terminating zero
00572                 // __set_variable(...) 
00573                 // calls __find_variable(...) which registers the search
00574                 // temporarily disable this
00575                 const bool tmp = __request_recording_f;
00576                 __request_recording_f = false;
00577                 __set_variable(arg.c_str(), p);  // v-name = c_str() bis 'p', value = rest
00578                 __request_recording_f = tmp;
00579                 *o = '=';                        // reset the original '='
00580                 break;
00581             }
00582         }
00583     }
00584 }
00585 
00586 
00587 inline STRING_VECTOR
00588 GetPot::__read_in_file(const char* FileName)
00589 {
00590     std::ifstream  i(FileName);
00591     if( ! i ) return STRING_VECTOR();
00592     // argv[0] == the filename of the file that was read in
00593     return __read_in_stream(i);
00594 }
00595 
00596 inline STRING_VECTOR
00597 GetPot::__read_in_stream(std::istream& istr)
00598 {
00599     STRING_VECTOR  brute_tokens;
00600     while(istr) {
00601         __skip_whitespace(istr);
00602         const std::string Token = __get_next_token(istr);
00603         if( Token.length() == 0 || Token[0] == EOF) break;
00604         brute_tokens.push_back(Token);
00605     }
00606 
00607     // -- reduce expressions of token1'='token2 to a single
00608     //    string 'token1=token2'
00609     // -- copy everything into 'argv'
00610     // -- arguments preceded by something like '[' name ']' (section)
00611     //    produce a second copy of each argument with a prefix '[name]argument'
00612     unsigned i1 = 0;
00613     unsigned i2 = 1;
00614     unsigned i3 = 2;
00615 
00616     STRING_VECTOR  arglist;
00617     while( i1 < brute_tokens.size() ) {
00618         const std::string& SRef = brute_tokens[i1];
00619         // 1) concatinate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef'
00620         // note: java.lang.String: substring(a,b) = from a to b-1
00621         //        C++ string:      substr(a,b)    = from a to a + b
00622         if( i2 < brute_tokens.size() && brute_tokens[i2] == "=" ) {
00623             if( i3 >= brute_tokens.size() )
00624                 arglist.push_back(brute_tokens[i1] + brute_tokens[i2]);
00625             else
00626                 arglist.push_back(brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3]);
00627             i1 = i3+1; i2 = i3+2; i3 = i3+3;
00628             continue;
00629         }
00630         else {
00631             arglist.push_back(SRef);
00632             i1=i2; i2=i3; i3++;
00633         }
00634     }
00635     return arglist;
00636 }
00637 
00638 inline void
00639 GetPot::__skip_whitespace(std::istream& istr)
00640     // find next non-whitespace while deleting comments
00641 {
00642     int tmp = istr.get();
00643     do {
00644         // -- search a non whitespace
00645         while( isspace(tmp) ) {
00646             tmp = istr.get();
00647             if( ! istr ) return;
00648         }
00649 
00650         // -- look if characters match the comment starter string
00651         unsigned    i=0;
00652         for(; i<_comment_start.length() ; ++i) {
00653             if( tmp != _comment_start[i] ) { 
00654                 // NOTE: Due to a 'strange behavior' in Microsoft's streaming lib we do
00655                 // a series of unget()s instead a quick seek. See 
00656                 // http://sourceforge.net/tracker/index.php?func=detail&aid=1545239&group_id=31994&atid=403915
00657                 // for a detailed discussion.
00658 
00659                 // -- one step more backwards, since 'tmp' already at non-whitespace
00660                 do istr.unget(); while( i-- != 0 ); 
00661                 return; 
00662             }
00663             tmp = istr.get();
00664             if( ! istr ) { istr.unget(); return; }
00665         }
00666         // 'tmp' contains last character of _comment_starter
00667 
00668         // -- comment starter found -> search for comment ender
00669         unsigned match_no=0;
00670         while(1+1 == 2) {
00671             tmp = istr.get();
00672             if( ! istr ) { istr.unget(); return; }
00673 
00674             if( tmp == _comment_end[match_no] ) { 
00675                 match_no++;
00676                 if( match_no == _comment_end.length() ) {
00677                     istr.unget();
00678                     break; // shuffle more whitespace, end of comment found
00679                 }
00680             }
00681             else
00682                 match_no = 0;
00683         }
00684 
00685         tmp = istr.get();
00686 
00687     } while( istr );
00688     istr.unget();
00689 }
00690 
00691 inline const std::string
00692 GetPot::__get_next_token(std::istream& istr)
00693     // get next concatinates string token. consider quotes that embrace
00694     // whitespaces
00695 {
00696     std::string token;
00697     int    tmp = 0;
00698     int    last_letter = 0;
00699     while(1+1 == 2) {
00700         last_letter = tmp; tmp = istr.get();
00701         if( tmp == EOF
00702             || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\') ) {
00703             return token;
00704         }
00705         else if( tmp == '\'' && last_letter != '\\' ) {
00706             // QUOTES: un-backslashed quotes => it's a string
00707             token += __get_string(istr);
00708             continue;
00709         }
00710         else if( tmp == '{' && last_letter == '$') {
00711             token += '{' + __get_until_closing_bracket(istr);
00712             continue;
00713         }
00714         else if( tmp == '$' && last_letter == '\\') {
00715             token += tmp; tmp = 0;  //  so that last_letter will become = 0, not '$';
00716             continue;
00717         }
00718         else if( tmp == '\\' && last_letter != '\\')
00719             continue;              // don't append un-backslashed backslashes
00720         token += tmp;
00721     }
00722 }
00723 
00724 inline const std::string
00725 GetPot::__get_string(std::istream& istr)
00726     // parse input until next matching '
00727 {
00728     std::string str;
00729     int    tmp = 0;
00730     int    last_letter = 0;
00731     while(1 + 1 == 2) {
00732         last_letter = tmp; tmp = istr.get();
00733         if( tmp == EOF)  return str;
00734         // un-backslashed quotes => it's the end of the string
00735         else if( tmp == '\'' && last_letter != '\\')  return str;
00736         else if( tmp == '\\' && last_letter != '\\')  continue; // don't append
00737 
00738         str += tmp;
00739     }
00740 }
00741 
00742 inline const std::string
00743 GetPot::__get_until_closing_bracket(std::istream& istr)
00744     // parse input until next matching }
00745 {
00746     std::string str = "";
00747     int    tmp = 0;
00748     int    last_letter = 0;
00749     int    brackets = 1;
00750     while(1 + 1 == 2) {
00751         last_letter = tmp; tmp = istr.get();
00752         if( tmp == EOF) return str;
00753         else if( tmp == '{' && last_letter == '$') brackets += 1;
00754         else if( tmp == '}') {
00755             brackets -= 1;
00756             // un-backslashed brackets => it's the end of the string
00757             if( brackets == 0) return str + '}';
00758             else if( tmp == '\\' && last_letter != '\\')
00759                 continue;  // do not append an unbackslashed backslash
00760         }
00761         str += tmp;
00762     }
00763 }
00764 
00765 inline std::string
00766 GetPot::__process_section_label(const std::string& Section,
00767                                 STRING_VECTOR& section_stack)
00768 {
00769     std::string sname = Section;
00770     //  1) subsection of actual section ('./' prefix)
00771     if( sname.length() >= 2 && sname.substr(0, 2) == "./" ) {
00772         sname = sname.substr(2);
00773     }
00774     //  2) subsection of parent section ('../' prefix)
00775     else if( sname.length() >= 3 && sname.substr(0, 3) == "../" ) {
00776         do {
00777             if( section_stack.end() != section_stack.begin() )
00778                 section_stack.pop_back();
00779             sname = sname.substr(3);
00780         } while( sname.substr(0, 3) == "../" );
00781     }
00782     // 3) subsection of the root-section
00783     else {
00784         section_stack.erase(section_stack.begin(), section_stack.end());
00785         // [] => back to root section
00786     }
00787 
00788     if( sname != "" ) {
00789         // parse section name for 'slashes'
00790         unsigned i=0;
00791         while( i < sname.length() ) {
00792             if( sname[i] == '/' ) {
00793                 section_stack.push_back(sname.substr(0,i));
00794                 if( i+1 < sname.length() ) 
00795                     sname = sname.substr(i+1);
00796                 i = 0;
00797             }
00798             else
00799                 ++i;
00800         }
00801         section_stack.push_back(sname);
00802     }
00803     std::string section = "";
00804     if( section_stack.size() != 0 ) {
00805         victorate(std::string, section_stack, it)
00806             section += *it + "/";
00807     }
00808     return section;
00809 }
00810 
00811 
00812 // convert string to DOUBLE, if not possible return Default
00813 inline double
00814 GetPot::__convert_to_type(const std::string& String, double Default) const
00815 {
00816     double tmp;
00817     if( sscanf(String.c_str(),"%lf", &tmp) != 1 ) return Default;
00818     return tmp;
00819 }
00820 
00821 // convert string to INT, if not possible return Default
00822 inline int
00823 GetPot::__convert_to_type(const std::string& String, int Default) const
00824 {
00825     // NOTE: intermediate results may be floating points, so that the string
00826     //       may look like 2.0e1 (i.e. float format) => use float conversion
00827     //       in any case.
00828     return (int)__convert_to_type(String, (double)Default);
00829 }
00830 
00832 // (*) cursor oriented functions
00833 //.............................................................................
00834 inline const std::string
00835 GetPot::__get_remaining_string(const std::string& String, const std::string& Start) const
00836     // Checks if 'String' begins with 'Start' and returns the remaining String.
00837     // Returns None if String does not begin with Start.
00838 {
00839     if( Start == "" ) return String;
00840     // note: java.lang.String: substring(a,b) = from a to b-1
00841     //        C++ string:      substr(a,b)    = from a to a + b
00842     if( String.find(Start) == 0 ) return String.substr(Start.length());
00843     else                          return "";
00844 }
00845 
00846 //     -- search for a certain argument and set cursor to position
00847 inline bool
00848 GetPot::search(const char* Option)
00849 {    
00850     unsigned           OldCursor  = cursor;
00851     const std::string  SearchTerm = prefix + Option;
00852 
00853     // (*) record requested arguments for later ufo detection
00854     __record_argument_request(SearchTerm);                             
00855 
00856     if( OldCursor >= argv.size() ) OldCursor = static_cast<unsigned int>(argv.size()) - 1;
00857     search_failed_f = true;
00858 
00859     // (*) first loop from cursor position until end
00860     unsigned  c = cursor;
00861     for(; c < argv.size(); c++) {
00862         if( argv[c] == SearchTerm )
00863         { cursor = c; search_failed_f = false; return true; }
00864     }
00865     if( ! search_loop_f ) return false;
00866 
00867     // (*) second loop from 0 to old cursor position
00868     for(c = 1; c < OldCursor; c++) {
00869         if( argv[c] == SearchTerm )
00870         { cursor = c; search_failed_f = false; return true; }
00871     }
00872     // in case nothing is found the cursor stays where it was
00873     return false;
00874 }
00875 
00876 
00877 inline bool
00878 GetPot::search(unsigned No, const char* P, ...)
00879 {
00880     // (*) recording the requested arguments happens in subroutine 'search'
00881     if( No == 0 ) return false;
00882 
00883     // search for the first argument
00884     if( search(P) == true ) return true;
00885 
00886     // start interpreting variable argument list
00887     va_list ap;
00888     va_start(ap, P);
00889     unsigned i = 1;
00890     for(; i < No; ++i) {
00891         char* Opt = va_arg(ap, char *);
00892         if( search(Opt) == true ) break;
00893     }
00894     
00895     if( i < No ) {
00896         ++i;
00897         // loop was left before end of array --> hit but 
00898         // make sure that the rest of the search terms is marked
00899         // as requested.
00900         for(; i < No; ++i) {
00901             char* Opt = va_arg(ap, char *);
00902             // (*) record requested arguments for later ufo detection
00903             __record_argument_request(Opt);
00904         }
00905         va_end(ap);
00906         return true;
00907     }
00908 
00909     va_end(ap);
00910     // loop was left normally --> no hit
00911     return false;
00912 }
00913 
00914 inline void
00915 GetPot::reset_cursor()
00916 { search_failed_f = false; cursor = 0; }
00917 
00918 inline void
00919 GetPot::init_multiple_occurrence()
00920 { disable_loop(); reset_cursor(); }
00922 // (*) direct access to command line arguments
00923 //.............................................................................
00924 //
00925 inline const std::string
00926 GetPot::operator[](unsigned idx) const
00927 { return idx < argv.size() ? argv[idx] : ""; }
00928 
00929 inline int
00930 GetPot::get(unsigned Idx, int Default) const
00931 {
00932     if( Idx >= argv.size() ) return Default;
00933     return __convert_to_type(argv[Idx], Default);
00934 }
00935 
00936 inline double
00937 GetPot::get(unsigned Idx, const double& Default) const
00938 {
00939     if( Idx >= argv.size() ) return Default;
00940     return __convert_to_type(argv[Idx], Default);
00941 }
00942 
00943 inline const std::string
00944 GetPot::get(unsigned Idx, const char* Default) const
00945 {
00946     if( Idx >= argv.size() ) return Default;
00947     else                     return argv[Idx];
00948 }
00949 
00950 inline unsigned
00951 GetPot::size() const
00952 { return static_cast<unsigned int>(argv.size()); }
00953 
00954 
00955 //     -- next() function group
00956 inline int
00957 GetPot::next(int Default)
00958 {
00959     if( search_failed_f ) return Default;
00960     cursor++;
00961     if( cursor >= argv.size() )  
00962     { cursor = static_cast<unsigned int>(argv.size()); return Default; }
00963 
00964     // (*) record requested argument for later ufo detection
00965     __record_argument_request(argv[cursor]);
00966 
00967     const std::string Remain = __get_remaining_string(argv[cursor], prefix);
00968 
00969     return Remain != "" ? __convert_to_type(Remain, Default) : Default;
00970 }
00971 
00972 inline double
00973 GetPot::next(const double& Default)
00974 {
00975     if( search_failed_f ) return Default;
00976     cursor++;
00977 
00978     if( cursor >= argv.size() )
00979     { cursor = static_cast<unsigned int>(argv.size()); return Default; }
00980 
00981     // (*) record requested argument for later ufo detection
00982     __record_argument_request(argv[cursor]);
00983 
00984     std::string Remain = __get_remaining_string(argv[cursor], prefix);
00985 
00986     return Remain != "" ? __convert_to_type(Remain, Default) : Default;
00987 }
00988 
00989 inline const std::string
00990 GetPot::next(const char* Default)
00991 {
00992     using namespace std;
00993 
00994     if( search_failed_f ) return Default;
00995     cursor++;
00996 
00997     if( cursor >= argv.size() )
00998     { cursor = static_cast<unsigned int>(argv.size()); return Default; }
00999 
01000     // (*) record requested argument for later ufo detection
01001     __record_argument_request(argv[cursor]);
01002 
01003     const std::string Remain = __get_remaining_string(argv[cursor], prefix);
01004 
01005     if( Remain == "" ) return Default;
01006 
01007 
01008     // (*) function returns a pointer to a char array (inside Remain)
01009     //     this array will be deleted, though after this function call.
01010     //     To ensure propper functioning, create a copy inside *this
01011     //     object and only delete it, when *this is deleted.
01012     char* result = new char[Remain.length()+1];
01013     strncpy(result, Remain.c_str(), Remain.length()+1);
01014 
01015     // store the created string internally, delete if when object deleted
01016     __internal_string_container.push_back(result);
01017 
01018     return result;
01019 }
01020 
01021 //     -- follow() function group
01022 //        distinct option to be searched for
01023 inline int
01024 GetPot::follow(int Default, const char* Option)
01025 {
01026     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01027     if( search(Option) == false ) return Default;
01028     return next(Default);
01029 }
01030 
01031 inline double
01032 GetPot::follow(const double& Default, const char* Option)
01033 {
01034     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01035     if( search(Option) == false ) return Default;
01036     return next(Default);
01037 }
01038 
01039 inline const std::string
01040 GetPot::follow(const char* Default, const char* Option)
01041 {
01042     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01043     if( search(Option) == false ) return Default;
01044     return next(Default);
01045 }
01046 
01047 //     -- second follow() function group
01048 //        multiple option to be searched for
01049 inline int
01050 GetPot::follow(int Default, unsigned No, const char* P, ...)
01051 {
01052     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01053     if( No == 0 ) return Default;
01054     if( search(P) == true ) return next(Default);
01055 
01056     va_list ap;
01057     va_start(ap, P);
01058     unsigned i=1;
01059     for(; i<No; ++i) {
01060         char* Opt = va_arg(ap, char *);
01061         if( search(Opt) == true ) {
01062             va_end(ap);
01063             return next(Default);
01064         }
01065     }
01066     va_end(ap);
01067     return Default;
01068 }
01069 
01070 inline double
01071 GetPot::follow(const double& Default, unsigned No, const char* P, ...)
01072 {
01073     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01074     if( No == 0 ) return Default;
01075     if( search(P) == true ) return next(Default);
01076 
01077     va_list ap;
01078     va_start(ap, P);
01079     for(unsigned i=1; i<No; ++i) {
01080         char* Opt = va_arg(ap, char *);
01081         if( search(Opt) == true ) {
01082             va_end(ap);
01083             return next(Default);
01084         }
01085     }
01086     va_end(ap);
01087     return Default;
01088 }
01089 
01090 inline const std::string
01091 GetPot::follow(const char* Default, unsigned No, const char* P, ...)
01092 {
01093     // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01094     if( No == 0 ) return Default;
01095     if( search(P) == true ) return next(Default);
01096 
01097     va_list ap;
01098     va_start(ap, P);
01099     unsigned i=1;
01100     for(; i<No; ++i) {
01101         char* Opt = va_arg(ap, char *);
01102         if( search(Opt) == true ) {
01103             va_end(ap);
01104             return next(Default);
01105         }
01106     }
01107     va_end(ap);
01108     return Default;
01109 }
01110 
01111 
01113 // (*) lists of nominus following an option
01114 //.............................................................................
01115 //
01116 inline std::vector<std::string> 
01117 GetPot::nominus_followers(const char* Option)
01118 {
01119     std::vector<std::string>  result_list;
01120     if( search(Option) == false ) return result_list;
01121     while( 1 + 1 == 2 ) {
01122         ++cursor;
01123         if( cursor >= argv.size() ) { 
01124             cursor = argv.size() - 1;
01125             return result_list;
01126         }
01127         if( argv[cursor].length() >= 1 ) {
01128             if( argv[cursor][0] == '-' ) {
01129                 return result_list;
01130             }
01131             // -- record for later ufo-detection
01132             __record_argument_request(argv[cursor]);
01133             // -- append to the result list
01134             result_list.push_back(argv[cursor]);
01135         }
01136     }
01137 }
01138 
01139 inline std::vector<std::string> 
01140 GetPot::nominus_followers(unsigned No, ...)
01141 {
01142     std::vector<std::string>  result_list;
01143     // (*) record requested of argument is entirely handled in 'search()' 
01144     //     and 'nominus_followers()'
01145     if( No == 0 ) return result_list;
01146 
01147     va_list ap;
01148     va_start(ap, No);   
01149     for(unsigned i=0; i<No; ++i) {
01150         char* Option = va_arg(ap, char *);
01151         std::vector<std::string> tmp = nominus_followers(Option);
01152         result_list.insert(result_list.end(), tmp.begin(), tmp.end());
01153 
01154         // std::cerr << "option = '" << Option << "'" << std::endl;
01155         // std::cerr << "length = " << tmp.size() << std::endl;
01156         // std::cerr << "new result list = <";
01157         // for(std::vector<std::string>::const_iterator it = result_list.begin();
01158         //    it != result_list.end(); ++it) 
01159         //    std::cerr << *it << ", ";
01160         // std::cerr << ">\n";
01161     }
01162     va_end(ap);
01163     return result_list;
01164 }
01165 
01166 
01168 // (*) directly connected options
01169 //.............................................................................
01170 //
01171 inline int
01172 GetPot::direct_follow(int Default, const char* Option)
01173 {
01174     const char* FollowStr = __match_starting_string(Option);
01175     if( FollowStr == 0x0 )  return Default;
01176 
01177     // (*) record requested of argument for later ufo-detection
01178     __record_argument_request(std::string(Option) + FollowStr);
01179 
01180     if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
01181     return __convert_to_type(FollowStr, Default);
01182 }
01183 
01184 inline double
01185 GetPot::direct_follow(const double& Default, const char* Option)
01186 {
01187     const char* FollowStr = __match_starting_string(Option);
01188     if( FollowStr == 0 )  return Default;
01189 
01190     // (*) record requested of argument for later ufo-detection
01191     __record_argument_request(std::string(Option) + FollowStr);
01192 
01193     if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
01194     return __convert_to_type(FollowStr, Default);
01195 }
01196 
01197 inline const std::string
01198 GetPot::direct_follow(const char* Default, const char* Option)
01199 {
01200     if( search_failed_f ) return Default;
01201     const char* FollowStr = __match_starting_string(Option);
01202     if( FollowStr == 0 )  return Default;
01203 
01204     // (*) record requested of argument for later ufo-detection
01205     if( FollowStr ) __record_argument_request(std::string(Option) + FollowStr);
01206 
01207     if( ++cursor >= static_cast<unsigned int>(argv.size()) ) cursor = static_cast<unsigned int>(argv.size());
01208     return std::string(FollowStr);
01209 }
01210 
01211 inline std::vector<std::string>
01212 GetPot::string_tails(const char* StartString)
01213 {
01214     std::vector<std::string>  result;
01215     const unsigned            N = static_cast<unsigned int>(strlen(StartString));
01216 
01217     std::vector<std::string>::iterator it = argv.begin();
01218 
01219     unsigned idx = 0;
01220     while( it != argv.end() ) {
01221         // (*) does start string match the given option?
01222         //     NO -> goto next option
01223         if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
01224 
01225         // append the found tail to the result vector
01226         result.push_back((*it).substr(N));
01227                 
01228         // adapt the nominus vector
01229         std::vector<unsigned>::iterator nit = idx_nominus.begin();
01230         for(; nit != idx_nominus.end(); ++nit) {
01231             if( *nit == idx ) {
01232                 idx_nominus.erase(nit);
01233                 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
01234                 break;
01235             }
01236         }
01237         
01238         // erase the found option
01239         argv.erase(it);
01240 
01241         // 100% safe solution: set iterator back to the beginning.
01242         // (normally, 'it--' would be enough, but who knows how the
01243         // iterator is implemented and .erase() definitely invalidates
01244         // the current iterator position.
01245         if( argv.empty() ) break;
01246         it = argv.begin();
01247     }
01248     cursor = 0;
01249     nominus_cursor = -1;
01250     return result;
01251 }
01252 
01253 inline std::vector<int>
01254 GetPot::int_tails(const char* StartString, const int Default /* = -1 */)
01255 {
01256     std::vector<int>  result;
01257     const unsigned    N = static_cast<unsigned int>(strlen(StartString));
01258 
01259     std::vector<std::string>::iterator it = argv.begin();
01260 
01261     unsigned idx = 0;
01262     while( it != argv.end() ) {
01263         // (*) does start string match the given option?
01264         //     NO -> goto next option
01265         if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
01266             
01267         // append the found tail to the result vector
01268         result.push_back(__convert_to_type((*it).substr(N), Default));
01269 
01270         // adapt the nominus vector
01271         std::vector<unsigned>::iterator nit = idx_nominus.begin();
01272         for(; nit != idx_nominus.end(); ++nit) {
01273             if( *nit == idx ) {
01274                 idx_nominus.erase(nit);
01275                 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
01276                 break;
01277             }
01278         }
01279 
01280         // erase the found option
01281         argv.erase(it);
01282         
01283         // 100% safe solution: set iterator back to the beginning.
01284         // (normally, 'it--' would be enough, but who knows how the
01285         // iterator is implemented and .erase() definitely invalidates
01286         // the current iterator position.
01287         if( argv.empty() ) break;
01288         it = argv.begin();
01289     }
01290     cursor = 0;
01291     nominus_cursor = -1;
01292     return result;
01293 }
01294 
01295 inline std::vector<double>
01296 GetPot::double_tails(const char*  StartString, 
01297                      const double Default /* = -1.0 */)
01298 {
01299     std::vector<double>  result;
01300     const unsigned       N = static_cast<unsigned int>(strlen(StartString));
01301 
01302     std::vector<std::string>::iterator it = argv.begin();
01303     unsigned                           idx = 0;
01304     while( it != argv.end() ) {
01305         // (*) does start string match the given option?
01306         //     NO -> goto next option
01307         if( strncmp(StartString, (*it).c_str(), N) != 0) { ++it; ++idx; continue; }
01308             
01309         // append the found tail to the result vector
01310         result.push_back(__convert_to_type((*it).substr(N), Default));
01311 
01312         // adapt the nominus vector
01313         std::vector<unsigned>::iterator nit = idx_nominus.begin();
01314         for(; nit != idx_nominus.end(); ++nit) {
01315             if( *nit == idx ) {
01316                 idx_nominus.erase(nit);
01317                 for(; nit != idx_nominus.end(); ++nit) *nit -= 1;
01318                 break;
01319             }
01320         }
01321 
01322         // erase the found option
01323         argv.erase(it);
01324         
01325         // 100% safe solution: set iterator back to the beginning.
01326         // (normally, 'it--' would be enough, but who knows how the
01327         // iterator is implemented and .erase() definitely invalidates
01328         // the current iterator position.
01329         if( argv.empty() ) break;
01330         it = argv.begin();
01331     }
01332     cursor = 0;
01333     nominus_cursor = -1;
01334     return result;
01335 }
01336 
01337 
01338 
01339 
01340 
01341 inline const char*
01342 GetPot::__match_starting_string(const char* StartString)
01343     // pointer  to the place where the string after
01344     //          the match inside the found argument starts.
01345     // 0        no argument matches the starting string.
01346 {
01347     const unsigned N         = static_cast<unsigned int>(strlen(StartString));
01348     unsigned       OldCursor = cursor;
01349 
01350     if( OldCursor >= static_cast<unsigned int>(argv.size()) ) OldCursor = static_cast<unsigned int>(argv.size()) - 1;
01351     search_failed_f = true;
01352 
01353     // (*) first loop from cursor position until end
01354     unsigned c = cursor;
01355     for(; c < argv.size(); c++) {
01356         if( strncmp(StartString, argv[c].c_str(), N) == 0)
01357         { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
01358     }
01359 
01360     if( ! search_loop_f ) return false;
01361 
01362     // (*) second loop from 0 to old cursor position
01363     for(c = 1; c < OldCursor; c++) {
01364         if( strncmp(StartString, argv[c].c_str(), N) == 0)
01365         { cursor = c; search_failed_f = false; return &(argv[c].c_str()[N]); }
01366     }
01367     return 0;
01368 }
01369 
01371 // (*) search for flags
01372 //.............................................................................
01373 //
01374 inline bool
01375 GetPot::options_contain(const char* FlagList) const
01376 {
01377     // go through all arguments that start with a '-' (but not '--')
01378     std::string str;
01379     STRING_VECTOR::const_iterator it = argv.begin();
01380     for(; it != argv.end(); ++it) {
01381         str = __get_remaining_string(*it, prefix);
01382 
01383         if( str.length() >= 2 && str[0] == '-' && str[1] != '-' )
01384             if( __check_flags(str, FlagList) ) return true;
01385     }
01386     return false;
01387 }
01388 
01389 inline bool
01390 GetPot::argument_contains(unsigned Idx, const char* FlagList) const
01391 {
01392     if( Idx >= argv.size() ) return false;
01393 
01394     // (*) record requested of argument for later ufo-detection
01395     //     an argument that is checked for flags is considered to be 'requested'
01396     ((GetPot*)this)->__record_argument_request(argv[Idx]);
01397 
01398     if( prefix == "" )
01399         // search argument for any flag in flag list
01400         return __check_flags(argv[Idx], FlagList);
01401 
01402     // if a prefix is set, then the argument index is the index
01403     //   inside the 'namespace'
01404     // => only check list of arguments that start with prefix
01405     unsigned no_matches = 0;
01406     unsigned i=0;
01407     for(; i<argv.size(); ++i) {
01408         const std::string Remain = __get_remaining_string(argv[i], prefix);
01409         if( Remain != "") {
01410             no_matches += 1;
01411             if( no_matches == Idx)
01412                 return __check_flags(Remain, FlagList);
01413         }
01414     }
01415     // no argument in this namespace
01416     return false;
01417 }
01418 
01419 inline bool
01420 GetPot::__check_flags(const std::string& Str, const char* FlagList) const
01421 {
01422     const char* p=FlagList;
01423     for(; *p != '\0' ; p++)
01424         if( Str.find(*p) != std::string::npos ) return true; // found something
01425     return false;
01426 }
01427 
01429 // (*) nominus arguments
01430 inline STRING_VECTOR
01431 GetPot::nominus_vector() const
01432     // return vector of nominus arguments
01433 {
01434     STRING_VECTOR nv;
01435     std::vector<unsigned>::const_iterator it = idx_nominus.begin();
01436     for(; it != idx_nominus.end(); ++it) {
01437         nv.push_back(argv[*it]);
01438 
01439         // (*) record for later ufo-detection
01440         //     when a nominus vector is requested, the entire set of nominus arguments are 
01441         //     tagged as 'requested'
01442         ((GetPot*)this)->__record_argument_request(argv[*it]);
01443     }
01444     return nv;
01445 }
01446 
01447 inline std::string
01448 GetPot::next_nominus()
01449 {
01450     if( nominus_cursor < int(idx_nominus.size()) - 1 ) {
01451         const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
01452 
01453         // (*) record for later ufo-detection
01454         __record_argument_request(Tmp);
01455 
01456         // -- cannot use the Tmp variable, since it is temporary and c_str() will return a pointer
01457         //    to something that does no longer exist.
01458         return Tmp; 
01459     }
01460     return std::string("");
01461 }
01462 
01464 // (*) variables
01465 //.............................................................................
01466 //
01467 inline int
01468 GetPot::operator()(const char* VarName, int Default) const
01469 {
01470     // (*) recording of requested variables happens in '__find_variable()'
01471     const variable*  sv = __find_variable(VarName);
01472     if( sv == 0 ) return Default;
01473     return __convert_to_type(sv->original, Default);
01474 }
01475 
01476 inline double
01477 GetPot::operator()(const char* VarName, const double& Default) const
01478 {
01479     // (*) recording of requested variables happens in '__find_variable()'
01480     const variable*  sv = __find_variable(VarName);
01481     if( sv == 0 ) return Default;
01482     return __convert_to_type(sv->original, Default);
01483 }
01484 
01485 inline const std::string
01486 GetPot::operator()(const char* VarName, const char* Default) const
01487 {
01488     // (*) recording of requested variables happens in '__find_variable()'
01489     const variable*  sv = __find_variable(VarName);
01490     if( sv == 0 ) return Default;
01491     // -- returning a c_str() pointer is OK here, since the variable remains existant,
01492     //    while 'sv' of course is delete at the end of the function.
01493     return sv->original;
01494 }
01495 
01496 inline int
01497 GetPot::operator()(const char* VarName, int Default, unsigned Idx) const
01498 {
01499     // (*) recording of requested variables happens in '__find_variable()'
01500     const variable* sv = __find_variable(VarName);
01501     if( sv == 0 ) return Default;
01502     const std::string*  element = sv->get_element(Idx);
01503     if( element == 0 ) return Default;
01504     return __convert_to_type(*element, Default);
01505 }
01506 
01507 inline double
01508 GetPot::operator()(const char* VarName, const double& Default, unsigned Idx) const
01509 {
01510     // (*) recording of requested variables happens in '__find_variable()'
01511     const variable* sv = __find_variable(VarName);
01512     if( sv == 0 ) return Default;
01513     const std::string*  element = sv->get_element(Idx);
01514     if( element == 0 ) return Default;
01515     return __convert_to_type(*element, Default);
01516 }
01517 
01518 inline const std::string
01519 GetPot::operator()(const char* VarName, const char* Default, unsigned Idx) const
01520 {
01521     // (*) recording of requested variables happens in '__find_variable()'
01522     const variable*  sv = __find_variable(VarName);
01523     if( sv == 0 ) return Default;
01524     const std::string* element = sv->get_element(Idx);
01525     if( element == 0 )  return Default;
01526     return *element;
01527 }
01528 
01529 inline void 
01530 GetPot::__record_argument_request(const std::string& Name)
01531 {
01532     if( ! __request_recording_f ) return; 
01533 
01534     // (*) record requested variable for later ufo detection
01535     _requested_arguments.push_back(Name);
01536 
01537     // (*) record considered section for ufo detection
01538     STRING_VECTOR      STree = __get_section_tree(Name);
01539     victorate(std::string, STree, it)
01540         if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() )
01541             if( section.length() != 0 ) _requested_sections.push_back(*it);
01542 }
01543 
01544 inline void 
01545 GetPot::__record_variable_request(const std::string& Name)
01546 {
01547     if( ! __request_recording_f ) return; 
01548 
01549     // (*) record requested variable for later ufo detection
01550     _requested_variables.push_back(Name);
01551 
01552     // (*) record considered section for ufo detection
01553     STRING_VECTOR      STree = __get_section_tree(Name);
01554     victorate(std::string, STree, it)
01555         if( find(_requested_sections.begin(), _requested_sections.end(), *it) == _requested_sections.end() )
01556             if( section.length() != 0 ) _requested_sections.push_back(*it);
01557 }
01558 
01559 // (*) following functions are to be used from 'outside', after getpot has parsed its
01560 //     arguments => append an argument in the argument vector that reflects the addition
01561 inline void
01562 GetPot::__set_variable(const char* VarName, const char* Value)
01563 {
01564     const GetPot::variable* Var = __find_variable(VarName);
01565     if( Var == 0 ) variables.push_back(variable(VarName, Value, _field_separator.c_str()));
01566     else           ((GetPot::variable*)Var)->take(Value, _field_separator.c_str());    
01567 }
01568 
01569 inline void
01570 GetPot::set(const char* VarName, const char* Value, const bool Requested /* = yes */)
01571 {     
01572     const std::string Arg = prefix + std::string(VarName) + std::string("=") + std::string(Value);
01573     argv.push_back(Arg);
01574     __set_variable(VarName, Value);
01575 
01576     // if user does not specify the variable as 'not being requested' it will be 
01577     // considered amongst the requested variables
01578     if( Requested ) __record_variable_request(Arg);
01579 }
01580 
01581 inline void
01582 GetPot::set(const char* VarName, const double& Value, const bool Requested /* = yes */)
01583 { __set_variable(VarName, __double2string(Value).c_str()); }
01584 
01585 inline void 
01586 GetPot::set(const char* VarName, const int Value, const bool Requested /* = yes */)
01587 { __set_variable(VarName, __int2string(Value).c_str()); }
01588 
01589 
01590 inline unsigned
01591 GetPot::vector_variable_size(const char* VarName) const
01592 {
01593     const variable*  sv = __find_variable(VarName);
01594     if( sv == 0 ) return 0;
01595     return static_cast<unsigned int>(sv->value.size());
01596 }
01597 
01598 inline STRING_VECTOR
01599 GetPot::get_variable_names() const
01600 {
01601     STRING_VECTOR  result;
01602     std::vector<GetPot::variable>::const_iterator it = variables.begin();
01603     for(; it != variables.end(); ++it) {
01604         const std::string Tmp = __get_remaining_string((*it).name, prefix);
01605         if( Tmp != "" ) result.push_back(Tmp);
01606     }
01607     return result;
01608 }
01609 
01610 inline STRING_VECTOR
01611 GetPot::get_section_names() const
01612 { return section_list; }
01613 
01614 inline const GetPot::variable*
01615 GetPot::__find_variable(const char* VarName) const
01616 {
01617     const std::string Name = prefix + VarName;
01618 
01619     // (*) record requested variable for later ufo detection
01620     ((GetPot*)this)->__record_variable_request(Name);
01621 
01622     std::vector<variable>::const_iterator it = variables.begin();
01623     for(; it != variables.end(); ++it) {
01624         if( (*it).name == Name ) return &(*it);
01625     }
01626     return 0;
01627 }
01628 
01630 // (*) ouput (basically for debugging reasons
01631 //.............................................................................
01632 //
01633 inline int
01634 GetPot::print() const
01635 {
01636     std::cout << "argc = " << static_cast<unsigned int>(argv.size()) << std::endl;
01637     STRING_VECTOR::const_iterator it = argv.begin();
01638     for(; it != argv.end(); ++it)
01639         std::cout << *it << std::endl;
01640     std::cout << std::endl;
01641     return 1;
01642 }
01643 
01644 // (*) dollar bracket expressions (DBEs) ------------------------------------
01645 //
01646 //     1) Entry Function: __DBE_expand_string()
01647 //        Takes a string such as
01648 //
01649 //          "${+ ${x} ${y}}   Subject-${& ${section} ${subsection}}:   ${title}"
01650 //
01651 //        calls __DBE_expand() for each of the expressions
01652 //
01653 //           ${+ ${x} ${y}}
01654 //           ${& ${section} ${subsection}}
01655 //           ${Title}
01656 //
01657 //        and returns the string
01658 //
01659 //          "4711 Subject-1.01:   Mit den Clowns kamen die Schwaene"
01660 //
01661 //        assuming that
01662 //            x          = "4699"
01663 //            y          = "12"
01664 //            section    = "1."
01665 //            subsection = "01"
01666 //            title      = "Mit den Clowns kamen die Schwaene"
01667 //
01668 //      2) __DBE_expand():
01669 //
01670 //           checks for the command, i.e. the 'sign' that follows '${'
01671 //           divides the argument list into sub-expressions using
01672 //           __DBE_get_expr_list()
01673 //
01674 //           ${+ ${x} ${y}}                 -> "${x}"  "${y}"
01675 //           ${& ${section} ${subsection}}  -> "${section}" "${subsection}"
01676 //           ${Title}                       -> Nothing, variable expansion
01677 //
01678 //      3) __DBE_expression_list():
01679 //
01680 //           builds a vector of unbracketed whitespace separated strings, i.e.
01681 //
01682 //           "  ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
01683 //
01684 //           is split into a vector
01685 //
01686 //              [0] ${Number}.a
01687 //              [1] ${: Das Marmorbild}
01688 //              [2] AB-${& Author= ${Eichendorf}}-1870
01689 //
01690 //           Each sub-expression is expanded using expand().
01691 //---------------------------------------------------------------------------
01692 inline std::string
01693 GetPot::__DBE_expand_string(const std::string str)
01694 {
01695     // Parses for closing operators '${ }' and expands them letting
01696     // white spaces and other letters as they are.
01697     std::string   new_string = "";
01698     unsigned open_brackets = 0;
01699     unsigned first = 0;
01700     unsigned i = 0;
01701     for(;  i<str.size(); ++i) {
01702         if( i < str.size() - 2 && str.substr(i, 2) == "${" ) {
01703             if( open_brackets == 0 ) first = i+2;
01704             open_brackets++;
01705         }
01706         else if( str[i] == '}' && open_brackets > 0) {
01707             open_brackets -= 1;
01708             if( open_brackets == 0 ) {
01709                 const std::string Replacement = __DBE_expand(str.substr(first, i - first));
01710                 new_string += Replacement;
01711             }
01712         }
01713         else if( open_brackets == 0 )
01714             new_string += str[i];
01715     }
01716     return new_string;
01717 }
01718 
01719 inline STRING_VECTOR
01720 GetPot::__DBE_get_expr_list(const std::string str_, const unsigned ExpectedNumber)
01721     // ensures that the resulting vector has the expected number
01722     // of arguments, but they may contain an error message
01723 {
01724     std::string str = str_;
01725     // Separates expressions by non-bracketed whitespaces, expands them
01726     // and puts them into a list.
01727 
01728     unsigned i=0;
01729     // (1) eat initial whitespaces
01730     for(; i < str.size(); ++i)
01731         if( ! isspace(str[i]) ) break;
01732 
01733     STRING_VECTOR   expr_list;
01734     unsigned         open_brackets = 0;
01735     std::vector<unsigned> start_idx;
01736     unsigned         start_new_string = i;
01737     unsigned         l = static_cast<unsigned int>(str.size());
01738 
01739     // (2) search for ${ } expressions ...
01740     while( i < l ) {
01741         const char letter = str[i];
01742         // whitespace -> end of expression
01743         if( isspace(letter) && open_brackets == 0) {
01744             expr_list.push_back(str.substr(start_new_string, i - start_new_string));
01745             bool no_breakout_f = true;
01746             for(++i; i < l ; ++i) {
01747                 if( ! isspace(str[i]) )
01748                 { no_breakout_f = false; start_new_string = i; break; }
01749             }
01750             if( no_breakout_f ) {
01751                 // end of expression list
01752                 if( expr_list.size() < ExpectedNumber ) {
01753                     const std::string   pre_tmp("<< ${ }: missing arguments>>");
01754                     STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
01755                     expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
01756                 }
01757                 return expr_list;
01758             }
01759         }
01760 
01761         // dollar-bracket expression
01762         if( str.length() >= i+2 && str.substr(i, 2) == "${" ) {
01763             open_brackets++;
01764             start_idx.push_back(i+2);
01765         }
01766         else if( letter == '}' && open_brackets > 0) {
01767             int start = start_idx[start_idx.size()-1];
01768             start_idx.pop_back();
01769             const std::string Replacement = __DBE_expand(str.substr(start, i-start));
01770             if( start - 3 < (int)0)
01771                 str = Replacement + str.substr(i+1);
01772             else
01773                 str = str.substr(0, start-2) + Replacement + str.substr(i+1);
01774             l = static_cast<unsigned int>(str.size());
01775             i = start + static_cast<unsigned int>(Replacement.size()) - 3;
01776             open_brackets--;
01777         }
01778         ++i;
01779     }
01780 
01781     // end of expression list
01782     expr_list.push_back(str.substr(start_new_string, i-start_new_string));
01783 
01784     if( expr_list.size() < ExpectedNumber ) {
01785         const std::string   pre_tmp("<< ${ }: missing arguments>>");
01786         STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
01787         expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
01788     }
01789 
01790     return expr_list;
01791 }
01792 
01793 inline const GetPot::variable*
01794 GetPot::__DBE_get_variable(std::string VarName)
01795 {
01796     static GetPot::variable ev;
01797     std::string secure_Prefix = prefix;
01798 
01799     prefix = section;
01800     // (1) first search in currently active section
01801     const GetPot::variable* var = __find_variable(VarName.c_str());
01802     if( var != 0 ) { prefix = secure_Prefix; return var; }
01803 
01804     // (2) search in root name space
01805     prefix = "";
01806     var = __find_variable(VarName.c_str());
01807     if( var != 0 ) { prefix = secure_Prefix; return var; }
01808 
01809     prefix = secure_Prefix;
01810 
01811     // error occured => variable name == ""
01812     char* tmp = new char[VarName.length() + 25];
01813 #ifndef WIN32
01814     snprintf(tmp, (int)sizeof(char)*(VarName.length() + 25), 
01815 #else
01816     _snprintf(tmp, sizeof(char)*(VarName.length() + 25), 
01817 #endif
01818              "<<${ } variable '%s' undefined>>", VarName.c_str());
01819     ev.name = "";
01820     ev.original = std::string(tmp);
01821     delete [] tmp;
01822     return &ev;
01823 }
01824 
01825 inline std::string
01826 GetPot::__DBE_expand(const std::string expr)
01827 {
01828     // ${: } pure text
01829     if( expr[0] == ':' )
01830         return expr.substr(1);
01831 
01832     // ${& expr expr ... } text concatination
01833     else if( expr[0] == '&' ) {
01834         const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 1);
01835 
01836         STRING_VECTOR::const_iterator it = A.begin();
01837         std::string result = *it++;
01838         for(; it != A.end(); ++it) result += *it;
01839 
01840         return result;
01841     }
01842 
01843     // ${<-> expr expr expr} text replacement
01844     else if( expr.length() >= 3 && expr.substr(0, 3) == "<->" ) {
01845         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(3), 3);
01846         std::string::size_type tmp = 0;
01847         const std::string::size_type L = A[1].length();
01848         while( (tmp = A[0].find(A[1])) != std::string::npos ) {
01849             A[0].replace(tmp, L, A[2]);
01850         }
01851         return A[0];
01852     }
01853     // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
01854     else if( expr[0] == '+' ) {
01855         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
01856         STRING_VECTOR::const_iterator it = A.begin();
01857         double result = __convert_to_type(*it++, 0.0);
01858         for(; it != A.end(); ++it)
01859             result += __convert_to_type(*it, 0.0);
01860 
01861         return __double2string(result);
01862     }
01863     else if( expr[0] == '-' ) {
01864         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
01865         STRING_VECTOR::const_iterator it = A.begin();
01866         double result = __convert_to_type(*it++, 0.0);
01867         for(; it != A.end(); ++it)
01868             result -= __convert_to_type(*it, 0.0);
01869 
01870         return __double2string(result);
01871     }
01872     else if( expr[0] == '*' ) {
01873         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
01874         STRING_VECTOR::const_iterator it = A.begin();
01875         double result = __convert_to_type(*it++, 0.0);
01876         for(; it != A.end(); ++it)
01877             result *= __convert_to_type(*it, 0.0);
01878 
01879         return __double2string(result);
01880     }
01881     else if( expr[0] == '/' ) {
01882 
01883         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
01884         STRING_VECTOR::const_iterator it = A.begin();
01885         double result = __convert_to_type(*it++, 0.0);
01886         if( result == 0 ) return "0.0";
01887         for(; it != A.end(); ++it) {
01888             const double Q = __convert_to_type(*it, 0.0);
01889             if( Q == 0.0 ) return "0.0";
01890             result /= Q;
01891         }
01892         return __double2string(result);
01893     }
01894 
01895     // ${^ ... } power expressions
01896     else if( expr[0] == '^' ) {
01897         STRING_VECTOR A = __DBE_get_expr_list(expr.substr(1), 2);
01898         STRING_VECTOR::const_iterator it = A.begin();
01899         double result = __convert_to_type(*it++, 0.0);
01900         for(; it != A.end(); ++it)
01901             result = pow(result, __convert_to_type(*it, 0.0));
01902         return __double2string(result);
01903     }
01904 
01905     // ${==  } ${<=  } ${>= } comparisons (return the number of the first 'match'
01906     else if( expr.length() >= 2 &&
01907              ( expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
01908                expr.substr(0,2) == "<=" || expr[0] == '>'           || expr[0] == '<')) {
01909         // differentiate between two and one sign operators
01910         unsigned op = 0;
01911         enum { EQ, GEQ, LEQ, GT, LT };
01912         if      ( expr.substr(0, 2) == "==" ) op = EQ;
01913         else if ( expr.substr(0, 2) == ">=" ) op = GEQ;
01914         else if ( expr.substr(0, 2) == "<=" ) op = LEQ;
01915         else if ( expr[0] == '>' )            op = GT;
01916         else    /*                     "<" */ op = LT;
01917 
01918         STRING_VECTOR a;
01919         if ( op == GT || op == LT ) a = __DBE_get_expr_list(expr.substr(1), 2);
01920         else                        a = __DBE_get_expr_list(expr.substr(2), 2);
01921 
01922         std::string   x_orig = a[0];
01923         double   x = __convert_to_type(x_orig, 1e37);
01924         unsigned i = 1;
01925 
01926         STRING_VECTOR::const_iterator y_orig = a.begin();
01927         for(y_orig++; y_orig != a.end(); y_orig++) {
01928             double y = __convert_to_type(*y_orig, 1e37);
01929 
01930             // set the strings as reference if one wasn't a number
01931             if ( x == 1e37 || y == 1e37 ) {
01932                 // it's a string comparison
01933                 if( (op == EQ  && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
01934                     (op == LEQ && x_orig <= *y_orig) || (op == GT  && x_orig >  *y_orig) ||
01935                     (op == LT  && x_orig <  *y_orig) )
01936                     return __int2string(i);
01937             }
01938             else {
01939                 // it's a number comparison
01940                 if( (op == EQ  && x == y) || (op == GEQ && x >= y) ||
01941                     (op == LEQ && x <= y) || (op == GT  && x >  y) ||
01942                     (op == LT  && x <  y) )
01943                     return __int2string(i);
01944             }
01945             ++i;
01946         }
01947 
01948         // nothing fulfills the condition => return 0
01949         return "0";
01950     }
01951     // ${?? expr expr} select
01952     else if( expr.length() >= 2 && expr.substr(0, 2) == "??" ) {
01953         STRING_VECTOR a = __DBE_get_expr_list(expr.substr(2), 2);
01954         double x = __convert_to_type(a[0], 1e37);
01955         // last element is always the default argument
01956         if( x == 1e37 || x < 0 || x >= a.size() - 1 ) return a[a.size()-1];
01957 
01958         // round x to closest integer
01959         return a[int(x+0.5)];
01960     }
01961     // ${? expr expr expr} if then else conditions
01962     else if( expr[0] == '?' ) {
01963         STRING_VECTOR a = __DBE_get_expr_list(expr.substr(1), 2);
01964         if( __convert_to_type(a[0], 0.0) == 1.0 ) return a[1];
01965         else if( a.size() > 2 ) return a[2];
01966     }
01967     // ${! expr} maxro expansion
01968     else if( expr[0] == '!' ) {
01969         const GetPot::variable* Var = __DBE_get_variable(expr.substr(1));
01970         // error
01971         if( Var->name == "" ) return std::string(Var->original);
01972 
01973         const STRING_VECTOR A = __DBE_get_expr_list(Var->original, 2);
01974         return A[0];
01975     }
01976     // ${@: } - string subscription
01977     else if( expr.length() >= 2 && expr.substr(0,2) == "@:" ) {
01978         const STRING_VECTOR A = __DBE_get_expr_list(expr.substr(2), 2);
01979         double x = __convert_to_type(A[1], 1e37);
01980 
01981         // last element is always the default argument
01982         if( x == 1e37 || x < 0 || x >= A[0].size() - 1)
01983             return "<<1st index out of range>>";
01984 
01985         if( A.size() > 2 ) {
01986             double y = __convert_to_type(A[2], 1e37);
01987             if ( y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x )
01988                 return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
01989             else if( y == -1 )
01990                 return A[0].substr(int(x+0.5));
01991             return "<<2nd index out of range>>";
01992         }
01993         else {
01994             char* tmp = new char[2];
01995             tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
01996             std::string result(tmp);
01997             delete [] tmp;
01998             return result;
01999         }
02000     }
02001     // ${@ } - vector subscription
02002     else if( expr[0] == '@' ) {
02003         STRING_VECTOR          A   = __DBE_get_expr_list(expr.substr(1), 2);
02004         const GetPot::variable* Var = __DBE_get_variable(A[0]);
02005         // error
02006         if( Var->name == "" ) {
02007             // make a copy of the string if an error occured
02008             // (since the error variable is a static variable inside get_variable())
02009             return std::string(Var->original);
02010         }
02011 
02012         double x = __convert_to_type(A[1], 1e37);
02013 
02014         // last element is always the default argument
02015         if (x == 1e37 || x < 0 || x >= Var->value.size() )
02016             return "<<1st index out of range>>";
02017 
02018         if ( A.size() > 2) {
02019             double y = __convert_to_type(A[2], 1e37);
02020             int    begin = int(x+0.5);
02021             int    end = 0;
02022             if ( y != 1e37 && y > 0 && y <= Var->value.size() && y > x)
02023                 end = int(y+1.5);
02024             else if( y == -1 )
02025                 end = static_cast<unsigned int>(Var->value.size());
02026             else
02027                 return "<<2nd index out of range>>";
02028 
02029             std::string result = *(Var->get_element(begin));
02030             int i = begin+1;
02031             for(; i < end; ++i)
02032                 result += std::string(" ") + *(Var->get_element(i));
02033             return result;
02034         }
02035         else
02036             return *(Var->get_element(int(x+0.5)));
02037     }
02038 
02039     const STRING_VECTOR    A = __DBE_get_expr_list(expr, 1);
02040     const GetPot::variable* B = __DBE_get_variable(A[0]);
02041 
02042     // make a copy of the string if an error occured
02043     // (since the error variable is a static variable inside get_variable())
02044     if( B->name == "" ) return std::string(B->original);
02045     // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces
02046     //  with:  else return B->original (thanks))
02047     return B->original;
02048 }
02049 
02050 
02052 // (*) unidentified flying objects
02053 //.............................................................................
02054 //
02055 inline bool
02056 GetPot::__search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
02057 {
02058     victorate(std::string, VecStr, itk) {
02059         if( *itk == Str ) return true;
02060     }
02061     return false;
02062 }
02063 
02064 inline STRING_VECTOR
02065 GetPot::unidentified_arguments(unsigned Number,
02066                                const char* KnownArgument1, ...) const
02067 {
02068     STRING_VECTOR known_arguments;
02069 
02070     // (1) create a vector of known arguments
02071     if( Number == 0 ) return STRING_VECTOR();
02072 
02073     va_list ap;
02074     va_start(ap, KnownArgument1);
02075     known_arguments.push_back(std::string(KnownArgument1));
02076     unsigned i=1;
02077     for(; i<Number; ++i)
02078         known_arguments.push_back(std::string(va_arg(ap, char *)));
02079     va_end(ap);
02080 
02081     return unidentified_arguments(known_arguments);
02082 }
02083 
02084 inline STRING_VECTOR
02085 GetPot::unidentified_arguments() const
02086 { return unidentified_arguments(_requested_arguments); }
02087 
02088 inline STRING_VECTOR
02089 GetPot::unidentified_arguments(const STRING_VECTOR& Knowns) const
02090 {
02091     STRING_VECTOR ufos;
02092     STRING_VECTOR::const_iterator it = argv.begin();
02093     ++it; // forget about argv[0] (application or filename)
02094     for(; it != argv.end(); ++it) {
02095         // -- argument belongs to prefixed section ?
02096         const std::string arg = __get_remaining_string(*it, prefix);
02097         if( arg == "" ) continue;
02098 
02099         // -- check if in list
02100         if( __search_string_vector(Knowns, arg) == false)
02101             ufos.push_back(*it);
02102     }
02103     return ufos;
02104 }
02105 
02106 inline STRING_VECTOR
02107 GetPot::unidentified_options(unsigned Number,
02108                              const char* KnownOption1, ...) const
02109 {
02110     STRING_VECTOR known_options;
02111 
02112     // (1) create a vector of known arguments
02113     if( Number == 0 ) return STRING_VECTOR();
02114 
02115     va_list ap;
02116     va_start(ap, KnownOption1);
02117     known_options.push_back(std::string(KnownOption1));
02118     unsigned i=1;
02119     for(; i<Number; ++i)
02120         known_options.push_back(std::string(va_arg(ap, char *)));
02121     va_end(ap);
02122 
02123     return unidentified_options(known_options);
02124 }
02125 
02126 inline STRING_VECTOR
02127 GetPot::unidentified_options() const
02128 { 
02129     // -- every option is an argument. 
02130     // -- the set of requested arguments contains the set of requested options. 
02131     // -- IF the set of requested arguments contains unrequested options, 
02132     //    THEN they were requested as 'follow' and 'next' arguments and not as real options.
02133     //
02134     // => it is not necessary to separate requested options from the list
02135     STRING_VECTOR option_list;
02136     victorate(std::string, _requested_arguments, it) {
02137         const std::string arg = *it;
02138         if( arg.length() == 0 ) continue;
02139         if( arg[0] == '-' )     option_list.push_back(arg);
02140     }   
02141     return unidentified_options(option_list); 
02142 }
02143 
02144 inline STRING_VECTOR
02145 GetPot::unidentified_options(const STRING_VECTOR& Knowns) const
02146 {
02147     STRING_VECTOR ufos;
02148     STRING_VECTOR::const_iterator it = argv.begin();
02149     ++it; // forget about argv[0] (application or filename)
02150     for(; it != argv.end(); ++it) {
02151         // -- argument belongs to prefixed section ?
02152         const std::string arg = __get_remaining_string(*it, prefix);
02153         if( arg == "" ) continue;
02154 
02155         // is argument really an option (starting with '-') ?
02156         if( arg.length() < 1 || arg[0] != '-' ) continue;
02157 
02158         if( __search_string_vector(Knowns, arg) == false)
02159             ufos.push_back(*it);
02160     }
02161 
02162     return ufos;
02163 }
02164 
02165 inline std::string
02166 GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
02167     // Two modes:
02168     //  ArgumentNumber >= 0 check specific argument
02169     //  ArgumentNumber == -1 check all options starting with one '-'
02170     //                       for flags
02171 {
02172     std::string         ufos;
02173     STRING_VECTOR known_arguments;
02174     std::string         KFL(KnownFlagList);
02175 
02176     // (2) iteration over '-' arguments (options)
02177     if( ArgumentNumber == -1 ) {
02178         STRING_VECTOR::const_iterator it = argv.begin();
02179         ++it; // forget about argv[0] (application or filename)
02180         for(; it != argv.end(); ++it) {
02181             // -- argument belongs to prefixed section ?
02182             const std::string arg = __get_remaining_string(*it, prefix);
02183             if( arg == "" ) continue;
02184 
02185             // -- does arguments start with '-' (but not '--')
02186             if     ( arg.length() < 2 ) continue;
02187             else if( arg[0] != '-' )    continue;
02188             else if( arg[1] == '-' )    continue;
02189 
02190             // -- check out if flags inside option are contained in KnownFlagList
02191             const char* p=arg.c_str();
02192             p++; // skip starting minus
02193             for(; *p != '\0' ; p++)
02194                 if( KFL.find(*p) == std::string::npos ) ufos += *p;
02195         }
02196     }
02197     // (1) check specific argument
02198     else {
02199         // -- only check arguments that start with prefix
02200         int no_matches = 0;
02201         unsigned i=1;
02202         for(; i<argv.size(); ++i) {
02203             const std::string Remain = __get_remaining_string(argv[i], prefix);
02204             if( Remain != "") {
02205                 no_matches++;
02206                 if( no_matches == ArgumentNumber) {
02207                     // -- the right argument number inside the section is found
02208                     // => check it for flags
02209                     const char* p = Remain.c_str();
02210                     p++; // skip starting minus
02211                     for(; *p != '\0' ; p++)
02212                         if( KFL.find(*p) == std::string::npos ) ufos += *p;
02213                     return ufos;
02214                 }
02215             }
02216         }
02217     }
02218     return ufos;
02219 }
02220 
02221 inline STRING_VECTOR
02222 GetPot::unidentified_variables(unsigned Number,
02223                                const char* KnownVariable1, ...) const
02224 {
02225     STRING_VECTOR known_variables;
02226 
02227     // create vector of known arguments
02228     if( Number == 0 ) return STRING_VECTOR();
02229 
02230     va_list ap;
02231     va_start(ap, KnownVariable1);
02232     known_variables.push_back(std::string(KnownVariable1));
02233     unsigned i=1;
02234     for(; i<Number; ++i)
02235         known_variables.push_back(std::string(va_arg(ap, char *)));
02236     va_end(ap);
02237 
02238     return unidentified_variables(known_variables);
02239 }
02240 
02241 inline STRING_VECTOR
02242 GetPot::unidentified_variables(const STRING_VECTOR& Knowns) const
02243 {
02244     STRING_VECTOR ufos;
02245 
02246     victorate(GetPot::variable, variables, it) {
02247         // -- check if variable has specific prefix
02248         const std::string var_name = __get_remaining_string((*it).name, prefix);
02249         if( var_name == "" ) continue;
02250 
02251         // -- check if variable is known
02252         if( __search_string_vector(Knowns, var_name) == false)
02253             ufos.push_back((*it).name);
02254     }
02255     return ufos;
02256 }
02257 
02258 inline STRING_VECTOR
02259 GetPot::unidentified_variables() const
02260 {  return unidentified_variables(_requested_variables); }
02261 
02262 
02263 inline STRING_VECTOR
02264 GetPot::unidentified_sections(unsigned Number,
02265                               const char* KnownSection1, ...) const
02266 {
02267     STRING_VECTOR known_sections;
02268 
02269     // (1) create a vector of known arguments
02270     if( Number == 0 ) return STRING_VECTOR();
02271 
02272     va_list ap;
02273     va_start(ap, KnownSection1);
02274     known_sections.push_back(std::string(KnownSection1));
02275     unsigned i=1;
02276     for(; i<Number; ++i) {
02277         std::string tmp = std::string(va_arg(ap, char *));
02278         if( tmp.length() == 0 ) continue;
02279         if( tmp[tmp.length()-1] != '/' ) tmp += '/';
02280         known_sections.push_back(tmp);
02281     }
02282     va_end(ap);
02283 
02284     return unidentified_sections(known_sections);
02285 }
02286 
02287 inline STRING_VECTOR
02288 GetPot::unidentified_sections() const
02289 { return unidentified_sections(_requested_sections); }
02290 
02291 inline STRING_VECTOR
02292 GetPot::unidentified_sections(const STRING_VECTOR& Knowns) const
02293 {
02294     STRING_VECTOR ufos;
02295 
02296     victorate(std::string, section_list, it) {
02297         // -- check if section conform to prefix
02298         const std::string sec_name = __get_remaining_string(*it, prefix);
02299         if( sec_name == "" ) continue;
02300 
02301         // -- check if section is known
02302         if( __search_string_vector(Knowns, sec_name) == false )
02303             ufos.push_back(*it);
02304     }
02305 
02306     return ufos;
02307 }
02308 
02309 
02310 inline STRING_VECTOR
02311 GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
02312 {
02313     STRING_VECTOR known_nominuses;
02314 
02315     // create vector of known arguments
02316     if( Number == 0 ) return STRING_VECTOR();
02317 
02318     va_list ap;
02319     va_start(ap, Known);
02320     known_nominuses.push_back(std::string(Known));
02321     unsigned i=1;
02322     for(; i<Number; ++i) {
02323         std::string tmp = std::string(va_arg(ap, char *));
02324         if( tmp.length() == 0 ) continue;
02325         known_nominuses.push_back(tmp);
02326     }
02327     va_end(ap);
02328 
02329     return unidentified_nominuses(known_nominuses);
02330 }
02331 
02332 inline STRING_VECTOR
02333 GetPot::unidentified_nominuses() const {
02334     // -- every nominus is an argument. 
02335     // -- the set of requested arguments contains the set of requested nominuss. 
02336     // -- IF the set of requested arguments contains unrequested nominuss, 
02337     //    THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
02338     //
02339     // => it is not necessary to separate requested nominus from the list
02340 
02341     return unidentified_nominuses(_requested_arguments);
02342 }
02343 
02344 inline STRING_VECTOR
02345 GetPot::unidentified_nominuses(const STRING_VECTOR& Knowns) const
02346 {
02347     STRING_VECTOR ufos;
02348 
02349     // (2) iterate over all arguments
02350     STRING_VECTOR::const_iterator it = argv.begin();
02351     ++it; // forget about argv[0] (application or filename)
02352     for(; it != argv.end(); ++it) {
02353         // -- check if nominus part of prefix
02354         const std::string arg = __get_remaining_string(*it, prefix);
02355         if( arg == "" )                                         continue;
02356 
02357         if( arg.length() < 1 )                                  continue;
02358         // option ? --> not a nomius
02359         if( arg[0] == '-' )                                     continue;
02360         // section ? --> not a real nominus
02361         if( arg[0] == '[' && arg[arg.length()-1] == ']' )       continue;
02362         // variable definition ? --> not a real nominus
02363         bool continue_f = false;
02364         unsigned i=0;
02365         for(; i<arg.length() ; ++i)
02366             if( arg[i] == '=' ) { continue_f = true; break; }
02367         if( continue_f )                                        continue;
02368 
02369         // real nominuses are compared with the given list
02370         if( __search_string_vector(Knowns, arg) == false )
02371             ufos.push_back(*it);
02372     }
02373     return ufos;
02374 }
02375 
02376 
02378 // (*) variable class
02379 //.............................................................................
02380 //
02381 inline
02382 GetPot::variable::variable()
02383 {}
02384 
02385 inline
02386 GetPot::variable::variable(const variable& That)
02387 {
02388 #ifdef WIN32
02389     operator=(That);
02390 #else
02391     GetPot::variable::operator=(That);
02392 #endif
02393 }
02394 
02395 
02396 inline
02397 GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
02398     : name(Name)
02399 {
02400     // make a copy of the 'Value'
02401     take(Value, FieldSeparator);
02402 }
02403 
02404 inline const std::string*
02405 GetPot::variable::get_element(unsigned Idx) const
02406 { if( Idx >= value.size() ) return 0; else return &(value[Idx]); }
02407 
02408 inline void
02409 GetPot::variable::take(const char* Value, const char* FieldSeparator)
02410 {
02411     using namespace std;
02412 
02413     original = std::string(Value);
02414 
02415     // separate string by white space delimiters using 'strtok'
02416     // thread safe usage of strtok (no static members)
02417     char* spt = 0;
02418     // make a copy of the 'Value'
02419     char* copy = new char[strlen(Value)+1];
02420     strcpy(copy, Value);
02421     char* follow_token = strtok_r(copy, FieldSeparator, &spt);
02422     if( value.size() != 0 ) value.erase(value.begin(), value.end());
02423     while(follow_token != 0) {
02424         value.push_back(std::string(follow_token));
02425         follow_token = strtok_r(NULL, FieldSeparator, &spt);
02426     }
02427 
02428     delete [] copy;
02429 }
02430 
02431 inline
02432 GetPot::variable::~variable()
02433 {}
02434 
02435 inline GetPot::variable&
02436 GetPot::variable::operator=(const GetPot::variable& That)
02437 {
02438     if( &That != this) {
02439         name     = That.name;
02440         value    = That.value;
02441         original = That.original;
02442     }
02443     return *this;
02444 }
02445 
02446 #undef victorate
02447 
02448 
02449 #endif // __include_guard_GETPOT_H__
02450 
02451 
02452 
02453 
All Classes Files Functions Variables Typedefs Friends Defines