$extrastylesheet
getpot.h
Go to the documentation of this file.
00001 //  -*- c++ -*-
00002 //  GetPot Version libMeshHPCT_fork-1.2                        Apr/14/2010
00003 //  Based on "getpot-1.1.1.tgz" version from SourceForge
00004 //
00005 //  New code (C) 2009-2013 Roy Stogner, Karl Schulz
00006 //
00007 //  GetPot Version 1.0                                        Sept/13/2002
00008 //
00009 //  WEBSITE: http://getpot.sourceforge.net
00010 //
00011 //  This library is  free software; you can redistribute  it and/or modify
00012 //  it  under  the terms  of  the GNU  Lesser  General  Public License  as
00013 //  published by the  Free Software Foundation; either version  2.1 of the
00014 //  License, or (at your option) any later version.
00015 //
00016 //  This library  is distributed in the  hope that it will  be useful, but
00017 //  WITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of
00018 //  MERCHANTABILITY  or FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
00019 //  Lesser General Public License for more details.
00020 //
00021 //  You  should have  received a  copy of  the GNU  Lesser  General Public
00022 //  License along  with this library; if  not, write to  the Free Software
00023 //  Foundation, Inc.,  59 Temple Place,  Suite 330, Boston,  MA 02111-1307
00024 //  USA
00025 //
00026 //  (C) 2001-2002 Frank R. Schaefer
00027 //==========================================================================
00028 #ifndef LIBMESH_GETPOT_H
00029 #define LIBMESH_GETPOT_H
00030 
00031 #if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC)
00032 #define strtok_r(a, b, c) strtok(a, b)
00033 #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
00034 
00035 #include <algorithm>
00036 #include <cstddef>
00037 #include <fstream>
00038 #include <iostream> // not every compiler distribution includes <iostream> with <fstream>
00039 #include <set>
00040 #include <sstream>
00041 #include <stdexcept>
00042 #include <string>
00043 #include <typeinfo>
00044 #include <vector>
00045 
00046 #include <cmath>
00047 #include <cstdlib>
00048 #include <ctime>
00049 
00050 extern "C" {
00051 #include <stdarg.h> // --> va_list and friends
00052 #include <string.h> // --> strcmp, strncmp, strlen, strncpy
00053 }
00054 
00055 // Undefine USE_LIBMESH to avoid libMesh-specific code
00056 
00057 #define USE_LIBMESH 1
00058 
00059 #ifdef USE_LIBMESH
00060 
00061 #include "libmesh/libmesh_common.h"
00062 
00063 // We need a mutex to keep const operations thread-safe in the
00064 // presence of mutable containers.  Right now GetPot supports a
00065 // Threads::scoped_mutex wrapper around TBB, and we're assuming that
00066 // users aren't doing any threaded GetPot usage when TBB threads are
00067 // disabled.
00068 #if !defined(GETPOT_DISABLE_MUTEX)
00069 #include "libmesh/threads.h"
00070 #define SCOPED_MUTEX  libMesh::Threads::spin_mutex::scoped_lock lock(_getpot_mtx)
00071 #else
00072 #define SCOPED_MUTEX
00073 #endif
00074 
00075 #define getpot_cerr libMesh::err
00076 #define getpot_error() libmesh_error()
00077 #define getpot_file_error(filename) libmesh_file_error(filename)
00078 #define getpot_cast_int libMesh::cast_int
00079 
00080 #else // USE_LIBMESH
00081 
00082 // Currently threaded GetPot use is only supported via libMesh Threads
00083 #define SCOPED_MUTEX
00084 
00085 #define getpot_cerr std::cerr
00086 #define getpot_error() throw std::runtime_error(std::string("GetPot Error"))
00087 #define getpot_file_error(filename) getpot_error()
00088 #define getpot_cast_int static_cast
00089 
00090 #endif
00091 
00092 // Clang provides the __has_builtin macro, we define it for compilers
00093 // that don't...
00094 #ifndef __has_builtin
00095 #define __has_builtin(x) 0
00096 #endif
00097 
00098 // Fine-grained ifdefs for all three inverse hyperbolic trig
00099 // functions.  This works for the two clang compilers I tried it
00100 // on... a hand-built one and one from Apple.
00101 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(asinh))
00102 #define HAVE_INVERSE_HYPERBOLIC_SINE
00103 #endif
00104 
00105 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(acosh))
00106 #define HAVE_INVERSE_HYPERBOLIC_COSINE
00107 #endif
00108 
00109 #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(atanh))
00110 #define HAVE_INVERSE_HYPERBOLIC_TANGENT
00111 #endif
00112 
00113 typedef  std::vector<std::string>  STRING_VECTOR;
00114 
00115 #define victorate(TYPE, VARIABLE, ITERATOR)                             \
00116   std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin();      \
00117   for (; (ITERATOR) != (VARIABLE).end(); ++(ITERATOR))
00118 
00119 // We allow GETPOT_NAMESPACE to be defined before this file is
00120 // included; if libraries using two different versions of GetPot might
00121 // be linked together, the result may be unsafe unless they're put in
00122 // different namespaces.
00123 #ifdef GETPOT_NAMESPACE
00124 namespace GETPOT_NAMESPACE {
00125 #endif
00126 
00133 class GetPot
00134 {
00135   inline void _basic_initialization();
00136 
00137 public:
00141   inline GetPot();
00142   inline GetPot(const GetPot&);
00143   inline GetPot(const int argc_, const char* const* argv_,
00144                 const char* FieldSeparator=0x0);
00145   inline GetPot(const char* FileName,
00146                 const char* CommentStart=0x0, const char* CommentEnd=0x0,
00147                 const char* FieldSeparator=0x0);
00148   inline GetPot(const std::string& FileName,
00149                 const std::string& CommentStart   = std::string("#"),
00150                 const std::string& CommentEnd     = std::string("\n"),
00151                 const std::string& FieldSeparator = std::string(" \t\n"));
00152   inline ~GetPot();
00153   inline GetPot& operator=(const GetPot&);
00154 
00158   inline void parse_command_line(const int argc_, const char * const* argv_,
00159                                  const char* FieldSeparator =0x0);
00160   inline void parse_input_file(const std::string& FileName,
00161                                const std::string& CommentStart=std::string("#"),
00162                                const std::string& CommentEnd=std::string("\n"),
00163                                const std::string& FieldSeparator=std::string(" \t\n"));
00164 
00168   inline void absorb(const GetPot& Other);
00169 
00173   inline void clear_requests();
00174   inline void disable_request_recording() { request_recording_f = false; }
00175   inline void enable_request_recording() { request_recording_f = true; }
00176 
00180   inline const char* operator[](unsigned Idx) const;
00181 
00182   template <typename T>
00183   inline T get(unsigned Idx, const T& Default) const;
00184 
00185   inline const char* get(unsigned Idx, const char* Default) const;
00186   inline unsigned size() const;
00187 
00191   inline bool options_contain(const char* FlagList) const;
00192   inline bool argument_contains(unsigned Idx, const char* FlagList) const;
00193 
00201   inline bool have_variable(const char* VarName) const;
00202   inline bool have_variable(const std::string& VarName) const;
00203 
00213   bool have_section(const char* section_name) const;
00214 
00224   bool have_section(const std::string& section_name) const;
00225 
00229   template<typename T>
00230   inline T operator()(const char* VarName, const T& Default) const;
00231 
00232   template<typename T>
00233   inline T operator()(const std::string& VarName, const T& Default) const;
00234 
00235   inline const char* operator()(const char* VarName, const char* Default) const;
00236   inline const char* operator()(const std::string& VarName, const char* Default) const;
00237 
00241   template<typename T>
00242   inline T operator()(const char* VarName, const T& Default, unsigned Idx) const;
00243 
00244   template<typename T>
00245   inline T operator()(const std::string& VarName, const T& Default, unsigned Idx) const;
00246 
00247   inline const char* operator()(const char* VarName, const char* Default, unsigned Idx) const;
00248   inline const char* operator()(const std::string& VarName, const char* Default, unsigned Idx) const;
00249 
00254   template<typename T>
00255   inline T get_value_no_default(const char* VarName, const T& Default) const;
00256 
00257   template<typename T>
00258   inline T get_value_no_default(const std::string& VarName, const T& Default) const;
00259 
00260   inline const char* get_value_no_default(const char* VarName, const char* Default) const;
00261   inline const char* get_value_no_default(const std::string& VarName, const char* Default) const;
00262 
00266   template<typename T>
00267   inline T get_value_no_default(const char* VarName, const T& Default, unsigned Idx) const;
00268 
00269   template<typename T>
00270   inline T get_value_no_default(const std::string& VarName, const T& Default, unsigned Idx) const;
00271 
00272   inline const char* get_value_no_default(const char* VarName, const char* Default, unsigned Idx) const;
00273   inline const char* get_value_no_default(const std::string& VarName, const char* Default, unsigned Idx) const;
00274 
00280   template<typename T>
00281   inline void set(const char* VarName, const T& Value, const bool Requested = true);
00282 
00283   template<typename T>
00284   inline void set(const std::string& VarName, const T& Value, const bool Requested = true);
00285 
00286   inline void set(const char* VarName, const char* Value, const bool Requested = true);
00287   inline void set(const std::string& VarName, const char* Value, const bool Requested = true);
00288 
00289   inline unsigned vector_variable_size(const char* VarName) const;
00290   inline unsigned vector_variable_size(const std::string& VarName) const;
00291   inline STRING_VECTOR get_variable_names() const;
00292   inline STRING_VECTOR get_section_names() const;
00293   inline std::set<std::string> get_overridden_variables() const;
00294 
00298   inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
00299   inline bool search_failed() const { return search_failed_f; }
00300 
00304   inline void disable_loop() { search_loop_f = false; }
00305   inline void enable_loop()  { search_loop_f = true; }
00306 
00310   inline void reset_cursor();
00311   inline void init_multiple_occurrence();
00312 
00316   inline bool search(const char* option);
00317   inline bool search(const std::string& option);
00318   inline bool search(unsigned No, const char* P, ...);
00319 
00323   template<typename T>
00324   inline T next(const T& Default);
00325 
00326   inline const char* next(const char* Default);
00327 
00331   template<typename T>
00332   inline T follow(const T& Default, const char* Option);
00333 
00334   inline const char* follow(const char* Default, const char* Option);
00335 
00339   template<typename T>
00340   inline T follow(const T& Default, unsigned No, const char* Option, ...);
00341 
00342   inline const char* follow(const char* Default, unsigned No, const char* Option, ...);
00343 
00347   template<typename T>
00348   inline T direct_follow(const T& Default, const char* Option);
00349 
00350   inline const char* direct_follow(const char* Default, const char* Option);
00351 
00355   inline void reset_nominus_cursor();
00356   inline STRING_VECTOR nominus_vector() const;
00357   inline unsigned nominus_size() const { return getpot_cast_int<unsigned>(idx_nominus.size()); }
00358   inline const char* next_nominus();
00359   inline std::string next_nominus_string();
00360 
00364   inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const;
00365   inline STRING_VECTOR unidentified_arguments(const std::set<std::string>& Knowns) const;
00366   inline STRING_VECTOR unidentified_arguments(const std::vector<std::string>& Knowns) const;
00367   inline STRING_VECTOR unidentified_arguments() const;
00368 
00369   inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const;
00370   inline STRING_VECTOR unidentified_options(const std::set<std::string>& Knowns) const;
00371   inline STRING_VECTOR unidentified_options(const std::vector<std::string>& Knowns) const;
00372   inline STRING_VECTOR unidentified_options() const;
00373 
00374   inline std::string unidentified_flags(const char* Known, int ArgumentNumber /* =-1 */) const;
00375 
00376   inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const;
00377   inline STRING_VECTOR unidentified_variables(const std::set<std::string>& Knowns) const;
00378   inline STRING_VECTOR unidentified_variables(const std::vector<std::string>& Knowns) const;
00379   inline STRING_VECTOR unidentified_variables() const;
00380 
00381   inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const;
00382   inline STRING_VECTOR unidentified_sections(const std::set<std::string>& Knowns) const;
00383   inline STRING_VECTOR unidentified_sections(const std::vector<std::string>& Knowns) const;
00384   inline STRING_VECTOR unidentified_sections() const;
00385 
00386   inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const;
00387   inline STRING_VECTOR unidentified_nominuses(const std::set<std::string>& Knowns) const;
00388   inline STRING_VECTOR unidentified_nominuses(const std::vector<std::string>& Knowns) const;
00389   inline STRING_VECTOR unidentified_nominuses() const;
00390 
00398   inline int print(std::ostream &out_stream = std::cout) const;
00399 
00405   inline int print(const char *custom_prefix,
00406                    std::ostream &out_stream = std::cout,
00407                    unsigned int skip_count=1) const;
00408 
00409 private:
00410 
00415   struct variable
00416   {
00420     variable();
00421     variable(const variable&);
00422     variable(const char* Name, const char* Value, const char* FieldSeparator);
00423     ~variable();
00424     variable& operator=(const variable& Other);
00425 
00426     void take(const char* Value, const char* FieldSeparator);
00427 
00432     const std::string* get_element(unsigned Idx) const;
00433 
00437     std::string name;      // identifier of variable
00438     STRING_VECTOR value;     // value of variable stored in vector
00439     std::string original;  // value of variable as given on command line
00440   };
00441 
00445   std::string prefix;          // prefix automatically added in queries
00446   std::string section;         // (for dollar bracket parsing)
00447   STRING_VECTOR section_list;    // list of all parsed sections
00448 
00452   STRING_VECTOR argv; // vector of command line arguments stored as strings
00453   unsigned cursor; // cursor for argv
00454   bool search_loop_f; // shall search start at beginning after reaching end of arg array ?
00455   bool search_failed_f; // flag indicating a failed search() operation (e.g. next() functions react with 'missed')
00456   std::set<std::string> overridden_vars; // vector of variables that were supplied more than once during parsing
00457 
00461   int nominus_cursor;  // cursor for nominus_pointers
00462   std::vector<unsigned> idx_nominus;     // indecies of 'no minus' arguments
00463 
00467   std::vector<variable> variables;
00468 
00472   std::string _comment_start;
00473   std::string _comment_end;
00474 
00478   std::string _field_separator;
00479 
00483   struct ltstr
00484   {
00485     bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
00486   };
00487 
00494 #if !defined(GETPOT_DISABLE_MUTEX)
00495   mutable libMesh::Threads::spin_mutex _getpot_mtx;
00496 #endif
00497 
00506   mutable std::set<const char*, ltstr> _internal_string_container;
00507 
00512   const char* _internal_managed_copy(const std::string& Arg) const;
00513 
00518   mutable std::set<std::string> _requested_arguments;
00519   mutable std::set<std::string> _requested_variables;
00520   mutable std::set<std::string> _requested_sections;
00521 
00522   bool request_recording_f;   // speed: request recording can be turned off
00523 
00530   void _record_argument_request(const std::string& Arg) const;
00531   void _record_variable_request(const std::string& Arg) const;
00532 
00540   inline void _set_variable(const std::string& VarName,
00541                             const std::string& Value,
00542                             const bool Requested);
00543 
00550   inline void _parse_argument_vector(const STRING_VECTOR& ARGV);
00551 
00559   inline const variable* _find_variable(const char*) const;
00560 
00564   inline const variable* _request_variable(const char*) const;
00565 
00569   inline const char* _match_starting_string(const char* StartString);
00570 
00574   inline bool _check_flags(const std::string& Str, const char* FlagList) const;
00575 
00579   template<typename T>
00580   inline T _convert_to_type(const std::string& String, const T& Default) const;
00581 
00582   inline std::string _convert_to_type(const std::string& String, const char* Default) const;
00583 
00584   template<typename T>
00585   inline T _convert_to_type_no_default(const char* VarName, const std::string& String, const T& Default) const;
00586 
00587   inline std::string _convert_to_type_no_default(const char* VarName, const std::string& String, const char* Default) const;
00588 
00592   const std::string _get_remaining_string(const std::string& String,
00593                                           const std::string& Start) const;
00597   inline bool _search_string_vector(const STRING_VECTOR& Vec,
00598                                     const std::string& Str) const;
00599 
00610   inline void _skip_whitespace(std::istream& istr);
00611   inline const std::string _get_next_token(std::istream& istr);
00612   inline const std::string _get_string(std::istream& istr);
00613   inline const std::string _get_until_closing_bracket(std::istream& istr);
00614   inline const std::string _get_until_closing_square_bracket(std::istream& istr);
00615 
00616   inline STRING_VECTOR _read_in_stream(std::istream& istr);
00617   inline STRING_VECTOR _read_in_file(const std::string& FileName);
00618   inline std::string _process_section_label(const std::string& Section,
00619                                             STRING_VECTOR& section_stack);
00620 
00624   std::string _DBE_expand_string(const std::string& str);
00625   std::string _DBE_expand(const std::string& str);
00626   const GetPot::variable* _DBE_get_variable(const std::string& str);
00627   STRING_VECTOR _DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber);
00628 
00629   template <typename T>
00630   static std::string _convert_from_type(const T& Value)
00631   {
00632     std::ostringstream out_string;
00633     out_string << Value;
00634     return out_string.str();
00635   }
00636 
00641   static STRING_VECTOR _get_section_tree(const std::string& FullPath)
00642   {
00643     STRING_VECTOR   result;
00644     for (std::size_t pos = 0; pos != FullPath.size(); ++pos)
00645       {
00646         if (FullPath[pos] == '/')
00647           result.push_back(FullPath.substr(0,pos));
00648       }
00649 
00650     return result;
00651   }
00652 };
00653 
00654 
00656 // (*) constructors, destructor, assignment operator
00657 //.............................................................................
00658 //
00659 inline void
00660 GetPot::_basic_initialization()
00661 {
00662   cursor = 0;
00663   nominus_cursor = -1;
00664   search_failed_f = true;
00665   search_loop_f = true;
00666   prefix = "";
00667   section = "";
00668 
00669   // automatic request recording for later ufo detection
00670   request_recording_f = true;
00671 
00672   // comment start and end strings
00673   _comment_start = std::string("#");
00674   _comment_end   = std::string("\n");
00675 
00676   // default: separate vector elements by whitespaces
00677   _field_separator = " \t\n";
00678 }
00679 
00680 
00681 
00682 inline
00683 GetPot::GetPot() :
00684   prefix(),
00685   section(),
00686   section_list(),
00687   argv(),
00688   cursor(),
00689   search_loop_f(),
00690   search_failed_f(),
00691   nominus_cursor(),
00692   idx_nominus(),
00693   variables(),
00694   _comment_start(),
00695   _comment_end(),
00696   _field_separator(),
00697 #if !defined(GETPOT_DISABLE_MUTEX)
00698   _getpot_mtx(),
00699 #endif
00700   _internal_string_container(),
00701   _requested_arguments(),
00702   _requested_variables(),
00703   _requested_sections(),
00704   request_recording_f()
00705 {
00706   _basic_initialization();
00707 }
00708 
00709 
00710 
00711 inline
00712 GetPot::GetPot(const int argc_, const char * const * argv_,
00713                const char* FieldSeparator /* =0x0 */) :
00714   // leave 'char**' non-const to honor less capable compilers ...
00715   prefix(),
00716   section(),
00717   section_list(),
00718   argv(),
00719   cursor(),
00720   search_loop_f(),
00721   search_failed_f(),
00722   nominus_cursor(),
00723   idx_nominus(),
00724   variables(),
00725   _comment_start(),
00726   _comment_end(),
00727   _field_separator(),
00728 #if !defined(GETPOT_DISABLE_MUTEX)
00729   _getpot_mtx(),
00730 #endif
00731   _internal_string_container(),
00732   _requested_arguments(),
00733   _requested_variables(),
00734   _requested_sections(),
00735   request_recording_f()
00736 {
00737   this->parse_command_line(argc_, argv_, FieldSeparator);
00738 }
00739 
00740 
00741 
00742 // leave 'char**' non-const to honor less capable compilers ...
00743 inline void
00744 GetPot::parse_command_line(const int argc_, const char * const * argv_,
00745                            const char* FieldSeparator /* =0x0 */)
00746 {
00747   _basic_initialization();
00748 
00749   // if specified -> overwrite default string
00750   if (FieldSeparator)
00751     _field_separator = std::string(FieldSeparator);
00752 
00753   // -- make an internal copy of the argument list:
00754   STRING_VECTOR _apriori_argv;
00755   // -- for the sake of clarity: we do want to include the first
00756   //    argument of the first parsing source in the argument vector!
00757   //    it will not be a nominus argument, though. This gives us a
00758   //    minimum vector size of one which facilitates error checking
00759   //    in many functions. Also the user will be able to retrieve
00760   //    the name of his application or input file by "get[0]"
00761   _apriori_argv.push_back(std::string(argv_[0]));
00762   for (int i=1; i<argc_; i++)
00763     {
00764       std::string tmp(argv_[i]);   // recall the problem with temporaries,
00765       _apriori_argv.push_back(tmp);       // reference counting in arguement lists ...
00766     }
00767   _parse_argument_vector(_apriori_argv);
00768 }
00769 
00770 
00771 
00772 inline
00773 GetPot::GetPot(const char* FileName,
00774                const char* CommentStart  /* = 0x0 */, const char* CommentEnd /* = 0x0 */,
00775                const char* FieldSeparator/* = 0x0 */) :
00776   prefix(),
00777   section(),
00778   section_list(),
00779   argv(),
00780   cursor(),
00781   search_loop_f(),
00782   search_failed_f(),
00783   nominus_cursor(),
00784   idx_nominus(),
00785   variables(),
00786   _comment_start(),
00787   _comment_end(),
00788   _field_separator(),
00789 #if !defined(GETPOT_DISABLE_MUTEX)
00790   _getpot_mtx(),
00791 #endif
00792   _internal_string_container(),
00793   _requested_arguments(),
00794   _requested_variables(),
00795   _requested_sections(),
00796   request_recording_f()
00797 {
00798   const std::string& StrCommentStart   = CommentStart   ? CommentStart   : std::string("#");
00799   const std::string& StrCommentEnd     = CommentEnd     ? CommentEnd     : std::string("\n");
00800   const std::string& StrFieldSeparator = FieldSeparator ? FieldSeparator : std::string(" \t\n");
00801   this->parse_input_file(FileName, StrCommentStart, StrCommentEnd, StrFieldSeparator);
00802 }
00803 
00804 
00805 
00806 inline
00807 GetPot::GetPot(const std::string& FileName,
00808                const std::string& CommentStart,
00809                const std::string& CommentEnd,
00810                const std::string& FieldSeparator) :
00811   prefix(),
00812   section(),
00813   section_list(),
00814   argv(),
00815   cursor(),
00816   search_loop_f(),
00817   search_failed_f(),
00818   nominus_cursor(),
00819   idx_nominus(),
00820   variables(),
00821   _comment_start(),
00822   _comment_end(),
00823   _field_separator(),
00824 #if !defined(GETPOT_DISABLE_MUTEX)
00825   _getpot_mtx(),
00826 #endif
00827   _internal_string_container(),
00828   _requested_arguments(),
00829   _requested_variables(),
00830   _requested_sections(),
00831   request_recording_f()
00832 {
00833   this->parse_input_file(FileName, CommentStart, CommentEnd, FieldSeparator);
00834 }
00835 
00836 
00837 
00838 inline void
00839 GetPot::parse_input_file(const std::string& FileName,
00840                          const std::string& CommentStart,
00841                          const std::string& CommentEnd,
00842                          const std::string& FieldSeparator)
00843 {
00844   _basic_initialization();
00845 
00846   // overwrite default strings
00847   _comment_start = std::string(CommentStart);
00848   _comment_end   = std::string(CommentEnd);
00849   _field_separator = FieldSeparator;
00850 
00851   STRING_VECTOR _apriori_argv;
00852   // -- the first element of the argument vector stores the name of
00853   //    the first parsing source; however, this element is not
00854   //    parsed for variable assignments or nominuses.
00855   //
00856   //    Regardless, we don't add more than one name to the argument
00857   //    vector.
00858   _apriori_argv.push_back(FileName);
00859 
00860   STRING_VECTOR args = _read_in_file(FileName);
00861   _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end());
00862   _parse_argument_vector(_apriori_argv);
00863 }
00864 
00865 
00866 
00867 inline
00868 GetPot::GetPot(const GetPot& Other) :
00869   prefix(Other.prefix),
00870   section(Other.section),
00871   section_list(Other.section_list),
00872   argv(Other.argv),
00873   cursor(Other.cursor),
00874   search_loop_f(Other.search_loop_f),
00875   search_failed_f(Other.search_failed_f),
00876   overridden_vars(),
00877   nominus_cursor(Other.nominus_cursor),
00878   idx_nominus(Other.idx_nominus),
00879   variables(Other.variables),
00880   _comment_start(Other._comment_start),
00881   _comment_end(Other._comment_end),
00882   _field_separator(Other._field_separator),
00883   // #if !defined(GETPOT_DISABLE_MUTEX)
00884   //   _getpot_mtx(Other._getpot_mtx),
00885   // #endif
00886   _internal_string_container(),
00887   _requested_arguments(Other._requested_arguments),
00888   _requested_variables(Other._requested_variables),
00889   _requested_sections(Other._requested_sections),
00890   request_recording_f(Other.request_recording_f)
00891 {
00892   std::set<const char*,ltstr>::const_iterator it =
00893     Other._internal_string_container.begin();
00894 
00895   const std::set<const char*,ltstr>::const_iterator end =
00896     Other._internal_string_container.end();
00897 
00898   for (; it != end; ++it)
00899     {
00900       const char* otherstr = *it;
00901       char* newcopy = new char[strlen(otherstr)+1];
00902       strncpy(newcopy, otherstr, strlen(otherstr)+1);
00903       this->_internal_string_container.insert(newcopy);
00904     }
00905 }
00906 
00907 
00908 
00909 inline
00910 GetPot::~GetPot()
00911 {
00912   // may be some return strings had to be created, delete now !
00913   std::set<const char*, ltstr>::const_iterator        it = _internal_string_container.begin();
00914   const std::set<const char*, ltstr>::const_iterator end = _internal_string_container.end();
00915   for (; it != end; ++it)
00916     delete [] *it;
00917 }
00918 
00919 
00920 
00921 inline GetPot&
00922 GetPot::operator=(const GetPot& Other)
00923 {
00924   if (&Other == this)
00925     return *this;
00926 
00927   prefix               = Other.prefix;
00928   section              = Other.section;
00929   section_list         = Other.section_list;
00930   argv                 = Other.argv;
00931   cursor               = Other.cursor;
00932   search_loop_f        = Other.search_loop_f;
00933   search_failed_f      = Other.search_failed_f;
00934   nominus_cursor       = Other.nominus_cursor;
00935   overridden_vars      = Other.overridden_vars;
00936   idx_nominus          = Other.idx_nominus;
00937   variables            = Other.variables;
00938   _comment_start       = Other._comment_start;
00939   _comment_end         = Other._comment_end;
00940   _field_separator     = Other._field_separator;
00941   // #if !defined(GETPOT_DISABLE_MUTEX)
00942   //   _getpot_mtx          = Other._getpot_mtx;
00943   // #endif
00944   _requested_arguments = Other._requested_arguments;
00945   _requested_variables = Other._requested_variables;
00946   _requested_sections  = Other._requested_sections;
00947   request_recording_f  = Other.request_recording_f;
00948 
00949   std::set<const char*, ltstr>::const_iterator        my_it =
00950     _internal_string_container.begin();
00951   const std::set<const char*, ltstr>::const_iterator my_end =
00952     _internal_string_container.end();
00953 
00954   for (; my_it != my_end; ++my_it)
00955     delete [] *my_it;
00956 
00957   _internal_string_container.clear();
00958 
00959   std::set<const char*,ltstr>::const_iterator it =
00960     Other._internal_string_container.begin();
00961   const std::set<const char*,ltstr>::const_iterator end =
00962     Other._internal_string_container.end();
00963 
00964   for (; it != end; ++it)
00965     {
00966       const char* otherstr = *it;
00967       char* newcopy = new char[strlen(otherstr)+1];
00968       strncpy(newcopy, otherstr, strlen(otherstr)+1);
00969       this->_internal_string_container.insert(newcopy);
00970     }
00971 
00972   return *this;
00973 }
00974 
00975 
00976 
00977 inline void
00978 GetPot::absorb(const GetPot& Other)
00979 {
00980   if (&Other == this)
00981     return;
00982 
00983   // variables that are not influenced by absorption:
00984   //               _comment_start
00985   //               _comment_end
00986   //               cursor
00987   //               nominus_cursor
00988   //               search_failed
00989   //               idx_nominus
00990   //               search_loop_f
00991   argv      = Other.argv;
00992   variables = Other.variables;
00993 
00994   if (request_recording_f)
00995     {
00996       // Get a lock before touching anything mutable
00997       SCOPED_MUTEX;
00998 
00999       _requested_arguments.insert(Other._requested_arguments.begin(), Other._requested_arguments.end());
01000       _requested_variables.insert(Other._requested_variables.begin(), Other._requested_variables.end());
01001       _requested_sections.insert(Other._requested_sections.begin(), Other._requested_sections.end());
01002     }
01003 }
01004 
01005 
01006 
01007 inline void
01008 GetPot::clear_requests()
01009 {
01010   // Get a lock before touching anything mutable
01011   SCOPED_MUTEX;
01012 
01013   _requested_arguments.clear();
01014   _requested_variables.clear();
01015   _requested_sections.clear();
01016 }
01017 
01018 
01019 
01020 inline void
01021 GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV)
01022 {
01023   if (ARGV.empty())
01024     return;
01025 
01026   // build internal databases:
01027   //   1) array with no-minus arguments (usually used as filenames)
01028   //   2) variable assignments:
01029   //             'variable name' '=' number | string
01030   STRING_VECTOR                 section_stack;
01031   STRING_VECTOR::const_iterator it = ARGV.begin();
01032 
01033 
01034   section = "";
01035 
01036   // -- do not parse the first argument, so that this parsing source
01037   // name is not interpreted a s a nominus or so.  If we already
01038   // have parsed arguments, don't bother adding another parsing
01039   // source name
01040   if (argv.empty())
01041     argv.push_back(*it);
01042   ++it;
01043 
01044   // -- loop over remaining arguments
01045   for (; it != ARGV.end(); ++it)
01046     {
01047       std::string arg = *it;
01048 
01049       if (arg.length() == 0)
01050         continue;
01051 
01052       // -- [section] labels and [include file] directives
01053       if (arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']')
01054         {
01055 
01056           // Is this an include file directive?
01057           std::size_t include_pos = arg.find("include ", 1);
01058           if (include_pos != std::string::npos)
01059             {
01060 
01061               const std::string includefile =
01062                 _DBE_expand_string(arg.substr(9, arg.length()-9-include_pos));
01063 
01064               this->parse_input_file
01065                 (includefile, _comment_start, _comment_end, _field_separator);
01066             }
01067 
01068           else
01069             {
01070               // (*) sections are considered 'requested arguments'
01071               if (request_recording_f)
01072                 {
01073                   // Get a lock before touching anything mutable
01074                   SCOPED_MUTEX;
01075 
01076                   _requested_arguments.insert(arg);
01077                 }
01078 
01079               const std::string Name = _DBE_expand_string(arg.substr(1, arg.length()-2));
01080               section = _process_section_label(Name, section_stack);
01081               // new section --> append to list of sections
01082               if (find(section_list.begin(), section_list.end(), section) == section_list.end())
01083                 if (section.length() != 0) section_list.push_back(section);
01084               argv.push_back(arg);
01085             }
01086         }
01087       else
01088         {
01089           arg = section + _DBE_expand_string(arg);
01090           argv.push_back(arg);
01091         }
01092 
01093       // -- separate array for nominus arguments
01094       if (arg[0] != '-')
01095         idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1));
01096 
01097       // -- variables: does arg contain a '=' operator ?
01098       const std::size_t equals_pos = arg.find_first_of('=');
01099       if (equals_pos != std::string::npos)
01100         {
01101           // (*) record for later ufo detection
01102           //     arguments carriying variables are always treated as 'requested' arguments.
01103           //     unrequested variables have to be detected with the ufo-variable
01104           //     detection routine.
01105           if (request_recording_f)
01106             {
01107               // Get a lock before touching anything mutable
01108               SCOPED_MUTEX;
01109 
01110               _requested_arguments.insert(arg);
01111             }
01112 
01113           // => arg (from start to '=') = Name of variable
01114           //        (from '=' to end)   = value of variable
01115           _set_variable(arg.substr(0,equals_pos),
01116                         arg.substr(equals_pos+1), false);
01117         }
01118     }
01119 }
01120 
01121 
01122 
01123 inline STRING_VECTOR
01124 GetPot::_read_in_file(const std::string& FileName)
01125 {
01126   std::ifstream  i(FileName.c_str());
01127 
01128   // if (!i) return STRING_VECTOR();
01129 
01130   if (!i)
01131     libmesh_file_error(FileName);
01132 
01133   // argv[0] == the filename of the file that was read in
01134   return _read_in_stream(i);
01135 }
01136 
01137 
01138 
01139 inline STRING_VECTOR
01140 GetPot::_read_in_stream(std::istream& istr)
01141 {
01142   STRING_VECTOR  brute_tokens;
01143   while (istr)
01144     {
01145       _skip_whitespace(istr);
01146       const std::string Token = _get_next_token(istr);
01147       // Allow 'keyword =' to parse with an empty string as value.
01148       // Only break at EOF.
01149       // if (Token.length() == 0 || Token[0] == EOF) break;
01150       if (Token[0] == EOF)
01151         break;
01152       brute_tokens.push_back(Token);
01153     }
01154 
01155   // -- reduce expressions of token1'='token2 to a single
01156   //    string 'token1=token2'
01157   // -- copy everything into 'argv'
01158   // -- arguments preceded by something like '[' name ']' (section)
01159   //    produce a second copy of each argument with a prefix '[name]argument'
01160   unsigned i1 = 0;
01161   unsigned i2 = 1;
01162   unsigned i3 = 2;
01163 
01164   STRING_VECTOR  arglist;
01165   while (i1 < brute_tokens.size())
01166     {
01167       // 1) concatenate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef'
01168       // note: java.lang.String: substring(a,b) = from a to b-1
01169       //        C++ string:      substr(a,b)    = from a to a + b
01170       std::string result;
01171       if (i2 < brute_tokens.size() && brute_tokens[i2] == "=")
01172         {
01173           if (i3 >= brute_tokens.size())
01174             result = brute_tokens[i1] + brute_tokens[i2];
01175           else
01176             result = brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3];
01177           i1 = i3+1; i2 = i3+2; i3 = i3+3;
01178         }
01179       else if (i2 < brute_tokens.size() &&
01180                brute_tokens[i2].length() > 0 &&
01181                brute_tokens[i2][0] == '=')
01182         {
01183           // This case should not be hit if '=' at the beginning of a word
01184           //   is always separated into its own word
01185           result = brute_tokens[i1] + brute_tokens[i2];
01186           i1 = i3; i2 = i3+1; i3 = i3+2;
01187         }
01188       else if (i2 < brute_tokens.size() && brute_tokens[i1][brute_tokens[i1].size()-1] == '=')
01189         {
01190           result = brute_tokens[i1] + brute_tokens[i2];
01191           i1 = i3; i2 = i3+1; i3 = i3+2;
01192         }
01193       else
01194         {
01195           result = brute_tokens[i1];
01196           i1=i2; i2=i3; i3++;
01197         }
01198 
01199       // Now strip out any comment
01200       size_t comment_start_loc = result.find(_comment_start, 0);
01201       if (comment_start_loc != std::string::npos)
01202         result = result.substr(0, comment_start_loc);
01203 
01204       arglist.push_back(result);
01205     }
01206   return arglist;
01207 }
01208 
01209 
01210 
01211 inline void
01212 GetPot::_skip_whitespace(std::istream& istr)
01213 {
01214   // find next non-whitespace while deleting comments
01215   int tmp = istr.get();
01216   do {
01217     // -- search a non whitespace
01218     while (isspace(tmp))
01219       {
01220         tmp = istr.get();
01221         if (!istr)
01222           return;
01223       }
01224 
01225     // -- look if characters match the comment starter string
01226     for (unsigned i=0; i<_comment_start.length() ; i++)
01227       {
01228         if (tmp != _comment_start[i])
01229           {
01230             // -- one step more backwards, since 'tmp' already at non-whitespace
01231             istr.unget();
01232             return;
01233           }
01234 
01235         // RHS: Why is this here?  It breaks on empty comments
01236         //    tmp = istr.get();
01237         //    if (!istr) { istr.unget(); return; }
01238       }
01239     // 'tmp' contains last character of _comment_starter
01240 
01241     // -- comment starter found -> search for comment ender
01242     unsigned match_no=0;
01243     while (true)
01244       {
01245         tmp = istr.get();
01246         if (!istr)
01247           {
01248             istr.unget();
01249             return;
01250           }
01251 
01252         if (tmp == _comment_end[match_no])
01253           {
01254             match_no++;
01255             if (match_no == _comment_end.length())
01256               {
01257                 istr.unget();
01258                 break; // shuffle more whitespace, end of comment found
01259               }
01260           }
01261         else
01262           match_no = 0;
01263       }
01264 
01265     tmp = istr.get();
01266 
01267   } while (istr);
01268   istr.unget();
01269 }
01270 
01271 
01272 
01273 inline const std::string
01274 GetPot::_get_next_token(std::istream& istr)
01275 {
01276   // get next concatenates string token. consider quotes that embrace
01277   // whitespaces
01278   std::string token;
01279   int    tmp = 0;
01280   while (true)
01281     {
01282       int last_letter = tmp;
01283       tmp = istr.get();
01284 
01285       if (tmp == '=')
01286         {
01287           // Always break at '='.
01288           // This separates '=' at the beginning of a word into its own word.
01289           token += getpot_cast_int<char>(tmp);
01290           return token;
01291         }
01292 
01293       else if (tmp == EOF || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\'))
01294         return token;
01295 
01296       else if (tmp == '\'' && last_letter != '\\')
01297         {
01298           // QUOTES: un-backslashed quotes => it's a string
01299           token += _get_string(istr);
01300           continue;
01301         }
01302 
01303       else if (tmp == '{' && last_letter == '$')
01304         {
01305           token += '{' + _get_until_closing_bracket(istr);
01306           continue;
01307         }
01308 
01309       else if (tmp == '[')
01310         {
01311           token += '[' + _get_until_closing_square_bracket(istr);
01312           continue;
01313         }
01314 
01315       else if (tmp == '$' && last_letter == '\\')
01316         {
01317           token += getpot_cast_int<char>(tmp); tmp = 0;  //  so that last_letter will become = 0, not '$';
01318           continue;
01319         }
01320 
01321       else if (tmp == '\\' && last_letter != '\\')
01322         continue;              // don't append un-backslashed backslashes
01323 
01324       token += getpot_cast_int<char>(tmp);
01325     }
01326 }
01327 
01328 
01329 
01330 inline const std::string
01331 GetPot::_get_string(std::istream& istr)
01332 {
01333   // parse input until next matching '
01334   std::string str;
01335   int    tmp = 0;
01336   while (true)
01337     {
01338       int last_letter = tmp;
01339       tmp = istr.get();
01340       if (tmp == EOF)
01341         return str;
01342 
01343       // un-backslashed quotes => it's the end of the string
01344       else if (tmp == '\'' && last_letter != '\\')
01345         return str;
01346 
01347       else if (tmp == '\\' && last_letter != '\\')
01348         continue; // don't append
01349 
01350       str += getpot_cast_int<char>(tmp);
01351     }
01352 }
01353 
01354 
01355 
01356 inline const std::string
01357 GetPot::_get_until_closing_bracket(std::istream& istr)
01358 {
01359   // parse input until next matching }
01360   std::string str = "";
01361   int    tmp = 0;
01362   int    brackets = 1;
01363   while (true)
01364     {
01365       int last_letter = tmp;
01366       tmp = istr.get();
01367       if (tmp == EOF)
01368         return str;
01369 
01370       else if (tmp == '{' && last_letter == '$')
01371         brackets += 1;
01372 
01373       else if (tmp == '}')
01374         {
01375           brackets -= 1;
01376           // un-backslashed brackets => it's the end of the string
01377           if (brackets == 0)
01378             return str + '}';
01379 
01380           else if (tmp == '\\' && last_letter != '\\')
01381             continue;  // do not append an unbackslashed backslash
01382         }
01383       str += getpot_cast_int<char>(tmp);
01384     }
01385 }
01386 
01387 
01388 
01389 inline const std::string
01390 GetPot::_get_until_closing_square_bracket(std::istream& istr)
01391 {
01392   // parse input until next matching ]
01393   std::string str = "";
01394   int    brackets = 1;
01395   while (true)
01396     {
01397       int tmp = istr.get();
01398       if (tmp == EOF)
01399         return str;
01400 
01401       else if (tmp == '[')
01402         brackets += 1;
01403 
01404       else if (tmp == ']')
01405         {
01406           brackets -= 1;
01407           if (brackets == 0)
01408             return str + ']';
01409         }
01410 
01411       str += getpot_cast_int<char>(tmp);
01412     }
01413 }
01414 
01415 
01416 
01417 inline std::string
01418 GetPot::_process_section_label(const std::string& Section,
01419                                STRING_VECTOR& section_stack)
01420 {
01421   std::string sname = Section;
01422   //  1) subsection of actual section ('./' prefix)
01423   if (sname.length() >= 2 && sname.substr(0, 2) == "./")
01424     sname = sname.substr(2);
01425 
01426   //  2) subsection of parent section ('../' prefix)
01427   else if (sname.length() >= 3 && sname.substr(0, 3) == "../")
01428     {
01429       do
01430         {
01431           if (section_stack.end() != section_stack.begin())
01432             section_stack.pop_back();
01433           sname = sname.substr(3);
01434         } while (sname.substr(0, 3) == "../");
01435     }
01436 
01437   // 3) subsection of the root-section
01438   else
01439     // [] => back to root section
01440     section_stack.erase(section_stack.begin(), section_stack.end());
01441 
01442   if (sname != "")
01443     {
01444       // parse section name for 'slashes'
01445       unsigned i=0;
01446       while (i < sname.length())
01447         {
01448           if (sname[i] == '/')
01449             {
01450               section_stack.push_back(sname.substr(0,i));
01451               if (i+1 < sname.length())
01452                 sname = sname.substr(i+1);
01453               i = 0;
01454             }
01455           else
01456             i++;
01457         }
01458       section_stack.push_back(sname);
01459     }
01460 
01461   std::string section_label = "";
01462   if (!section_stack.empty())
01463     {
01464       victorate(std::string, section_stack, it)
01465         section_label += *it + "/";
01466     }
01467   return section_label;
01468 }
01469 
01470 
01471 
01472 // Use C++ istream/ostream to handle most type conversions.
01473 template <typename T>
01474 inline T
01475 GetPot::_convert_to_type(const std::string& String, const T& Default) const
01476 {
01477   std::istringstream in_string(String);
01478   T retval;
01479   in_string >> retval;
01480   if (in_string.fail())
01481     retval = Default;
01482   return retval;
01483 }
01484 
01485 
01486 
01487 // copy string - operator>> would have stopped upon seeing whitespace!
01488 template <>
01489 inline std::string
01490 GetPot::_convert_to_type(const std::string& String, const std::string&) const
01491 {
01492   return String;
01493 }
01494 
01495 
01496 
01497 // copy string
01498 inline std::string
01499 GetPot::_convert_to_type(const std::string& String, const char*) const
01500 {
01501   return String;
01502 }
01503 
01504 
01505 
01506 // be more liberal than std C++ in what we interpret as a boolean
01507 template<>
01508 inline bool
01509 GetPot::_convert_to_type<bool>(const std::string& String, const bool& Default) const
01510 {
01511   std::string newstring(String);
01512   //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
01513   for (unsigned int i=0; i<newstring.length(); ++i)
01514     newstring[i] = getpot_cast_int<char>(toupper(newstring[i]));
01515 
01516   // "true"/"True"/"TRUE" should work
01517   if (newstring.find("TRUE")!=std::string::npos)
01518     return true;
01519 
01520   if (newstring.find("FALSE")!=std::string::npos)
01521     return false;
01522 
01523   // And if we don't find that, let's search for an integer and use C unsigned
01524   // int->bool conversion before giving up; i.e. a user could specify "0" for
01525   // false or "1" for true
01526   std::istringstream in_string(String);
01527   unsigned int retval;
01528   in_string >> retval;
01529   if (in_string.fail())
01530     return Default;
01531 
01532   return retval;
01533 }
01534 
01535 
01536 
01537 // Use C++ istream/ostream to handle most type conversions.
01538 template <typename T>
01539 inline T
01540 GetPot::_convert_to_type_no_default(const char* VarName, const std::string& String, const T&) const
01541 {
01542   std::istringstream in_string(String);
01543   T retval;
01544   in_string >> retval;
01545   if (in_string.fail())
01546     {
01547       getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
01548       getpot_cerr <<"       value = "<<String<<" expected type = "<<typeid(T).name()<<std::endl;
01549       getpot_error();
01550     }
01551   return retval;
01552 }
01553 
01554 
01555 
01556 // copy string - operator>> would have stopped upon seeing whitespace!
01557 template <>
01558 inline std::string
01559 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const std::string&) const
01560 {
01561   return String;
01562 }
01563 
01564 
01565 
01566 // copy string
01567 inline std::string
01568 GetPot::_convert_to_type_no_default(const char*, const std::string& String, const char*) const
01569 {
01570   return String;
01571 }
01572 
01573 
01574 
01575 // be more liberal than std C++ in what we interpret as a boolean
01576 template<>
01577 inline bool
01578 GetPot::_convert_to_type_no_default<bool>(const char* VarName, const std::string& String, const bool&) const
01579 {
01580   std::string newstring(String);
01581   //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
01582   for (unsigned int i=0; i<newstring.length(); ++i)
01583     {
01584       newstring[i]=getpot_cast_int<char>(toupper(newstring[i]));
01585     }
01586 
01587   // "true"/"True"/"TRUE" should work
01588   if (newstring.find("TRUE")!=std::string::npos)
01589     return true;
01590 
01591   if (newstring.find("FALSE")!=std::string::npos)
01592     return false;
01593 
01594   // And if we don't find that, let's search for an integer and use C unsigned
01595   // int->bool conversion before giving up; i.e. a user could specify "0" for
01596   // false or "1" for true
01597   std::istringstream in_string(String);
01598   unsigned int retval;
01599   in_string >> retval;
01600   if (in_string.fail())
01601     {
01602       getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
01603       getpot_cerr <<"       value = "<<String<<" expected type = "<<typeid(bool).name()<<std::endl;
01604       getpot_error();
01605     }
01606 
01607   return retval;
01608 }
01609 
01610 
01611 
01612 inline const char*
01613 GetPot::_internal_managed_copy(const std::string& Arg) const
01614 {
01615   const char* arg = Arg.c_str();
01616 
01617   // Get a lock before touching anything mutable
01618   SCOPED_MUTEX;
01619 
01620   // See if there's already an identical string saved
01621   std::set<const char*,ltstr>::const_iterator it =
01622     _internal_string_container.find(arg);
01623 
01624   // If so, return it
01625   if (it != _internal_string_container.end())
01626     return *it;
01627 
01628   // Otherwise, create a new one
01629   char* newcopy = new char[strlen(arg)+1];
01630   strncpy(newcopy, arg, strlen(arg)+1);
01631   _internal_string_container.insert(newcopy);
01632   return newcopy;
01633 }
01634 
01635 
01636 
01638 // (*) cursor oriented functions
01639 //.............................................................................
01640 
01641 // Checks if 'String' begins with 'Start' and returns the remaining String.
01642 // Returns None if String does not begin with Start.
01643 inline const std::string
01644 GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const
01645 {
01646   if (Start == "")
01647     return String;
01648 
01649   // note: java.lang.String: substring(a,b) = from a to b-1
01650   //        C++ string:      substr(a,b)    = from a to a + b
01651   if (String.find(Start) == 0)
01652     return String.substr(Start.length());
01653 
01654   else
01655     return "";
01656 }
01657 
01658 
01659 
01660 // -- search for a certain argument and set cursor to position
01661 inline bool
01662 GetPot::search(const std::string &Option)
01663 {
01664   return search(Option.c_str());
01665 }
01666 
01667 
01668 
01669 // -- search for a certain argument and set cursor to position
01670 inline bool
01671 GetPot::search(const char* Option)
01672 {
01673   unsigned           OldCursor = cursor;
01674   const std::string  SearchTerm = prefix + Option;
01675 
01676   // (*) record requested arguments for later ufo detection
01677   _record_argument_request(SearchTerm);
01678 
01679   if (OldCursor >= argv.size())
01680     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
01681   search_failed_f = true;
01682 
01683   // (*) first loop from cursor position until end
01684   for (unsigned c = cursor; c < argv.size(); c++)
01685     {
01686       if (argv[c] == SearchTerm)
01687         {
01688           cursor = c;
01689           search_failed_f = false;
01690           return true;
01691         }
01692     }
01693   if (!search_loop_f)
01694     return false;
01695 
01696   // (*) second loop from 0 to old cursor position
01697   for (unsigned c = 1; c < OldCursor; c++)
01698     {
01699       if (argv[c] == SearchTerm)
01700         {
01701           cursor = c;
01702           search_failed_f = false;
01703           return true;
01704         }
01705     }
01706 
01707   // in case nothing is found the cursor stays where it was
01708   return false;
01709 }
01710 
01711 
01712 
01713 inline bool
01714 GetPot::search(unsigned No, const char* P, ...)
01715 {
01716   // (*) recording the requested arguments happens in subroutine 'search'
01717   if (No == 0)
01718     return false;
01719 
01720   // search for the first argument
01721   if (search(P) == true)
01722     return true;
01723 
01724   // start interpreting variable argument list
01725   va_list ap;
01726   va_start(ap, P);
01727   unsigned i = 1;
01728   for (; i < No; i++)
01729     {
01730       char* Opt = va_arg(ap, char *);
01731       // (*) search records itself for later ufo detection
01732       if (search(Opt) == true)
01733         break;
01734     }
01735 
01736   if (i < No)
01737     {
01738       i++;
01739       // loop was left before end of array --> hit but
01740       // make sure that the rest of the search terms is marked
01741       // as requested.
01742       for (; i < No; i++)
01743         {
01744           char* Opt = va_arg(ap, char *);
01745           // (*) record requested arguments for later ufo detection
01746           _record_argument_request(Opt);
01747         }
01748       va_end(ap);
01749       return true;
01750     }
01751 
01752   va_end(ap);
01753   // loop was left normally --> no hit
01754   return false;
01755 }
01756 
01757 
01758 
01759 inline void
01760 GetPot::reset_cursor()
01761 {
01762   search_failed_f = false;
01763   cursor = 0;
01764 }
01765 
01766 
01767 
01768 inline void
01769 GetPot::init_multiple_occurrence()
01770 {
01771   disable_loop();
01772   reset_cursor();
01773 }
01774 
01775 
01776 
01778 // (*) direct access to command line arguments
01779 //.............................................................................
01780 //
01781 inline const char*
01782 GetPot::operator[](unsigned idx) const
01783 {
01784   return idx<argv.size() ? argv[idx].c_str() : 0;
01785 }
01786 
01787 
01788 
01789 template <typename T>
01790 inline T
01791 GetPot::get(unsigned int Idx, const T& Default) const
01792 {
01793   if (Idx >= argv.size())
01794     return Default;
01795   return _convert_to_type(argv[Idx], Default);
01796 }
01797 
01798 
01799 
01800 inline const char*
01801 GetPot::get(unsigned int Idx, const char* Default) const
01802 {
01803   if (Idx >= argv.size())
01804     return Default;
01805   return argv[Idx].c_str();
01806 }
01807 
01808 
01809 
01810 inline unsigned
01811 GetPot::size() const
01812 {
01813   return getpot_cast_int<unsigned>(argv.size());
01814 }
01815 
01816 
01817 
01818 // -- next() function group
01819 template <typename T>
01820 inline T
01821 GetPot::next(const T& Default)
01822 {
01823   if (search_failed_f)
01824     return Default;
01825   cursor++;
01826   if (cursor >= argv.size())
01827     {
01828       cursor = getpot_cast_int<unsigned>(argv.size());
01829       return Default;
01830     }
01831 
01832   // (*) record requested argument for later ufo detection
01833   _record_argument_request(argv[cursor]);
01834 
01835   const std::string Remain = _get_remaining_string(argv[cursor], prefix);
01836 
01837   return Remain != "" ? _convert_to_type(Remain, Default) : Default;
01838 }
01839 
01840 
01841 
01842 inline const char*
01843 GetPot::next(const char* Default)
01844 {
01845   return _internal_managed_copy(next(std::string(Default)));
01846 }
01847 
01848 
01849 
01850 // -- follow() function group
01851 //    distinct option to be searched for
01852 template <typename T>
01853 inline T
01854 GetPot::follow(const T& Default, const char* Option)
01855 {
01856   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01857   if (search(Option) == false)
01858     return Default;
01859 
01860   return next(Default);
01861 }
01862 
01863 
01864 
01865 inline const char*
01866 GetPot::follow(const char* Default, const char* Option)
01867 {
01868   return _internal_managed_copy(follow(std::string(Default), Option));
01869 }
01870 
01871 
01872 
01873 // -- second follow() function group
01874 //    multiple option to be searched for
01875 template <typename T>
01876 inline T
01877 GetPot::follow(const T& Default, unsigned int No, const char* P, ...)
01878 {
01879   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01880   if (No == 0)
01881     return Default;
01882 
01883   if (search(P) == true)
01884     return next(Default);
01885 
01886   va_list ap;
01887   va_start(ap, P);
01888   for (unsigned i=1; i<No; i++)
01889     {
01890       char* Opt = va_arg(ap, char *);
01891       if (search(Opt) == true)
01892         {
01893           va_end(ap);
01894           return next(Default);
01895         }
01896     }
01897   va_end(ap);
01898   return Default;
01899 }
01900 
01901 
01902 
01903 inline const char*
01904 GetPot::follow(const char* Default, unsigned No, const char* P, ...)
01905 {
01906   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
01907   if (No == 0)
01908     return Default;
01909 
01910   if (search(P) == true)
01911     return next(Default);
01912 
01913   va_list ap;
01914   va_start(ap, P);
01915   for (unsigned i=1; i<No; i++)
01916     {
01917       char* Opt = va_arg(ap, char *);
01918       if (search(Opt) == true)
01919         {
01920           va_end(ap);
01921           return next(Default);
01922         }
01923     }
01924   va_end(ap);
01925   return Default;
01926 }
01927 
01928 
01929 
01931 // (*) directly connected options
01932 //.............................................................................
01933 //
01934 template <typename T>
01935 inline T
01936 GetPot::direct_follow(const T& Default, const char* Option)
01937 {
01938   const char* FollowStr = _match_starting_string(Option);
01939 
01940   // (*) record requested of argument for later ufo-detection
01941   _record_argument_request(std::string(Option) + FollowStr);
01942 
01943   if (FollowStr == 0)
01944     return Default;
01945 
01946   if (++cursor >= argv.size())
01947     cursor = getpot_cast_int<unsigned>(argv.size());
01948   return _convert_to_type(FollowStr, Default);
01949 }
01950 
01951 
01952 
01953 inline const char*
01954 GetPot::direct_follow(const char* Default, const char* Option)
01955 {
01956   return _internal_managed_copy(direct_follow(std::string(Default), Option));
01957 }
01958 
01959 
01960 
01961 // pointer  to the place where the string after
01962 //          the match inside the found argument starts.
01963 // 0        no argument matches the starting string.
01964 inline const char*
01965 GetPot::_match_starting_string(const char* StartString)
01966 {
01967   const unsigned N =
01968     getpot_cast_int<unsigned>(strlen(StartString));
01969   unsigned       OldCursor = cursor;
01970 
01971   if (OldCursor >= argv.size())
01972     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
01973   search_failed_f = true;
01974 
01975   // (*) first loop from cursor position until end
01976   for (unsigned c = cursor; c < argv.size(); c++)
01977     {
01978       if (strncmp(StartString, argv[c].c_str(), N) == 0)
01979         {
01980           cursor = c;
01981           search_failed_f = false;
01982           return &(argv[c].c_str()[N]);
01983         }
01984     }
01985 
01986   if (!search_loop_f)
01987     return NULL;
01988 
01989   // (*) second loop from 0 to old cursor position
01990   for (unsigned c = 1; c < OldCursor; c++)
01991     {
01992       if (strncmp(StartString, argv[c].c_str(), N) == 0)
01993         {
01994           cursor = c;
01995           search_failed_f = false;
01996           return &(argv[c].c_str()[N]);
01997         }
01998     }
01999   return 0;
02000 }
02001 
02002 
02003 
02005 // (*) search for flags
02006 //.............................................................................
02007 //
02008 inline bool
02009 GetPot::options_contain(const char* FlagList) const
02010 {
02011   // go through all arguments that start with a '-' (but not '--')
02012   std::string str;
02013   STRING_VECTOR::const_iterator it = argv.begin();
02014   for (; it != argv.end(); ++it)
02015     {
02016       str = _get_remaining_string(*it, prefix);
02017 
02018       if (str.length() >= 2 && str[0] == '-' && str[1] != '-')
02019         if (_check_flags(str, FlagList))
02020           return true;
02021     }
02022   return false;
02023 }
02024 
02025 
02026 
02027 inline bool
02028 GetPot::argument_contains(unsigned Idx, const char* FlagList) const
02029 {
02030   if (Idx >= argv.size())
02031     return false;
02032 
02033   // (*) record requested of argument for later ufo-detection
02034   //     an argument that is checked for flags is considered to be 'requested'
02035   _record_argument_request(argv[Idx]);
02036 
02037   if (prefix == "")
02038     // search argument for any flag in flag list
02039     return _check_flags(argv[Idx], FlagList);
02040 
02041   // if a prefix is set, then the argument index is the index
02042   //   inside the 'namespace'
02043   // => only check list of arguments that start with prefix
02044   unsigned no_matches = 0;
02045   for (unsigned i=0; i<argv.size(); i++)
02046     {
02047       const std::string Remain = _get_remaining_string(argv[i], prefix);
02048       if (Remain != "")
02049         {
02050           no_matches += 1;
02051           if (no_matches == Idx)
02052             return _check_flags(Remain, FlagList);
02053         }
02054     }
02055 
02056   // no argument in this namespace
02057   return false;
02058 }
02059 
02060 
02061 
02062 inline bool
02063 GetPot::_check_flags(const std::string& Str, const char* FlagList) const
02064 {
02065   for (const char* p=FlagList; *p != '\0' ; p++)
02066     if (Str.find(*p) != std::string::npos)
02067       return true; // found something
02068   return false;
02069 }
02070 
02071 
02072 
02074 // (*) nominus arguments
02075 
02076 // return vector of nominus arguments
02077 inline STRING_VECTOR
02078 GetPot::nominus_vector() const
02079 {
02080   STRING_VECTOR nv;
02081   std::vector<unsigned>::const_iterator it = idx_nominus.begin();
02082   for (; it != idx_nominus.end(); ++it)
02083     {
02084       nv.push_back(argv[*it]);
02085 
02086       // (*) record for later ufo-detection
02087       //     when a nominus vector is requested, the entire set of nominus arguments are
02088       //     tagged as 'requested'
02089       _record_argument_request(argv[*it]);
02090     }
02091   return nv;
02092 }
02093 
02094 
02095 
02096 inline const char*
02097 GetPot::next_nominus()
02098 {
02099   if (nominus_cursor < int(idx_nominus.size()) - 1)
02100     {
02101       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
02102 
02103       // (*) record for later ufo-detection
02104       _record_argument_request(Tmp);
02105 
02106       return _internal_managed_copy(Tmp);
02107     }
02108 
02109   return 0;
02110 }
02111 
02112 
02113 inline std::string
02114 GetPot::next_nominus_string()
02115 {
02116   if (nominus_cursor < int(idx_nominus.size()) - 1)
02117     {
02118       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
02119 
02120       // (*) record for later ufo-detection
02121       _record_argument_request(Tmp);
02122 
02123       return Tmp;
02124     }
02125 
02126   return "";
02127 }
02128 
02129 
02130 
02131 inline void
02132 GetPot::reset_nominus_cursor()
02133 {
02134   nominus_cursor = -1;
02135 }
02136 
02137 
02138 
02140 // (*) variables
02141 //.............................................................................
02142 //
02143 inline bool
02144 GetPot::have_variable(const char* VarName) const
02145 {
02146   const variable* sv = _request_variable(VarName);
02147 
02148   if (sv == 0)
02149     return false;
02150 
02151   return true;
02152 }
02153 
02154 
02155 
02156 inline bool
02157 GetPot::have_variable(const std::string& VarName) const
02158 {
02159   return have_variable(VarName.c_str());
02160 }
02161 
02162 inline bool
02163 GetPot::have_section(const char* section_name) const
02164 {
02165   std::string s = std::string(section_name);
02166   return this->have_section(s);
02167 }
02168 
02169 inline bool
02170 GetPot::have_section(const std::string& section_name) const
02171 {
02172   const char slash('/');
02173 
02174   std::string::const_reverse_iterator it = section_name.rbegin();
02175 
02176   bool found_section = false;
02177 
02178   /* Check if section_name ends with a "/". If not, append it for the search since
02179      the section names are stored with a "/" at the end.*/
02180   if( (*it) != slash )
02181     /* We need to use a linear search because we can't sort section_list
02182      without violating some assumptions. See libMesh #481 for more discussion. */
02183     found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() );
02184   else
02185     found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() );
02186 
02187   return found_section;
02188 }
02189 
02190 template <typename T>
02191 inline T
02192 GetPot::operator()(const char* VarName, const T& Default) const
02193 {
02194   // (*) recording of requested variables happens in '_request_variable()'
02195   const variable*  sv = _request_variable(VarName);
02196 
02197   if (sv == 0)
02198     return Default;
02199 
02200   return _convert_to_type(sv->original, Default);
02201 }
02202 
02203 
02204 
02205 template <typename T>
02206 inline T
02207 GetPot::operator()(const std::string& VarName, const T& Default) const
02208 {
02209   return operator()(VarName.c_str(), Default);
02210 }
02211 
02212 
02213 
02214 inline const char*
02215 GetPot::operator()(const char* VarName, const char* Default) const
02216 {
02217   return _internal_managed_copy(operator()(VarName, std::string(Default)));
02218 }
02219 
02220 
02221 
02222 inline const char*
02223 GetPot::operator()(const std::string& VarName, const char* Default) const
02224 {
02225   return operator()(VarName.c_str(), Default);
02226 }
02227 
02228 
02229 
02230 template <typename T>
02231 inline T
02232 GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const
02233 {
02234   // (*) recording of requested variables happens in '_request_variable()'
02235   const variable* sv = _request_variable(VarName);
02236   if (sv == 0)
02237     return Default;
02238 
02239   const std::string*  element = sv->get_element(Idx);
02240   if (element == 0)
02241     return Default;
02242   return _convert_to_type(*element, Default);
02243 }
02244 
02245 
02246 
02247 template <typename T>
02248 inline T
02249 GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const
02250 {
02251   return operator()(VarName.c_str(), Default, Idx);
02252 }
02253 
02254 
02255 
02256 inline const char*
02257 GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const
02258 {
02259   return _internal_managed_copy(operator()(VarName, std::string(Default), Idx));
02260 }
02261 
02262 
02263 
02264 inline const char*
02265 GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const
02266 {
02267   return operator()(VarName.c_str(), Default, Idx);
02268 }
02269 
02270 
02271 
02272 template <typename T>
02273 inline T
02274 GetPot::get_value_no_default(const char* VarName, const T& Default) const
02275 {
02276   // (*) recording of requested variables happens in '_request_variable()'
02277   const variable*  sv = _request_variable(VarName);
02278   if (sv == 0)
02279     {
02280       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
02281       getpot_error();
02282     }
02283   return _convert_to_type_no_default(VarName, sv->original, Default);
02284 }
02285 
02286 
02287 
02288 template <typename T>
02289 inline T
02290 GetPot::get_value_no_default(const std::string& VarName, const T& Default) const
02291 {
02292   return get_value_no_default(VarName.c_str(),Default);
02293 }
02294 
02295 
02296 
02297 inline const char*
02298 GetPot::get_value_no_default(const char* VarName, const char* Default) const
02299 {
02300   return _internal_managed_copy(get_value_no_default(VarName, Default));
02301 }
02302 
02303 
02304 
02305 inline const char*
02306 GetPot::get_value_no_default(const std::string& VarName, const char* Default) const
02307 {
02308   return get_value_no_default(VarName.c_str(),Default);
02309 }
02310 
02311 
02312 
02313 template <typename T>
02314 inline T
02315 GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const
02316 {
02317   // (*) recording of requested variables happens in '_request_variable()'
02318   const variable* sv = _request_variable(VarName);
02319   if (sv == 0)
02320     {
02321       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
02322       getpot_error();
02323     }
02324 
02325   const std::string*  element = sv->get_element(Idx);
02326   if (element == 0)
02327     {
02328       getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl;
02329       getpot_error();
02330     }
02331   return _convert_to_type_no_default(VarName, *element, Default);
02332 }
02333 
02334 
02335 
02336 template <typename T>
02337 inline T
02338 GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const
02339 {
02340   return get_value_no_default(VarName.c_str(), Default, Idx);
02341 }
02342 
02343 
02344 
02345 inline const char*
02346 GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const
02347 {
02348   return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx));
02349 }
02350 
02351 
02352 
02353 inline const char*
02354 GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const
02355 {
02356   return get_value_no_default(VarName.c_str(), Default, Idx);
02357 }
02358 
02359 
02360 
02361 inline void
02362 GetPot::_record_argument_request(const std::string& Name) const
02363 {
02364   if (!request_recording_f)
02365     return;
02366 
02367   // Get a lock before touching anything mutable
02368   SCOPED_MUTEX;
02369 
02370   // (*) record requested variable for later ufo detection
02371   _requested_arguments.insert(Name);
02372 
02373   // (*) record considered section for ufo detection
02374   STRING_VECTOR      STree = _get_section_tree(Name);
02375   victorate(std::string, STree, it)
02376     if (_requested_sections.find(*it) == _requested_sections.end())
02377       if (section.length() != 0)
02378         _requested_sections.insert(*it);
02379 }
02380 
02381 
02382 
02383 inline void
02384 GetPot::_record_variable_request(const std::string& Name) const
02385 {
02386   if (!request_recording_f)
02387     return;
02388 
02389   // Get a lock before touching anything mutable
02390   SCOPED_MUTEX;
02391 
02392   // (*) record requested variable for later ufo detection
02393   _requested_variables.insert(Name);
02394 
02395   // (*) record considered section for ufo detection
02396   STRING_VECTOR      STree = _get_section_tree(Name);
02397   victorate(std::string, STree, it)
02398     if (_requested_sections.find(*it) == _requested_sections.end())
02399       if (section.length() != 0)
02400         _requested_sections.insert(*it);
02401 }
02402 
02403 
02404 
02405 // (*) following functions are to be used from 'outside', after getpot has parsed its
02406 //     arguments => append an argument in the argument vector that reflects the addition
02407 inline void
02408 GetPot::_set_variable(const std::string& VarName,
02409                       const std::string& Value, const bool Requested /* = true */)
02410 {
02411   const GetPot::variable* Var = Requested ?
02412     _request_variable(VarName.c_str()) :
02413     _find_variable(VarName.c_str());
02414   if (Var == 0)
02415     variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str()));
02416   else
02417     {
02418       overridden_vars.insert(VarName.c_str());
02419       (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str());
02420     }
02421 }
02422 
02423 
02424 
02425 template <typename T>
02426 inline void
02427 GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */)
02428 {
02429   std::ostringstream string_value;
02430   string_value << Value;
02431   _set_variable(VarName, string_value.str().c_str(), Requested);
02432 }
02433 
02434 
02435 
02436 template <typename T>
02437 inline void
02438 GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */)
02439 {
02440   set(VarName.c_str(), Value, Requested);
02441 }
02442 
02443 
02444 
02445 inline void
02446 GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */)
02447 {
02448   _set_variable(VarName, Value, Requested);
02449 }
02450 
02451 
02452 
02453 inline void
02454 GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */)
02455 {
02456   set(VarName.c_str(), Value, Requested);
02457 }
02458 
02459 
02460 
02461 inline unsigned
02462 GetPot::vector_variable_size(const char* VarName) const
02463 {
02464   const variable*  sv = _request_variable(VarName);
02465   if (sv == 0)
02466     return 0;
02467   return (unsigned)(sv->value.size());
02468 }
02469 
02470 
02471 
02472 inline unsigned
02473 GetPot::vector_variable_size(const std::string& VarName) const
02474 {
02475   return vector_variable_size(VarName.c_str());
02476 }
02477 
02478 
02479 
02480 inline STRING_VECTOR
02481 GetPot::get_variable_names() const
02482 {
02483   STRING_VECTOR  result;
02484   std::vector<GetPot::variable>::const_iterator it = variables.begin();
02485   for (; it != variables.end(); ++it)
02486     {
02487       const std::string Tmp = _get_remaining_string((*it).name, prefix);
02488       if (Tmp != "")
02489         result.push_back(Tmp);
02490     }
02491   return result;
02492 }
02493 
02494 
02495 
02496 inline STRING_VECTOR
02497 GetPot::get_section_names() const
02498 {
02499   return section_list;
02500 }
02501 
02502 
02503 
02504 inline std::set<std::string>
02505 GetPot::get_overridden_variables() const
02506 {
02507   return overridden_vars;
02508 }
02509 
02510 
02511 
02512 inline const GetPot::variable*
02513 GetPot::_find_variable(const char* VarName) const
02514 {
02515   const std::string Name = prefix + VarName;
02516 
02517   std::vector<variable>::const_iterator it = variables.begin();
02518   for (; it != variables.end(); ++it)
02519     {
02520       if ((*it).name == Name)
02521         return &(*it);
02522     }
02523   return 0;
02524 }
02525 
02526 
02527 
02528 inline const GetPot::variable*
02529 GetPot::_request_variable(const char* VarName) const
02530 {
02531   // (*) record requested variable for later ufo detection
02532   this->_record_variable_request(VarName);
02533 
02534   return this->_find_variable(VarName);
02535 }
02536 
02537 
02538 
02540 // (*) ouput (basically for debugging reasons
02541 //.............................................................................
02542 //
02543 inline int
02544 GetPot::print(std::ostream &out_stream) const
02545 {
02546   out_stream << "argc = " << argv.size() << std::endl;
02547   STRING_VECTOR::const_iterator it = argv.begin();
02548   for (; it != argv.end(); ++it)
02549     out_stream << *it << std::endl;
02550   out_stream << std::endl;
02551   return 1;
02552 }
02553 
02554 
02555 
02556 // PECOS/HPCT Addition - add option to prepend output with a delimiter
02557 // while also disabling argc print and skipping first print (the name
02558 // of the input file)
02559 //
02560 // PECOS Development Team: (ks. 4/16/09)
02561 inline int
02562 GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const
02563 {
02564   STRING_VECTOR::const_iterator it = argv.begin();
02565   it += skip_count;
02566   for (; it != argv.end(); ++it)
02567     {
02568       out_stream << custom_prefix;
02569       out_stream << *it << std::endl;
02570     }
02571   out_stream << std::endl;
02572   return 1;
02573 }
02574 
02575 
02576 
02577 // (*) dollar bracket expressions (DBEs) ------------------------------------
02578 //
02579 //     1) Entry Function: _DBE_expand_string()
02580 //        Takes a string such as
02581 //
02582 //          "${+ ${x} ${y}}   Subject-${& ${section} ${subsection}}:   ${title}"
02583 //
02584 //        calls _DBE_expand() for each of the expressions
02585 //
02586 //           ${+ ${x} ${y}}
02587 //           ${& ${section} ${subsection}}
02588 //           ${Title}
02589 //
02590 //        and returns the string
02591 //
02592 //          "4711 Subject-1.01:   Mit den Clowns kamen die Schwaene"
02593 //
02594 //        assuming that
02595 //            x          = "4699"
02596 //            y          = "12"
02597 //            section    = "1."
02598 //            subsection = "01"
02599 //            title      = "Mit den Clowns kamen die Schwaene"
02600 //
02601 //      2) _DBE_expand():
02602 //
02603 //           checks for the command, i.e. the 'sign' that follows '${'
02604 //           divides the argument list into sub-expressions using
02605 //           _DBE_get_expr_list()
02606 //
02607 //           ${+ ${x} ${y}}                 -> "${x}"  "${y}"
02608 //           ${& ${section} ${subsection}}  -> "${section}" "${subsection}"
02609 //           ${Title}                       -> Nothing, variable expansion
02610 //
02611 //      3) _DBE_expression_list():
02612 //
02613 //           builds a vector of unbracketed whitespace separated strings, i.e.
02614 //
02615 //           "  ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
02616 //
02617 //           is split into a vector
02618 //
02619 //              [0] ${Number}.a
02620 //              [1] ${: Das Marmorbild}
02621 //              [2] AB-${& Author= ${Eichendorf}}-1870
02622 //
02623 //           Each sub-expression is expanded using expand().
02624 //---------------------------------------------------------------------------
02625 inline std::string
02626 GetPot::_DBE_expand_string(const std::string& str)
02627 {
02628   // Parses for closing operators '${ }' and expands them letting
02629   // white spaces and other letters as they are.
02630   std::string   new_string = "";
02631   unsigned open_brackets = 0;
02632   unsigned first = 0;
02633   for (unsigned i = 0;  i<str.size(); i++)
02634     {
02635       if (i < str.size() - 2 && str.substr(i, 2) == "${")
02636         {
02637           if (open_brackets == 0)
02638             first = i+2;
02639           open_brackets++;
02640         }
02641       else if (str[i] == '}' && open_brackets > 0)
02642         {
02643           open_brackets -= 1;
02644           if (open_brackets == 0)
02645             {
02646               const std::string Replacement = _DBE_expand(str.substr(first, i - first));
02647               new_string += Replacement;
02648             }
02649         }
02650       else if (open_brackets == 0)
02651         new_string += str[i];
02652     }
02653   return new_string;
02654 }
02655 
02656 
02657 
02658 inline STRING_VECTOR
02659 GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
02660 {
02661   // ensures that the resulting vector has the expected number
02662   // of arguments, but they may contain an error message
02663   std::string str = str_;
02664   // Separates expressions by non-bracketed whitespaces, expands them
02665   // and puts them into a list.
02666 
02667   unsigned i=0;
02668   // (1) eat initial whitespaces
02669   for (; i < str.size(); i++)
02670     if (!isspace(str[i]))
02671       break;
02672 
02673   STRING_VECTOR   expr_list;
02674   unsigned         open_brackets = 0;
02675   std::vector<unsigned> start_idx;
02676   unsigned         start_new_string = i;
02677   unsigned         l = (unsigned)(str.size());
02678 
02679   // (2) search for ${ } expressions ...
02680   while (i < l)
02681     {
02682       const char letter = str[i];
02683       // whitespace -> end of expression
02684       if (isspace(letter) && open_brackets == 0)
02685         {
02686           expr_list.push_back(str.substr(start_new_string, i - start_new_string));
02687           bool no_breakout_f = true;
02688           for (i++; i < l ; i++)
02689             {
02690               if (!isspace(str[i]))
02691                 {
02692                   no_breakout_f = false;
02693                   start_new_string = i;
02694                   break;
02695                 }
02696             }
02697 
02698           if (no_breakout_f)
02699             {
02700               // end of expression list
02701               if (expr_list.size() < ExpectedNumber)
02702                 {
02703                   const std::string   pre_tmp("<< ${ }: missing arguments>>");
02704                   STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
02705                   expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
02706                 }
02707               return expr_list;
02708             }
02709         }
02710 
02711       // dollar-bracket expression
02712       if (str.length() >= i+2 && str.substr(i, 2) == "${")
02713         {
02714           open_brackets++;
02715           start_idx.push_back(i+2);
02716         }
02717 
02718       else if (letter == '}' && open_brackets > 0)
02719         {
02720           int start = start_idx[start_idx.size()-1];
02721           start_idx.pop_back();
02722           const std::string Replacement = _DBE_expand(str.substr(start, i-start));
02723           if (start - 3 < (int)0)
02724             str = Replacement + str.substr(i+1);
02725           else
02726             str = str.substr(0, start-2) + Replacement + str.substr(i+1);
02727           l = (int)(str.size());
02728           i = start + (int)(Replacement.size()) - 3;
02729           open_brackets--;
02730         }
02731       i++;
02732     }
02733 
02734   // end of expression list
02735   expr_list.push_back(str.substr(start_new_string, i-start_new_string));
02736 
02737   if (expr_list.size() < ExpectedNumber)
02738     {
02739       const std::string   pre_tmp("<< ${ }: missing arguments>>");
02740       STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
02741       expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
02742     }
02743 
02744   return expr_list;
02745 }
02746 
02747 
02748 
02749 inline const GetPot::variable*
02750 GetPot::_DBE_get_variable(const std::string& VarName)
02751 {
02752   static GetPot::variable ev;
02753   std::string secure_Prefix = prefix;
02754 
02755   prefix = section;
02756   // (1) first search in currently active section
02757   const GetPot::variable* var = _request_variable(VarName.c_str());
02758   if (var != 0)
02759     {
02760       prefix = secure_Prefix;
02761       return var;
02762     }
02763 
02764   // (2) search in root name space
02765   prefix = "";
02766   var = _request_variable(VarName.c_str());
02767   if (var != 0)
02768     {
02769       prefix = secure_Prefix;
02770       return var;
02771     }
02772 
02773   prefix = secure_Prefix;
02774 
02775   // error occured => variable name == ""
02776   ev.original = "<<${ } variable '";
02777   ev.original += VarName + "' undefined>>";
02778   return &ev;
02779 }
02780 
02781 
02782 
02783 inline std::string
02784 GetPot::_DBE_expand(const std::string& expr)
02785 {
02786   // ${: } pure text
02787   if (expr[0] == ':')
02788     return expr.substr(1);
02789 
02790   // ${& expr expr ... } text concatination
02791   else if (expr[0] == '&')
02792     {
02793       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1);
02794 
02795       STRING_VECTOR::const_iterator it = A.begin();
02796       std::string result = *it++;
02797       for (; it != A.end(); ++it) result += *it;
02798 
02799       return result;
02800     }
02801 
02802   // ${<-> expr expr expr} text replacement
02803   else if (expr.length() >= 3 && expr.substr(0, 3) == "<->")
02804     {
02805       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3);
02806       size_t tmp = 0;
02807       const size_t L = A[1].length();
02808 
02809       while ((tmp = A[0].find(A[1])) != std::string::npos)
02810         A[0].replace(tmp, L, A[2]);
02811 
02812       return A[0];
02813     }
02814 
02815   // ${=func [expr...] } function evaluation
02816   else if (expr.length() >= 2 &&
02817            expr.substr(0, 1) == "=" &&
02818            expr.substr(0, 2) != "==")
02819     {
02820       size_t funcnamestart = expr.find_first_not_of(" \t", 1);
02821       if (funcnamestart != std::string::npos)
02822         {
02823           size_t funcnameend = expr.find_first_of(" \t",funcnamestart);
02824           std::string funcname = expr.substr(funcnamestart,
02825                                              funcnameend-funcnamestart);
02826           if (funcname == "log")
02827             {
02828               STRING_VECTOR A =
02829                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02830               double arg = _convert_to_type(A[0], 0.0);
02831               return _convert_from_type(std::log(arg));
02832             }
02833           else if (funcname == "log10")
02834             {
02835               STRING_VECTOR A =
02836                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02837               double arg = _convert_to_type(A[0], 0.0);
02838               return _convert_from_type(std::log10(arg));
02839             }
02840           else if (funcname == "exp")
02841             {
02842               STRING_VECTOR A =
02843                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02844               double arg = _convert_to_type(A[0], 0.0);
02845               return _convert_from_type(std::exp(arg));
02846             }
02847           else if (funcname == "sin")
02848             {
02849               STRING_VECTOR A =
02850                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02851               double arg = _convert_to_type(A[0], 0.0);
02852               return _convert_from_type(std::sin(arg));
02853             }
02854           else if (funcname == "cos")
02855             {
02856               STRING_VECTOR A =
02857                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02858               double arg = _convert_to_type(A[0], 0.0);
02859               return _convert_from_type(std::cos(arg));
02860             }
02861           else if (funcname == "tan")
02862             {
02863               STRING_VECTOR A =
02864                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02865               double arg = _convert_to_type(A[0], 0.0);
02866               return _convert_from_type(std::tan(arg));
02867             }
02868           else if (funcname == "asin")
02869             {
02870               STRING_VECTOR A =
02871                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02872               double arg = _convert_to_type(A[0], 0.0);
02873               return _convert_from_type(std::asin(arg));
02874             }
02875           else if (funcname == "acos")
02876             {
02877               STRING_VECTOR A =
02878                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02879               double arg = _convert_to_type(A[0], 0.0);
02880               return _convert_from_type(std::acos(arg));
02881             }
02882           else if (funcname == "atan")
02883             {
02884               STRING_VECTOR A =
02885                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02886               double arg = _convert_to_type(A[0], 0.0);
02887               return _convert_from_type(std::atan(arg));
02888             }
02889           else if (funcname == "atan2")
02890             {
02891               STRING_VECTOR A =
02892                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
02893               double arg1 = _convert_to_type(A[0], 0.0);
02894               double arg2 = _convert_to_type(A[1], 0.0);
02895               return _convert_from_type(std::atan2(arg1, arg2));
02896             }
02897           else if (funcname == "sinh")
02898             {
02899               STRING_VECTOR A =
02900                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02901               double arg = _convert_to_type(A[0], 0.0);
02902               return _convert_from_type(std::sinh(arg));
02903             }
02904           else if (funcname == "cosh")
02905             {
02906               STRING_VECTOR A =
02907                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02908               double arg = _convert_to_type(A[0], 0.0);
02909               return _convert_from_type(std::cosh(arg));
02910             }
02911           else if (funcname == "tanh")
02912             {
02913               STRING_VECTOR A =
02914                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02915               double arg = _convert_to_type(A[0], 0.0);
02916               return _convert_from_type(std::tanh(arg));
02917             }
02918 #ifdef HAVE_INVERSE_HYPERBOLIC_SINE
02919           else if (funcname == "asinh")
02920             {
02921               STRING_VECTOR A =
02922                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02923               double arg = _convert_to_type(A[0], 0.0);
02924               return _convert_from_type(std::asinh(arg));
02925             }
02926 #endif
02927 #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE
02928           else if (funcname == "acosh")
02929             {
02930               STRING_VECTOR A =
02931                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02932               double arg = _convert_to_type(A[0], 0.0);
02933               return _convert_from_type(std::acosh(arg));
02934             }
02935 #endif
02936 #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT
02937           else if (funcname == "atanh")
02938             {
02939               STRING_VECTOR A =
02940                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02941               double arg = _convert_to_type(A[0], 0.0);
02942               return _convert_from_type(std::atanh(arg));
02943             }
02944 #endif
02945           else if (funcname == "sqrt")
02946             {
02947               STRING_VECTOR A =
02948                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02949               double arg = _convert_to_type(A[0], 0.0);
02950               return _convert_from_type(std::sqrt(arg));
02951             }
02952           else if (funcname == "abs")
02953             {
02954               STRING_VECTOR A =
02955                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02956               double arg = _convert_to_type(A[0], 0.0);
02957               return _convert_from_type(std::abs(arg));
02958             }
02959           else if (funcname == "max")
02960             {
02961               STRING_VECTOR A =
02962                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02963               STRING_VECTOR::const_iterator it = A.begin();
02964               double result = _convert_to_type(*it++, 0.0);
02965               for (; it != A.end(); ++it)
02966                 result = std::max(result, _convert_to_type(*it, 0.0));
02967               return _convert_from_type(result);
02968             }
02969           else if (funcname == "min")
02970             {
02971               STRING_VECTOR A =
02972                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02973               STRING_VECTOR::const_iterator it = A.begin();
02974               double result = _convert_to_type(*it++, 0.0);
02975               for (; it != A.end(); ++it)
02976                 result = std::min(result, _convert_to_type(*it, 0.0));
02977               return _convert_from_type(result);
02978             }
02979           else if (funcname == "ceil")
02980             {
02981               STRING_VECTOR A =
02982                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02983               double arg = _convert_to_type(A[0], 0.0);
02984               return _convert_from_type(std::ceil(arg));
02985             }
02986           else if (funcname == "floor")
02987             {
02988               STRING_VECTOR A =
02989                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
02990               double arg = _convert_to_type(A[0], 0.0);
02991               return _convert_from_type(std::floor(arg));
02992             }
02993           else if (funcname == "fmod")
02994             {
02995               STRING_VECTOR A =
02996                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
02997               double arg1 = _convert_to_type(A[0], 0.0);
02998               double arg2 = _convert_to_type(A[1], 0.0);
02999               return _convert_from_type(std::fmod(arg1, arg2));
03000             }
03001           else if (funcname == "srand")
03002             {
03003               STRING_VECTOR A =
03004                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
03005               unsigned int arg = _convert_to_type(A[0], 0u);
03006               std::srand(arg);
03007               return A[0];
03008             }
03009           // ${=rand range} with default range==RAND_MAX
03010           else if (funcname == "rand")
03011             {
03012               if (funcnameend >= expr.length() ||
03013                   expr.find_first_not_of(" \t", funcnameend) == std::string::npos)
03014                 return _convert_from_type(std::rand());
03015 
03016               STRING_VECTOR A =
03017                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
03018               unsigned int range = _convert_to_type(A[0],0u);
03019               if (!range)
03020                 return _convert_from_type(0);
03021               const unsigned int x = (RAND_MAX + 1u) / range;
03022               const unsigned int y = x * range;
03023               unsigned int returnval;
03024               do
03025                 {
03026                   returnval = rand();
03027                 } while (returnval >= y);
03028               return _convert_from_type(returnval / x);
03029             }
03030           else if (funcname == "time")
03031             return _convert_from_type(std::time(NULL));
03032           else
03033             {
03034               getpot_cerr << "ERROR: unrecognized function "
03035                           << funcname << std::endl;
03036               getpot_error();
03037             }
03038         }
03039     }
03040 
03041   // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
03042   else if (expr[0] == '+')
03043     {
03044       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
03045       STRING_VECTOR::const_iterator it = A.begin();
03046       double result = _convert_to_type(*it++, 0.0);
03047       for (; it != A.end(); ++it)
03048         result += _convert_to_type(*it, 0.0);
03049 
03050       return _convert_from_type(result);
03051     }
03052   else if (expr[0] == '-')
03053     {
03054       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
03055       STRING_VECTOR::const_iterator it = A.begin();
03056       double result = _convert_to_type(*it++, 0.0);
03057       for (; it != A.end(); ++it)
03058         result -= _convert_to_type(*it, 0.0);
03059 
03060       return _convert_from_type(result);
03061     }
03062   else if (expr[0] == '*')
03063     {
03064       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
03065       STRING_VECTOR::const_iterator it = A.begin();
03066       double result = _convert_to_type(*it++, 0.0);
03067       for (; it != A.end(); ++it)
03068         result *= _convert_to_type(*it, 0.0);
03069 
03070       return _convert_from_type(result);
03071     }
03072   else if (expr[0] == '/')
03073     {
03074       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
03075       STRING_VECTOR::const_iterator it = A.begin();
03076       double result = _convert_to_type(*it++, 0.0);
03077       if (result == 0)
03078         return "0.0";
03079 
03080       for (; it != A.end(); ++it)
03081         {
03082           const double Q = _convert_to_type(*it, 0.0);
03083           result /= Q;
03084         }
03085       return _convert_from_type(result);
03086     }
03087 
03088   // ${^ ... } power expressions
03089   else if (expr[0] == '^')
03090     {
03091       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
03092       STRING_VECTOR::const_iterator it = A.begin();
03093       double result = _convert_to_type(*it++, 0.0);
03094       for (; it != A.end(); ++it)
03095         result = pow(result, _convert_to_type(*it, 0.0));
03096       return _convert_from_type(result);
03097     }
03098 
03099   // ${==  } ${<=  } ${>= } comparisons (return the number of the first 'match'
03100   else if (expr.length() >= 2 &&
03101            (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
03102             expr.substr(0,2) == "<=" || expr[0] == '>'           || expr[0] == '<'))
03103     {
03104       // differentiate between two and one sign operators
03105       unsigned op = 0;
03106       enum { EQ, GEQ, LEQ, GT, LT };
03107 
03108       if (expr.substr(0, 2) == "==")
03109         op = EQ;
03110 
03111       else if (expr.substr(0, 2) == ">=")
03112         op = GEQ;
03113 
03114       else if (expr.substr(0, 2) == "<=")
03115         op = LEQ;
03116 
03117       else if (expr[0] == '>')
03118         op = GT;
03119 
03120       else
03121         op = LT;
03122 
03123       STRING_VECTOR a;
03124       if (op == GT || op == LT)
03125         a = _DBE_get_expr_list(expr.substr(1), 2);
03126 
03127       else
03128         a = _DBE_get_expr_list(expr.substr(2), 2);
03129 
03130       std::string   x_orig = a[0];
03131       double   x = _convert_to_type(x_orig, 1e37);
03132       unsigned i = 1;
03133 
03134       STRING_VECTOR::const_iterator y_orig = a.begin();
03135       for (y_orig++; y_orig != a.end(); ++y_orig)
03136         {
03137           double y = _convert_to_type(*y_orig, 1e37);
03138 
03139           // set the strings as reference if one wasn't a number
03140           if (x == 1e37 || y == 1e37)
03141             {
03142               // it's a string comparison
03143               if ((op == EQ  && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
03144                   (op == LEQ && x_orig <= *y_orig) || (op == GT  && x_orig >  *y_orig) ||
03145                   (op == LT  && x_orig <  *y_orig))
03146                 return _convert_from_type(i);
03147             }
03148           else
03149             {
03150               // it's a number comparison
03151               if ((op == EQ  && x == y) || (op == GEQ && x >= y) ||
03152                   (op == LEQ && x <= y) || (op == GT  && x >  y) ||
03153                   (op == LT  && x <  y))
03154                 return _convert_from_type(i);
03155             }
03156           i++;
03157         }
03158 
03159       // nothing fulfills the condition => return 0
03160       return "0";
03161     }
03162 
03163   // ${?? expr expr} select
03164   else if (expr.length() >= 2 && expr.substr(0, 2) == "??")
03165     {
03166       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2);
03167       double x = _convert_to_type(a[0], 1e37);
03168 
03169       // last element is always the default argument
03170       if (x == 1e37 || x < 0 || x >= a.size() - 1)
03171         return a[a.size()-1];
03172 
03173       // round x to closest integer
03174       return a[int(x+0.5)];
03175     }
03176 
03177   // ${? expr expr expr} if then else conditions
03178   else if (expr[0] == '?')
03179     {
03180       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2);
03181 
03182       if (_convert_to_type(a[0], 0.0) == 1.0)
03183         return a[1];
03184 
03185       else if (a.size() > 2)
03186         return a[2];
03187     }
03188   // ${! expr} maxro expansion
03189   else if (expr[0] == '!')
03190     {
03191       const GetPot::variable* Var = _DBE_get_variable(expr.substr(1));
03192       // error
03193       if (Var->name == "")
03194         return std::string(Var->original);
03195 
03196       const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2);
03197       return A[0];
03198     }
03199   // ${@: } - string subscription
03200   else if (expr.length() >= 2 && expr.substr(0,2) == "@:")
03201     {
03202       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2);
03203       double x = _convert_to_type(A[1], 1e37);
03204 
03205       // last element is always the default argument
03206       if (x == 1e37 || x < 0 || x >= A[0].size() - 1)
03207         return "<<1st index out of range>>";
03208 
03209       if (A.size() > 2)
03210         {
03211           double y = _convert_to_type(A[2], 1e37);
03212           if (y != 1e37 && y > 0 && y <= A[0].size() - 1 && y > x)
03213             return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
03214 
03215           else if (y == -1)
03216             return A[0].substr(int(x+0.5));
03217 
03218           return "<<2nd index out of range>>";
03219         }
03220       else
03221         {
03222           char* tmp = new char[2];
03223           tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
03224           std::string result(tmp);
03225           delete [] tmp;
03226           return result;
03227         }
03228     }
03229   // ${@ } - vector subscription
03230   else if (expr[0] == '@')
03231     {
03232       STRING_VECTOR          A   = _DBE_get_expr_list(expr.substr(1), 2);
03233       const GetPot::variable* Var = _DBE_get_variable(A[0]);
03234       // error
03235       if (Var->name == "")
03236         {
03237           // make a copy of the string if an error occured
03238           // (since the error variable is a static variable inside get_variable())
03239           return std::string(Var->original);
03240         }
03241 
03242       double x = _convert_to_type(A[1], 1e37);
03243 
03244       // last element is always the default argument
03245       if (x == 1e37 || x < 0 || x >= Var->value.size())
03246         return "<<1st index out of range>>";
03247 
03248       if (A.size() > 2)
03249         {
03250           double y = _convert_to_type(A[2], 1e37);
03251           int    begin = int(x+0.5);
03252           int    end = 0;
03253           if (y != 1e37 && y > 0 && y <= Var->value.size() && y > x)
03254             end = int(y+1.5);
03255           else if (y == -1)
03256             end = int(Var->value.size());
03257           else
03258             return "<<2nd index out of range>>";
03259 
03260           std::string result = *(Var->get_element(begin));
03261           for (int i = begin+1; i < end; i++)
03262             result += std::string(" ") + *(Var->get_element(i));
03263           return result;
03264         }
03265       else
03266         return *(Var->get_element(int(x+0.5)));
03267     }
03268 
03269   const STRING_VECTOR    A = _DBE_get_expr_list(expr, 1);
03270   const GetPot::variable* B = _DBE_get_variable(A[0]);
03271 
03272   // make a copy of the string if an error occured
03273   // (since the error variable is a static variable inside get_variable())
03274   if (B->name == "")
03275     return std::string(B->original);
03276 
03277   // (psuggs@pobox.com mentioned to me the warning MSVC++6.0 produces
03278   //  with:  else return B->original (thanks))
03279   return B->original;
03280 }
03281 
03282 
03283 
03285 // (*) unidentified flying objects
03286 //.............................................................................
03287 //
03288 inline bool
03289 GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
03290 {
03291   victorate(std::string, VecStr, itk)
03292     {
03293       if (*itk == Str)
03294         return true;
03295     }
03296   return false;
03297 }
03298 
03299 
03300 
03301 inline STRING_VECTOR
03302 GetPot::unidentified_arguments(unsigned Number,
03303                                const char* KnownArgument1, ...) const
03304 {
03305   std::set<std::string> known_arguments;
03306 
03307   // (1) create a vector of known arguments
03308   if (Number == 0)
03309     return STRING_VECTOR();
03310 
03311   va_list ap;
03312   va_start(ap, KnownArgument1);
03313   known_arguments.insert(std::string(KnownArgument1));
03314   for (unsigned i=1; i<Number; i++)
03315     known_arguments.insert(std::string(va_arg(ap, char *)));
03316   va_end(ap);
03317 
03318   return unidentified_arguments(known_arguments);
03319 }
03320 
03321 
03322 
03323 inline STRING_VECTOR
03324 GetPot::unidentified_arguments() const
03325 {
03326   return unidentified_arguments(_requested_arguments);
03327 }
03328 
03329 
03330 
03331 inline STRING_VECTOR
03332 GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
03333 {
03334   // We use set for efficiency, but want to support vector inputs for
03335   // backwards compatibility.
03336   return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end()));
03337 }
03338 
03339 
03340 
03341 inline STRING_VECTOR
03342 GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const
03343 {
03344   STRING_VECTOR ufos;
03345   STRING_VECTOR::const_iterator it = argv.begin();
03346   ++it; // forget about argv[0] (application or filename)
03347   for (; it != argv.end(); ++it)
03348     {
03349       // -- argument belongs to prefixed section ?
03350       const std::string arg = _get_remaining_string(*it, prefix);
03351       if (arg == "")
03352         continue;
03353 
03354       // -- check if in list
03355       if (Knowns.find(arg) == Knowns.end())
03356         ufos.push_back(*it);
03357     }
03358   return ufos;
03359 }
03360 
03361 
03362 
03363 inline STRING_VECTOR
03364 GetPot::unidentified_options(unsigned Number,
03365                              const char* KnownOption1, ...) const
03366 {
03367   std::set<std::string> known_options;
03368 
03369   // (1) create a vector of known arguments
03370   if (Number == 0)
03371     return STRING_VECTOR();
03372 
03373   va_list ap;
03374   va_start(ap, KnownOption1);
03375   known_options.insert(std::string(KnownOption1));
03376   for (unsigned i=1; i<Number; i++)
03377     known_options.insert(std::string(va_arg(ap, char *)));
03378   va_end(ap);
03379 
03380   return unidentified_options(known_options);
03381 }
03382 
03383 
03384 
03385 inline STRING_VECTOR
03386 GetPot::unidentified_options() const
03387 {
03388   // -- every option is an argument.
03389   // -- the set of requested arguments contains the set of requested options.
03390   // -- IF the set of requested arguments contains unrequested options,
03391   //    THEN they were requested as 'follow' and 'next' arguments and not as real options.
03392   //
03393   // => it is not necessary to separate requested options from the list
03394   return unidentified_arguments(_requested_arguments);
03395 }
03396 
03397 
03398 
03399 inline STRING_VECTOR
03400 GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
03401 {
03402   // We use set for efficiency, but want to support vector inputs for
03403   // backwards compatibility.
03404   return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end()));
03405 }
03406 
03407 
03408 
03409 inline STRING_VECTOR
03410 GetPot::unidentified_options(const std::set<std::string>& Knowns) const
03411 {
03412   STRING_VECTOR ufos;
03413   STRING_VECTOR::const_iterator it = argv.begin();
03414   ++it; // forget about argv[0] (application or filename)
03415   for (; it != argv.end(); ++it)
03416     {
03417       // -- argument belongs to prefixed section ?
03418       const std::string arg = _get_remaining_string(*it, prefix);
03419       if (arg == "")
03420         continue;
03421 
03422       // is argument really an option (starting with '-') ?
03423       if (arg.length() < 1 || arg[0] != '-')
03424         continue;
03425 
03426       if (Knowns.find(arg) == Knowns.end())
03427         ufos.push_back(*it);
03428     }
03429 
03430   return ufos;
03431 }
03432 
03433 
03434 
03435 // Two modes:
03436 //  ArgumentNumber >= 0 check specific argument
03437 //  ArgumentNumber == -1 check all options starting with one '-'
03438 //                       for flags
03439 inline std::string
03440 GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
03441 {
03442   std::string         ufos;
03443   // STRING_VECTOR known_arguments;
03444   std::string         KFL(KnownFlagList);
03445 
03446   // (2) iteration over '-' arguments (options)
03447   if (ArgumentNumber == -1)
03448     {
03449       STRING_VECTOR::const_iterator it = argv.begin();
03450       ++it; // forget about argv[0] (application or filename)
03451       for (; it != argv.end(); ++it)
03452         {
03453           // -- argument belongs to prefixed section ?
03454           const std::string arg = _get_remaining_string(*it, prefix);
03455           if (arg == "") continue;
03456 
03457           // -- does arguments start with '-' (but not '--')
03458           if (arg.length() < 2)
03459             continue;
03460 
03461           else if (arg[0] != '-')
03462             continue;
03463 
03464           else if (arg[1] == '-')
03465             continue;
03466 
03467           // -- check out if flags inside option are contained in KnownFlagList
03468           const char* p=arg.c_str();
03469           p++; // skip starting minus
03470           for (; *p != '\0' ; p++)
03471             if (KFL.find(*p) == std::string::npos) ufos += *p;
03472         }
03473     }
03474   // (1) check specific argument
03475   else
03476     {
03477       // -- only check arguments that start with prefix
03478       int no_matches = 0;
03479       for (unsigned i=1; i<argv.size(); i++)
03480         {
03481           const std::string Remain = _get_remaining_string(argv[i], prefix);
03482           if (Remain != "")
03483             {
03484               no_matches++;
03485               if (no_matches == ArgumentNumber)
03486                 {
03487                   // -- the right argument number inside the section is found
03488                   // => check it for flags
03489                   const char* p = Remain.c_str();
03490                   p++; // skip starting minus
03491                   for (; *p != '\0' ; p++)
03492                     if (KFL.find(*p) == std::string::npos) ufos += *p;
03493                   return ufos;
03494                 }
03495             }
03496         }
03497     }
03498   return ufos;
03499 }
03500 
03501 
03502 
03503 inline STRING_VECTOR
03504 GetPot::unidentified_variables(unsigned Number,
03505                                const char* KnownVariable1, ...) const
03506 {
03507   std::set<std::string> known_variables;
03508 
03509   // create vector of known arguments
03510   if (Number == 0)
03511     return STRING_VECTOR();
03512 
03513   va_list ap;
03514   va_start(ap, KnownVariable1);
03515   known_variables.insert(std::string(KnownVariable1));
03516   for (unsigned i=1; i<Number; i++)
03517     known_variables.insert(std::string(va_arg(ap, char *)));
03518   va_end(ap);
03519 
03520   return unidentified_variables(known_variables);
03521 }
03522 
03523 
03524 
03525 inline STRING_VECTOR
03526 GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
03527 {
03528   // We use set for efficiency, but want to support vector inputs for
03529   // backwards compatibility.
03530   return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end()));
03531 }
03532 
03533 
03534 
03535 inline STRING_VECTOR
03536 GetPot::unidentified_variables(const std::set<std::string>& Knowns) const
03537 {
03538   STRING_VECTOR ufos;
03539 
03540   victorate(GetPot::variable, variables, it)
03541     {
03542       // -- check if variable has specific prefix
03543       const std::string var_name = _get_remaining_string((*it).name, prefix);
03544       if (var_name == "")
03545         continue;
03546 
03547       // -- check if variable is known
03548       if (Knowns.find(var_name) == Knowns.end())
03549         ufos.push_back((*it).name);
03550     }
03551   return ufos;
03552 }
03553 
03554 
03555 
03556 inline STRING_VECTOR
03557 GetPot::unidentified_variables() const
03558 {
03559   return unidentified_variables(_requested_variables);
03560 }
03561 
03562 
03563 
03564 inline STRING_VECTOR
03565 GetPot::unidentified_sections(unsigned Number,
03566                               const char* KnownSection1, ...) const
03567 {
03568   std::set<std::string> known_sections;
03569 
03570   // (1) create a vector of known arguments
03571   if (Number == 0)
03572     return STRING_VECTOR();
03573 
03574   va_list ap;
03575   va_start(ap, KnownSection1);
03576   known_sections.insert(std::string(KnownSection1));
03577   for (unsigned i=1; i<Number; i++)
03578     {
03579       std::string tmp = std::string(va_arg(ap, char *));
03580 
03581       if (tmp.length() == 0)
03582         continue;
03583 
03584       if (tmp[tmp.length()-1] != '/')
03585         tmp += '/';
03586 
03587       known_sections.insert(tmp);
03588     }
03589   va_end(ap);
03590 
03591   return unidentified_sections(known_sections);
03592 }
03593 
03594 
03595 
03596 inline STRING_VECTOR
03597 GetPot::unidentified_sections() const
03598 {
03599   return unidentified_sections(_requested_sections);
03600 }
03601 
03602 
03603 
03604 inline STRING_VECTOR
03605 GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
03606 {
03607   // We use set for efficiency, but want to support vector inputs for
03608   // backwards compatibility.
03609   return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end()));
03610 }
03611 
03612 
03613 
03614 inline STRING_VECTOR
03615 GetPot::unidentified_sections(const std::set<std::string>& Knowns) const
03616 {
03617   STRING_VECTOR ufos;
03618 
03619   victorate(std::string, section_list, it)
03620     {
03621       // -- check if section conform to prefix
03622       const std::string sec_name = _get_remaining_string(*it, prefix);
03623       if (sec_name == "")
03624         continue;
03625 
03626       // -- check if section is known
03627       if (Knowns.find(sec_name) == Knowns.end())
03628         ufos.push_back(*it);
03629     }
03630 
03631   return ufos;
03632 }
03633 
03634 
03635 
03636 inline STRING_VECTOR
03637 GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
03638 {
03639   std::set<std::string> known_nominuses;
03640 
03641   // create vector of known arguments
03642   if (Number == 0)
03643     return STRING_VECTOR();
03644 
03645   va_list ap;
03646   va_start(ap, Known);
03647   known_nominuses.insert(std::string(Known));
03648   for (unsigned i=1; i<Number; i++)
03649     {
03650       std::string tmp = std::string(va_arg(ap, char *));
03651       if (tmp.length() == 0)
03652         continue;
03653       known_nominuses.insert(tmp);
03654     }
03655   va_end(ap);
03656 
03657   return unidentified_nominuses(known_nominuses);
03658 }
03659 
03660 
03661 
03662 inline STRING_VECTOR
03663 GetPot::unidentified_nominuses() const
03664 {
03665   // -- every nominus is an argument.
03666   // -- the set of requested arguments contains the set of requested nominuss.
03667   // -- IF the set of requested arguments contains unrequested nominuss,
03668   //    THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
03669   //
03670   // => it is not necessary to separate requested nominus from the list
03671 
03672   return unidentified_nominuses(_requested_arguments);
03673 }
03674 
03675 
03676 
03677 inline STRING_VECTOR
03678 GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
03679 {
03680   // We use set for efficiency, but want to support vector inputs for
03681   // backwards compatibility.
03682   return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end()));
03683 }
03684 
03685 
03686 
03687 inline STRING_VECTOR
03688 GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const
03689 {
03690   STRING_VECTOR ufos;
03691 
03692   // (2) iterate over all arguments
03693   STRING_VECTOR::const_iterator it = argv.begin();
03694   ++it; // forget about argv[0] (application or filename)
03695   for (; it != argv.end(); ++it)
03696     {
03697       // -- check if nominus part of prefix
03698       const std::string arg = _get_remaining_string(*it, prefix);
03699       if (arg == "")
03700         continue;
03701 
03702       if (arg.length() < 1)
03703         continue;
03704 
03705       // option ? --> not a nomius
03706       if (arg[0] == '-')
03707         continue;
03708 
03709       // section ? --> not a real nominus
03710       if (arg[0] == '[' && arg[arg.length()-1] == ']')
03711         continue;
03712 
03713       // variable definition ? --> not a real nominus
03714       bool continue_f = false;
03715       for (unsigned i=0; i<arg.length() ; i++)
03716         if (arg[i] == '=')
03717           {
03718             continue_f = true;
03719             break;
03720           }
03721 
03722       if (continue_f)
03723         continue;
03724 
03725       // real nominuses are compared with the given list
03726       if (Knowns.find(arg) == Knowns.end())
03727         ufos.push_back(*it);
03728     }
03729   return ufos;
03730 }
03731 
03732 
03733 
03735 // (*) variable class
03736 //.............................................................................
03737 //
03738 inline
03739 GetPot::variable::variable()
03740   : name(),
03741     value(),
03742     original()
03743 {}
03744 
03745 
03746 
03747 inline
03748 GetPot::variable::variable(const variable& Other)
03749 {
03750 #ifdef WIN32
03751   operator=(Other);
03752 #else
03753   GetPot::variable::operator=(Other);
03754 #endif
03755 }
03756 
03757 
03758 
03759 inline
03760 GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
03761   : name(Name)
03762 {
03763   // make a copy of the 'Value'
03764   take(Value, FieldSeparator);
03765 }
03766 
03767 
03768 
03769 inline const std::string*
03770 GetPot::variable::get_element(unsigned Idx) const
03771 {
03772   if (Idx >= value.size())
03773     return 0;
03774   else
03775     return &(value[Idx]);
03776 }
03777 
03778 
03779 
03780 inline void
03781 GetPot::variable::take(const char* Value, const char* FieldSeparator)
03782 {
03783   original = std::string(Value); // string member var
03784   value.clear();                 // vector<string> member var
03785 
03786   /*
03787   // separate string by white space delimiters using 'strtok'
03788   // thread safe usage of strtok (no static members)
03789   char* spt = 0;
03790   // make a copy of the 'Value'
03791   char* copy = new char[strlen(Value)+1];
03792   strcpy(copy, Value);
03793   char* follow_token = strtok_r(copy, FieldSeparator, &spt);
03794   while (follow_token != 0)
03795   {
03796   value.push_back(std::string(follow_token));
03797   follow_token = strtok_r(NULL, FieldSeparator, &spt);
03798   }
03799 
03800   delete [] copy;
03801   */
03802 
03803   // Don't use strtok, instead tokenize the input char "Value" using std::string operations so
03804   // that the results end up in the local "value" member
03805 
03806   // Construct std::string objects from the input char*s.  I think the only
03807   // FieldSeparator recognized by GetPot is whitespace?
03808   std::string Value_str = std::string(Value);
03809   std::string delimiters = std::string(FieldSeparator);
03810 
03811   // Skip delimiters at beginning.
03812   std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0);
03813 
03814   // Find first "non-delimiter".
03815   std::string::size_type pos     = Value_str.find_first_of(delimiters, lastPos);
03816 
03817   // Loop over the input string until all the tokens have been pushed back
03818   // into the local "value" member.
03819   while (std::string::npos != pos || std::string::npos != lastPos)
03820     {
03821       // Found a token, add it to the vector.
03822       value.push_back(Value_str.substr(lastPos, pos - lastPos));
03823 
03824       // Skip delimiters.  Note the "not_of"
03825       lastPos = Value_str.find_first_not_of(delimiters, pos);
03826 
03827       // Find next "non-delimiter"
03828       pos = Value_str.find_first_of(delimiters, lastPos);
03829     }
03830 
03831   // We're done, all the tokens should now be in the vector<string>
03832 }
03833 
03834 inline
03835 GetPot::variable::~variable()
03836 {}
03837 
03838 
03839 
03840 inline GetPot::variable&
03841 GetPot::variable::operator=(const GetPot::variable& Other)
03842 {
03843   if (&Other != this)
03844     {
03845       name     = Other.name;
03846       value    = Other.value;
03847       original = Other.original;
03848     }
03849   return *this;
03850 }
03851 
03852 #ifdef GETPOT_NAMESPACE
03853 }
03854 #endif
03855 
03856 #undef victorate
03857 
03858 #endif // LIBMESH_GETPOT_H