LCOV - code coverage report
Current view: top level - include/base - getpot.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 246 940 26.2 %
Date: 2026-06-03 14:29:06 Functions: 55 122 45.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //  -*- c++ -*-
       2             : //  GetPot Version libMeshHPCT_fork-1.2                        Apr/14/2010
       3             : //  Based on "getpot-1.1.1.tgz" version from SourceForge
       4             : //
       5             : //  New code (C) 2009-2013 Roy Stogner, Karl Schulz
       6             : //
       7             : //  GetPot Version 1.0                                        Sept/13/2002
       8             : //
       9             : //  WEBSITE: http://getpot.sourceforge.net
      10             : //
      11             : //  This library is  free software; you can redistribute  it and/or modify
      12             : //  it  under  the terms  of  the GNU  Lesser  General  Public License  as
      13             : //  published by the  Free Software Foundation; either version  2.1 of the
      14             : //  License, or (at your option) any later version.
      15             : //
      16             : //  This library  is distributed in the  hope that it will  be useful, but
      17             : //  WITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of
      18             : //  MERCHANTABILITY  or FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
      19             : //  Lesser General Public License for more details.
      20             : //
      21             : //  You  should have  received a  copy of  the GNU  Lesser  General Public
      22             : //  License along  with this library; if  not, write to  the Free Software
      23             : //  Foundation, Inc.,  59 Temple Place,  Suite 330, Boston,  MA 02111-1307
      24             : //  USA
      25             : //
      26             : //  (C) 2001-2002 Frank R. Schaefer
      27             : //==========================================================================
      28             : #ifndef LIBMESH_GETPOT_H
      29             : #define LIBMESH_GETPOT_H
      30             : 
      31             : #if defined(WIN32) || defined(SOLARIS_RAW) || (__GNUC__ == 2) || defined(__HP_aCC)
      32             : #define strtok_r(a, b, c) strtok(a, b)
      33             : #endif // WINDOWS or SOLARIS or gcc 2.* or HP aCC
      34             : 
      35             : #include <algorithm>
      36             : #include <cstddef>
      37             : #include <fstream>
      38             : #include <iostream> // not every compiler distribution includes <iostream> with <fstream>
      39             : #include <memory>
      40             : #include <set>
      41             : #include <sstream>
      42             : #include <stdexcept>
      43             : #include <string>
      44             : #include <typeinfo>
      45             : #include <vector>
      46             : 
      47             : #include <cmath>
      48             : #include <cstdlib>
      49             : #include <ctime>
      50             : #include <cctype>
      51             : 
      52             : extern "C" {
      53             : #include <stdarg.h> // --> va_list and friends
      54             : #include <string.h> // --> strcmp, strncmp, strlen, strncpy
      55             : }
      56             : 
      57             : // Undefine USE_LIBMESH to avoid libMesh-specific code
      58             : 
      59             : #define USE_LIBMESH 1
      60             : 
      61             : #ifdef USE_LIBMESH
      62             : 
      63             : #include "libmesh/libmesh_common.h"
      64             : 
      65             : // We need a mutex to keep const operations thread-safe in the
      66             : // presence of mutable containers.  Right now GetPot supports a
      67             : // Threads::scoped_mutex wrapper around TBB, and we're assuming that
      68             : // users aren't doing any threaded GetPot usage when TBB threads are
      69             : // disabled.
      70             : #if !defined(GETPOT_DISABLE_MUTEX)
      71             : #include "libmesh/threads.h"
      72             : #define SCOPED_MUTEX  libMesh::Threads::spin_mutex::scoped_lock lock(_getpot_mtx)
      73             : #define GETPOT_MUTEX_DECLARE mutable libMesh::Threads::spin_mutex _getpot_mtx
      74             : #else
      75             : #define SCOPED_MUTEX
      76             : #define GETPOT_MUTEX_DECLARE
      77             : #endif
      78             : 
      79             : #define getpot_cerr libMesh::err
      80             : #define getpot_error() libmesh_error()
      81             : #define getpot_file_error(filename) libmesh_file_error(filename)
      82             : #define getpot_cast_int libMesh::cast_int
      83             : 
      84             : // If libmesh detected the inverse hyperbolic trig functions, set
      85             : // special #defines for getpot.h
      86             : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_SINE
      87             : #define HAVE_INVERSE_HYPERBOLIC_SINE
      88             : #endif
      89             : 
      90             : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE
      91             : #define HAVE_INVERSE_HYPERBOLIC_COSINE
      92             : #endif
      93             : 
      94             : #ifdef LIBMESH_HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT
      95             : #define HAVE_INVERSE_HYPERBOLIC_TANGENT
      96             : #endif
      97             : 
      98             : #else // !USE_LIBMESH
      99             : 
     100             : // Currently threaded GetPot use is only supported via libMesh Threads
     101             : #define GETPOT_DISABLE_MUTEX
     102             : #define SCOPED_MUTEX
     103             : #define GETPOT_MUTEX_DECLARE
     104             : 
     105             : #define getpot_cerr std::cerr
     106             : #define getpot_error() throw std::runtime_error(std::string("GetPot Error"))
     107             : #define getpot_file_error(filename) getpot_error()
     108             : #define getpot_cast_int static_cast
     109             : 
     110             : // Clang provides the __has_builtin macro, we define it for compilers
     111             : // that don't...
     112             : #ifndef __has_builtin
     113             : #define __has_builtin(x) 0
     114             : #endif
     115             : 
     116             : // Fine-grained ifdefs for all three inverse hyperbolic trig
     117             : // functions.  This works for the two clang compilers I tried it
     118             : // on... a hand-built one and one from Apple.
     119             : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(asinh))
     120             : #define HAVE_INVERSE_HYPERBOLIC_SINE
     121             : #endif
     122             : 
     123             : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(acosh))
     124             : #define HAVE_INVERSE_HYPERBOLIC_COSINE
     125             : #endif
     126             : 
     127             : #if __cplusplus > 199711L && (!defined(__clang__) || __has_builtin(atanh))
     128             : #define HAVE_INVERSE_HYPERBOLIC_TANGENT
     129             : #endif
     130             : 
     131             : #endif // #ifdef USE_LIBMESH
     132             : 
     133             : 
     134             : typedef  std::vector<std::string>  STRING_VECTOR;
     135             : 
     136             : #define victorate(TYPE, VARIABLE, ITERATOR)                             \
     137             :   std::vector<TYPE>::const_iterator ITERATOR = (VARIABLE).begin();      \
     138             :   for (; (ITERATOR) != (VARIABLE).end(); ++(ITERATOR))
     139             : 
     140             : // We allow GETPOT_NAMESPACE to be defined before this file is
     141             : // included; if libraries using two different versions of GetPot might
     142             : // be linked together, the result may be unsafe unless they're put in
     143             : // different namespaces.
     144             : #ifdef GETPOT_NAMESPACE
     145             : namespace GETPOT_NAMESPACE {
     146             : #endif
     147             : 
     148             : /**
     149             :  * GetPot - A class for parsing command line arguments and
     150             :  * configuration files.
     151             :  *
     152             :  * \author Frank R. Schaefer
     153             :  * \date (C) 2001-2002
     154             :  */
     155        3064 : class GetPot
     156             : {
     157             :   inline void _basic_initialization();
     158             : 
     159             : public:
     160             :   /**
     161             :    * constructors, destructor, assignment operator
     162             :    */
     163             :   inline GetPot();
     164             :   inline GetPot(const GetPot&);
     165             :   inline GetPot(const int argc_, const char* const* argv_,
     166             :                 const char* FieldSeparator=0x0);
     167             :   inline GetPot(const char* FileName,
     168             :                 const char* CommentStart=0x0, const char* CommentEnd=0x0,
     169             :                 const char* FieldSeparator=0x0);
     170             :   inline GetPot(const std::string& FileName,
     171             :                 const std::string& CommentStart   = std::string("#"),
     172             :                 const std::string& CommentEnd     = std::string("\n"),
     173             :                 const std::string& FieldSeparator = std::string(" \t\n"));
     174             : 
     175             :   /**
     176             :    * This constructor is mainly for testing. The std::string based constructor
     177             :    * should be preferred.
     178             :    */
     179             :   inline GetPot(std::istream& FileStream,
     180             :                 const std::string& CommentStart   = std::string("#"),
     181             :                 const std::string& CommentEnd     = std::string("\n"),
     182             :                 const std::string& FieldSeparator = std::string(" \t\n"));
     183             :   inline ~GetPot();
     184             :   inline GetPot& operator=(const GetPot&);
     185             : 
     186             :   /**
     187             :    * Re-initialization methods
     188             :    */
     189             :   inline void parse_command_line(const int argc_, const char * const* argv_,
     190             :                                  const char* FieldSeparator =0x0);
     191             :   inline void parse_input_file(const std::string& FileName,
     192             :                                const std::string& CommentStart=std::string("#"),
     193             :                                const std::string& CommentEnd=std::string("\n"),
     194             :                                const std::string& FieldSeparator=std::string(" \t\n"));
     195             : 
     196             :   inline void parse_input_stream(std::istream& FileStream,
     197             :                                  const std::string& FileName=std::string("ParsedFromStream"),
     198             :                                  const std::string& CommentStart=std::string("#"),
     199             :                                  const std::string& CommentEnd=std::string("\n"),
     200             :                                  const std::string& FieldSeparator=std::string(" \t\n"));
     201             : 
     202             :   /**
     203             :    * absorbing contents of another GetPot object
     204             :    */
     205             :   inline void absorb(const GetPot& Other);
     206             : 
     207             :   /**
     208             :    * for ufo detection: recording requested arguments, options etc.
     209             :    */
     210             :   inline void clear_requests();
     211             :   inline void disable_request_recording() { request_recording_f = false; }
     212             :   inline void enable_request_recording() { request_recording_f = true; }
     213             : 
     214             :   /**
     215             :    * direct access to command line arguments
     216             :    */
     217             :   inline const char* operator[](unsigned Idx) const;
     218             : 
     219             :   template <typename T>
     220             :   inline T get(unsigned Idx, const T& Default) const;
     221             : 
     222             :   inline const char* get(unsigned Idx, const char* Default) const;
     223             :   inline unsigned size() const;
     224             : 
     225             :   /**
     226             :    * flags
     227             :    */
     228             :   inline bool options_contain(const char* FlagList) const;
     229             :   inline bool argument_contains(unsigned Idx, const char* FlagList) const;
     230             : 
     231             :   /**
     232             :    * variables
     233             :    */
     234             : 
     235             :   /**
     236             :    * check for a variable
     237             :    */
     238             :   inline bool have_variable(const char* VarName) const;
     239             :   inline bool have_variable(const std::string& VarName) const;
     240             : 
     241             :   /**
     242             :    * Check for a section name. When querying, the section_name
     243             :    * can be of the form
     244             :    * Section1 or Section1/
     245             :    *
     246             :    * Section1/Section2 or Section1/Section2/
     247             :    *
     248             :    * etc.
     249             :    */
     250             :   bool have_section(const char* section_name) const;
     251             : 
     252             :   /**
     253             :    * Check for a section name. When querying, the section_name
     254             :    * can be of the form
     255             :    * Section1 or Section1/
     256             :    *
     257             :    * Section1/Section2 or Section1/Section2/
     258             :    *
     259             :    * etc.
     260             :    */
     261             :   bool have_section(const std::string& section_name) const;
     262             : 
     263             :   /**
     264             :    * scalar values
     265             :    */
     266             :   template<typename T>
     267             :   inline T operator()(const char* VarName, const T& Default) const;
     268             : 
     269             :   template<typename T>
     270             :   inline T operator()(const std::string& VarName, const T& Default) const;
     271             : 
     272             :   inline const char* operator()(const char* VarName, const char* Default) const;
     273             :   inline const char* operator()(const std::string& VarName, const char* Default) const;
     274             : 
     275             :   /**
     276             :    * vectors
     277             :    */
     278             :   template<typename T>
     279             :   inline T operator()(const char* VarName, const T& Default, unsigned Idx) const;
     280             : 
     281             :   template<typename T>
     282             :   inline T operator()(const std::string& VarName, const T& Default, unsigned Idx) const;
     283             : 
     284             :   inline const char* operator()(const char* VarName, const char* Default, unsigned Idx) const;
     285             :   inline const char* operator()(const std::string& VarName, const char* Default, unsigned Idx) const;
     286             : 
     287             :   /**
     288             :    * access variables, but error out if not present
     289             :    * scalar values
     290             :    */
     291             :   template<typename T>
     292             :   inline T get_value_no_default(const char* VarName, const T& Default) const;
     293             : 
     294             :   template<typename T>
     295             :   inline T get_value_no_default(const std::string& VarName, const T& Default) const;
     296             : 
     297             :   inline const char* get_value_no_default(const char* VarName, const char* Default) const;
     298             :   inline const char* get_value_no_default(const std::string& VarName, const char* Default) const;
     299             : 
     300             :   /**
     301             :    * vectors
     302             :    */
     303             :   template<typename T>
     304             :   inline T get_value_no_default(const char* VarName, const T& Default, unsigned Idx) const;
     305             : 
     306             :   template<typename T>
     307             :   inline T get_value_no_default(const std::string& VarName, const T& Default, unsigned Idx) const;
     308             : 
     309             :   inline const char* get_value_no_default(const char* VarName, const char* Default, unsigned Idx) const;
     310             :   inline const char* get_value_no_default(const std::string& VarName, const char* Default, unsigned Idx) const;
     311             : 
     312             :   /**
     313             :    * setting variables
     314             :    *   i) from outside of GetPot (considering prefix etc.)
     315             :    *   ii) from inside, use '_set_variable()' below
     316             :    */
     317             :   template<typename T>
     318             :   inline void set(const char* VarName, const T& Value, const bool Requested = true);
     319             : 
     320             :   template<typename T>
     321             :   inline void set(const std::string& VarName, const T& Value, const bool Requested = true);
     322             : 
     323             :   inline void set(const char* VarName, const char* Value, const bool Requested = true);
     324             :   inline void set(const std::string& VarName, const char* Value, const bool Requested = true);
     325             : 
     326             :   inline unsigned vector_variable_size(const char* VarName) const;
     327             :   inline unsigned vector_variable_size(const std::string& VarName) const;
     328             : 
     329             :   /*
     330             :    * Return a list of all variables set by the current input
     331             :    */
     332             :   inline STRING_VECTOR get_variable_names() const;
     333             : 
     334             :   /*
     335             :    * Return a list of all sections present in the current input
     336             :    */
     337             :   inline STRING_VECTOR get_section_names() const;
     338             : 
     339             :   /*
     340             :    * Return a list of all subsections of the given section name in the
     341             :    * current input.
     342             :    *
     343             :    * Subsections will be returned in the order they appear in the
     344             :    * input.
     345             :    *
     346             :    * Subsections which exist multiple times in the input file will
     347             :    * only be returned once, in the position of their first appearance.
     348             :    */
     349             :   inline STRING_VECTOR get_subsection_names(const std::string & section_name) const;
     350             : 
     351             :   inline std::set<std::string> get_overridden_variables() const;
     352             : 
     353             :   /**
     354             :    * cursor oriented functions
     355             :    */
     356             :   inline void set_prefix(const char* Prefix) { prefix = std::string(Prefix); }
     357             :   inline bool search_failed() const { return search_failed_f; }
     358             : 
     359             :   /**
     360             :    * enable/disable search for an option in loop
     361             :    */
     362           0 :   inline void disable_loop() { search_loop_f = false; }
     363           0 :   inline void enable_loop()  { search_loop_f = true; }
     364             : 
     365             :   /**
     366             :    * reset cursor to position '1'
     367             :    */
     368             :   inline void reset_cursor();
     369             :   inline void init_multiple_occurrence();
     370             : 
     371             :   /**
     372             :    * search for a certain option and set cursor to position
     373             :    */
     374             :   inline bool search(const char* option);
     375             :   inline bool search(const std::string& option);
     376             :   inline bool search(unsigned No, const char* P, ...);
     377             : 
     378             :   /**
     379             :    * get argument at cursor++
     380             :    */
     381             :   template<typename T>
     382             :   inline T next(const T& Default);
     383             : 
     384             :   inline const char* next(const char* Default);
     385             : 
     386             :   /**
     387             :    * search for option and get argument at cursor++
     388             :    */
     389             :   template<typename T>
     390             :   inline T follow(const T& Default, const char* Option);
     391             : 
     392             :   inline const char* follow(const char* Default, const char* Option);
     393             : 
     394             :   /**
     395             :    * search for one of the given options and get argument that follows it
     396             :    */
     397             :   template<typename T>
     398             :   inline T follow(const T& Default, unsigned No, const char* Option, ...);
     399             : 
     400             :   inline const char* follow(const char* Default, unsigned No, const char* Option, ...);
     401             : 
     402             :   /**
     403             :    * directly followed arguments
     404             :    */
     405             :   template<typename T>
     406             :   inline T direct_follow(const T& Default, const char* Option);
     407             : 
     408             :   inline const char* direct_follow(const char* Default, const char* Option);
     409             : 
     410             :   /**
     411             :    * nominus arguments
     412             :    */
     413             :   inline void reset_nominus_cursor();
     414             :   inline STRING_VECTOR nominus_vector() const;
     415             :   inline unsigned nominus_size() const { return getpot_cast_int<unsigned>(idx_nominus.size()); }
     416             :   inline const char* next_nominus();
     417             :   inline std::string next_nominus_string();
     418             : 
     419             :   /**
     420             :    * unidentified flying objects
     421             :    */
     422             :   inline STRING_VECTOR unidentified_arguments(unsigned Number, const char* Known, ...) const;
     423             :   inline STRING_VECTOR unidentified_arguments(const std::set<std::string>& Knowns) const;
     424             :   inline STRING_VECTOR unidentified_arguments(const std::vector<std::string>& Knowns) const;
     425             :   inline STRING_VECTOR unidentified_arguments() const;
     426             : 
     427             :   inline STRING_VECTOR unidentified_options(unsigned Number, const char* Known, ...) const;
     428             :   inline STRING_VECTOR unidentified_options(const std::set<std::string>& Knowns) const;
     429             :   inline STRING_VECTOR unidentified_options(const std::vector<std::string>& Knowns) const;
     430             :   inline STRING_VECTOR unidentified_options() const;
     431             : 
     432             :   inline std::string unidentified_flags(const char* Known, int ArgumentNumber /* =-1 */) const;
     433             : 
     434             :   inline STRING_VECTOR unidentified_variables(unsigned Number, const char* Known, ...) const;
     435             :   inline STRING_VECTOR unidentified_variables(const std::set<std::string>& Knowns) const;
     436             :   inline STRING_VECTOR unidentified_variables(const std::vector<std::string>& Knowns) const;
     437             :   inline STRING_VECTOR unidentified_variables() const;
     438             : 
     439             :   inline STRING_VECTOR unidentified_sections(unsigned Number, const char* Known, ...) const;
     440             :   inline STRING_VECTOR unidentified_sections(const std::set<std::string>& Knowns) const;
     441             :   inline STRING_VECTOR unidentified_sections(const std::vector<std::string>& Knowns) const;
     442             :   inline STRING_VECTOR unidentified_sections() const;
     443             : 
     444             :   inline STRING_VECTOR unidentified_nominuses(unsigned Number, const char* Known, ...) const;
     445             :   inline STRING_VECTOR unidentified_nominuses(const std::set<std::string>& Knowns) const;
     446             :   inline STRING_VECTOR unidentified_nominuses(const std::vector<std::string>& Knowns) const;
     447             :   inline STRING_VECTOR unidentified_nominuses() const;
     448             : 
     449             :   /**
     450             :    * Accessors for requested variables
     451             :    */
     452             :   std::set<std::string> get_requested_arguments() const;
     453             :   std::set<std::string> get_requested_variables() const;
     454             :   std::set<std::string> get_requested_sections() const;
     455             : 
     456             :   /**
     457             :    * output
     458             :    */
     459             : 
     460             :   /**
     461             :    * Print everything
     462             :    */
     463             :   inline int print(std::ostream &out_stream = std::cout) const;
     464             : 
     465             :   /**
     466             :    * Print everything after skipping skip_count arguments, with a
     467             :    * custom prefix.  skip_count defaults to 1 to handle the common
     468             :    * "executable input_file" command line case.
     469             :    */
     470             :   inline int print(const char *custom_prefix,
     471             :                    std::ostream &out_stream = std::cout,
     472             :                    unsigned int skip_count=1) const;
     473             : 
     474             : private:
     475             : 
     476             :   /**
     477             :    * Variable to be specified on the command line or in input files.
     478             :    * (i.e. of the form var='12 312 341')
     479             :    */
     480             :   struct variable
     481             :   {
     482             :     /**
     483             :      * constructors, destructors, assignment operator
     484             :      */
     485             :     variable();
     486             :     variable(const variable&);
     487             :     variable(const char* Name, const char* Value, const char* FieldSeparator);
     488             :     ~variable();
     489             :     variable& operator=(const variable& Other);
     490             : 
     491             :     void take(const char* Value, const char* FieldSeparator);
     492             : 
     493             :     /**
     494             :      * get a specific element in the string vector
     495             :      * (return 0 if not present)
     496             :      */
     497             :     const std::string* get_element(unsigned Idx) const;
     498             : 
     499             :     /**
     500             :      * data members
     501             :      */
     502             :     std::string name;      // identifier of variable
     503             :     STRING_VECTOR value;     // value of variable stored in vector
     504             :     std::string original;  // value of variable as given on command line
     505             :   };
     506             : 
     507             :   /**
     508             :    * member variables
     509             :    */
     510             :   std::string prefix;          // prefix automatically added in queries
     511             :   std::string section;         // (for dollar bracket parsing)
     512             :   STRING_VECTOR section_list;    // list of all parsed sections
     513             : 
     514             :   /**
     515             :    * argument vector
     516             :    */
     517             :   STRING_VECTOR argv; // vector of command line arguments stored as strings
     518             :   unsigned cursor; // cursor for argv
     519             :   bool search_loop_f; // shall search start at beginning after reaching end of arg array ?
     520             :   bool search_failed_f; // flag indicating a failed search() operation (e.g. next() functions react with 'missed')
     521             :   std::set<std::string> overridden_vars; // vector of variables that were supplied more than once during parsing
     522             : 
     523             :   /**
     524             :    * nominus vector
     525             :    */
     526             :   int nominus_cursor;  // cursor for nominus_pointers
     527             :   std::vector<unsigned> idx_nominus;     // indices of 'no minus' arguments
     528             : 
     529             :   /**
     530             :    * variables (arguments of the form "variable=value")
     531             :    */
     532             :   std::vector<variable> variables;
     533             : 
     534             :   /**
     535             :    * comment delimiters
     536             :    */
     537             :   std::string _comment_start;
     538             :   std::string _comment_end;
     539             : 
     540             :   /**
     541             :    * field separator (separating elements of a vector)
     542             :    */
     543             :   std::string _field_separator;
     544             : 
     545             :   /**
     546             :    * we have some mutable non-thread-safe members, but we
     547             :    * want to be able to call const member functions from
     548             :    * multiple threads at once, so we'll wrap access to
     549             :    * mutable objects in a mutex.
     550             :    */
     551             :   GETPOT_MUTEX_DECLARE;
     552             : 
     553             :   /**
     554             :    * Transparent comparator object used for making std::sets that
     555             :    * contain unique_ptrs.
     556             :    */
     557             :   struct ltstr
     558             :   {
     559             :     /**
     560             :      * As of C++14, std::set::find() can be a templated overload.
     561             :      * https://en.cppreference.com/w/cpp/container/set/find
     562             :      * We enable this by defining is_transparent as a type.
     563             :      * See also: the CompareUnderlying struct in libmesh/utility.h
     564             :      */
     565             :     using is_transparent = void;
     566             : 
     567          28 :     bool operator()(const std::unique_ptr<const char[]> & s1,
     568             :                     const std::unique_ptr<const char[]> & s2) const
     569        1005 :     { return strcmp(s1.get(), s2.get()) < 0; }
     570             : 
     571          12 :     bool operator()(const std::unique_ptr<const char[]> & s1,
     572             :                     const char * const & s2) const
     573         507 :     { return strcmp(s1.get(), s2) < 0; }
     574             : 
     575           0 :     bool operator()(const char * const & s1,
     576             :                     const std::unique_ptr<const char[]> & s2) const
     577          24 :     { return strcmp(s1, s2.get()) < 0; }
     578             :   };
     579             : 
     580             :   /**
     581             :    * some functions return a char pointer to a string created on the fly.
     582             :    * this container makes them 'available' until the getpot object is destroyed.
     583             :    * user codes are recommended to instead request std::string values.
     584             :    * We use char* here because c_str() results are only
     585             :    * guaranteed to remain valid until a non-const string
     586             :    * method is called
     587             :    */
     588             :   mutable std::set<std::unique_ptr<const char[]>, ltstr> _internal_string_container;
     589             : 
     590             :   /**
     591             :    * some functions return a char pointer to a temporarily existing string
     592             :    * this function adds them to our container
     593             :    */
     594             :   const char* _internal_managed_copy(const std::string& Arg) const;
     595             : 
     596             :   /**
     597             :    * keeping track about arguments that are requested, so that the UFO detection
     598             :    * can be simplified
     599             :    */
     600             :   mutable std::set<std::string> _requested_arguments;
     601             :   mutable std::set<std::string> _requested_variables;
     602             :   mutable std::set<std::string> _requested_sections;
     603             : 
     604             :   bool request_recording_f;   // speed: request recording can be turned off
     605             : 
     606             :   /**
     607             :    * if an argument is requested record it and the 'tag' the section branch to which
     608             :    * it belongs. Caution: both functions mark the sections as 'tagged'.
     609             :    * These are "const" functions but they do modify the
     610             :    * mutable _requested_* members
     611             :    */
     612             :   void _record_argument_request(const std::string& Arg) const;
     613             :   void _record_variable_request(const std::string& Arg) const;
     614             : 
     615             :   /**
     616             :    * helper functions
     617             :    */
     618             : 
     619             :   /**
     620             :    * set variable from inside GetPot (no prefix considered)
     621             :    */
     622             :   inline void _set_variable(const std::string& VarName,
     623             :                             const std::string& Value,
     624             :                             const bool Requested);
     625             : 
     626             :   /**
     627             :    * produce three basic data vectors:
     628             :    *   - argument vector
     629             :    *   - nominus vector
     630             :    *   - variable dictionary
     631             :    */
     632             :   inline void _parse_argument_vector(const STRING_VECTOR& ARGV);
     633             : 
     634             :   /**
     635             :    * helpers for argument list processing
     636             :    */
     637             : 
     638             :   /**
     639             :    * search for a variable in 'variables' array
     640             :    */
     641             :   inline const variable* _find_variable(const char*) const;
     642             : 
     643             :   /**
     644             :    * search (and record request) for a variable in 'variables' array
     645             :    */
     646             :   inline const variable* _request_variable(const char*) const;
     647             : 
     648             :   /**
     649             :    * support finding directly followed arguments
     650             :    */
     651             :   inline const char* _match_starting_string(const char* StartString);
     652             : 
     653             :   /**
     654             :    * support search for flags in a specific argument
     655             :    */
     656             :   inline bool _check_flags(const std::string& Str, const char* FlagList) const;
     657             : 
     658             :   /**
     659             :    * type conversion if possible
     660             :    */
     661             :   template<typename T>
     662             :   inline T _convert_to_type(const std::string& String, const T& Default) const;
     663             : 
     664             :   inline std::string _convert_to_type(const std::string& String, const char* Default) const;
     665             : 
     666             :   template<typename T>
     667             :   inline T _convert_to_type_no_default(const char* VarName, const std::string& String, const T& Default) const;
     668             : 
     669             :   inline std::string _convert_to_type_no_default(const char* VarName, const std::string& String, const char* Default) const;
     670             : 
     671             :   /**
     672             :    * prefix extraction
     673             :    */
     674             :   const std::string _get_remaining_string(const std::string& String,
     675             :                                           const std::string& Start) const;
     676             :   /**
     677             :    * search for a specific string
     678             :    */
     679             :   inline bool _search_string_vector(const STRING_VECTOR& Vec,
     680             :                                     const std::string& Str) const;
     681             : 
     682             :   /**
     683             :    * helpers to parse input file
     684             :    * create an argument vector based on data found in an input file, i.e.:
     685             :    *    1) delete comments (in between '_comment_start' '_comment_end')
     686             :    *    2) contract assignment expressions, such as
     687             :    *            my-variable   =    '007 J. B.'
     688             :    *      into
     689             :    *            my-variable='007 J. B.'
     690             :    *    3) interpret sections like '[../my-section]' etc.
     691             :    */
     692             :   inline void _skip_whitespace(std::istream& istr);
     693             :   inline const std::string _get_next_token(std::istream& istr);
     694             :   inline const std::string _get_string(std::istream& istr);
     695             :   inline const std::string _get_until_closing_bracket(std::istream& istr);
     696             :   inline const std::string _get_until_closing_square_bracket(std::istream& istr);
     697             : 
     698             :   inline STRING_VECTOR _read_in_stream(std::istream& istr);
     699             :   inline std::string _process_section_label(const std::string& Section,
     700             :                                             STRING_VECTOR& section_stack);
     701             : 
     702             :   /**
     703             :    * dollar bracket expressions
     704             :    */
     705             :   std::string _DBE_expand_string(const std::string& str);
     706             :   std::string _DBE_expand(const std::string& str);
     707             :   const GetPot::variable* _DBE_get_variable(const std::string& str);
     708             :   STRING_VECTOR _DBE_get_expr_list(const std::string& str, const unsigned ExpectedNumber);
     709             : 
     710             :   template <typename T>
     711           0 :   static std::string _convert_from_type(const T& Value)
     712             :   {
     713           0 :     std::ostringstream out_string;
     714           0 :     out_string << Value;
     715           0 :     return out_string.str();
     716           0 :   }
     717             : 
     718             :   /**
     719             :    * cuts a variable name into a tree of sub-sections. this is requested for recording
     720             :    * requested sections when dealing with 'ufo' detection.
     721             :    */
     722    12370742 :   static STRING_VECTOR _get_section_tree(const std::string& FullPath)
     723             :   {
     724       41886 :     STRING_VECTOR   result;
     725   316731526 :     for (std::size_t pos = 0; pos != FullPath.size(); ++pos)
     726             :       {
     727   304360784 :         if (FullPath[pos] == '/')
     728          16 :           result.push_back(FullPath.substr(0,pos));
     729             :       }
     730             : 
     731    12370742 :     return result;
     732           0 :   }
     733             : };
     734             : 
     735             : 
     736             : ///////////////////////////////////////////////////////////////////////////////
     737             : // (*) constructors, destructor, assignment operator
     738             : //.............................................................................
     739             : //
     740             : inline void
     741        9216 : GetPot::_basic_initialization()
     742             : {
     743        9216 :   cursor = 0;
     744        9216 :   nominus_cursor = -1;
     745        9216 :   search_failed_f = true;
     746        9216 :   search_loop_f = true;
     747        9216 :   prefix = "";
     748        9216 :   section = "";
     749             : 
     750             :   // automatic request recording for later ufo detection
     751        9216 :   request_recording_f = true;
     752             : 
     753             :   // comment start and end strings
     754        9216 :   _comment_start = std::string("#");
     755        9216 :   _comment_end   = std::string("\n");
     756             : 
     757             :   // default: separate vector elements by whitespaces
     758        9216 :   _field_separator = " \t\n";
     759        9216 : }
     760             : 
     761             : 
     762             : 
     763             : inline
     764             : GetPot::GetPot() :
     765             :   prefix(),
     766             :   section(),
     767             :   section_list(),
     768             :   argv(),
     769             :   cursor(),
     770             :   search_loop_f(),
     771             :   search_failed_f(),
     772             :   nominus_cursor(),
     773             :   idx_nominus(),
     774             :   variables(),
     775             :   _comment_start(),
     776             :   _comment_end(),
     777             :   _field_separator(),
     778             : #if !defined(GETPOT_DISABLE_MUTEX)
     779             :   _getpot_mtx(),
     780             : #endif
     781             :   _internal_string_container(),
     782             :   _requested_arguments(),
     783             :   _requested_variables(),
     784             :   _requested_sections(),
     785             :   request_recording_f()
     786             : {
     787             :   _basic_initialization();
     788             : }
     789             : 
     790             : 
     791             : 
     792             : inline
     793       31130 : GetPot::GetPot(const int argc_, const char * const * argv_,
     794       31130 :                const char* FieldSeparator /* =0x0 */) :
     795             :   // leave 'char**' non-const to honor less capable compilers ...
     796       29322 :   prefix(),
     797       29322 :   section(),
     798       29322 :   section_list(),
     799       29322 :   argv(),
     800       29322 :   cursor(),
     801       29322 :   search_loop_f(),
     802       29322 :   search_failed_f(),
     803       29322 :   nominus_cursor(),
     804             :   idx_nominus(),
     805       29322 :   variables(),
     806       29322 :   _comment_start(),
     807       29322 :   _comment_end(),
     808       29322 :   _field_separator(),
     809             : #if !defined(GETPOT_DISABLE_MUTEX)
     810             :   _getpot_mtx(),
     811             : #endif
     812             :   _internal_string_container(),
     813             :   _requested_arguments(),
     814             :   _requested_variables(),
     815             :   _requested_sections(),
     816       34874 :   request_recording_f()
     817             : {
     818       31130 :   this->parse_command_line(argc_, argv_, FieldSeparator);
     819       31130 : }
     820             : 
     821             : 
     822             : 
     823             : // leave 'char**' non-const to honor less capable compilers ...
     824             : inline void
     825       24146 : GetPot::parse_command_line(const int argc_, const char * const * argv_,
     826             :                            const char* FieldSeparator /* =0x0 */)
     827             : {
     828       24146 :   _basic_initialization();
     829             : 
     830             :   // if specified -> overwrite default string
     831       24146 :   if (FieldSeparator)
     832           0 :     _field_separator = std::string(FieldSeparator);
     833             : 
     834             :   // -- make an internal copy of the argument list:
     835        1480 :   STRING_VECTOR _apriori_argv;
     836             :   // -- for the sake of clarity: we do want to include the first
     837             :   //    argument of the first parsing source in the argument vector!
     838             :   //    it will not be a nominus argument, though. This gives us a
     839             :   //    minimum vector size of one which facilitates error checking
     840             :   //    in many functions. Also the user will be able to retrieve
     841             :   //    the name of his application or input file by "get[0]"
     842       25082 :   _apriori_argv.push_back(std::string(argv_[0]));
     843      370510 :   for (int i=1; i<argc_; i++)
     844             :     {
     845      347636 :       std::string tmp(argv_[i]);   // recall the problem with temporaries,
     846      346364 :       _apriori_argv.push_back(tmp);       // reference counting in argument lists ...
     847             :     }
     848       24146 :   _parse_argument_vector(_apriori_argv);
     849       24146 : }
     850             : 
     851             : 
     852             : 
     853             : inline
     854           0 : GetPot::GetPot(const char* FileName,
     855             :                const char* CommentStart  /* = 0x0 */, const char* CommentEnd /* = 0x0 */,
     856           0 :                const char* FieldSeparator/* = 0x0 */) :
     857           0 :   prefix(),
     858           0 :   section(),
     859           0 :   section_list(),
     860           0 :   argv(),
     861           0 :   cursor(),
     862           0 :   search_loop_f(),
     863           0 :   search_failed_f(),
     864           0 :   nominus_cursor(),
     865             :   idx_nominus(),
     866           0 :   variables(),
     867           0 :   _comment_start(),
     868           0 :   _comment_end(),
     869           0 :   _field_separator(),
     870             : #if !defined(GETPOT_DISABLE_MUTEX)
     871             :   _getpot_mtx(),
     872             : #endif
     873             :   _internal_string_container(),
     874             :   _requested_arguments(),
     875             :   _requested_variables(),
     876             :   _requested_sections(),
     877           0 :   request_recording_f()
     878             : {
     879           0 :   const std::string& StrCommentStart   = CommentStart   ? CommentStart   : std::string("#");
     880           0 :   const std::string& StrCommentEnd     = CommentEnd     ? CommentEnd     : std::string("\n");
     881           0 :   const std::string& StrFieldSeparator = FieldSeparator ? FieldSeparator : std::string(" \t\n");
     882           0 :   this->parse_input_file(FileName, StrCommentStart, StrCommentEnd, StrFieldSeparator);
     883           0 : }
     884             : 
     885             : 
     886             : 
     887             : inline
     888          12 : GetPot::GetPot(const std::string& FileName,
     889             :                const std::string& CommentStart,
     890             :                const std::string& CommentEnd,
     891          12 :                const std::string& FieldSeparator) :
     892           0 :   prefix(),
     893           0 :   section(),
     894           0 :   section_list(),
     895           0 :   argv(),
     896           0 :   cursor(),
     897           0 :   search_loop_f(),
     898           0 :   search_failed_f(),
     899           0 :   nominus_cursor(),
     900             :   idx_nominus(),
     901           0 :   variables(),
     902           0 :   _comment_start(),
     903           0 :   _comment_end(),
     904           0 :   _field_separator(),
     905             : #if !defined(GETPOT_DISABLE_MUTEX)
     906             :   _getpot_mtx(),
     907             : #endif
     908             :   _internal_string_container(),
     909             :   _requested_arguments(),
     910             :   _requested_variables(),
     911             :   _requested_sections(),
     912          60 :   request_recording_f()
     913             : {
     914          12 :   this->parse_input_file(FileName, CommentStart, CommentEnd, FieldSeparator);
     915          12 : }
     916             : 
     917             : inline void
     918           0 : GetPot::parse_input_file(const std::string& FileName,
     919             :                          const std::string& CommentStart,
     920             :                          const std::string& CommentEnd,
     921             :                          const std::string& FieldSeparator)
     922             : {
     923           0 :   std::ifstream input(FileName.c_str());
     924             : 
     925           0 :   if (!input)
     926           0 :     getpot_file_error(FileName);
     927             : 
     928           0 :   this->parse_input_stream(input,FileName,CommentStart,CommentEnd,FieldSeparator);
     929           0 : }
     930             : 
     931             : 
     932             : inline
     933             : GetPot::GetPot(std::istream& FileStream,
     934             :                const std::string& CommentStart,
     935             :                const std::string& CommentEnd,
     936             :                const std::string& FieldSeparator) :
     937             :   prefix(),
     938             :   section(),
     939             :   section_list(),
     940             :   argv(),
     941             :   cursor(),
     942             :   search_loop_f(),
     943             :   search_failed_f(),
     944             :   nominus_cursor(),
     945             :   idx_nominus(),
     946             :   variables(),
     947             :   _comment_start(),
     948             :   _comment_end(),
     949             :   _field_separator(),
     950             : #if !defined(GETPOT_DISABLE_MUTEX)
     951             :   _getpot_mtx(),
     952             : #endif
     953             :   _internal_string_container(),
     954             :   _requested_arguments(),
     955             :   _requested_variables(),
     956             :   _requested_sections(),
     957             :   request_recording_f()
     958             : {
     959             :   this->parse_input_stream(FileStream,
     960             :                            std::string("ParsedFromStream"),// We don't have a filename here
     961             :                            CommentStart, CommentEnd, FieldSeparator);
     962             : }
     963             : 
     964             : 
     965             : inline void
     966           0 : GetPot::parse_input_stream(std::istream& FileStream,
     967             :                            const std::string& FileName,
     968             :                            const std::string& CommentStart,
     969             :                            const std::string& CommentEnd,
     970             :                            const std::string& FieldSeparator)
     971             : {
     972           0 :   _basic_initialization();
     973             : 
     974             :   // overwrite default strings
     975           0 :   _comment_start = std::string(CommentStart);
     976           0 :   _comment_end   = std::string(CommentEnd);
     977           0 :   _field_separator = FieldSeparator;
     978             : 
     979           0 :   STRING_VECTOR _apriori_argv;
     980             :   // -- the first element of the argument vector stores the name of
     981             :   //    the first parsing source; however, this element is not
     982             :   //    parsed for variable assignments or nominuses.
     983             :   //
     984             :   //    Regardless, we don't add more than one name to the argument
     985             :   //    vector. In this case, we're parsing from a stream, so we'll
     986             :   //    hardcode the "filename" to "ParsedFromStream"
     987           0 :   _apriori_argv.push_back(FileName);
     988             : 
     989           0 :   STRING_VECTOR args = _read_in_stream(FileStream);
     990           0 :   _apriori_argv.insert(_apriori_argv.begin()+1, args.begin(), args.end());
     991           0 :   _parse_argument_vector(_apriori_argv);
     992           0 : }
     993             : 
     994             : 
     995             : 
     996             : inline
     997             : GetPot::GetPot(const GetPot& Other) :
     998             :   prefix(Other.prefix),
     999             :   section(Other.section),
    1000             :   section_list(Other.section_list),
    1001             :   argv(Other.argv),
    1002             :   cursor(Other.cursor),
    1003             :   search_loop_f(Other.search_loop_f),
    1004             :   search_failed_f(Other.search_failed_f),
    1005             :   overridden_vars(),
    1006             :   nominus_cursor(Other.nominus_cursor),
    1007             :   idx_nominus(Other.idx_nominus),
    1008             :   variables(Other.variables),
    1009             :   _comment_start(Other._comment_start),
    1010             :   _comment_end(Other._comment_end),
    1011             :   _field_separator(Other._field_separator),
    1012             :   // #if !defined(GETPOT_DISABLE_MUTEX)
    1013             :   //   _getpot_mtx(Other._getpot_mtx),
    1014             :   // #endif
    1015             :   _internal_string_container(),
    1016             :   _requested_arguments(Other._requested_arguments),
    1017             :   _requested_variables(Other._requested_variables),
    1018             :   _requested_sections(Other._requested_sections),
    1019             :   request_recording_f(Other.request_recording_f)
    1020             : {
    1021             :   for (const auto & otherstr : Other._internal_string_container)
    1022             :     {
    1023             :       auto newlen = strlen(otherstr.get()) + 1;
    1024             :       auto newcopy = std::make_unique<char[]>(newlen);
    1025             :       strncpy(newcopy.get(), otherstr.get(), newlen);
    1026             :       this->_internal_string_container.insert(std::move(newcopy));
    1027             :     }
    1028             : }
    1029             : 
    1030             : 
    1031             : 
    1032             : inline
    1033       26076 : GetPot::~GetPot() = default;
    1034             : 
    1035             : 
    1036             : 
    1037             : inline GetPot&
    1038             : GetPot::operator=(const GetPot& Other)
    1039             : {
    1040             :   if (&Other == this)
    1041             :     return *this;
    1042             : 
    1043             :   prefix               = Other.prefix;
    1044             :   section              = Other.section;
    1045             :   section_list         = Other.section_list;
    1046             :   argv                 = Other.argv;
    1047             :   cursor               = Other.cursor;
    1048             :   search_loop_f        = Other.search_loop_f;
    1049             :   search_failed_f      = Other.search_failed_f;
    1050             :   nominus_cursor       = Other.nominus_cursor;
    1051             :   overridden_vars      = Other.overridden_vars;
    1052             :   idx_nominus          = Other.idx_nominus;
    1053             :   variables            = Other.variables;
    1054             :   _comment_start       = Other._comment_start;
    1055             :   _comment_end         = Other._comment_end;
    1056             :   _field_separator     = Other._field_separator;
    1057             :   // #if !defined(GETPOT_DISABLE_MUTEX)
    1058             :   //   _getpot_mtx          = Other._getpot_mtx;
    1059             :   // #endif
    1060             :   _requested_arguments = Other._requested_arguments;
    1061             :   _requested_variables = Other._requested_variables;
    1062             :   _requested_sections  = Other._requested_sections;
    1063             :   request_recording_f  = Other.request_recording_f;
    1064             : 
    1065             :   // Clear existing strings
    1066             :   _internal_string_container.clear();
    1067             : 
    1068             :   for (const auto & otherstr : Other._internal_string_container)
    1069             :     {
    1070             :       auto newlen = strlen(otherstr.get()) + 1;
    1071             :       auto newcopy = std::make_unique<char[]>(newlen);
    1072             :       strncpy(newcopy.get(), otherstr.get(), newlen);
    1073             :       this->_internal_string_container.insert(std::move(newcopy));
    1074             :     }
    1075             : 
    1076             :   return *this;
    1077             : }
    1078             : 
    1079             : 
    1080             : 
    1081             : inline void
    1082             : GetPot::absorb(const GetPot& Other)
    1083             : {
    1084             :   if (&Other == this)
    1085             :     return;
    1086             : 
    1087             :   // variables that are not influenced by absorption:
    1088             :   //               _comment_start
    1089             :   //               _comment_end
    1090             :   //               cursor
    1091             :   //               nominus_cursor
    1092             :   //               search_failed
    1093             :   //               idx_nominus
    1094             :   //               search_loop_f
    1095             :   argv      = Other.argv;
    1096             :   variables = Other.variables;
    1097             : 
    1098             :   if (request_recording_f)
    1099             :     {
    1100             :       // Get a lock before touching anything mutable
    1101             :       SCOPED_MUTEX;
    1102             : 
    1103             :       _requested_arguments.insert(Other._requested_arguments.begin(), Other._requested_arguments.end());
    1104             :       _requested_variables.insert(Other._requested_variables.begin(), Other._requested_variables.end());
    1105             :       _requested_sections.insert(Other._requested_sections.begin(), Other._requested_sections.end());
    1106             :     }
    1107             : }
    1108             : 
    1109             : 
    1110             : 
    1111             : inline void
    1112             : GetPot::clear_requests()
    1113             : {
    1114             :   // Get a lock before touching anything mutable
    1115             :   SCOPED_MUTEX;
    1116             : 
    1117             :   _requested_arguments.clear();
    1118             :   _requested_variables.clear();
    1119             :   _requested_sections.clear();
    1120             : }
    1121             : 
    1122             : 
    1123             : 
    1124             : inline void
    1125        9204 : GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV)
    1126             : {
    1127        9204 :   if (ARGV.empty())
    1128           0 :     return;
    1129             : 
    1130             :   // build internal databases:
    1131             :   //   1) array with no-minus arguments (usually used as filenames)
    1132             :   //   2) variable assignments:
    1133             :   //             'variable name' '=' number | string
    1134         768 :   STRING_VECTOR                 section_stack;
    1135         256 :   STRING_VECTOR::const_iterator it = ARGV.begin();
    1136             : 
    1137             : 
    1138        9204 :   section = "";
    1139             : 
    1140             :   // -- do not parse the first argument, so that this parsing source
    1141             :   // name is not interpreted a s a nominus or so.  If we already
    1142             :   // have parsed arguments, don't bother adding another parsing
    1143             :   // source name
    1144        9204 :   if (argv.empty())
    1145        9204 :     argv.push_back(*it);
    1146         256 :   ++it;
    1147             : 
    1148             :   // -- loop over remaining arguments
    1149      150124 :   for (; it != ARGV.end(); ++it)
    1150             :     {
    1151      139728 :       std::string arg = *it;
    1152             : 
    1153      140920 :       if (arg.length() == 0)
    1154           0 :         continue;
    1155             : 
    1156             :       // -- [section] labels and [include file] directives
    1157      140920 :       if (arg.length() > 1 && arg[0] == '[' && arg[arg.length()-1] == ']')
    1158             :         {
    1159             : 
    1160             :           // Is this an include file directive?
    1161           0 :           std::size_t include_pos = arg.find("include ", 1);
    1162           0 :           if (include_pos != std::string::npos)
    1163             :             {
    1164             : 
    1165             :               const std::string includefile =
    1166           0 :                 _DBE_expand_string(arg.substr(9, arg.length()-9-include_pos));
    1167             : 
    1168             :               this->parse_input_file
    1169           0 :                 (includefile, _comment_start, _comment_end, _field_separator);
    1170             :             }
    1171             : 
    1172             :           else
    1173             :             {
    1174             :               // (*) sections are considered 'requested arguments'
    1175           0 :               if (request_recording_f)
    1176             :                 {
    1177             :                   // Get a lock before touching anything mutable
    1178           0 :                   SCOPED_MUTEX;
    1179             : 
    1180           0 :                   _requested_arguments.insert(arg);
    1181             :                 }
    1182             : 
    1183           0 :               const std::string Name = _DBE_expand_string(arg.substr(1, arg.length()-2));
    1184           0 :               section = _process_section_label(Name, section_stack);
    1185             :               // new section --> append to list of sections
    1186           0 :               if (find(section_list.begin(), section_list.end(), section) == section_list.end())
    1187           0 :                 if (section.length() != 0) section_list.push_back(section);
    1188           0 :               argv.push_back(arg);
    1189             :             }
    1190             :         }
    1191             :       else
    1192             :         {
    1193      142112 :           arg = section + _DBE_expand_string(arg);
    1194      140920 :           argv.push_back(arg);
    1195             :         }
    1196             : 
    1197             :       // -- separate array for nominus arguments
    1198      140920 :       if (arg[0] != '-')
    1199       69606 :         idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1));
    1200             : 
    1201             :       // -- variables: does arg contain a '=' operator ?
    1202        1192 :       const std::size_t equals_pos = arg.find_first_of('=');
    1203      140920 :       if (equals_pos != std::string::npos)
    1204             :         {
    1205             :           // (*) record for later ufo detection
    1206             :           //     arguments carrying variables are always treated as 'requested' arguments.
    1207             :           //     unrequested variables have to be detected with the ufo-variable
    1208             :           //     detection routine.
    1209        4760 :           if (request_recording_f)
    1210             :             {
    1211             :               // Get a lock before touching anything mutable
    1212         656 :               SCOPED_MUTEX;
    1213             : 
    1214        4432 :               _requested_arguments.insert(arg);
    1215             :             }
    1216             : 
    1217             :           // => arg (from start to '=') = Name of variable
    1218             :           //        (from '=' to end)   = value of variable
    1219        9192 :           _set_variable(arg.substr(0,equals_pos),
    1220        9520 :                         arg.substr(equals_pos+1), false);
    1221             :         }
    1222             :     }
    1223        8692 : }
    1224             : 
    1225             : 
    1226             : 
    1227             : inline STRING_VECTOR
    1228           0 : GetPot::_read_in_stream(std::istream& istr)
    1229             : {
    1230           0 :   STRING_VECTOR  brute_tokens;
    1231           0 :   while (istr)
    1232             :     {
    1233           0 :       _skip_whitespace(istr);
    1234           0 :       const std::string Token = _get_next_token(istr);
    1235             :       // Allow 'keyword =' to parse with an empty string as value.
    1236             :       // Only break at EOF.
    1237             :       // if (Token.length() == 0 || Token[0] == EOF) break;
    1238           0 :       if (Token[0] == EOF)
    1239           0 :         break;
    1240           0 :       brute_tokens.push_back(Token);
    1241             :     }
    1242             : 
    1243             :   // -- reduce expressions of token1'='token2 to a single
    1244             :   //    string 'token1=token2'
    1245             :   // -- copy everything into 'argv'
    1246             :   // -- arguments preceded by something like '[' name ']' (section)
    1247             :   //    produce a second copy of each argument with a prefix '[name]argument'
    1248           0 :   unsigned i1 = 0;
    1249           0 :   unsigned i2 = 1;
    1250           0 :   unsigned i3 = 2;
    1251             : 
    1252           0 :   STRING_VECTOR  arglist;
    1253           0 :   while (i1 < brute_tokens.size())
    1254             :     {
    1255             :       // 1) concatenate 'abcdef' '=' 'efgasdef' to 'abcdef=efgasdef'
    1256             :       // note: java.lang.String: substring(a,b) = from a to b-1
    1257             :       //        C++ string:      substr(a,b)    = from a to a + b
    1258           0 :       std::string result;
    1259           0 :       if (i2 < brute_tokens.size() && brute_tokens[i2] == "=")
    1260             :         {
    1261           0 :           if (i3 >= brute_tokens.size())
    1262           0 :             result = brute_tokens[i1] + brute_tokens[i2];
    1263             :           else
    1264           0 :             result = brute_tokens[i1] + brute_tokens[i2] + brute_tokens[i3];
    1265           0 :           i1 = i3+1; i2 = i3+2; i3 = i3+3;
    1266             :         }
    1267           0 :       else if (i2 < brute_tokens.size() &&
    1268           0 :                brute_tokens[i2].length() > 0 &&
    1269           0 :                brute_tokens[i2][0] == '=')
    1270             :         {
    1271             :           // This case should not be hit if '=' at the beginning of a word
    1272             :           //   is always separated into its own word
    1273           0 :           result = brute_tokens[i1] + brute_tokens[i2];
    1274           0 :           i1 = i3; i2 = i3+1; i3 = i3+2;
    1275             :         }
    1276           0 :       else if (i2 < brute_tokens.size() && brute_tokens[i1][brute_tokens[i1].size()-1] == '=')
    1277             :         {
    1278           0 :           result = brute_tokens[i1] + brute_tokens[i2];
    1279           0 :           i1 = i3; i2 = i3+1; i3 = i3+2;
    1280             :         }
    1281             :       else
    1282             :         {
    1283           0 :           result = brute_tokens[i1];
    1284           0 :           i1=i2; i2=i3; i3++;
    1285             :         }
    1286             : 
    1287             :       // Now strip out any comment
    1288           0 :       size_t comment_start_loc = result.find(_comment_start, 0);
    1289           0 :       if (comment_start_loc != std::string::npos)
    1290           0 :         result = result.substr(0, comment_start_loc);
    1291             : 
    1292           0 :       arglist.push_back(result);
    1293             :     }
    1294           0 :   return arglist;
    1295           0 : }
    1296             : 
    1297             : 
    1298             : 
    1299             : inline void
    1300           0 : GetPot::_skip_whitespace(std::istream& istr)
    1301             : {
    1302             :   // find next non-whitespace while deleting comments
    1303           0 :   int tmp = istr.get();
    1304           0 :   do {
    1305             :     // -- search a non whitespace
    1306           0 :     while (std::isspace(tmp))
    1307             :       {
    1308           0 :         tmp = istr.get();
    1309           0 :         if (!istr)
    1310           0 :           return;
    1311             :       }
    1312             : 
    1313             :     // -- look if characters match the comment starter string
    1314           0 :     for (unsigned i=0; i<_comment_start.length() ; i++)
    1315             :       {
    1316           0 :         if (tmp != _comment_start[i])
    1317             :           {
    1318             :             // -- one step more backwards, since 'tmp' already at non-whitespace
    1319           0 :             istr.unget();
    1320           0 :             return;
    1321             :           }
    1322             : 
    1323             :         // RHS: Why is this here?  It breaks on empty comments
    1324             :         //    tmp = istr.get();
    1325             :         //    if (!istr) { istr.unget(); return; }
    1326             :       }
    1327             :     // 'tmp' contains last character of _comment_starter
    1328             : 
    1329             :     // -- comment starter found -> search for comment ender
    1330           0 :     unsigned match_no=0;
    1331             :     while (true)
    1332             :       {
    1333           0 :         tmp = istr.get();
    1334           0 :         if (!istr)
    1335             :           {
    1336           0 :             istr.unget();
    1337           0 :             return;
    1338             :           }
    1339             : 
    1340           0 :         if (tmp == _comment_end[match_no])
    1341             :           {
    1342           0 :             match_no++;
    1343           0 :             if (match_no == _comment_end.length())
    1344             :               {
    1345           0 :                 istr.unget();
    1346           0 :                 break; // shuffle more whitespace, end of comment found
    1347             :               }
    1348             :           }
    1349             :         else
    1350           0 :           match_no = 0;
    1351             :       }
    1352             : 
    1353           0 :     tmp = istr.get();
    1354             : 
    1355           0 :   } while (istr);
    1356           0 :   istr.unget();
    1357             : }
    1358             : 
    1359             : 
    1360             : 
    1361             : inline const std::string
    1362           0 : GetPot::_get_next_token(std::istream& istr)
    1363             : {
    1364             :   // get next concatenates string token. consider quotes that embrace
    1365             :   // whitespaces
    1366           0 :   std::string token;
    1367           0 :   int    tmp = 0;
    1368             :   while (true)
    1369             :     {
    1370           0 :       int last_letter = tmp;
    1371           0 :       tmp = istr.get();
    1372             : 
    1373           0 :       if (tmp == '=')
    1374             :         {
    1375             :           // Always break at '='.
    1376             :           // This separates '=' at the beginning of a word into its own word.
    1377           0 :           token += getpot_cast_int<char>(tmp);
    1378           0 :           return token;
    1379             :         }
    1380             : 
    1381           0 :       else if (tmp == EOF || ((tmp == ' ' || tmp == '\t' || tmp == '\n') && last_letter != '\\'))
    1382           0 :         return token;
    1383             : 
    1384           0 :       else if (tmp == '\'' && last_letter != '\\')
    1385             :         {
    1386             :           // QUOTES: un-backslashed quotes => it's a string
    1387           0 :           token += _get_string(istr);
    1388           0 :           continue;
    1389             :         }
    1390             : 
    1391           0 :       else if (tmp == '{' && last_letter == '$')
    1392             :         {
    1393           0 :           token += '{' + _get_until_closing_bracket(istr);
    1394           0 :           continue;
    1395             :         }
    1396             : 
    1397           0 :       else if (tmp == '[')
    1398             :         {
    1399           0 :           token += '[' + _get_until_closing_square_bracket(istr);
    1400           0 :           continue;
    1401             :         }
    1402             : 
    1403           0 :       else if (tmp == '$' && last_letter == '\\')
    1404             :         {
    1405           0 :           token += getpot_cast_int<char>(tmp); tmp = 0;  //  so that last_letter will become = 0, not '$';
    1406           0 :           continue;
    1407             :         }
    1408             : 
    1409           0 :       else if (tmp == '\\' && last_letter != '\\')
    1410           0 :         continue;              // don't append un-backslashed backslashes
    1411             : 
    1412           0 :       token += getpot_cast_int<char>(tmp);
    1413           0 :     }
    1414             : }
    1415             : 
    1416             : 
    1417             : 
    1418             : inline const std::string
    1419           0 : GetPot::_get_string(std::istream& istr)
    1420             : {
    1421             :   // parse input until next matching '
    1422           0 :   std::string str;
    1423           0 :   int    tmp = 0;
    1424             :   while (true)
    1425             :     {
    1426           0 :       int last_letter = tmp;
    1427           0 :       tmp = istr.get();
    1428           0 :       if (tmp == EOF)
    1429           0 :         return str;
    1430             : 
    1431             :       // un-backslashed quotes => it's the end of the string
    1432           0 :       else if (tmp == '\'' && last_letter != '\\')
    1433           0 :         return str;
    1434             : 
    1435           0 :       else if (tmp == '\\' && last_letter != '\\')
    1436           0 :         continue; // don't append
    1437             : 
    1438           0 :       str += getpot_cast_int<char>(tmp);
    1439           0 :     }
    1440             : }
    1441             : 
    1442             : 
    1443             : 
    1444             : inline const std::string
    1445           0 : GetPot::_get_until_closing_bracket(std::istream& istr)
    1446             : {
    1447             :   // parse input until next matching }
    1448           0 :   std::string str = "";
    1449           0 :   int    tmp = 0;
    1450           0 :   int    brackets = 1;
    1451             :   while (true)
    1452             :     {
    1453           0 :       int last_letter = tmp;
    1454           0 :       tmp = istr.get();
    1455           0 :       if (tmp == EOF)
    1456           0 :         return str;
    1457             : 
    1458           0 :       else if (tmp == '{' && last_letter == '$')
    1459           0 :         brackets += 1;
    1460             : 
    1461           0 :       else if (tmp == '}')
    1462             :         {
    1463           0 :           brackets -= 1;
    1464             :           // un-backslashed brackets => it's the end of the string
    1465           0 :           if (brackets == 0)
    1466           0 :             return str + '}';
    1467             : 
    1468           0 :           else if (tmp == '\\' && last_letter != '\\')
    1469           0 :             continue;  // do not append an unbackslashed backslash
    1470             :         }
    1471           0 :       str += getpot_cast_int<char>(tmp);
    1472           0 :     }
    1473             : }
    1474             : 
    1475             : 
    1476             : 
    1477             : inline const std::string
    1478           0 : GetPot::_get_until_closing_square_bracket(std::istream& istr)
    1479             : {
    1480             :   // parse input until next matching ]
    1481           0 :   std::string str = "";
    1482           0 :   int    brackets = 1;
    1483             :   while (true)
    1484             :     {
    1485           0 :       int tmp = istr.get();
    1486           0 :       if (tmp == EOF)
    1487           0 :         return str;
    1488             : 
    1489           0 :       else if (tmp == '[')
    1490           0 :         brackets += 1;
    1491             : 
    1492           0 :       else if (tmp == ']')
    1493             :         {
    1494           0 :           brackets -= 1;
    1495           0 :           if (brackets == 0)
    1496           0 :             return str + ']';
    1497             :         }
    1498             : 
    1499           0 :       str += getpot_cast_int<char>(tmp);
    1500           0 :     }
    1501             : }
    1502             : 
    1503             : 
    1504             : 
    1505             : inline std::string
    1506           0 : GetPot::_process_section_label(const std::string& Section,
    1507             :                                STRING_VECTOR& section_stack)
    1508             : {
    1509           0 :   std::string sname = Section;
    1510             :   //  1) subsection of actual section ('./' prefix)
    1511           0 :   if (sname.length() >= 2 && sname.substr(0, 2) == "./")
    1512           0 :     sname = sname.substr(2);
    1513             : 
    1514             :   //  2) subsection of parent section ('../' prefix)
    1515           0 :   else if (sname.length() >= 3 && sname.substr(0, 3) == "../")
    1516             :     {
    1517           0 :       do
    1518             :         {
    1519           0 :           if (section_stack.end() != section_stack.begin())
    1520           0 :             section_stack.pop_back();
    1521           0 :           sname = sname.substr(3);
    1522           0 :         } while (sname.substr(0, 3) == "../");
    1523             :     }
    1524             : 
    1525             :   // 3) subsection of the root-section
    1526             :   else
    1527             :     // [] => back to root section
    1528           0 :     section_stack.erase(section_stack.begin(), section_stack.end());
    1529             : 
    1530           0 :   if (sname != "")
    1531             :     {
    1532             :       // parse section name for 'slashes'
    1533           0 :       unsigned i=0;
    1534           0 :       while (i < sname.length())
    1535             :         {
    1536           0 :           if (sname[i] == '/')
    1537             :             {
    1538           0 :               section_stack.push_back(sname.substr(0,i));
    1539           0 :               if (i+1 < sname.length())
    1540           0 :                 sname = sname.substr(i+1);
    1541           0 :               i = 0;
    1542             :             }
    1543             :           else
    1544           0 :             i++;
    1545             :         }
    1546           0 :       section_stack.push_back(sname);
    1547             :     }
    1548             : 
    1549           0 :   std::string section_label = "";
    1550           0 :   if (!section_stack.empty())
    1551             :     {
    1552           0 :       victorate(std::string, section_stack, it)
    1553           0 :         section_label += *it + "/";
    1554             :     }
    1555           0 :   return section_label;
    1556             : }
    1557             : 
    1558             : 
    1559             : 
    1560             : // Use C++ istream/ostream to handle most type conversions.
    1561             : template <typename T>
    1562             : inline T
    1563       17102 : GetPot::_convert_to_type(const std::string& String, const T& Default) const
    1564             : {
    1565       17102 :   std::istringstream in_string(String);
    1566             :   T retval;
    1567       11558 :   in_string >> retval;
    1568       17102 :   if (in_string.fail())
    1569           0 :     retval = Default;
    1570       17690 :   return retval;
    1571       16514 : }
    1572             : 
    1573             : 
    1574             : 
    1575             : // copy string - operator>> would have stopped upon seeing whitespace!
    1576             : template <>
    1577             : inline std::string
    1578         270 : GetPot::_convert_to_type(const std::string& String, const std::string&) const
    1579             : {
    1580        2550 :   return String;
    1581             : }
    1582             : 
    1583             : 
    1584             : 
    1585             : // copy string
    1586             : inline std::string
    1587             : GetPot::_convert_to_type(const std::string& String, const char*) const
    1588             : {
    1589             :   return String;
    1590             : }
    1591             : 
    1592             : 
    1593             : 
    1594             : // be more liberal than std C++ in what we interpret as a boolean
    1595             : template<>
    1596             : inline bool
    1597         277 : GetPot::_convert_to_type<bool>(const std::string& String, const bool & Default) const
    1598             : {
    1599         269 :   std::string newstring(String);
    1600             :   //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
    1601        1525 :   for (unsigned int i=0; i<newstring.length(); ++i)
    1602        1284 :     newstring[i] = getpot_cast_int<char>(toupper(newstring[i]));
    1603             : 
    1604             :   // "true"/"True"/"TRUE" should work
    1605         277 :   if (newstring.find("TRUE")!=std::string::npos)
    1606           0 :     return true;
    1607             : 
    1608         140 :   if (newstring.find("FALSE")!=std::string::npos)
    1609           0 :     return false;
    1610             : 
    1611             :   // And if we don't find that, let's search for an integer and use C unsigned
    1612             :   // int->bool conversion before giving up; i.e. a user could specify "0" for
    1613             :   // false or "1" for true
    1614           0 :   std::istringstream in_string(String);
    1615             :   unsigned int retval;
    1616           0 :   in_string >> retval;
    1617           0 :   if (in_string.fail())
    1618           0 :     return Default;
    1619             : 
    1620           0 :   return retval;
    1621           0 : }
    1622             : 
    1623             : 
    1624             : 
    1625             : // Use C++ istream/ostream to handle most type conversions.
    1626             : template <typename T>
    1627             : inline T
    1628             : GetPot::_convert_to_type_no_default(const char* VarName, const std::string& String, const T&) const
    1629             : {
    1630             :   std::istringstream in_string(String);
    1631             :   T retval;
    1632             :   in_string >> retval;
    1633             :   if (in_string.fail())
    1634             :     {
    1635             :       getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
    1636             :       getpot_cerr <<"       value = "<<String<<" expected type = "<<typeid(T).name()<<std::endl;
    1637             :       getpot_error();
    1638             :     }
    1639             :   return retval;
    1640             : }
    1641             : 
    1642             : 
    1643             : 
    1644             : // copy string - operator>> would have stopped upon seeing whitespace!
    1645             : template <>
    1646             : inline std::string
    1647             : GetPot::_convert_to_type_no_default(const char*, const std::string& String, const std::string&) const
    1648             : {
    1649             :   return String;
    1650             : }
    1651             : 
    1652             : 
    1653             : 
    1654             : // copy string
    1655             : inline std::string
    1656             : GetPot::_convert_to_type_no_default(const char*, const std::string& String, const char*) const
    1657             : {
    1658             :   return String;
    1659             : }
    1660             : 
    1661             : 
    1662             : 
    1663             : // be more liberal than std C++ in what we interpret as a boolean
    1664             : template<>
    1665             : inline bool
    1666             : GetPot::_convert_to_type_no_default<bool>(const char* VarName, const std::string& String, const bool &) const
    1667             : {
    1668             :   std::string newstring(String);
    1669             :   //std::transform(newstring.begin(), newstring.end(), newstring.begin(), std::toupper);
    1670             :   for (unsigned int i=0; i<newstring.length(); ++i)
    1671             :     {
    1672             :       newstring[i]=getpot_cast_int<char>(toupper(newstring[i]));
    1673             :     }
    1674             : 
    1675             :   // "true"/"True"/"TRUE" should work
    1676             :   if (newstring.find("TRUE")!=std::string::npos)
    1677             :     return true;
    1678             : 
    1679             :   if (newstring.find("FALSE")!=std::string::npos)
    1680             :     return false;
    1681             : 
    1682             :   // And if we don't find that, let's search for an integer and use C unsigned
    1683             :   // int->bool conversion before giving up; i.e. a user could specify "0" for
    1684             :   // false or "1" for true
    1685             :   std::istringstream in_string(String);
    1686             :   unsigned int retval;
    1687             :   in_string >> retval;
    1688             :   if (in_string.fail())
    1689             :     {
    1690             :       getpot_cerr <<"ERROR: Input value for variable "<<VarName<<" is of the wrong type."<<std::endl;
    1691             :       getpot_cerr <<"       value = "<<String<<" expected type = "<<typeid(bool).name()<<std::endl;
    1692             :       getpot_error();
    1693             :     }
    1694             : 
    1695             :   return retval;
    1696             : }
    1697             : 
    1698             : 
    1699             : 
    1700             : inline const char*
    1701         462 : GetPot::_internal_managed_copy(const std::string& Arg) const
    1702             : {
    1703         462 :   const char* arg = Arg.c_str();
    1704             : 
    1705             :   // Get a lock before touching anything mutable
    1706          24 :   SCOPED_MUTEX;
    1707             : 
    1708             :   // See if there's already an identical string saved
    1709             :   // If so, return it
    1710         462 :   if (auto it = _internal_string_container.find(arg);
    1711          12 :       it != _internal_string_container.end())
    1712           0 :     return it->get();
    1713             : 
    1714             :   // Otherwise, create a new one
    1715         474 :   auto newcopy = std::make_unique<char[]>(strlen(arg)+1);
    1716             :   // Note: strcpy() is safe here because we allocated enough space and
    1717             :   // "arg" is guaranteed to be null-terminated.
    1718         462 :   strcpy(newcopy.get(), arg);
    1719         868 :   auto pr = _internal_string_container.insert(std::move(newcopy));
    1720          12 :   return pr.first->get();
    1721             : }
    1722             : 
    1723             : 
    1724             : 
    1725             : //////////////////////////////////////////////////////////////////////////////
    1726             : // (*) cursor oriented functions
    1727             : //.............................................................................
    1728             : 
    1729             : // Checks if 'String' begins with 'Start' and returns the remaining String.
    1730             : // Returns None if String does not begin with Start.
    1731             : inline const std::string
    1732       12916 : GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const
    1733             : {
    1734       12916 :   if (Start == "")
    1735       12442 :     return String;
    1736             : 
    1737             :   // note: java.lang.String: substring(a,b) = from a to b-1
    1738             :   //        C++ string:      substr(a,b)    = from a to a + b
    1739           0 :   if (String.find(Start) == 0)
    1740           0 :     return String.substr(Start.length());
    1741             : 
    1742             :   else
    1743           0 :     return "";
    1744             : }
    1745             : 
    1746             : 
    1747             : 
    1748             : // -- search for a certain argument and set cursor to position
    1749             : inline bool
    1750      365170 : GetPot::search(const std::string &Option)
    1751             : {
    1752    14059609 :   return search(Option.c_str());
    1753             : }
    1754             : 
    1755             : 
    1756             : 
    1757             : // -- search for a certain argument and set cursor to position
    1758             : inline bool
    1759    13196712 : GetPot::search(const char* Option)
    1760             : {
    1761    13196712 :   unsigned           OldCursor = cursor;
    1762    13531794 :   const std::string  SearchTerm = prefix + Option;
    1763             : 
    1764             :   // (*) record requested arguments for later ufo detection
    1765    13196712 :   _record_argument_request(SearchTerm);
    1766             : 
    1767    13531674 :   if (OldCursor >= argv.size())
    1768           0 :     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
    1769    13196712 :   search_failed_f = true;
    1770             : 
    1771             :   // (*) first loop from cursor position until end
    1772   213867748 :   for (unsigned c = cursor; c < argv.size(); c++)
    1773             :     {
    1774   199546910 :       if (argv[c] == SearchTerm)
    1775             :         {
    1776        7588 :           cursor = c;
    1777        7588 :           search_failed_f = false;
    1778        7588 :           return true;
    1779             :         }
    1780             :     }
    1781    13189124 :   if (!search_loop_f)
    1782           0 :     return false;
    1783             : 
    1784             :   // (*) second loop from 0 to old cursor position
    1785    44345830 :   for (unsigned c = 1; c <= OldCursor; c++)
    1786             :     {
    1787    31165065 :       if (argv[c] == SearchTerm)
    1788             :         {
    1789        8359 :           cursor = c;
    1790        8359 :           search_failed_f = false;
    1791        8359 :           return true;
    1792             :         }
    1793             :     }
    1794             : 
    1795             :   // in case nothing is found the cursor stays where it was
    1796      334518 :   return false;
    1797             : }
    1798             : 
    1799             : 
    1800             : 
    1801             : inline bool
    1802           0 : GetPot::search(unsigned No, const char* P, ...)
    1803             : {
    1804             :   // (*) recording the requested arguments happens in subroutine 'search'
    1805           0 :   if (No == 0)
    1806           0 :     return false;
    1807             : 
    1808             :   // search for the first argument
    1809           0 :   if (search(P) == true)
    1810           0 :     return true;
    1811             : 
    1812             :   // start interpreting variable argument list
    1813             :   va_list ap;
    1814           0 :   va_start(ap, P);
    1815           0 :   unsigned i = 1;
    1816           0 :   for (; i < No; i++)
    1817             :     {
    1818           0 :       char* Opt = va_arg(ap, char *);
    1819             :       // (*) search records itself for later ufo detection
    1820           0 :       if (search(Opt) == true)
    1821           0 :         break;
    1822             :     }
    1823             : 
    1824           0 :   if (i < No)
    1825             :     {
    1826           0 :       i++;
    1827             :       // loop was left before end of array --> hit but
    1828             :       // make sure that the rest of the search terms is marked
    1829             :       // as requested.
    1830           0 :       for (; i < No; i++)
    1831             :         {
    1832           0 :           char* Opt = va_arg(ap, char *);
    1833             :           // (*) record requested arguments for later ufo detection
    1834           0 :           _record_argument_request(Opt);
    1835             :         }
    1836           0 :       va_end(ap);
    1837           0 :       return true;
    1838             :     }
    1839             : 
    1840           0 :   va_end(ap);
    1841             :   // loop was left normally --> no hit
    1842           0 :   return false;
    1843             : }
    1844             : 
    1845             : 
    1846             : 
    1847             : inline void
    1848           0 : GetPot::reset_cursor()
    1849             : {
    1850           0 :   search_failed_f = false;
    1851           0 :   cursor = 0;
    1852           0 : }
    1853             : 
    1854             : 
    1855             : 
    1856             : inline void
    1857             : GetPot::init_multiple_occurrence()
    1858             : {
    1859             :   disable_loop();
    1860             :   reset_cursor();
    1861             : }
    1862             : 
    1863             : 
    1864             : 
    1865             : ///////////////////////////////////////////////////////////////////////////////
    1866             : // (*) direct access to command line arguments
    1867             : //.............................................................................
    1868             : //
    1869             : inline const char*
    1870             : GetPot::operator[](unsigned idx) const
    1871             : {
    1872             :   return idx<argv.size() ? argv[idx].c_str() : 0;
    1873             : }
    1874             : 
    1875             : 
    1876             : 
    1877             : template <typename T>
    1878             : inline T
    1879             : GetPot::get(unsigned int Idx, const T& Default) const
    1880             : {
    1881             :   if (Idx >= argv.size())
    1882             :     return Default;
    1883             :   return _convert_to_type(argv[Idx], Default);
    1884             : }
    1885             : 
    1886             : 
    1887             : 
    1888             : inline const char*
    1889             : GetPot::get(unsigned int Idx, const char* Default) const
    1890             : {
    1891             :   if (Idx >= argv.size())
    1892             :     return Default;
    1893             :   return argv[Idx].c_str();
    1894             : }
    1895             : 
    1896             : 
    1897             : 
    1898             : inline unsigned
    1899             : GetPot::size() const
    1900             : {
    1901             :   return getpot_cast_int<unsigned>(argv.size());
    1902             : }
    1903             : 
    1904             : 
    1905             : 
    1906             : // -- next() function group
    1907             : template <typename T>
    1908             : inline T
    1909       12920 : GetPot::next(const T& Default)
    1910             : {
    1911       12920 :   if (search_failed_f)
    1912           0 :     return Default;
    1913       12920 :   cursor++;
    1914       13394 :   if (cursor >= argv.size())
    1915             :     {
    1916           0 :       cursor = getpot_cast_int<unsigned>(argv.size());
    1917           0 :       return Default;
    1918             :     }
    1919             : 
    1920             :   // (*) record requested argument for later ufo detection
    1921       12920 :   _record_argument_request(argv[cursor]);
    1922             : 
    1923       13428 :   const std::string Remain = _get_remaining_string(argv[cursor], prefix);
    1924             : 
    1925       12954 :   return Remain != "" ? _convert_to_type(Remain, Default) : Default;
    1926             : }
    1927             : 
    1928             : 
    1929             : 
    1930             : inline const char*
    1931           0 : GetPot::next(const char* Default)
    1932             : {
    1933           0 :   return _internal_managed_copy(next(std::string(Default)));
    1934             : }
    1935             : 
    1936             : 
    1937             : 
    1938             : // -- follow() function group
    1939             : //    distinct option to be searched for
    1940             : template <typename T>
    1941             : inline T
    1942           0 : GetPot::follow(const T& Default, const char* Option)
    1943             : {
    1944             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1945           0 :   if (search(Option) == false)
    1946           0 :     return Default;
    1947             : 
    1948           0 :   return next(Default);
    1949             : }
    1950             : 
    1951             : 
    1952             : 
    1953             : inline const char*
    1954             : GetPot::follow(const char* Default, const char* Option)
    1955             : {
    1956             :   return _internal_managed_copy(follow(std::string(Default), Option));
    1957             : }
    1958             : 
    1959             : 
    1960             : 
    1961             : // -- second follow() function group
    1962             : //    multiple option to be searched for
    1963             : template <typename T>
    1964             : inline T
    1965             : GetPot::follow(const T& Default, unsigned int No, const char* P, ...)
    1966             : {
    1967             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1968             :   if (No == 0)
    1969             :     return Default;
    1970             : 
    1971             :   if (search(P) == true)
    1972             :     return next(Default);
    1973             : 
    1974             :   va_list ap;
    1975             :   va_start(ap, P);
    1976             :   for (unsigned i=1; i<No; i++)
    1977             :     {
    1978             :       char* Opt = va_arg(ap, char *);
    1979             :       if (search(Opt) == true)
    1980             :         {
    1981             :           va_end(ap);
    1982             :           return next(Default);
    1983             :         }
    1984             :     }
    1985             :   va_end(ap);
    1986             :   return Default;
    1987             : }
    1988             : 
    1989             : 
    1990             : 
    1991             : inline const char*
    1992             : GetPot::follow(const char* Default, unsigned No, const char* P, ...)
    1993             : {
    1994             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1995             :   if (No == 0)
    1996             :     return Default;
    1997             : 
    1998             :   if (search(P) == true)
    1999             :     return next(Default);
    2000             : 
    2001             :   va_list ap;
    2002             :   va_start(ap, P);
    2003             :   for (unsigned i=1; i<No; i++)
    2004             :     {
    2005             :       char* Opt = va_arg(ap, char *);
    2006             :       if (search(Opt) == true)
    2007             :         {
    2008             :           va_end(ap);
    2009             :           return next(Default);
    2010             :         }
    2011             :     }
    2012             :   va_end(ap);
    2013             :   return Default;
    2014             : }
    2015             : 
    2016             : 
    2017             : 
    2018             : ///////////////////////////////////////////////////////////////////////////////
    2019             : // (*) directly connected options
    2020             : //.............................................................................
    2021             : //
    2022             : template <typename T>
    2023             : inline T
    2024             : GetPot::direct_follow(const T& Default, const char* Option)
    2025             : {
    2026             :   const char* FollowStr = _match_starting_string(Option);
    2027             : 
    2028             :   // (*) record requested of argument for later ufo-detection
    2029             :   _record_argument_request(std::string(Option) + FollowStr);
    2030             : 
    2031             :   if (FollowStr == 0)
    2032             :     return Default;
    2033             : 
    2034             :   if (++cursor >= argv.size())
    2035             :     cursor = getpot_cast_int<unsigned>(argv.size());
    2036             :   return _convert_to_type(FollowStr, Default);
    2037             : }
    2038             : 
    2039             : 
    2040             : 
    2041             : inline const char*
    2042             : GetPot::direct_follow(const char* Default, const char* Option)
    2043             : {
    2044             :   return _internal_managed_copy(direct_follow(std::string(Default), Option));
    2045             : }
    2046             : 
    2047             : 
    2048             : 
    2049             : // pointer  to the place where the string after
    2050             : //          the match inside the found argument starts.
    2051             : // 0        no argument matches the starting string.
    2052             : inline const char*
    2053             : GetPot::_match_starting_string(const char* StartString)
    2054             : {
    2055             :   const unsigned N =
    2056             :     getpot_cast_int<unsigned>(strlen(StartString));
    2057             :   unsigned       OldCursor = cursor;
    2058             : 
    2059             :   if (OldCursor >= argv.size())
    2060             :     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
    2061             :   search_failed_f = true;
    2062             : 
    2063             :   // (*) first loop from cursor position until end
    2064             :   for (unsigned c = cursor; c < argv.size(); c++)
    2065             :     {
    2066             :       if (strncmp(StartString, argv[c].c_str(), N) == 0)
    2067             :         {
    2068             :           cursor = c;
    2069             :           search_failed_f = false;
    2070             :           return &(argv[c].c_str()[N]);
    2071             :         }
    2072             :     }
    2073             : 
    2074             :   if (!search_loop_f)
    2075             :     return NULL;
    2076             : 
    2077             :   // (*) second loop from 0 to old cursor position
    2078             :   for (unsigned c = 1; c < OldCursor; c++)
    2079             :     {
    2080             :       if (strncmp(StartString, argv[c].c_str(), N) == 0)
    2081             :         {
    2082             :           cursor = c;
    2083             :           search_failed_f = false;
    2084             :           return &(argv[c].c_str()[N]);
    2085             :         }
    2086             :     }
    2087             :   return 0;
    2088             : }
    2089             : 
    2090             : 
    2091             : 
    2092             : ///////////////////////////////////////////////////////////////////////////////
    2093             : // (*) search for flags
    2094             : //.............................................................................
    2095             : //
    2096             : inline bool
    2097             : GetPot::options_contain(const char* FlagList) const
    2098             : {
    2099             :   // go through all arguments that start with a '-' (but not '--')
    2100             :   std::string str;
    2101             :   STRING_VECTOR::const_iterator it = argv.begin();
    2102             :   for (; it != argv.end(); ++it)
    2103             :     {
    2104             :       str = _get_remaining_string(*it, prefix);
    2105             : 
    2106             :       if (str.length() >= 2 && str[0] == '-' && str[1] != '-')
    2107             :         if (_check_flags(str, FlagList))
    2108             :           return true;
    2109             :     }
    2110             :   return false;
    2111             : }
    2112             : 
    2113             : 
    2114             : 
    2115             : inline bool
    2116             : GetPot::argument_contains(unsigned Idx, const char* FlagList) const
    2117             : {
    2118             :   if (Idx >= argv.size())
    2119             :     return false;
    2120             : 
    2121             :   // (*) record requested of argument for later ufo-detection
    2122             :   //     an argument that is checked for flags is considered to be 'requested'
    2123             :   _record_argument_request(argv[Idx]);
    2124             : 
    2125             :   if (prefix == "")
    2126             :     // search argument for any flag in flag list
    2127             :     return _check_flags(argv[Idx], FlagList);
    2128             : 
    2129             :   // if a prefix is set, then the argument index is the index
    2130             :   //   inside the 'namespace'
    2131             :   // => only check list of arguments that start with prefix
    2132             :   unsigned no_matches = 0;
    2133             :   for (unsigned i=0; i<argv.size(); i++)
    2134             :     {
    2135             :       const std::string Remain = _get_remaining_string(argv[i], prefix);
    2136             :       if (Remain != "")
    2137             :         {
    2138             :           no_matches += 1;
    2139             :           if (no_matches == Idx)
    2140             :             return _check_flags(Remain, FlagList);
    2141             :         }
    2142             :     }
    2143             : 
    2144             :   // no argument in this namespace
    2145             :   return false;
    2146             : }
    2147             : 
    2148             : 
    2149             : 
    2150             : inline bool
    2151             : GetPot::_check_flags(const std::string& Str, const char* FlagList) const
    2152             : {
    2153             :   for (const char* p=FlagList; *p != '\0' ; p++)
    2154             :     if (Str.find(*p) != std::string::npos)
    2155             :       return true; // found something
    2156             :   return false;
    2157             : }
    2158             : 
    2159             : 
    2160             : 
    2161             : ///////////////////////////////////////////////////////////////////////////////
    2162             : // (*) nominus arguments
    2163             : 
    2164             : // return vector of nominus arguments
    2165             : inline STRING_VECTOR
    2166             : GetPot::nominus_vector() const
    2167             : {
    2168             :   STRING_VECTOR nv;
    2169             :   std::vector<unsigned>::const_iterator it = idx_nominus.begin();
    2170             :   for (; it != idx_nominus.end(); ++it)
    2171             :     {
    2172             :       nv.push_back(argv[*it]);
    2173             : 
    2174             :       // (*) record for later ufo-detection
    2175             :       //     when a nominus vector is requested, the entire set of nominus arguments are
    2176             :       //     tagged as 'requested'
    2177             :       _record_argument_request(argv[*it]);
    2178             :     }
    2179             :   return nv;
    2180             : }
    2181             : 
    2182             : 
    2183             : 
    2184             : inline const char*
    2185             : GetPot::next_nominus()
    2186             : {
    2187             :   if (nominus_cursor < int(idx_nominus.size()) - 1)
    2188             :     {
    2189             :       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
    2190             : 
    2191             :       // (*) record for later ufo-detection
    2192             :       _record_argument_request(Tmp);
    2193             : 
    2194             :       return _internal_managed_copy(Tmp);
    2195             :     }
    2196             : 
    2197             :   return 0;
    2198             : }
    2199             : 
    2200             : 
    2201             : inline std::string
    2202             : GetPot::next_nominus_string()
    2203             : {
    2204             :   if (nominus_cursor < int(idx_nominus.size()) - 1)
    2205             :     {
    2206             :       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
    2207             : 
    2208             :       // (*) record for later ufo-detection
    2209             :       _record_argument_request(Tmp);
    2210             : 
    2211             :       return Tmp;
    2212             :     }
    2213             : 
    2214             :   return "";
    2215             : }
    2216             : 
    2217             : 
    2218             : 
    2219             : inline void
    2220             : GetPot::reset_nominus_cursor()
    2221             : {
    2222             :   nominus_cursor = -1;
    2223             : }
    2224             : 
    2225             : 
    2226             : 
    2227             : ///////////////////////////////////////////////////////////////////////////////
    2228             : // (*) variables
    2229             : //.............................................................................
    2230             : //
    2231             : inline bool
    2232        2116 : GetPot::have_variable(const char* VarName) const
    2233             : {
    2234      393613 :   const variable* sv = _request_variable(VarName);
    2235             : 
    2236      393613 :   if (sv == 0)
    2237        1708 :     return false;
    2238             : 
    2239         408 :   return true;
    2240             : }
    2241             : 
    2242             : 
    2243             : 
    2244             : inline bool
    2245       11324 : GetPot::have_variable(const std::string& VarName) const
    2246             : {
    2247       11324 :   return have_variable(VarName.c_str());
    2248             : }
    2249             : 
    2250             : inline bool
    2251             : GetPot::have_section(const char* section_name) const
    2252             : {
    2253             :   std::string s = std::string(section_name);
    2254             :   return this->have_section(s);
    2255             : }
    2256             : 
    2257             : inline bool
    2258             : GetPot::have_section(const std::string& section_name) const
    2259             : {
    2260             :   const char slash('/');
    2261             : 
    2262             :   std::string::const_reverse_iterator it = section_name.rbegin();
    2263             : 
    2264             :   bool found_section = false;
    2265             : 
    2266             :   // Check if section_name ends with a "/". If not, append it for the search since
    2267             :   // the section names are stored with a "/" at the end.
    2268             :   if( (*it) != slash )
    2269             :     // We need to use a linear search because we can't sort section_list
    2270             :     // without violating some assumptions. See libMesh #481 for more discussion.
    2271             :     found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() );
    2272             :   else
    2273             :     found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() );
    2274             : 
    2275             :   return found_section;
    2276             : }
    2277             : 
    2278             : template <typename T>
    2279             : inline T
    2280       40970 : GetPot::operator()(const char* VarName, const T& Default) const
    2281             : {
    2282             :   // (*) recording of requested variables happens in '_request_variable()'
    2283       40970 :   const variable*  sv = _request_variable(VarName);
    2284             : 
    2285       40970 :   if (sv == 0)
    2286       32738 :     return Default;
    2287             : 
    2288        7214 :   return _convert_to_type(sv->original, Default);
    2289             : }
    2290             : 
    2291             : 
    2292             : 
    2293             : template <typename T>
    2294             : inline T
    2295        1302 : GetPot::operator()(const std::string& VarName, const T& Default) const
    2296             : {
    2297       37096 :   return operator()(VarName.c_str(), Default);
    2298             : }
    2299             : 
    2300             : 
    2301             : 
    2302             : inline const char*
    2303         146 : GetPot::operator()(const char* VarName, const char* Default) const
    2304             : {
    2305         288 :   return _internal_managed_copy(operator()(VarName, std::string(Default)));
    2306             : }
    2307             : 
    2308             : 
    2309             : 
    2310             : inline const char*
    2311             : GetPot::operator()(const std::string& VarName, const char* Default) const
    2312             : {
    2313             :   return operator()(VarName.c_str(), Default);
    2314             : }
    2315             : 
    2316             : 
    2317             : 
    2318             : template <typename T>
    2319             : inline T
    2320        4129 : GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const
    2321             : {
    2322             :   // (*) recording of requested variables happens in '_request_variable()'
    2323        4129 :   const variable* sv = _request_variable(VarName);
    2324        4129 :   if (sv == 0)
    2325           3 :     return Default;
    2326             : 
    2327         116 :   const std::string*  element = sv->get_element(Idx);
    2328        4126 :   if (element == 0)
    2329           0 :     return Default;
    2330        2880 :   return _convert_to_type(*element, Default);
    2331             : }
    2332             : 
    2333             : 
    2334             : 
    2335             : template <typename T>
    2336             : inline T
    2337          80 : GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const
    2338             : {
    2339        2844 :   return operator()(VarName.c_str(), Default, Idx);
    2340             : }
    2341             : 
    2342             : 
    2343             : 
    2344             : inline const char*
    2345        1282 : GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const
    2346             : {
    2347        2528 :   return _internal_managed_copy(operator()(VarName, std::string(Default), Idx));
    2348             : }
    2349             : 
    2350             : 
    2351             : 
    2352             : inline const char*
    2353             : GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const
    2354             : {
    2355             :   return operator()(VarName.c_str(), Default, Idx);
    2356             : }
    2357             : 
    2358             : 
    2359             : 
    2360             : template <typename T>
    2361             : inline T
    2362             : GetPot::get_value_no_default(const char* VarName, const T& Default) const
    2363             : {
    2364             :   // (*) recording of requested variables happens in '_request_variable()'
    2365             :   const variable*  sv = _request_variable(VarName);
    2366             :   if (sv == 0)
    2367             :     {
    2368             :       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
    2369             :       getpot_error();
    2370             :     }
    2371             :   return _convert_to_type_no_default(VarName, sv->original, Default);
    2372             : }
    2373             : 
    2374             : 
    2375             : 
    2376             : template <typename T>
    2377             : inline T
    2378             : GetPot::get_value_no_default(const std::string& VarName, const T& Default) const
    2379             : {
    2380             :   return get_value_no_default(VarName.c_str(),Default);
    2381             : }
    2382             : 
    2383             : 
    2384             : 
    2385             : inline const char*
    2386             : GetPot::get_value_no_default(const char* VarName, const char* Default) const
    2387             : {
    2388             :   return _internal_managed_copy(get_value_no_default(VarName, std::string(Default)));
    2389             : }
    2390             : 
    2391             : 
    2392             : 
    2393             : inline const char*
    2394             : GetPot::get_value_no_default(const std::string& VarName, const char* Default) const
    2395             : {
    2396             :   return get_value_no_default(VarName.c_str(),Default);
    2397             : }
    2398             : 
    2399             : 
    2400             : 
    2401             : template <typename T>
    2402             : inline T
    2403             : GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const
    2404             : {
    2405             :   // (*) recording of requested variables happens in '_request_variable()'
    2406             :   const variable* sv = _request_variable(VarName);
    2407             :   if (sv == 0)
    2408             :     {
    2409             :       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
    2410             :       getpot_error();
    2411             :     }
    2412             : 
    2413             :   const std::string*  element = sv->get_element(Idx);
    2414             :   if (element == 0)
    2415             :     {
    2416             :       getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl;
    2417             :       getpot_error();
    2418             :     }
    2419             :   return _convert_to_type_no_default(VarName, *element, Default);
    2420             : }
    2421             : 
    2422             : 
    2423             : 
    2424             : template <typename T>
    2425             : inline T
    2426             : GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const
    2427             : {
    2428             :   return get_value_no_default(VarName.c_str(), Default, Idx);
    2429             : }
    2430             : 
    2431             : 
    2432             : 
    2433             : inline const char*
    2434             : GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const
    2435             : {
    2436             :   return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx));
    2437             : }
    2438             : 
    2439             : 
    2440             : 
    2441             : inline const char*
    2442             : GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const
    2443             : {
    2444             :   return get_value_no_default(VarName.c_str(), Default, Idx);
    2445             : }
    2446             : 
    2447             : 
    2448             : 
    2449             : inline void
    2450    13209632 : GetPot::_record_argument_request(const std::string& Name) const
    2451             : {
    2452    13209632 :   if (!request_recording_f)
    2453           0 :     return;
    2454             : 
    2455             :   // Get a lock before touching anything mutable
    2456      671112 :   SCOPED_MUTEX;
    2457             : 
    2458             :   // (*) record requested variable for later ufo detection
    2459    12874196 :   _requested_arguments.insert(Name);
    2460             : 
    2461             :   // (*) record considered section for ufo detection
    2462    13880624 :   STRING_VECTOR      STree = _get_section_tree(Name);
    2463    13209642 :   victorate(std::string, STree, it)
    2464          10 :     if (_requested_sections.find(*it) == _requested_sections.end())
    2465          10 :       if (section.length() != 0)
    2466           0 :         _requested_sections.insert(*it);
    2467    12538640 : }
    2468             : 
    2469             : 
    2470             : 
    2471             : inline void
    2472       40886 : GetPot::_record_variable_request(const std::string& Name) const
    2473             : {
    2474       40886 :   if (!request_recording_f)
    2475           0 :     return;
    2476             : 
    2477             :   // Get a lock before touching anything mutable
    2478        2352 :   SCOPED_MUTEX;
    2479             : 
    2480             :   // (*) record requested variable for later ufo detection
    2481       39710 :   _requested_variables.insert(Name);
    2482             : 
    2483             :   // (*) record considered section for ufo detection
    2484       43238 :   STRING_VECTOR      STree = _get_section_tree(Name);
    2485       40886 :   victorate(std::string, STree, it)
    2486           0 :     if (_requested_sections.find(*it) == _requested_sections.end())
    2487           0 :       if (section.length() != 0)
    2488           0 :         _requested_sections.insert(*it);
    2489       38534 : }
    2490             : 
    2491             : 
    2492             : 
    2493             : // (*) following functions are to be used from 'outside', after getpot has parsed its
    2494             : //     arguments => append an argument in the argument vector that reflects the addition
    2495             : inline void
    2496        4760 : GetPot::_set_variable(const std::string& VarName,
    2497             :                       const std::string& Value, const bool Requested /* = true */)
    2498             : {
    2499        4760 :   const GetPot::variable* Var = Requested ?
    2500           0 :     _request_variable(VarName.c_str()) :
    2501        4760 :     _find_variable(VarName.c_str());
    2502        4760 :   if (Var == 0)
    2503        9520 :     variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str()));
    2504             :   else
    2505             :     {
    2506           0 :       overridden_vars.insert(VarName.c_str());
    2507           0 :       (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str());
    2508             :     }
    2509        4760 : }
    2510             : 
    2511             : 
    2512             : 
    2513             : template <typename T>
    2514             : inline void
    2515             : GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */)
    2516             : {
    2517             :   std::ostringstream string_value;
    2518             :   string_value << Value;
    2519             :   _set_variable(VarName, string_value.str().c_str(), Requested);
    2520             : }
    2521             : 
    2522             : 
    2523             : 
    2524             : template <typename T>
    2525             : inline void
    2526             : GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */)
    2527             : {
    2528             :   set(VarName.c_str(), Value, Requested);
    2529             : }
    2530             : 
    2531             : 
    2532             : 
    2533             : inline void
    2534             : GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */)
    2535             : {
    2536             :   _set_variable(VarName, Value, Requested);
    2537             : }
    2538             : 
    2539             : 
    2540             : 
    2541             : inline void
    2542             : GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */)
    2543             : {
    2544             :   set(VarName.c_str(), Value, Requested);
    2545             : }
    2546             : 
    2547             : 
    2548             : 
    2549             : inline unsigned
    2550         826 : GetPot::vector_variable_size(const char* VarName) const
    2551             : {
    2552         850 :   const variable*  sv = _request_variable(VarName);
    2553         850 :   if (sv == 0)
    2554           8 :     return 0;
    2555         581 :   return (unsigned)(sv->value.size());
    2556             : }
    2557             : 
    2558             : 
    2559             : 
    2560             : inline unsigned
    2561           8 : GetPot::vector_variable_size(const std::string& VarName) const
    2562             : {
    2563         272 :   return vector_variable_size(VarName.c_str());
    2564             : }
    2565             : 
    2566             : 
    2567             : 
    2568             : inline STRING_VECTOR
    2569             : GetPot::get_variable_names() const
    2570             : {
    2571             :   STRING_VECTOR  result;
    2572             :   std::vector<GetPot::variable>::const_iterator it = variables.begin();
    2573             :   for (; it != variables.end(); ++it)
    2574             :     {
    2575             :       const std::string Tmp = _get_remaining_string((*it).name, prefix);
    2576             :       if (Tmp != "")
    2577             :         result.push_back(Tmp);
    2578             :     }
    2579             :   return result;
    2580             : }
    2581             : 
    2582             : 
    2583             : 
    2584             : inline STRING_VECTOR
    2585             : GetPot::get_section_names() const
    2586             : {
    2587             :   return section_list;
    2588             : }
    2589             : 
    2590             : 
    2591             : 
    2592             : inline STRING_VECTOR
    2593             : GetPot::get_subsection_names(const std::string & sec_prefix) const
    2594             : {
    2595             :   // GetPot functions should understand user-provided section names
    2596             :   // either with or without a trailing slash.
    2597             :   const std::string full_prefix =
    2598             :     *sec_prefix.rbegin() == '/' ? sec_prefix : sec_prefix + '/';
    2599             : 
    2600             :   const std::size_t full_prefix_len = full_prefix.size();
    2601             : 
    2602             :   // Subsections-of-subsections are in the section_list, so we'll be
    2603             :   // adding subsections multiple times.  Using std::set as an
    2604             :   // intermediate data structure helps us check for duplicates with
    2605             :   // O(N log N) rather than O(N^2) cost.
    2606             :   std::set<std::string> subsections;
    2607             : 
    2608             :   STRING_VECTOR returnval;
    2609             : 
    2610             :   for (STRING_VECTOR::const_iterator it = section_list.begin();
    2611             :        it != section_list.end(); ++it)
    2612             :     {
    2613             :       const std::string & section_name = *it;
    2614             : 
    2615             :       // If this section name begins with the prefix
    2616             :       if (section_name.compare(0, full_prefix_len, full_prefix) == 0)
    2617             :         {
    2618             :           const std::size_t next_slash_len =
    2619             :             section_name.find('/', full_prefix_len);
    2620             : 
    2621             :           const std::string subsection_name =
    2622             :             section_name.substr(full_prefix_len,
    2623             :                                 next_slash_len - full_prefix_len);
    2624             : 
    2625             :           // If there is a subsection, and if this is the first time
    2626             :           // we've seen it, add the prefix-less, postfix-less
    2627             :           // subsection name.
    2628             :           if (!subsection_name.empty() &&
    2629             :               !subsections.count(subsection_name))
    2630             :             {
    2631             :               returnval.push_back(subsection_name);
    2632             :               subsections.insert(subsection_name);
    2633             :             }
    2634             :         }
    2635             :     }
    2636             : 
    2637             :   return returnval;
    2638             : }
    2639             : 
    2640             : 
    2641             : 
    2642             : inline std::set<std::string>
    2643             : GetPot::get_overridden_variables() const
    2644             : {
    2645             :   return overridden_vars;
    2646             : }
    2647             : 
    2648             : 
    2649             : 
    2650             : inline const GetPot::variable*
    2651       45646 : GetPot::_find_variable(const char* VarName) const
    2652             : {
    2653       47150 :   const std::string Name = prefix + VarName;
    2654             : 
    2655        3008 :   std::vector<variable>::const_iterator it = variables.begin();
    2656      109060 :   for (; it != variables.end(); ++it)
    2657             :     {
    2658       68212 :       if ((*it).name == Name)
    2659         516 :         return &(*it);
    2660             :     }
    2661         988 :   return 0;
    2662             : }
    2663             : 
    2664             : 
    2665             : 
    2666             : inline const GetPot::variable*
    2667       40886 : GetPot::_request_variable(const char* VarName) const
    2668             : {
    2669             :   // (*) record requested variable for later ufo detection
    2670       40886 :   this->_record_variable_request(VarName);
    2671             : 
    2672       40886 :   return this->_find_variable(VarName);
    2673             : }
    2674             : 
    2675             : 
    2676             : 
    2677             : ///////////////////////////////////////////////////////////////////////////////
    2678             : // (*) output (basically for debugging reasons
    2679             : //.............................................................................
    2680             : //
    2681             : inline int
    2682             : GetPot::print(std::ostream &out_stream) const
    2683             : {
    2684             :   out_stream << "argc = " << argv.size() << std::endl;
    2685             :   STRING_VECTOR::const_iterator it = argv.begin();
    2686             :   for (; it != argv.end(); ++it)
    2687             :     out_stream << *it << std::endl;
    2688             :   out_stream << std::endl;
    2689             :   return 1;
    2690             : }
    2691             : 
    2692             : 
    2693             : 
    2694             : // PECOS/HPCT Addition - add option to prepend output with a delimiter
    2695             : // while also disabling argc print and skipping first print (the name
    2696             : // of the input file)
    2697             : //
    2698             : // PECOS Development Team: (ks. 4/16/09)
    2699             : inline int
    2700           0 : GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const
    2701             : {
    2702           0 :   STRING_VECTOR::const_iterator it = argv.begin();
    2703           0 :   it += skip_count;
    2704           0 :   for (; it != argv.end(); ++it)
    2705             :     {
    2706           0 :       out_stream << custom_prefix;
    2707           0 :       out_stream << *it << std::endl;
    2708             :     }
    2709           0 :   out_stream << std::endl;
    2710           0 :   return 1;
    2711             : }
    2712             : 
    2713             : 
    2714             : 
    2715             : // (*) dollar bracket expressions (DBEs) ------------------------------------
    2716             : //
    2717             : //     1) Entry Function: _DBE_expand_string()
    2718             : //        Takes a string such as
    2719             : //
    2720             : //          "${+ ${x} ${y}}   Subject-${& ${section} ${subsection}}:   ${title}"
    2721             : //
    2722             : //        calls _DBE_expand() for each of the expressions
    2723             : //
    2724             : //           ${+ ${x} ${y}}
    2725             : //           ${& ${section} ${subsection}}
    2726             : //           ${Title}
    2727             : //
    2728             : //        and returns the string
    2729             : //
    2730             : //          "4711 Subject-1.01:   Mit den Clowns kamen die Schwaene"
    2731             : //
    2732             : //        assuming that
    2733             : //            x          = "4699"
    2734             : //            y          = "12"
    2735             : //            section    = "1."
    2736             : //            subsection = "01"
    2737             : //            title      = "Mit den Clowns kamen die Schwaene"
    2738             : //
    2739             : //      2) _DBE_expand():
    2740             : //
    2741             : //           checks for the command, i.e. the 'sign' that follows '${'
    2742             : //           divides the argument list into sub-expressions using
    2743             : //           _DBE_get_expr_list()
    2744             : //
    2745             : //           ${+ ${x} ${y}}                 -> "${x}"  "${y}"
    2746             : //           ${& ${section} ${subsection}}  -> "${section}" "${subsection}"
    2747             : //           ${Title}                       -> Nothing, variable expansion
    2748             : //
    2749             : //      3) _DBE_expression_list():
    2750             : //
    2751             : //           builds a vector of unbracketed whitespace separated strings, i.e.
    2752             : //
    2753             : //           "  ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
    2754             : //
    2755             : //           is split into a vector
    2756             : //
    2757             : //              [0] ${Number}.a
    2758             : //              [1] ${: Das Marmorbild}
    2759             : //              [2] AB-${& Author= ${Eichendorf}}-1870
    2760             : //
    2761             : //           Each sub-expression is expanded using expand().
    2762             : //---------------------------------------------------------------------------
    2763             : inline std::string
    2764      140920 : GetPot::_DBE_expand_string(const std::string& str)
    2765             : {
    2766             :   // Parses for closing operators '${ }' and expands them letting
    2767             :   // white spaces and other letters as they are.
    2768      140920 :   std::string   new_string = "";
    2769        1192 :   unsigned open_brackets = 0;
    2770        1192 :   unsigned first = 0;
    2771     1651900 :   for (unsigned i = 0;  i<str.size(); i++)
    2772             :     {
    2773     4002752 :       if (i + 2 < str.size() && str.substr(i, 2) == "${")
    2774             :         {
    2775           0 :           if (open_brackets == 0)
    2776           0 :             first = i+2;
    2777           0 :           open_brackets++;
    2778             :         }
    2779     1510980 :       else if (str[i] == '}' && open_brackets > 0)
    2780             :         {
    2781           0 :           open_brackets -= 1;
    2782           0 :           if (open_brackets == 0)
    2783             :             {
    2784           0 :               const std::string Replacement = _DBE_expand(str.substr(first, i - first));
    2785           0 :               new_string += Replacement;
    2786             :             }
    2787             :         }
    2788     1510980 :       else if (open_brackets == 0)
    2789     1510980 :         new_string += str[i];
    2790             :     }
    2791      140920 :   return new_string;
    2792             : }
    2793             : 
    2794             : 
    2795             : 
    2796             : inline STRING_VECTOR
    2797           0 : GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
    2798             : {
    2799             :   // ensures that the resulting vector has the expected number
    2800             :   // of arguments, but they may contain an error message
    2801           0 :   std::string str = str_;
    2802             :   // Separates expressions by non-bracketed whitespaces, expands them
    2803             :   // and puts them into a list.
    2804             : 
    2805           0 :   unsigned i=0;
    2806             :   // (1) eat initial whitespaces
    2807           0 :   for (; i < str.size(); i++)
    2808           0 :     if (!std::isspace(str[i]))
    2809           0 :       break;
    2810             : 
    2811           0 :   STRING_VECTOR   expr_list;
    2812           0 :   unsigned         open_brackets = 0;
    2813           0 :   std::vector<unsigned> start_idx;
    2814           0 :   unsigned         start_new_string = i;
    2815           0 :   unsigned         l = (unsigned)(str.size());
    2816             : 
    2817             :   // (2) search for ${ } expressions ...
    2818           0 :   while (i < l)
    2819             :     {
    2820           0 :       const char letter = str[i];
    2821             :       // whitespace -> end of expression
    2822           0 :       if (std::isspace(letter) && open_brackets == 0)
    2823             :         {
    2824           0 :           expr_list.push_back(str.substr(start_new_string, i - start_new_string));
    2825           0 :           bool no_breakout_f = true;
    2826           0 :           for (i++; i < l ; i++)
    2827             :             {
    2828           0 :               if (!std::isspace(str[i]))
    2829             :                 {
    2830           0 :                   no_breakout_f = false;
    2831           0 :                   start_new_string = i;
    2832           0 :                   break;
    2833             :                 }
    2834             :             }
    2835             : 
    2836           0 :           if (no_breakout_f)
    2837             :             {
    2838             :               // end of expression list
    2839           0 :               if (expr_list.size() < ExpectedNumber)
    2840             :                 {
    2841           0 :                   const std::string   pre_tmp("<< ${ }: missing arguments>>");
    2842           0 :                   STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
    2843           0 :                   expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
    2844           0 :                 }
    2845           0 :               return expr_list;
    2846             :             }
    2847             :         }
    2848             : 
    2849             :       // dollar-bracket expression
    2850           0 :       if (str.length() >= i+2 && str.substr(i, 2) == "${")
    2851             :         {
    2852           0 :           open_brackets++;
    2853           0 :           start_idx.push_back(i+2);
    2854             :         }
    2855             : 
    2856           0 :       else if (letter == '}' && open_brackets > 0)
    2857             :         {
    2858           0 :           int start = start_idx[start_idx.size()-1];
    2859           0 :           start_idx.pop_back();
    2860           0 :           const std::string Replacement = _DBE_expand(str.substr(start, i-start));
    2861           0 :           if (start - 3 < (int)0)
    2862           0 :             str = Replacement + str.substr(i+1);
    2863             :           else
    2864           0 :             str = str.substr(0, start-2) + Replacement + str.substr(i+1);
    2865           0 :           l = (int)(str.size());
    2866           0 :           i = start + (int)(Replacement.size()) - 3;
    2867           0 :           open_brackets--;
    2868             :         }
    2869           0 :       i++;
    2870             :     }
    2871             : 
    2872             :   // end of expression list
    2873           0 :   expr_list.push_back(str.substr(start_new_string, i-start_new_string));
    2874             : 
    2875           0 :   if (expr_list.size() < ExpectedNumber)
    2876             :     {
    2877           0 :       const std::string   pre_tmp("<< ${ }: missing arguments>>");
    2878           0 :       STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
    2879           0 :       expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
    2880           0 :     }
    2881             : 
    2882           0 :   return expr_list;
    2883           0 : }
    2884             : 
    2885             : 
    2886             : 
    2887             : inline const GetPot::variable*
    2888           0 : GetPot::_DBE_get_variable(const std::string& VarName)
    2889             : {
    2890           0 :   static GetPot::variable ev;
    2891           0 :   std::string secure_Prefix = prefix;
    2892             : 
    2893           0 :   prefix = section;
    2894             :   // (1) first search in currently active section
    2895           0 :   const GetPot::variable* var = _request_variable(VarName.c_str());
    2896           0 :   if (var != 0)
    2897             :     {
    2898           0 :       prefix = secure_Prefix;
    2899           0 :       return var;
    2900             :     }
    2901             : 
    2902             :   // (2) search in root name space
    2903           0 :   prefix = "";
    2904           0 :   var = _request_variable(VarName.c_str());
    2905           0 :   if (var != 0)
    2906             :     {
    2907           0 :       prefix = secure_Prefix;
    2908           0 :       return var;
    2909             :     }
    2910             : 
    2911           0 :   prefix = secure_Prefix;
    2912             : 
    2913             :   // error occurred => variable name == ""
    2914           0 :   ev.original = "<<${ } variable '";
    2915           0 :   ev.original += VarName + "' undefined>>";
    2916           0 :   return &ev;
    2917             : }
    2918             : 
    2919             : 
    2920             : 
    2921             : inline std::string
    2922           0 : GetPot::_DBE_expand(const std::string& expr)
    2923             : {
    2924             :   // ${: } pure text
    2925           0 :   if (expr[0] == ':')
    2926           0 :     return expr.substr(1);
    2927             : 
    2928             :   // ${& expr expr ... } text concatenation
    2929           0 :   else if (expr[0] == '&')
    2930             :     {
    2931           0 :       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1);
    2932             : 
    2933           0 :       STRING_VECTOR::const_iterator it = A.begin();
    2934           0 :       std::string result = *it++;
    2935           0 :       for (; it != A.end(); ++it) result += *it;
    2936             : 
    2937           0 :       return result;
    2938           0 :     }
    2939             : 
    2940             :   // ${<-> expr expr expr} text replacement
    2941           0 :   else if (expr.length() >= 3 && expr.substr(0, 3) == "<->")
    2942             :     {
    2943           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3);
    2944           0 :       size_t tmp = 0;
    2945           0 :       const size_t L = A[1].length();
    2946             : 
    2947           0 :       while ((tmp = A[0].find(A[1])) != std::string::npos)
    2948           0 :         A[0].replace(tmp, L, A[2]);
    2949             : 
    2950           0 :       return A[0];
    2951           0 :     }
    2952             : 
    2953             :   // ${=func [expr...] } function evaluation
    2954           0 :   else if (expr.length() >= 2 &&
    2955           0 :            expr.substr(0, 1) == "=" &&
    2956           0 :            expr.substr(0, 2) != "==")
    2957             :     {
    2958           0 :       size_t funcnamestart = expr.find_first_not_of(" \t", 1);
    2959           0 :       if (funcnamestart != std::string::npos)
    2960             :         {
    2961           0 :           size_t funcnameend = expr.find_first_of(" \t",funcnamestart);
    2962             :           std::string funcname = expr.substr(funcnamestart,
    2963           0 :                                              funcnameend-funcnamestart);
    2964           0 :           if (funcname == "log")
    2965             :             {
    2966             :               STRING_VECTOR A =
    2967           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2968           0 :               double arg = _convert_to_type(A[0], 0.0);
    2969           0 :               return _convert_from_type(std::log(arg));
    2970           0 :             }
    2971           0 :           else if (funcname == "log10")
    2972             :             {
    2973             :               STRING_VECTOR A =
    2974           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2975           0 :               double arg = _convert_to_type(A[0], 0.0);
    2976           0 :               return _convert_from_type(std::log10(arg));
    2977           0 :             }
    2978           0 :           else if (funcname == "exp")
    2979             :             {
    2980             :               STRING_VECTOR A =
    2981           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2982           0 :               double arg = _convert_to_type(A[0], 0.0);
    2983           0 :               return _convert_from_type(std::exp(arg));
    2984           0 :             }
    2985           0 :           else if (funcname == "sin")
    2986             :             {
    2987             :               STRING_VECTOR A =
    2988           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2989           0 :               double arg = _convert_to_type(A[0], 0.0);
    2990           0 :               return _convert_from_type(std::sin(arg));
    2991           0 :             }
    2992           0 :           else if (funcname == "cos")
    2993             :             {
    2994             :               STRING_VECTOR A =
    2995           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2996           0 :               double arg = _convert_to_type(A[0], 0.0);
    2997           0 :               return _convert_from_type(std::cos(arg));
    2998           0 :             }
    2999           0 :           else if (funcname == "tan")
    3000             :             {
    3001             :               STRING_VECTOR A =
    3002           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3003           0 :               double arg = _convert_to_type(A[0], 0.0);
    3004           0 :               return _convert_from_type(std::tan(arg));
    3005           0 :             }
    3006           0 :           else if (funcname == "asin")
    3007             :             {
    3008             :               STRING_VECTOR A =
    3009           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3010           0 :               double arg = _convert_to_type(A[0], 0.0);
    3011           0 :               return _convert_from_type(std::asin(arg));
    3012           0 :             }
    3013           0 :           else if (funcname == "acos")
    3014             :             {
    3015             :               STRING_VECTOR A =
    3016           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3017           0 :               double arg = _convert_to_type(A[0], 0.0);
    3018           0 :               return _convert_from_type(std::acos(arg));
    3019           0 :             }
    3020           0 :           else if (funcname == "atan")
    3021             :             {
    3022             :               STRING_VECTOR A =
    3023           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3024           0 :               double arg = _convert_to_type(A[0], 0.0);
    3025           0 :               return _convert_from_type(std::atan(arg));
    3026           0 :             }
    3027           0 :           else if (funcname == "atan2")
    3028             :             {
    3029             :               STRING_VECTOR A =
    3030           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
    3031           0 :               double arg1 = _convert_to_type(A[0], 0.0);
    3032           0 :               double arg2 = _convert_to_type(A[1], 0.0);
    3033           0 :               return _convert_from_type(std::atan2(arg1, arg2));
    3034           0 :             }
    3035           0 :           else if (funcname == "sinh")
    3036             :             {
    3037             :               STRING_VECTOR A =
    3038           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3039           0 :               double arg = _convert_to_type(A[0], 0.0);
    3040           0 :               return _convert_from_type(std::sinh(arg));
    3041           0 :             }
    3042           0 :           else if (funcname == "cosh")
    3043             :             {
    3044             :               STRING_VECTOR A =
    3045           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3046           0 :               double arg = _convert_to_type(A[0], 0.0);
    3047           0 :               return _convert_from_type(std::cosh(arg));
    3048           0 :             }
    3049           0 :           else if (funcname == "tanh")
    3050             :             {
    3051             :               STRING_VECTOR A =
    3052           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3053           0 :               double arg = _convert_to_type(A[0], 0.0);
    3054           0 :               return _convert_from_type(std::tanh(arg));
    3055           0 :             }
    3056             : #ifdef HAVE_INVERSE_HYPERBOLIC_SINE
    3057           0 :           else if (funcname == "asinh")
    3058             :             {
    3059             :               STRING_VECTOR A =
    3060           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3061           0 :               double arg = _convert_to_type(A[0], 0.0);
    3062           0 :               return _convert_from_type(std::asinh(arg));
    3063           0 :             }
    3064             : #endif
    3065             : #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE
    3066           0 :           else if (funcname == "acosh")
    3067             :             {
    3068             :               STRING_VECTOR A =
    3069           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3070           0 :               double arg = _convert_to_type(A[0], 0.0);
    3071           0 :               return _convert_from_type(std::acosh(arg));
    3072           0 :             }
    3073             : #endif
    3074             : #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT
    3075           0 :           else if (funcname == "atanh")
    3076             :             {
    3077             :               STRING_VECTOR A =
    3078           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3079           0 :               double arg = _convert_to_type(A[0], 0.0);
    3080           0 :               return _convert_from_type(std::atanh(arg));
    3081           0 :             }
    3082             : #endif
    3083           0 :           else if (funcname == "sqrt")
    3084             :             {
    3085             :               STRING_VECTOR A =
    3086           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3087           0 :               double arg = _convert_to_type(A[0], 0.0);
    3088           0 :               return _convert_from_type(std::sqrt(arg));
    3089           0 :             }
    3090           0 :           else if (funcname == "abs")
    3091             :             {
    3092             :               STRING_VECTOR A =
    3093           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3094           0 :               double arg = _convert_to_type(A[0], 0.0);
    3095           0 :               return _convert_from_type(std::abs(arg));
    3096           0 :             }
    3097           0 :           else if (funcname == "max")
    3098             :             {
    3099             :               STRING_VECTOR A =
    3100           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3101           0 :               STRING_VECTOR::const_iterator it = A.begin();
    3102           0 :               double result = _convert_to_type(*it++, 0.0);
    3103           0 :               for (; it != A.end(); ++it)
    3104           0 :                 result = std::max(result, _convert_to_type(*it, 0.0));
    3105           0 :               return _convert_from_type(result);
    3106           0 :             }
    3107           0 :           else if (funcname == "min")
    3108             :             {
    3109             :               STRING_VECTOR A =
    3110           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3111           0 :               STRING_VECTOR::const_iterator it = A.begin();
    3112           0 :               double result = _convert_to_type(*it++, 0.0);
    3113           0 :               for (; it != A.end(); ++it)
    3114           0 :                 result = std::min(result, _convert_to_type(*it, 0.0));
    3115           0 :               return _convert_from_type(result);
    3116           0 :             }
    3117           0 :           else if (funcname == "ceil")
    3118             :             {
    3119             :               STRING_VECTOR A =
    3120           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3121           0 :               double arg = _convert_to_type(A[0], 0.0);
    3122           0 :               return _convert_from_type(std::ceil(arg));
    3123           0 :             }
    3124           0 :           else if (funcname == "floor")
    3125             :             {
    3126             :               STRING_VECTOR A =
    3127           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3128           0 :               double arg = _convert_to_type(A[0], 0.0);
    3129           0 :               return _convert_from_type(std::floor(arg));
    3130           0 :             }
    3131           0 :           else if (funcname == "fmod")
    3132             :             {
    3133             :               STRING_VECTOR A =
    3134           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
    3135           0 :               double arg1 = _convert_to_type(A[0], 0.0);
    3136           0 :               double arg2 = _convert_to_type(A[1], 0.0);
    3137           0 :               return _convert_from_type(std::fmod(arg1, arg2));
    3138           0 :             }
    3139           0 :           else if (funcname == "srand")
    3140             :             {
    3141             :               STRING_VECTOR A =
    3142           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3143           0 :               unsigned int arg = _convert_to_type(A[0], 0u);
    3144           0 :               std::srand(arg);
    3145           0 :               return A[0];
    3146           0 :             }
    3147             :           // ${=rand range} with default range==RAND_MAX
    3148           0 :           else if (funcname == "rand")
    3149             :             {
    3150           0 :               if (funcnameend >= expr.length() ||
    3151           0 :                   expr.find_first_not_of(" \t", funcnameend) == std::string::npos)
    3152           0 :                 return _convert_from_type(std::rand());
    3153             : 
    3154             :               STRING_VECTOR A =
    3155           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3156           0 :               unsigned int range = _convert_to_type(A[0],0u);
    3157           0 :               if (!range)
    3158           0 :                 return _convert_from_type(0);
    3159           0 :               const unsigned int x = (RAND_MAX + 1u) / range;
    3160           0 :               const unsigned int y = x * range;
    3161             :               unsigned int returnval;
    3162           0 :               do
    3163             :                 {
    3164           0 :                   returnval = rand();
    3165           0 :                 } while (returnval >= y);
    3166           0 :               return _convert_from_type(returnval / x);
    3167           0 :             }
    3168           0 :           else if (funcname == "time")
    3169           0 :             return _convert_from_type(std::time(NULL));
    3170             :           else
    3171             :             {
    3172           0 :               getpot_cerr << "ERROR: unrecognized function "
    3173           0 :                           << funcname << std::endl;
    3174           0 :               getpot_error();
    3175             :             }
    3176             :         }
    3177             :     }
    3178             : 
    3179             :   // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
    3180           0 :   else if (expr[0] == '+')
    3181             :     {
    3182           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3183           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3184           0 :       double result = _convert_to_type(*it++, 0.0);
    3185           0 :       for (; it != A.end(); ++it)
    3186           0 :         result += _convert_to_type(*it, 0.0);
    3187             : 
    3188           0 :       return _convert_from_type(result);
    3189           0 :     }
    3190           0 :   else if (expr[0] == '-')
    3191             :     {
    3192           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3193           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3194           0 :       double result = _convert_to_type(*it++, 0.0);
    3195           0 :       for (; it != A.end(); ++it)
    3196           0 :         result -= _convert_to_type(*it, 0.0);
    3197             : 
    3198           0 :       return _convert_from_type(result);
    3199           0 :     }
    3200           0 :   else if (expr[0] == '*')
    3201             :     {
    3202           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3203           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3204           0 :       double result = _convert_to_type(*it++, 0.0);
    3205           0 :       for (; it != A.end(); ++it)
    3206           0 :         result *= _convert_to_type(*it, 0.0);
    3207             : 
    3208           0 :       return _convert_from_type(result);
    3209           0 :     }
    3210           0 :   else if (expr[0] == '/')
    3211             :     {
    3212           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3213           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3214           0 :       double result = _convert_to_type(*it++, 0.0);
    3215           0 :       if (result == 0)
    3216           0 :         return "0.0";
    3217             : 
    3218           0 :       for (; it != A.end(); ++it)
    3219             :         {
    3220           0 :           const double Q = _convert_to_type(*it, 0.0);
    3221           0 :           result /= Q;
    3222             :         }
    3223           0 :       return _convert_from_type(result);
    3224           0 :     }
    3225             : 
    3226             :   // ${^ ... } power expressions
    3227           0 :   else if (expr[0] == '^')
    3228             :     {
    3229           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3230           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3231           0 :       double result = _convert_to_type(*it++, 0.0);
    3232           0 :       for (; it != A.end(); ++it)
    3233           0 :         result = pow(result, _convert_to_type(*it, 0.0));
    3234           0 :       return _convert_from_type(result);
    3235           0 :     }
    3236             : 
    3237             :   // ${==  } ${<=  } ${>= } comparisons (return the number of the first 'match'
    3238           0 :   else if (expr.length() >= 2 &&
    3239           0 :            (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
    3240           0 :             expr.substr(0,2) == "<=" || expr[0] == '>'           || expr[0] == '<'))
    3241             :     {
    3242             :       // differentiate between two and one sign operators
    3243           0 :       unsigned op = 0;
    3244             :       enum { EQ, GEQ, LEQ, GT, LT };
    3245             : 
    3246           0 :       if (expr.substr(0, 2) == "==")
    3247           0 :         op = EQ;
    3248             : 
    3249           0 :       else if (expr.substr(0, 2) == ">=")
    3250           0 :         op = GEQ;
    3251             : 
    3252           0 :       else if (expr.substr(0, 2) == "<=")
    3253           0 :         op = LEQ;
    3254             : 
    3255           0 :       else if (expr[0] == '>')
    3256           0 :         op = GT;
    3257             : 
    3258             :       else
    3259           0 :         op = LT;
    3260             : 
    3261           0 :       STRING_VECTOR a;
    3262           0 :       if (op == GT || op == LT)
    3263           0 :         a = _DBE_get_expr_list(expr.substr(1), 2);
    3264             : 
    3265             :       else
    3266           0 :         a = _DBE_get_expr_list(expr.substr(2), 2);
    3267             : 
    3268           0 :       std::string   x_orig = a[0];
    3269           0 :       double   x = _convert_to_type(x_orig, 1e37);
    3270           0 :       unsigned i = 1;
    3271             : 
    3272           0 :       STRING_VECTOR::const_iterator y_orig = a.begin();
    3273           0 :       for (y_orig++; y_orig != a.end(); ++y_orig)
    3274             :         {
    3275           0 :           double y = _convert_to_type(*y_orig, 1e37);
    3276             : 
    3277             :           // set the strings as reference if one wasn't a number
    3278           0 :           if (x == 1e37 || y == 1e37)
    3279             :             {
    3280             :               // it's a string comparison
    3281           0 :               if ((op == EQ  && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
    3282           0 :                   (op == LEQ && x_orig <= *y_orig) || (op == GT  && x_orig >  *y_orig) ||
    3283           0 :                   (op == LT  && x_orig <  *y_orig))
    3284           0 :                 return _convert_from_type(i);
    3285             :             }
    3286             :           else
    3287             :             {
    3288             :               // it's a number comparison
    3289           0 :               if ((op == EQ  && x == y) || (op == GEQ && x >= y) ||
    3290           0 :                   (op == LEQ && x <= y) || (op == GT  && x >  y) ||
    3291           0 :                   (op == LT  && x <  y))
    3292           0 :                 return _convert_from_type(i);
    3293             :             }
    3294           0 :           i++;
    3295             :         }
    3296             : 
    3297             :       // nothing fulfills the condition => return 0
    3298           0 :       return "0";
    3299           0 :     }
    3300             : 
    3301             :   // ${?? expr expr} select
    3302           0 :   else if (expr.length() >= 2 && expr.substr(0, 2) == "??")
    3303             :     {
    3304           0 :       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2);
    3305           0 :       double x = _convert_to_type(a[0], 1e37);
    3306             : 
    3307             :       // last element is always the default argument
    3308           0 :       if (x == 1e37 || x < 0 || x >= double(a.size() - 1))
    3309           0 :         return a[a.size()-1];
    3310             : 
    3311             :       // round x to closest integer
    3312           0 :       return a[int(x+0.5)];
    3313           0 :     }
    3314             : 
    3315             :   // ${? expr expr expr} if then else conditions
    3316           0 :   else if (expr[0] == '?')
    3317             :     {
    3318           0 :       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2);
    3319             : 
    3320           0 :       if (_convert_to_type(a[0], 0.0) == 1.0)
    3321           0 :         return a[1];
    3322             : 
    3323           0 :       else if (a.size() > 2)
    3324           0 :         return a[2];
    3325           0 :     }
    3326             :   // ${! expr} maxro expansion
    3327           0 :   else if (expr[0] == '!')
    3328             :     {
    3329           0 :       const GetPot::variable* Var = _DBE_get_variable(expr.substr(1));
    3330             :       // error
    3331           0 :       if (Var->name == "")
    3332           0 :         return std::string(Var->original);
    3333             : 
    3334           0 :       const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2);
    3335           0 :       return A[0];
    3336           0 :     }
    3337             :   // ${@: } - string subscription
    3338           0 :   else if (expr.length() >= 2 && expr.substr(0,2) == "@:")
    3339             :     {
    3340           0 :       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2);
    3341           0 :       double x = _convert_to_type(A[1], 1e37);
    3342             : 
    3343             :       // last element is always the default argument
    3344           0 :       if (x == 1e37 || x < 0 || x >= double(A[0].size() - 1))
    3345           0 :         return "<<1st index out of range>>";
    3346             : 
    3347           0 :       if (A.size() > 2)
    3348             :         {
    3349           0 :           double y = _convert_to_type(A[2], 1e37);
    3350           0 :           if (y != 1e37 && y > 0 && y <= double(A[0].size() - 1) && y > x)
    3351           0 :             return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
    3352             : 
    3353           0 :           else if (y == -1)
    3354           0 :             return A[0].substr(int(x+0.5));
    3355             : 
    3356           0 :           return "<<2nd index out of range>>";
    3357             :         }
    3358             :       else
    3359             :         {
    3360           0 :           char* tmp = new char[2];
    3361           0 :           tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
    3362           0 :           std::string result(tmp);
    3363           0 :           delete [] tmp;
    3364           0 :           return result;
    3365             :         }
    3366           0 :     }
    3367             :   // ${@ } - vector subscription
    3368           0 :   else if (expr[0] == '@')
    3369             :     {
    3370           0 :       STRING_VECTOR          A   = _DBE_get_expr_list(expr.substr(1), 2);
    3371           0 :       const GetPot::variable* Var = _DBE_get_variable(A[0]);
    3372             :       // error
    3373           0 :       if (Var->name == "")
    3374             :         {
    3375             :           // make a copy of the string if an error occurred
    3376             :           // (since the error variable is a static variable inside get_variable())
    3377           0 :           return std::string(Var->original);
    3378             :         }
    3379             : 
    3380           0 :       double x = _convert_to_type(A[1], 1e37);
    3381             : 
    3382             :       // last element is always the default argument
    3383           0 :       if (x == 1e37 || x < 0 || x >= double(Var->value.size()))
    3384           0 :         return "<<1st index out of range>>";
    3385             : 
    3386           0 :       if (A.size() > 2)
    3387             :         {
    3388           0 :           double y = _convert_to_type(A[2], 1e37);
    3389           0 :           int    begin = int(x+0.5);
    3390           0 :           int    end = 0;
    3391           0 :           if (y != 1e37 && y > 0 && y <= double(Var->value.size()) && y > x)
    3392           0 :             end = int(y+1.5);
    3393           0 :           else if (y == -1)
    3394           0 :             end = int(Var->value.size());
    3395             :           else
    3396           0 :             return "<<2nd index out of range>>";
    3397             : 
    3398           0 :           std::string result = *(Var->get_element(begin));
    3399           0 :           for (int i = begin+1; i < end; i++)
    3400           0 :             result += std::string(" ") + *(Var->get_element(i));
    3401           0 :           return result;
    3402             :         }
    3403             :       else
    3404           0 :         return *(Var->get_element(int(x+0.5)));
    3405           0 :     }
    3406             : 
    3407           0 :   const STRING_VECTOR    A = _DBE_get_expr_list(expr, 1);
    3408           0 :   const GetPot::variable* B = _DBE_get_variable(A[0]);
    3409             : 
    3410             :   // make a copy of the string if an error occurred
    3411             :   // (since the error variable is a static variable inside get_variable())
    3412           0 :   if (B->name == "")
    3413           0 :     return std::string(B->original);
    3414             : 
    3415             :   // ([email protected] mentioned to me the warning MSVC++6.0 produces
    3416             :   //  with:  else return B->original (thanks))
    3417           0 :   return B->original;
    3418           0 : }
    3419             : 
    3420             : 
    3421             : 
    3422             : ///////////////////////////////////////////////////////////////////////////////
    3423             : // (*) unidentified flying objects
    3424             : //.............................................................................
    3425             : //
    3426             : inline bool
    3427             : GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
    3428             : {
    3429             :   victorate(std::string, VecStr, itk)
    3430             :     {
    3431             :       if (*itk == Str)
    3432             :         return true;
    3433             :     }
    3434             :   return false;
    3435             : }
    3436             : 
    3437             : 
    3438             : 
    3439             : inline STRING_VECTOR
    3440             : GetPot::unidentified_arguments(unsigned Number,
    3441             :                                const char* KnownArgument1, ...) const
    3442             : {
    3443             :   std::set<std::string> known_arguments;
    3444             : 
    3445             :   // (1) create a vector of known arguments
    3446             :   if (Number == 0)
    3447             :     return STRING_VECTOR();
    3448             : 
    3449             :   va_list ap;
    3450             :   va_start(ap, KnownArgument1);
    3451             :   known_arguments.insert(std::string(KnownArgument1));
    3452             :   for (unsigned i=1; i<Number; i++)
    3453             :     known_arguments.insert(std::string(va_arg(ap, char *)));
    3454             :   va_end(ap);
    3455             : 
    3456             :   return unidentified_arguments(known_arguments);
    3457             : }
    3458             : 
    3459             : 
    3460             : 
    3461             : inline STRING_VECTOR
    3462             : GetPot::unidentified_arguments() const
    3463             : {
    3464             :   return unidentified_arguments(_requested_arguments);
    3465             : }
    3466             : 
    3467             : 
    3468             : 
    3469             : inline STRING_VECTOR
    3470             : GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
    3471             : {
    3472             :   // We use set for efficiency, but want to support vector inputs for
    3473             :   // backwards compatibility.
    3474             :   return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3475             : }
    3476             : 
    3477             : 
    3478             : 
    3479             : inline STRING_VECTOR
    3480             : GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const
    3481             : {
    3482             :   STRING_VECTOR ufos;
    3483             :   STRING_VECTOR::const_iterator it = argv.begin();
    3484             :   ++it; // forget about argv[0] (application or filename)
    3485             :   for (; it != argv.end(); ++it)
    3486             :     {
    3487             :       // -- argument belongs to prefixed section ?
    3488             :       const std::string arg = _get_remaining_string(*it, prefix);
    3489             :       if (arg == "")
    3490             :         continue;
    3491             : 
    3492             :       // -- check if in list
    3493             :       if (Knowns.find(arg) == Knowns.end())
    3494             :         ufos.push_back(*it);
    3495             :     }
    3496             :   return ufos;
    3497             : }
    3498             : 
    3499             : 
    3500             : 
    3501             : inline STRING_VECTOR
    3502             : GetPot::unidentified_options(unsigned Number,
    3503             :                              const char* KnownOption1, ...) const
    3504             : {
    3505             :   std::set<std::string> known_options;
    3506             : 
    3507             :   // (1) create a vector of known arguments
    3508             :   if (Number == 0)
    3509             :     return STRING_VECTOR();
    3510             : 
    3511             :   va_list ap;
    3512             :   va_start(ap, KnownOption1);
    3513             :   known_options.insert(std::string(KnownOption1));
    3514             :   for (unsigned i=1; i<Number; i++)
    3515             :     known_options.insert(std::string(va_arg(ap, char *)));
    3516             :   va_end(ap);
    3517             : 
    3518             :   return unidentified_options(known_options);
    3519             : }
    3520             : 
    3521             : 
    3522             : 
    3523             : inline STRING_VECTOR
    3524             : GetPot::unidentified_options() const
    3525             : {
    3526             :   // -- every option is an argument.
    3527             :   // -- the set of requested arguments contains the set of requested options.
    3528             :   // -- IF the set of requested arguments contains unrequested options,
    3529             :   //    THEN they were requested as 'follow' and 'next' arguments and not as real options.
    3530             :   //
    3531             :   // => it is not necessary to separate requested options from the list
    3532             :   return unidentified_arguments(_requested_arguments);
    3533             : }
    3534             : 
    3535             : 
    3536             : 
    3537             : inline STRING_VECTOR
    3538             : GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
    3539             : {
    3540             :   // We use set for efficiency, but want to support vector inputs for
    3541             :   // backwards compatibility.
    3542             :   return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3543             : }
    3544             : 
    3545             : 
    3546             : 
    3547             : inline STRING_VECTOR
    3548             : GetPot::unidentified_options(const std::set<std::string>& Knowns) const
    3549             : {
    3550             :   STRING_VECTOR ufos;
    3551             :   STRING_VECTOR::const_iterator it = argv.begin();
    3552             :   ++it; // forget about argv[0] (application or filename)
    3553             :   for (; it != argv.end(); ++it)
    3554             :     {
    3555             :       // -- argument belongs to prefixed section ?
    3556             :       const std::string arg = _get_remaining_string(*it, prefix);
    3557             :       if (arg == "")
    3558             :         continue;
    3559             : 
    3560             :       // is argument really an option (starting with '-') ?
    3561             :       if (arg.length() < 1 || arg[0] != '-')
    3562             :         continue;
    3563             : 
    3564             :       if (Knowns.find(arg) == Knowns.end())
    3565             :         ufos.push_back(*it);
    3566             :     }
    3567             : 
    3568             :   return ufos;
    3569             : }
    3570             : 
    3571             : 
    3572             : 
    3573             : // Two modes:
    3574             : //  ArgumentNumber >= 0 check specific argument
    3575             : //  ArgumentNumber == -1 check all options starting with one '-'
    3576             : //                       for flags
    3577             : inline std::string
    3578             : GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
    3579             : {
    3580             :   std::string         ufos;
    3581             :   // STRING_VECTOR known_arguments;
    3582             :   std::string         KFL(KnownFlagList);
    3583             : 
    3584             :   // (2) iteration over '-' arguments (options)
    3585             :   if (ArgumentNumber == -1)
    3586             :     {
    3587             :       STRING_VECTOR::const_iterator it = argv.begin();
    3588             :       ++it; // forget about argv[0] (application or filename)
    3589             :       for (; it != argv.end(); ++it)
    3590             :         {
    3591             :           // -- argument belongs to prefixed section ?
    3592             :           const std::string arg = _get_remaining_string(*it, prefix);
    3593             :           if (arg == "") continue;
    3594             : 
    3595             :           // -- does arguments start with '-' (but not '--')
    3596             :           if (arg.length() < 2)
    3597             :             continue;
    3598             : 
    3599             :           else if (arg[0] != '-')
    3600             :             continue;
    3601             : 
    3602             :           else if (arg[1] == '-')
    3603             :             continue;
    3604             : 
    3605             :           // -- check out if flags inside option are contained in KnownFlagList
    3606             :           const char* p=arg.c_str();
    3607             :           p++; // skip starting minus
    3608             :           for (; *p != '\0' ; p++)
    3609             :             if (KFL.find(*p) == std::string::npos) ufos += *p;
    3610             :         }
    3611             :     }
    3612             :   // (1) check specific argument
    3613             :   else
    3614             :     {
    3615             :       // -- only check arguments that start with prefix
    3616             :       int no_matches = 0;
    3617             :       for (unsigned i=1; i<argv.size(); i++)
    3618             :         {
    3619             :           const std::string Remain = _get_remaining_string(argv[i], prefix);
    3620             :           if (Remain != "")
    3621             :             {
    3622             :               no_matches++;
    3623             :               if (no_matches == ArgumentNumber)
    3624             :                 {
    3625             :                   // -- the right argument number inside the section is found
    3626             :                   // => check it for flags
    3627             :                   const char* p = Remain.c_str();
    3628             :                   p++; // skip starting minus
    3629             :                   for (; *p != '\0' ; p++)
    3630             :                     if (KFL.find(*p) == std::string::npos) ufos += *p;
    3631             :                   return ufos;
    3632             :                 }
    3633             :             }
    3634             :         }
    3635             :     }
    3636             :   return ufos;
    3637             : }
    3638             : 
    3639             : 
    3640             : 
    3641             : inline STRING_VECTOR
    3642             : GetPot::unidentified_variables(unsigned Number,
    3643             :                                const char* KnownVariable1, ...) const
    3644             : {
    3645             :   std::set<std::string> known_variables;
    3646             : 
    3647             :   // create vector of known arguments
    3648             :   if (Number == 0)
    3649             :     return STRING_VECTOR();
    3650             : 
    3651             :   va_list ap;
    3652             :   va_start(ap, KnownVariable1);
    3653             :   known_variables.insert(std::string(KnownVariable1));
    3654             :   for (unsigned i=1; i<Number; i++)
    3655             :     known_variables.insert(std::string(va_arg(ap, char *)));
    3656             :   va_end(ap);
    3657             : 
    3658             :   return unidentified_variables(known_variables);
    3659             : }
    3660             : 
    3661             : 
    3662             : 
    3663             : inline STRING_VECTOR
    3664             : GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
    3665             : {
    3666             :   // We use set for efficiency, but want to support vector inputs for
    3667             :   // backwards compatibility.
    3668             :   return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3669             : }
    3670             : 
    3671             : 
    3672             : 
    3673             : inline STRING_VECTOR
    3674             : GetPot::unidentified_variables(const std::set<std::string>& Knowns) const
    3675             : {
    3676             :   STRING_VECTOR ufos;
    3677             : 
    3678             :   victorate(GetPot::variable, variables, it)
    3679             :     {
    3680             :       // -- check if variable has specific prefix
    3681             :       const std::string var_name = _get_remaining_string((*it).name, prefix);
    3682             :       if (var_name == "")
    3683             :         continue;
    3684             : 
    3685             :       // -- check if variable is known
    3686             :       if (Knowns.find(var_name) == Knowns.end())
    3687             :         ufos.push_back((*it).name);
    3688             :     }
    3689             :   return ufos;
    3690             : }
    3691             : 
    3692             : 
    3693             : 
    3694             : inline STRING_VECTOR
    3695             : GetPot::unidentified_variables() const
    3696             : {
    3697             :   return unidentified_variables(_requested_variables);
    3698             : }
    3699             : 
    3700             : 
    3701             : 
    3702             : inline STRING_VECTOR
    3703             : GetPot::unidentified_sections(unsigned Number,
    3704             :                               const char* KnownSection1, ...) const
    3705             : {
    3706             :   std::set<std::string> known_sections;
    3707             : 
    3708             :   // (1) create a vector of known arguments
    3709             :   if (Number == 0)
    3710             :     return STRING_VECTOR();
    3711             : 
    3712             :   va_list ap;
    3713             :   va_start(ap, KnownSection1);
    3714             :   known_sections.insert(std::string(KnownSection1));
    3715             :   for (unsigned i=1; i<Number; i++)
    3716             :     {
    3717             :       std::string tmp = std::string(va_arg(ap, char *));
    3718             : 
    3719             :       if (tmp.length() == 0)
    3720             :         continue;
    3721             : 
    3722             :       if (tmp[tmp.length()-1] != '/')
    3723             :         tmp += '/';
    3724             : 
    3725             :       known_sections.insert(tmp);
    3726             :     }
    3727             :   va_end(ap);
    3728             : 
    3729             :   return unidentified_sections(known_sections);
    3730             : }
    3731             : 
    3732             : 
    3733             : 
    3734             : inline STRING_VECTOR
    3735             : GetPot::unidentified_sections() const
    3736             : {
    3737             :   return unidentified_sections(_requested_sections);
    3738             : }
    3739             : 
    3740             : 
    3741             : 
    3742             : inline STRING_VECTOR
    3743             : GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
    3744             : {
    3745             :   // We use set for efficiency, but want to support vector inputs for
    3746             :   // backwards compatibility.
    3747             :   return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3748             : }
    3749             : 
    3750             : 
    3751             : 
    3752             : inline STRING_VECTOR
    3753             : GetPot::unidentified_sections(const std::set<std::string>& Knowns) const
    3754             : {
    3755             :   STRING_VECTOR ufos;
    3756             : 
    3757             :   victorate(std::string, section_list, it)
    3758             :     {
    3759             :       // -- check if section conform to prefix
    3760             :       const std::string sec_name = _get_remaining_string(*it, prefix);
    3761             :       if (sec_name == "")
    3762             :         continue;
    3763             : 
    3764             :       // -- check if section is known
    3765             :       if (Knowns.find(sec_name) == Knowns.end())
    3766             :         ufos.push_back(*it);
    3767             :     }
    3768             : 
    3769             :   return ufos;
    3770             : }
    3771             : 
    3772             : 
    3773             : 
    3774             : inline STRING_VECTOR
    3775             : GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
    3776             : {
    3777             :   std::set<std::string> known_nominuses;
    3778             : 
    3779             :   // create vector of known arguments
    3780             :   if (Number == 0)
    3781             :     return STRING_VECTOR();
    3782             : 
    3783             :   va_list ap;
    3784             :   va_start(ap, Known);
    3785             :   known_nominuses.insert(std::string(Known));
    3786             :   for (unsigned i=1; i<Number; i++)
    3787             :     {
    3788             :       std::string tmp = std::string(va_arg(ap, char *));
    3789             :       if (tmp.length() == 0)
    3790             :         continue;
    3791             :       known_nominuses.insert(tmp);
    3792             :     }
    3793             :   va_end(ap);
    3794             : 
    3795             :   return unidentified_nominuses(known_nominuses);
    3796             : }
    3797             : 
    3798             : 
    3799             : 
    3800             : inline STRING_VECTOR
    3801             : GetPot::unidentified_nominuses() const
    3802             : {
    3803             :   // -- every nominus is an argument.
    3804             :   // -- the set of requested arguments contains the set of requested nominuss.
    3805             :   // -- IF the set of requested arguments contains unrequested nominuss,
    3806             :   //    THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
    3807             :   //
    3808             :   // => it is not necessary to separate requested nominus from the list
    3809             : 
    3810             :   return unidentified_nominuses(_requested_arguments);
    3811             : }
    3812             : 
    3813             : 
    3814             : 
    3815             : inline STRING_VECTOR
    3816             : GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
    3817             : {
    3818             :   // We use set for efficiency, but want to support vector inputs for
    3819             :   // backwards compatibility.
    3820             :   return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3821             : }
    3822             : 
    3823             : 
    3824             : 
    3825             : inline STRING_VECTOR
    3826             : GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const
    3827             : {
    3828             :   STRING_VECTOR ufos;
    3829             : 
    3830             :   // (2) iterate over all arguments
    3831             :   STRING_VECTOR::const_iterator it = argv.begin();
    3832             :   ++it; // forget about argv[0] (application or filename)
    3833             :   for (; it != argv.end(); ++it)
    3834             :     {
    3835             :       // -- check if nominus part of prefix
    3836             :       const std::string arg = _get_remaining_string(*it, prefix);
    3837             :       if (arg == "")
    3838             :         continue;
    3839             : 
    3840             :       if (arg.length() < 1)
    3841             :         continue;
    3842             : 
    3843             :       // option ? --> not a nomius
    3844             :       if (arg[0] == '-')
    3845             :         continue;
    3846             : 
    3847             :       // section ? --> not a real nominus
    3848             :       if (arg[0] == '[' && arg[arg.length()-1] == ']')
    3849             :         continue;
    3850             : 
    3851             :       // variable definition ? --> not a real nominus
    3852             :       bool continue_f = false;
    3853             :       for (unsigned i=0; i<arg.length() ; i++)
    3854             :         if (arg[i] == '=')
    3855             :           {
    3856             :             continue_f = true;
    3857             :             break;
    3858             :           }
    3859             : 
    3860             :       if (continue_f)
    3861             :         continue;
    3862             : 
    3863             :       // real nominuses are compared with the given list
    3864             :       if (Knowns.find(arg) == Knowns.end())
    3865             :         ufos.push_back(*it);
    3866             :     }
    3867             :   return ufos;
    3868             : }
    3869             : 
    3870             : 
    3871             : ///////////////////////////////////////////////////////////////////////////////
    3872             : // (*) Accessors for requested types
    3873             : //.............................................................................
    3874             : 
    3875             : inline
    3876             : std::set<std::string>
    3877          71 : GetPot::get_requested_arguments() const
    3878             : {
    3879          71 :   return _requested_arguments;
    3880             : }
    3881             : 
    3882             : 
    3883             : 
    3884             : inline
    3885             : std::set<std::string>
    3886          71 : GetPot::get_requested_variables() const
    3887             : {
    3888          71 :   return _requested_variables;
    3889             : }
    3890             : 
    3891             : 
    3892             : 
    3893             : inline
    3894             : std::set<std::string>
    3895          71 : GetPot::get_requested_sections() const
    3896             : {
    3897          71 :   return _requested_sections;
    3898             : }
    3899             : 
    3900             : 
    3901             : 
    3902             : ///////////////////////////////////////////////////////////////////////////////
    3903             : // (*) variable class
    3904             : //.............................................................................
    3905             : //
    3906             : inline
    3907           0 : GetPot::variable::variable()
    3908             :   : name(),
    3909             :     value(),
    3910           0 :     original()
    3911           0 : {}
    3912             : 
    3913             : 
    3914             : 
    3915             : inline
    3916        9180 : GetPot::variable::variable(const variable& Other)
    3917             : {
    3918             : #ifdef WIN32
    3919             :   operator=(Other);
    3920             : #else
    3921        8740 :   GetPot::variable::operator=(Other);
    3922             : #endif
    3923        8740 : }
    3924             : 
    3925             : 
    3926             : 
    3927             : inline
    3928        4760 : GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
    3929        4760 :   : name(Name)
    3930             : {
    3931             :   // make a copy of the 'Value'
    3932        4760 :   take(Value, FieldSeparator);
    3933        4760 : }
    3934             : 
    3935             : 
    3936             : 
    3937             : inline const std::string*
    3938           8 : GetPot::variable::get_element(unsigned Idx) const
    3939             : {
    3940        4134 :   if (Idx >= value.size())
    3941           0 :     return 0;
    3942             :   else
    3943           8 :     return &(value[Idx]);
    3944             : }
    3945             : 
    3946             : 
    3947             : 
    3948             : inline void
    3949        4760 : GetPot::variable::take(const char* Value, const char* FieldSeparator)
    3950             : {
    3951        5088 :   original = std::string(Value); // string member var
    3952        4432 :   value.clear();                 // vector<string> member var
    3953             : 
    3954             :   /*
    3955             :   // separate string by white space delimiters using 'strtok'
    3956             :   // thread safe usage of strtok (no static members)
    3957             :   char* spt = 0;
    3958             :   // make a copy of the 'Value'
    3959             :   char* copy = new char[strlen(Value)+1];
    3960             :   strcpy(copy, Value);
    3961             :   char* follow_token = strtok_r(copy, FieldSeparator, &spt);
    3962             :   while (follow_token != 0)
    3963             :   {
    3964             :   value.push_back(std::string(follow_token));
    3965             :   follow_token = strtok_r(NULL, FieldSeparator, &spt);
    3966             :   }
    3967             : 
    3968             :   delete [] copy;
    3969             :   */
    3970             : 
    3971             :   // Don't use strtok, instead tokenize the input char "Value" using std::string operations so
    3972             :   // that the results end up in the local "value" member
    3973             : 
    3974             :   // Construct std::string objects from the input char*s.  I think the only
    3975             :   // FieldSeparator recognized by GetPot is whitespace?
    3976        5088 :   std::string Value_str = std::string(Value);
    3977        5088 :   std::string delimiters = std::string(FieldSeparator);
    3978             : 
    3979             :   // Skip delimiters at beginning.
    3980         656 :   std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0);
    3981             : 
    3982             :   // Find first "non-delimiter".
    3983         328 :   std::string::size_type pos     = Value_str.find_first_of(delimiters, lastPos);
    3984             : 
    3985             :   // Loop over the input string until all the tokens have been pushed back
    3986             :   // into the local "value" member.
    3987        9520 :   while (std::string::npos != pos || std::string::npos != lastPos)
    3988             :     {
    3989             :       // Found a token, add it to the vector.
    3990        8864 :       value.push_back(Value_str.substr(lastPos, pos - lastPos));
    3991             : 
    3992             :       // Skip delimiters.  Note the "not_of"
    3993         656 :       lastPos = Value_str.find_first_not_of(delimiters, pos);
    3994             : 
    3995             :       // Find next "non-delimiter"
    3996         328 :       pos = Value_str.find_first_of(delimiters, lastPos);
    3997             :     }
    3998             : 
    3999             :   // We're done, all the tokens should now be in the vector<string>
    4000        4760 : }
    4001             : 
    4002             : inline
    4003       15836 : GetPot::variable::~variable()
    4004       15808 : {}
    4005             : 
    4006             : 
    4007             : 
    4008             : inline GetPot::variable&
    4009        8740 : GetPot::variable::operator=(const GetPot::variable& Other)
    4010             : {
    4011        8740 :   if (&Other != this)
    4012             :     {
    4013        8740 :       name     = Other.name;
    4014        8740 :       value    = Other.value;
    4015        8740 :       original = Other.original;
    4016             :     }
    4017        8740 :   return *this;
    4018             : }
    4019             : 
    4020             : #ifdef GETPOT_NAMESPACE
    4021             : }
    4022             : #endif
    4023             : 
    4024             : #undef victorate
    4025             : 
    4026             : #endif // LIBMESH_GETPOT_H

Generated by: LCOV version 1.14