LCOV - code coverage report
Current view: top level - include/base - getpot.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 247 941 26.2 %
Date: 2025-08-19 19:27:09 Functions: 54 122 44.3 %
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        3020 : 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    11240433 :   static STRING_VECTOR _get_section_tree(const std::string& FullPath)
     723             :   {
     724       34720 :     STRING_VECTOR   result;
     725   285516383 :     for (std::size_t pos = 0; pos != FullPath.size(); ++pos)
     726             :       {
     727   274275950 :         if (FullPath[pos] == '/')
     728          16 :           result.push_back(FullPath.substr(0,pos));
     729             :       }
     730             : 
     731    11240433 :     return result;
     732           0 :   }
     733             : };
     734             : 
     735             : 
     736             : ///////////////////////////////////////////////////////////////////////////////
     737             : // (*) constructors, destructor, assignment operator
     738             : //.............................................................................
     739             : //
     740             : inline void
     741        8936 : GetPot::_basic_initialization()
     742             : {
     743        8936 :   cursor = 0;
     744        8936 :   nominus_cursor = -1;
     745        8936 :   search_failed_f = true;
     746        8936 :   search_loop_f = true;
     747        8936 :   prefix = "";
     748        8936 :   section = "";
     749             : 
     750             :   // automatic request recording for later ufo detection
     751        8936 :   request_recording_f = true;
     752             : 
     753             :   // comment start and end strings
     754        8936 :   _comment_start = std::string("#");
     755        8936 :   _comment_end   = std::string("\n");
     756             : 
     757             :   // default: separate vector elements by whitespaces
     758        8936 :   _field_separator = " \t\n";
     759        8936 : }
     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       30692 : GetPot::GetPot(const int argc_, const char * const * argv_,
     794       30692 :                const char* FieldSeparator /* =0x0 */) :
     795             :   // leave 'char**' non-const to honor less capable compilers ...
     796       28908 :   prefix(),
     797       28908 :   section(),
     798       28908 :   section_list(),
     799       28908 :   argv(),
     800       28908 :   cursor(),
     801       28908 :   search_loop_f(),
     802       28908 :   search_failed_f(),
     803       28908 :   nominus_cursor(),
     804             :   idx_nominus(),
     805       28908 :   variables(),
     806       28908 :   _comment_start(),
     807       28908 :   _comment_end(),
     808       28908 :   _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       34388 :   request_recording_f()
     817             : {
     818       30692 :   this->parse_command_line(argc_, argv_, FieldSeparator);
     819       30692 : }
     820             : 
     821             : 
     822             : 
     823             : // leave 'char**' non-const to honor less capable compilers ...
     824             : inline void
     825       23712 : GetPot::parse_command_line(const int argc_, const char * const * argv_,
     826             :                            const char* FieldSeparator /* =0x0 */)
     827             : {
     828       23712 :   _basic_initialization();
     829             : 
     830             :   // if specified -> overwrite default string
     831       23712 :   if (FieldSeparator)
     832           0 :     _field_separator = std::string(FieldSeparator);
     833             : 
     834             :   // -- make an internal copy of the argument list:
     835        1452 :   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       24636 :   _apriori_argv.push_back(std::string(argv_[0]));
     843      361562 :   for (int i=1; i<argc_; i++)
     844             :     {
     845      338990 :       std::string tmp(argv_[i]);   // recall the problem with temporaries,
     846      337850 :       _apriori_argv.push_back(tmp);       // reference counting in argument lists ...
     847             :     }
     848       23712 :   _parse_argument_vector(_apriori_argv);
     849       23712 : }
     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       25284 : 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        8924 : GetPot::_parse_argument_vector(const STRING_VECTOR& ARGV)
    1126             : {
    1127        8924 :   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         744 :   STRING_VECTOR                 section_stack;
    1135         248 :   STRING_VECTOR::const_iterator it = ARGV.begin();
    1136             : 
    1137             : 
    1138        8924 :   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        8924 :   if (argv.empty())
    1145        8924 :     argv.push_back(*it);
    1146         248 :   ++it;
    1147             : 
    1148             :   // -- loop over remaining arguments
    1149      145224 :   for (; it != ARGV.end(); ++it)
    1150             :     {
    1151      135240 :       std::string arg = *it;
    1152             : 
    1153      136300 :       if (arg.length() == 0)
    1154           0 :         continue;
    1155             : 
    1156             :       // -- [section] labels and [include file] directives
    1157      136300 :       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      137360 :           arg = section + _DBE_expand_string(arg);
    1194      136300 :           argv.push_back(arg);
    1195             :         }
    1196             : 
    1197             :       // -- separate array for nominus arguments
    1198      136300 :       if (arg[0] != '-')
    1199       67386 :         idx_nominus.push_back(getpot_cast_int<unsigned>(argv.size()-1));
    1200             : 
    1201             :       // -- variables: does arg contain a '=' operator ?
    1202        1060 :       const std::size_t equals_pos = arg.find_first_of('=');
    1203      136300 :       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        8428 : }
    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       13090 : GetPot::_convert_to_type(const std::string& String, const T& Default) const
    1564             : {
    1565       13090 :   std::istringstream in_string(String);
    1566             :   T retval;
    1567        8008 :   in_string >> retval;
    1568       13090 :   if (in_string.fail())
    1569           0 :     retval = Default;
    1570       13560 :   return retval;
    1571       12620 : }
    1572             : 
    1573             : 
    1574             : 
    1575             : // copy string - operator>> would have stopped upon seeing whitespace!
    1576             : template <>
    1577             : inline std::string
    1578         274 : GetPot::_convert_to_type(const std::string& String, const std::string&) const
    1579             : {
    1580        2554 :   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         462 :   const std::size_t bufsize = strlen(arg)+1;
    1716         430 :   auto newcopy = std::make_unique<char[]>(bufsize);
    1717         462 :   strncpy(newcopy.get(), arg, bufsize);
    1718         868 :   auto pr = _internal_string_container.insert(std::move(newcopy));
    1719          12 :   return pr.first->get();
    1720             : }
    1721             : 
    1722             : 
    1723             : 
    1724             : //////////////////////////////////////////////////////////////////////////////
    1725             : // (*) cursor oriented functions
    1726             : //.............................................................................
    1727             : 
    1728             : // Checks if 'String' begins with 'Start' and returns the remaining String.
    1729             : // Returns None if String does not begin with Start.
    1730             : inline const std::string
    1731        8786 : GetPot::_get_remaining_string(const std::string& String, const std::string& Start) const
    1732             : {
    1733        8786 :   if (Start == "")
    1734        8430 :     return String;
    1735             : 
    1736             :   // note: java.lang.String: substring(a,b) = from a to b-1
    1737             :   //        C++ string:      substr(a,b)    = from a to a + b
    1738           0 :   if (String.find(Start) == 0)
    1739           0 :     return String.substr(Start.length());
    1740             : 
    1741             :   else
    1742           0 :     return "";
    1743             : }
    1744             : 
    1745             : 
    1746             : 
    1747             : // -- search for a certain argument and set cursor to position
    1748             : inline bool
    1749      339292 : GetPot::search(const std::string &Option)
    1750             : {
    1751    12891919 :   return search(Option.c_str());
    1752             : }
    1753             : 
    1754             : 
    1755             : 
    1756             : // -- search for a certain argument and set cursor to position
    1757             : inline bool
    1758    12043414 : GetPot::search(const char* Option)
    1759             : {
    1760    12043414 :   unsigned           OldCursor = cursor;
    1761    12358452 :   const std::string  SearchTerm = prefix + Option;
    1762             : 
    1763             :   // (*) record requested arguments for later ufo detection
    1764    12043414 :   _record_argument_request(SearchTerm);
    1765             : 
    1766    12358428 :   if (OldCursor >= argv.size())
    1767           0 :     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
    1768    12043414 :   search_failed_f = true;
    1769             : 
    1770             :   // (*) first loop from cursor position until end
    1771   196364221 :   for (unsigned c = cursor; c < argv.size(); c++)
    1772             :     {
    1773   183272569 :       if (argv[c] == SearchTerm)
    1774             :         {
    1775        6888 :           cursor = c;
    1776        6888 :           search_failed_f = false;
    1777        6888 :           return true;
    1778             :         }
    1779             :     }
    1780    12036526 :   if (!search_loop_f)
    1781           0 :     return false;
    1782             : 
    1783             :   // (*) second loop from 0 to old cursor position
    1784    39045941 :   for (unsigned c = 1; c <= OldCursor; c++)
    1785             :     {
    1786    27014064 :       if (argv[c] == SearchTerm)
    1787             :         {
    1788        4649 :           cursor = c;
    1789        4649 :           search_failed_f = false;
    1790        4649 :           return true;
    1791             :         }
    1792             :     }
    1793             : 
    1794             :   // in case nothing is found the cursor stays where it was
    1795      314600 :   return false;
    1796             : }
    1797             : 
    1798             : 
    1799             : 
    1800             : inline bool
    1801           0 : GetPot::search(unsigned No, const char* P, ...)
    1802             : {
    1803             :   // (*) recording the requested arguments happens in subroutine 'search'
    1804           0 :   if (No == 0)
    1805           0 :     return false;
    1806             : 
    1807             :   // search for the first argument
    1808           0 :   if (search(P) == true)
    1809           0 :     return true;
    1810             : 
    1811             :   // start interpreting variable argument list
    1812             :   va_list ap;
    1813           0 :   va_start(ap, P);
    1814           0 :   unsigned i = 1;
    1815           0 :   for (; i < No; i++)
    1816             :     {
    1817           0 :       char* Opt = va_arg(ap, char *);
    1818             :       // (*) search records itself for later ufo detection
    1819           0 :       if (search(Opt) == true)
    1820           0 :         break;
    1821             :     }
    1822             : 
    1823           0 :   if (i < No)
    1824             :     {
    1825           0 :       i++;
    1826             :       // loop was left before end of array --> hit but
    1827             :       // make sure that the rest of the search terms is marked
    1828             :       // as requested.
    1829           0 :       for (; i < No; i++)
    1830             :         {
    1831           0 :           char* Opt = va_arg(ap, char *);
    1832             :           // (*) record requested arguments for later ufo detection
    1833           0 :           _record_argument_request(Opt);
    1834             :         }
    1835           0 :       va_end(ap);
    1836           0 :       return true;
    1837             :     }
    1838             : 
    1839           0 :   va_end(ap);
    1840             :   // loop was left normally --> no hit
    1841           0 :   return false;
    1842             : }
    1843             : 
    1844             : 
    1845             : 
    1846             : inline void
    1847           0 : GetPot::reset_cursor()
    1848             : {
    1849           0 :   search_failed_f = false;
    1850           0 :   cursor = 0;
    1851           0 : }
    1852             : 
    1853             : 
    1854             : 
    1855             : inline void
    1856             : GetPot::init_multiple_occurrence()
    1857             : {
    1858             :   disable_loop();
    1859             :   reset_cursor();
    1860             : }
    1861             : 
    1862             : 
    1863             : 
    1864             : ///////////////////////////////////////////////////////////////////////////////
    1865             : // (*) direct access to command line arguments
    1866             : //.............................................................................
    1867             : //
    1868             : inline const char*
    1869             : GetPot::operator[](unsigned idx) const
    1870             : {
    1871             :   return idx<argv.size() ? argv[idx].c_str() : 0;
    1872             : }
    1873             : 
    1874             : 
    1875             : 
    1876             : template <typename T>
    1877             : inline T
    1878             : GetPot::get(unsigned int Idx, const T& Default) const
    1879             : {
    1880             :   if (Idx >= argv.size())
    1881             :     return Default;
    1882             :   return _convert_to_type(argv[Idx], Default);
    1883             : }
    1884             : 
    1885             : 
    1886             : 
    1887             : inline const char*
    1888             : GetPot::get(unsigned int Idx, const char* Default) const
    1889             : {
    1890             :   if (Idx >= argv.size())
    1891             :     return Default;
    1892             :   return argv[Idx].c_str();
    1893             : }
    1894             : 
    1895             : 
    1896             : 
    1897             : inline unsigned
    1898             : GetPot::size() const
    1899             : {
    1900             :   return getpot_cast_int<unsigned>(argv.size());
    1901             : }
    1902             : 
    1903             : 
    1904             : 
    1905             : // -- next() function group
    1906             : template <typename T>
    1907             : inline T
    1908        8790 : GetPot::next(const T& Default)
    1909             : {
    1910        8790 :   if (search_failed_f)
    1911           0 :     return Default;
    1912        8790 :   cursor++;
    1913        9146 :   if (cursor >= argv.size())
    1914             :     {
    1915           0 :       cursor = getpot_cast_int<unsigned>(argv.size());
    1916           0 :       return Default;
    1917             :     }
    1918             : 
    1919             :   // (*) record requested argument for later ufo detection
    1920        8790 :   _record_argument_request(argv[cursor]);
    1921             : 
    1922        9180 :   const std::string Remain = _get_remaining_string(argv[cursor], prefix);
    1923             : 
    1924        8824 :   return Remain != "" ? _convert_to_type(Remain, Default) : Default;
    1925             : }
    1926             : 
    1927             : 
    1928             : 
    1929             : inline const char*
    1930           0 : GetPot::next(const char* Default)
    1931             : {
    1932           0 :   return _internal_managed_copy(next(std::string(Default)));
    1933             : }
    1934             : 
    1935             : 
    1936             : 
    1937             : // -- follow() function group
    1938             : //    distinct option to be searched for
    1939             : template <typename T>
    1940             : inline T
    1941           0 : GetPot::follow(const T& Default, const char* Option)
    1942             : {
    1943             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1944           0 :   if (search(Option) == false)
    1945           0 :     return Default;
    1946             : 
    1947           0 :   return next(Default);
    1948             : }
    1949             : 
    1950             : 
    1951             : 
    1952             : inline const char*
    1953             : GetPot::follow(const char* Default, const char* Option)
    1954             : {
    1955             :   return _internal_managed_copy(follow(std::string(Default), Option));
    1956             : }
    1957             : 
    1958             : 
    1959             : 
    1960             : // -- second follow() function group
    1961             : //    multiple option to be searched for
    1962             : template <typename T>
    1963             : inline T
    1964             : GetPot::follow(const T& Default, unsigned int No, const char* P, ...)
    1965             : {
    1966             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1967             :   if (No == 0)
    1968             :     return Default;
    1969             : 
    1970             :   if (search(P) == true)
    1971             :     return next(Default);
    1972             : 
    1973             :   va_list ap;
    1974             :   va_start(ap, P);
    1975             :   for (unsigned i=1; i<No; i++)
    1976             :     {
    1977             :       char* Opt = va_arg(ap, char *);
    1978             :       if (search(Opt) == true)
    1979             :         {
    1980             :           va_end(ap);
    1981             :           return next(Default);
    1982             :         }
    1983             :     }
    1984             :   va_end(ap);
    1985             :   return Default;
    1986             : }
    1987             : 
    1988             : 
    1989             : 
    1990             : inline const char*
    1991             : GetPot::follow(const char* Default, unsigned No, const char* P, ...)
    1992             : {
    1993             :   // (*) record requested of argument is entirely handled in 'search()' and 'next()'
    1994             :   if (No == 0)
    1995             :     return Default;
    1996             : 
    1997             :   if (search(P) == true)
    1998             :     return next(Default);
    1999             : 
    2000             :   va_list ap;
    2001             :   va_start(ap, P);
    2002             :   for (unsigned i=1; i<No; i++)
    2003             :     {
    2004             :       char* Opt = va_arg(ap, char *);
    2005             :       if (search(Opt) == true)
    2006             :         {
    2007             :           va_end(ap);
    2008             :           return next(Default);
    2009             :         }
    2010             :     }
    2011             :   va_end(ap);
    2012             :   return Default;
    2013             : }
    2014             : 
    2015             : 
    2016             : 
    2017             : ///////////////////////////////////////////////////////////////////////////////
    2018             : // (*) directly connected options
    2019             : //.............................................................................
    2020             : //
    2021             : template <typename T>
    2022             : inline T
    2023             : GetPot::direct_follow(const T& Default, const char* Option)
    2024             : {
    2025             :   const char* FollowStr = _match_starting_string(Option);
    2026             : 
    2027             :   // (*) record requested of argument for later ufo-detection
    2028             :   _record_argument_request(std::string(Option) + FollowStr);
    2029             : 
    2030             :   if (FollowStr == 0)
    2031             :     return Default;
    2032             : 
    2033             :   if (++cursor >= argv.size())
    2034             :     cursor = getpot_cast_int<unsigned>(argv.size());
    2035             :   return _convert_to_type(FollowStr, Default);
    2036             : }
    2037             : 
    2038             : 
    2039             : 
    2040             : inline const char*
    2041             : GetPot::direct_follow(const char* Default, const char* Option)
    2042             : {
    2043             :   return _internal_managed_copy(direct_follow(std::string(Default), Option));
    2044             : }
    2045             : 
    2046             : 
    2047             : 
    2048             : // pointer  to the place where the string after
    2049             : //          the match inside the found argument starts.
    2050             : // 0        no argument matches the starting string.
    2051             : inline const char*
    2052             : GetPot::_match_starting_string(const char* StartString)
    2053             : {
    2054             :   const unsigned N =
    2055             :     getpot_cast_int<unsigned>(strlen(StartString));
    2056             :   unsigned       OldCursor = cursor;
    2057             : 
    2058             :   if (OldCursor >= argv.size())
    2059             :     OldCursor = getpot_cast_int<unsigned>(argv.size() - 1);
    2060             :   search_failed_f = true;
    2061             : 
    2062             :   // (*) first loop from cursor position until end
    2063             :   for (unsigned c = cursor; c < argv.size(); c++)
    2064             :     {
    2065             :       if (strncmp(StartString, argv[c].c_str(), N) == 0)
    2066             :         {
    2067             :           cursor = c;
    2068             :           search_failed_f = false;
    2069             :           return &(argv[c].c_str()[N]);
    2070             :         }
    2071             :     }
    2072             : 
    2073             :   if (!search_loop_f)
    2074             :     return NULL;
    2075             : 
    2076             :   // (*) second loop from 0 to old cursor position
    2077             :   for (unsigned c = 1; c < OldCursor; c++)
    2078             :     {
    2079             :       if (strncmp(StartString, argv[c].c_str(), N) == 0)
    2080             :         {
    2081             :           cursor = c;
    2082             :           search_failed_f = false;
    2083             :           return &(argv[c].c_str()[N]);
    2084             :         }
    2085             :     }
    2086             :   return 0;
    2087             : }
    2088             : 
    2089             : 
    2090             : 
    2091             : ///////////////////////////////////////////////////////////////////////////////
    2092             : // (*) search for flags
    2093             : //.............................................................................
    2094             : //
    2095             : inline bool
    2096             : GetPot::options_contain(const char* FlagList) const
    2097             : {
    2098             :   // go through all arguments that start with a '-' (but not '--')
    2099             :   std::string str;
    2100             :   STRING_VECTOR::const_iterator it = argv.begin();
    2101             :   for (; it != argv.end(); ++it)
    2102             :     {
    2103             :       str = _get_remaining_string(*it, prefix);
    2104             : 
    2105             :       if (str.length() >= 2 && str[0] == '-' && str[1] != '-')
    2106             :         if (_check_flags(str, FlagList))
    2107             :           return true;
    2108             :     }
    2109             :   return false;
    2110             : }
    2111             : 
    2112             : 
    2113             : 
    2114             : inline bool
    2115             : GetPot::argument_contains(unsigned Idx, const char* FlagList) const
    2116             : {
    2117             :   if (Idx >= argv.size())
    2118             :     return false;
    2119             : 
    2120             :   // (*) record requested of argument for later ufo-detection
    2121             :   //     an argument that is checked for flags is considered to be 'requested'
    2122             :   _record_argument_request(argv[Idx]);
    2123             : 
    2124             :   if (prefix == "")
    2125             :     // search argument for any flag in flag list
    2126             :     return _check_flags(argv[Idx], FlagList);
    2127             : 
    2128             :   // if a prefix is set, then the argument index is the index
    2129             :   //   inside the 'namespace'
    2130             :   // => only check list of arguments that start with prefix
    2131             :   unsigned no_matches = 0;
    2132             :   for (unsigned i=0; i<argv.size(); i++)
    2133             :     {
    2134             :       const std::string Remain = _get_remaining_string(argv[i], prefix);
    2135             :       if (Remain != "")
    2136             :         {
    2137             :           no_matches += 1;
    2138             :           if (no_matches == Idx)
    2139             :             return _check_flags(Remain, FlagList);
    2140             :         }
    2141             :     }
    2142             : 
    2143             :   // no argument in this namespace
    2144             :   return false;
    2145             : }
    2146             : 
    2147             : 
    2148             : 
    2149             : inline bool
    2150             : GetPot::_check_flags(const std::string& Str, const char* FlagList) const
    2151             : {
    2152             :   for (const char* p=FlagList; *p != '\0' ; p++)
    2153             :     if (Str.find(*p) != std::string::npos)
    2154             :       return true; // found something
    2155             :   return false;
    2156             : }
    2157             : 
    2158             : 
    2159             : 
    2160             : ///////////////////////////////////////////////////////////////////////////////
    2161             : // (*) nominus arguments
    2162             : 
    2163             : // return vector of nominus arguments
    2164             : inline STRING_VECTOR
    2165             : GetPot::nominus_vector() const
    2166             : {
    2167             :   STRING_VECTOR nv;
    2168             :   std::vector<unsigned>::const_iterator it = idx_nominus.begin();
    2169             :   for (; it != idx_nominus.end(); ++it)
    2170             :     {
    2171             :       nv.push_back(argv[*it]);
    2172             : 
    2173             :       // (*) record for later ufo-detection
    2174             :       //     when a nominus vector is requested, the entire set of nominus arguments are
    2175             :       //     tagged as 'requested'
    2176             :       _record_argument_request(argv[*it]);
    2177             :     }
    2178             :   return nv;
    2179             : }
    2180             : 
    2181             : 
    2182             : 
    2183             : inline const char*
    2184             : GetPot::next_nominus()
    2185             : {
    2186             :   if (nominus_cursor < int(idx_nominus.size()) - 1)
    2187             :     {
    2188             :       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
    2189             : 
    2190             :       // (*) record for later ufo-detection
    2191             :       _record_argument_request(Tmp);
    2192             : 
    2193             :       return _internal_managed_copy(Tmp);
    2194             :     }
    2195             : 
    2196             :   return 0;
    2197             : }
    2198             : 
    2199             : 
    2200             : inline std::string
    2201             : GetPot::next_nominus_string()
    2202             : {
    2203             :   if (nominus_cursor < int(idx_nominus.size()) - 1)
    2204             :     {
    2205             :       const std::string Tmp = argv[idx_nominus[++nominus_cursor]];
    2206             : 
    2207             :       // (*) record for later ufo-detection
    2208             :       _record_argument_request(Tmp);
    2209             : 
    2210             :       return Tmp;
    2211             :     }
    2212             : 
    2213             :   return "";
    2214             : }
    2215             : 
    2216             : 
    2217             : 
    2218             : inline void
    2219             : GetPot::reset_nominus_cursor()
    2220             : {
    2221             :   nominus_cursor = -1;
    2222             : }
    2223             : 
    2224             : 
    2225             : 
    2226             : ///////////////////////////////////////////////////////////////////////////////
    2227             : // (*) variables
    2228             : //.............................................................................
    2229             : //
    2230             : inline bool
    2231        2112 : GetPot::have_variable(const char* VarName) const
    2232             : {
    2233      363267 :   const variable* sv = _request_variable(VarName);
    2234             : 
    2235      363267 :   if (sv == 0)
    2236        1702 :     return false;
    2237             : 
    2238         410 :   return true;
    2239             : }
    2240             : 
    2241             : 
    2242             : 
    2243             : inline bool
    2244       10470 : GetPot::have_variable(const std::string& VarName) const
    2245             : {
    2246       10470 :   return have_variable(VarName.c_str());
    2247             : }
    2248             : 
    2249             : inline bool
    2250             : GetPot::have_section(const char* section_name) const
    2251             : {
    2252             :   std::string s = std::string(section_name);
    2253             :   return this->have_section(s);
    2254             : }
    2255             : 
    2256             : inline bool
    2257             : GetPot::have_section(const std::string& section_name) const
    2258             : {
    2259             :   const char slash('/');
    2260             : 
    2261             :   std::string::const_reverse_iterator it = section_name.rbegin();
    2262             : 
    2263             :   bool found_section = false;
    2264             : 
    2265             :   // Check if section_name ends with a "/". If not, append it for the search since
    2266             :   // the section names are stored with a "/" at the end.
    2267             :   if( (*it) != slash )
    2268             :     // We need to use a linear search because we can't sort section_list
    2269             :     // without violating some assumptions. See libMesh #481 for more discussion.
    2270             :     found_section = ( std::find(section_list.begin(), section_list.end(), section_name+slash) != section_list.end() );
    2271             :   else
    2272             :     found_section = ( std::find(section_list.begin(), section_list.end(), section_name) != section_list.end() );
    2273             : 
    2274             :   return found_section;
    2275             : }
    2276             : 
    2277             : template <typename T>
    2278             : inline T
    2279       40410 : GetPot::operator()(const char* VarName, const T& Default) const
    2280             : {
    2281             :   // (*) recording of requested variables happens in '_request_variable()'
    2282       40410 :   const variable*  sv = _request_variable(VarName);
    2283             : 
    2284       40410 :   if (sv == 0)
    2285       32312 :     return Default;
    2286             : 
    2287        7088 :   return _convert_to_type(sv->original, Default);
    2288             : }
    2289             : 
    2290             : 
    2291             : 
    2292             : template <typename T>
    2293             : inline T
    2294        1294 : GetPot::operator()(const std::string& VarName, const T& Default) const
    2295             : {
    2296       36536 :   return operator()(VarName.c_str(), Default);
    2297             : }
    2298             : 
    2299             : 
    2300             : 
    2301             : inline const char*
    2302         146 : GetPot::operator()(const char* VarName, const char* Default) const
    2303             : {
    2304         288 :   return _internal_managed_copy(operator()(VarName, std::string(Default)));
    2305             : }
    2306             : 
    2307             : 
    2308             : 
    2309             : inline const char*
    2310             : GetPot::operator()(const std::string& VarName, const char* Default) const
    2311             : {
    2312             :   return operator()(VarName.c_str(), Default);
    2313             : }
    2314             : 
    2315             : 
    2316             : 
    2317             : template <typename T>
    2318             : inline T
    2319        4129 : GetPot::operator()(const char* VarName, const T& Default, unsigned int Idx) const
    2320             : {
    2321             :   // (*) recording of requested variables happens in '_request_variable()'
    2322        4129 :   const variable* sv = _request_variable(VarName);
    2323        4129 :   if (sv == 0)
    2324           3 :     return Default;
    2325             : 
    2326         116 :   const std::string*  element = sv->get_element(Idx);
    2327        4126 :   if (element == 0)
    2328           0 :     return Default;
    2329        2880 :   return _convert_to_type(*element, Default);
    2330             : }
    2331             : 
    2332             : 
    2333             : 
    2334             : template <typename T>
    2335             : inline T
    2336          80 : GetPot::operator()(const std::string& VarName, const T& Default, unsigned int Idx) const
    2337             : {
    2338        2844 :   return operator()(VarName.c_str(), Default, Idx);
    2339             : }
    2340             : 
    2341             : 
    2342             : 
    2343             : inline const char*
    2344        1282 : GetPot::operator()(const char* VarName, const char* Default, unsigned int Idx) const
    2345             : {
    2346        2528 :   return _internal_managed_copy(operator()(VarName, std::string(Default), Idx));
    2347             : }
    2348             : 
    2349             : 
    2350             : 
    2351             : inline const char*
    2352             : GetPot::operator()(const std::string& VarName, const char* Default, unsigned int Idx) const
    2353             : {
    2354             :   return operator()(VarName.c_str(), Default, Idx);
    2355             : }
    2356             : 
    2357             : 
    2358             : 
    2359             : template <typename T>
    2360             : inline T
    2361             : GetPot::get_value_no_default(const char* VarName, const T& Default) const
    2362             : {
    2363             :   // (*) recording of requested variables happens in '_request_variable()'
    2364             :   const variable*  sv = _request_variable(VarName);
    2365             :   if (sv == 0)
    2366             :     {
    2367             :       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
    2368             :       getpot_error();
    2369             :     }
    2370             :   return _convert_to_type_no_default(VarName, sv->original, Default);
    2371             : }
    2372             : 
    2373             : 
    2374             : 
    2375             : template <typename T>
    2376             : inline T
    2377             : GetPot::get_value_no_default(const std::string& VarName, const T& Default) const
    2378             : {
    2379             :   return get_value_no_default(VarName.c_str(),Default);
    2380             : }
    2381             : 
    2382             : 
    2383             : 
    2384             : inline const char*
    2385             : GetPot::get_value_no_default(const char* VarName, const char* Default) const
    2386             : {
    2387             :   return _internal_managed_copy(get_value_no_default(VarName, std::string(Default)));
    2388             : }
    2389             : 
    2390             : 
    2391             : 
    2392             : inline const char*
    2393             : GetPot::get_value_no_default(const std::string& VarName, const char* Default) const
    2394             : {
    2395             :   return get_value_no_default(VarName.c_str(),Default);
    2396             : }
    2397             : 
    2398             : 
    2399             : 
    2400             : template <typename T>
    2401             : inline T
    2402             : GetPot::get_value_no_default(const char* VarName, const T& Default, unsigned int Idx) const
    2403             : {
    2404             :   // (*) recording of requested variables happens in '_request_variable()'
    2405             :   const variable* sv = _request_variable(VarName);
    2406             :   if (sv == 0)
    2407             :     {
    2408             :       getpot_cerr << "ERROR: cannot find variable "<<VarName<<std::endl;
    2409             :       getpot_error();
    2410             :     }
    2411             : 
    2412             :   const std::string*  element = sv->get_element(Idx);
    2413             :   if (element == 0)
    2414             :     {
    2415             :       getpot_cerr << "ERROR: cannot find index "<<Idx<<" of variable "<<VarName<<std::endl;
    2416             :       getpot_error();
    2417             :     }
    2418             :   return _convert_to_type_no_default(VarName, *element, Default);
    2419             : }
    2420             : 
    2421             : 
    2422             : 
    2423             : template <typename T>
    2424             : inline T
    2425             : GetPot::get_value_no_default(const std::string& VarName, const T& Default, unsigned int Idx) const
    2426             : {
    2427             :   return get_value_no_default(VarName.c_str(), Default, Idx);
    2428             : }
    2429             : 
    2430             : 
    2431             : 
    2432             : inline const char*
    2433             : GetPot::get_value_no_default(const char* VarName, const char* Default, unsigned int Idx) const
    2434             : {
    2435             :   return _internal_managed_copy(get_value_no_default(VarName, std::string(Default), Idx));
    2436             : }
    2437             : 
    2438             : 
    2439             : 
    2440             : inline const char*
    2441             : GetPot::get_value_no_default(const std::string& VarName, const char* Default, unsigned int Idx) const
    2442             : {
    2443             :   return get_value_no_default(VarName.c_str(), Default, Idx);
    2444             : }
    2445             : 
    2446             : 
    2447             : 
    2448             : inline void
    2449    12052204 : GetPot::_record_argument_request(const std::string& Name) const
    2450             : {
    2451    12052204 :   if (!request_recording_f)
    2452           0 :     return;
    2453             : 
    2454             :   // Get a lock before touching anything mutable
    2455      630788 :   SCOPED_MUTEX;
    2456             : 
    2457             :   // (*) record requested variable for later ufo detection
    2458    11736834 :   _requested_arguments.insert(Name);
    2459             : 
    2460             :   // (*) record considered section for ufo detection
    2461    12682968 :   STRING_VECTOR      STree = _get_section_tree(Name);
    2462    12052214 :   victorate(std::string, STree, it)
    2463          10 :     if (_requested_sections.find(*it) == _requested_sections.end())
    2464          10 :       if (section.length() != 0)
    2465           0 :         _requested_sections.insert(*it);
    2466    11421440 : }
    2467             : 
    2468             : 
    2469             : 
    2470             : inline void
    2471       39906 : GetPot::_record_variable_request(const std::string& Name) const
    2472             : {
    2473       39906 :   if (!request_recording_f)
    2474           0 :     return;
    2475             : 
    2476             :   // Get a lock before touching anything mutable
    2477        2296 :   SCOPED_MUTEX;
    2478             : 
    2479             :   // (*) record requested variable for later ufo detection
    2480       38758 :   _requested_variables.insert(Name);
    2481             : 
    2482             :   // (*) record considered section for ufo detection
    2483       42202 :   STRING_VECTOR      STree = _get_section_tree(Name);
    2484       39906 :   victorate(std::string, STree, it)
    2485           0 :     if (_requested_sections.find(*it) == _requested_sections.end())
    2486           0 :       if (section.length() != 0)
    2487           0 :         _requested_sections.insert(*it);
    2488       37610 : }
    2489             : 
    2490             : 
    2491             : 
    2492             : // (*) following functions are to be used from 'outside', after getpot has parsed its
    2493             : //     arguments => append an argument in the argument vector that reflects the addition
    2494             : inline void
    2495        4760 : GetPot::_set_variable(const std::string& VarName,
    2496             :                       const std::string& Value, const bool Requested /* = true */)
    2497             : {
    2498        4760 :   const GetPot::variable* Var = Requested ?
    2499           0 :     _request_variable(VarName.c_str()) :
    2500        4760 :     _find_variable(VarName.c_str());
    2501        4760 :   if (Var == 0)
    2502        9520 :     variables.push_back(variable(VarName.c_str(), Value.c_str(), _field_separator.c_str()));
    2503             :   else
    2504             :     {
    2505           0 :       overridden_vars.insert(VarName.c_str());
    2506           0 :       (const_cast<GetPot::variable*>(Var))->take(Value.c_str(), _field_separator.c_str());
    2507             :     }
    2508        4760 : }
    2509             : 
    2510             : 
    2511             : 
    2512             : template <typename T>
    2513             : inline void
    2514             : GetPot::set(const char* VarName, const T& Value, const bool Requested /* = true */)
    2515             : {
    2516             :   std::ostringstream string_value;
    2517             :   string_value << Value;
    2518             :   _set_variable(VarName, string_value.str().c_str(), Requested);
    2519             : }
    2520             : 
    2521             : 
    2522             : 
    2523             : template <typename T>
    2524             : inline void
    2525             : GetPot::set(const std::string& VarName, const T& Value, const bool Requested /* = true */)
    2526             : {
    2527             :   set(VarName.c_str(), Value, Requested);
    2528             : }
    2529             : 
    2530             : 
    2531             : 
    2532             : inline void
    2533             : GetPot::set(const char* VarName, const char* Value, const bool Requested /* = true */)
    2534             : {
    2535             :   _set_variable(VarName, Value, Requested);
    2536             : }
    2537             : 
    2538             : 
    2539             : 
    2540             : inline void
    2541             : GetPot::set(const std::string& VarName, const char* Value, const bool Requested /* = true */)
    2542             : {
    2543             :   set(VarName.c_str(), Value, Requested);
    2544             : }
    2545             : 
    2546             : 
    2547             : 
    2548             : inline unsigned
    2549         826 : GetPot::vector_variable_size(const char* VarName) const
    2550             : {
    2551         850 :   const variable*  sv = _request_variable(VarName);
    2552         850 :   if (sv == 0)
    2553           8 :     return 0;
    2554         581 :   return (unsigned)(sv->value.size());
    2555             : }
    2556             : 
    2557             : 
    2558             : 
    2559             : inline unsigned
    2560           8 : GetPot::vector_variable_size(const std::string& VarName) const
    2561             : {
    2562         272 :   return vector_variable_size(VarName.c_str());
    2563             : }
    2564             : 
    2565             : 
    2566             : 
    2567             : inline STRING_VECTOR
    2568             : GetPot::get_variable_names() const
    2569             : {
    2570             :   STRING_VECTOR  result;
    2571             :   std::vector<GetPot::variable>::const_iterator it = variables.begin();
    2572             :   for (; it != variables.end(); ++it)
    2573             :     {
    2574             :       const std::string Tmp = _get_remaining_string((*it).name, prefix);
    2575             :       if (Tmp != "")
    2576             :         result.push_back(Tmp);
    2577             :     }
    2578             :   return result;
    2579             : }
    2580             : 
    2581             : 
    2582             : 
    2583             : inline STRING_VECTOR
    2584             : GetPot::get_section_names() const
    2585             : {
    2586             :   return section_list;
    2587             : }
    2588             : 
    2589             : 
    2590             : 
    2591             : inline STRING_VECTOR
    2592             : GetPot::get_subsection_names(const std::string & sec_prefix) const
    2593             : {
    2594             :   // GetPot functions should understand user-provided section names
    2595             :   // either with or without a trailing slash.
    2596             :   const std::string full_prefix =
    2597             :     *sec_prefix.rbegin() == '/' ? sec_prefix : sec_prefix + '/';
    2598             : 
    2599             :   const std::size_t full_prefix_len = full_prefix.size();
    2600             : 
    2601             :   // Subsections-of-subsections are in the section_list, so we'll be
    2602             :   // adding subsections multiple times.  Using std::set as an
    2603             :   // intermediate data structure helps us check for duplicates with
    2604             :   // O(N log N) rather than O(N^2) cost.
    2605             :   std::set<std::string> subsections;
    2606             : 
    2607             :   STRING_VECTOR returnval;
    2608             : 
    2609             :   for (STRING_VECTOR::const_iterator it = section_list.begin();
    2610             :        it != section_list.end(); ++it)
    2611             :     {
    2612             :       const std::string & section_name = *it;
    2613             : 
    2614             :       // If this section name begins with the prefix
    2615             :       if (section_name.compare(0, full_prefix_len, full_prefix) == 0)
    2616             :         {
    2617             :           const std::size_t next_slash_len =
    2618             :             section_name.find('/', full_prefix_len);
    2619             : 
    2620             :           const std::string subsection_name =
    2621             :             section_name.substr(full_prefix_len,
    2622             :                                 next_slash_len - full_prefix_len);
    2623             : 
    2624             :           // If there is a subsection, and if this is the first time
    2625             :           // we've seen it, add the prefix-less, postfix-less
    2626             :           // subsection name.
    2627             :           if (!subsection_name.empty() &&
    2628             :               !subsections.count(subsection_name))
    2629             :             {
    2630             :               returnval.push_back(subsection_name);
    2631             :               subsections.insert(subsection_name);
    2632             :             }
    2633             :         }
    2634             :     }
    2635             : 
    2636             :   return returnval;
    2637             : }
    2638             : 
    2639             : 
    2640             : 
    2641             : inline std::set<std::string>
    2642             : GetPot::get_overridden_variables() const
    2643             : {
    2644             :   return overridden_vars;
    2645             : }
    2646             : 
    2647             : 
    2648             : 
    2649             : inline const GetPot::variable*
    2650       44666 : GetPot::_find_variable(const char* VarName) const
    2651             : {
    2652       46142 :   const std::string Name = prefix + VarName;
    2653             : 
    2654        2952 :   std::vector<variable>::const_iterator it = variables.begin();
    2655      108080 :   for (; it != variables.end(); ++it)
    2656             :     {
    2657       68212 :       if ((*it).name == Name)
    2658         516 :         return &(*it);
    2659             :     }
    2660         960 :   return 0;
    2661             : }
    2662             : 
    2663             : 
    2664             : 
    2665             : inline const GetPot::variable*
    2666       39906 : GetPot::_request_variable(const char* VarName) const
    2667             : {
    2668             :   // (*) record requested variable for later ufo detection
    2669       39906 :   this->_record_variable_request(VarName);
    2670             : 
    2671       39906 :   return this->_find_variable(VarName);
    2672             : }
    2673             : 
    2674             : 
    2675             : 
    2676             : ///////////////////////////////////////////////////////////////////////////////
    2677             : // (*) output (basically for debugging reasons
    2678             : //.............................................................................
    2679             : //
    2680             : inline int
    2681             : GetPot::print(std::ostream &out_stream) const
    2682             : {
    2683             :   out_stream << "argc = " << argv.size() << std::endl;
    2684             :   STRING_VECTOR::const_iterator it = argv.begin();
    2685             :   for (; it != argv.end(); ++it)
    2686             :     out_stream << *it << std::endl;
    2687             :   out_stream << std::endl;
    2688             :   return 1;
    2689             : }
    2690             : 
    2691             : 
    2692             : 
    2693             : // PECOS/HPCT Addition - add option to prepend output with a delimiter
    2694             : // while also disabling argc print and skipping first print (the name
    2695             : // of the input file)
    2696             : //
    2697             : // PECOS Development Team: (ks. 4/16/09)
    2698             : inline int
    2699           0 : GetPot::print(const char* custom_prefix, std::ostream &out_stream, unsigned int skip_count) const
    2700             : {
    2701           0 :   STRING_VECTOR::const_iterator it = argv.begin();
    2702           0 :   it += skip_count;
    2703           0 :   for (; it != argv.end(); ++it)
    2704             :     {
    2705           0 :       out_stream << custom_prefix;
    2706           0 :       out_stream << *it << std::endl;
    2707             :     }
    2708           0 :   out_stream << std::endl;
    2709           0 :   return 1;
    2710             : }
    2711             : 
    2712             : 
    2713             : 
    2714             : // (*) dollar bracket expressions (DBEs) ------------------------------------
    2715             : //
    2716             : //     1) Entry Function: _DBE_expand_string()
    2717             : //        Takes a string such as
    2718             : //
    2719             : //          "${+ ${x} ${y}}   Subject-${& ${section} ${subsection}}:   ${title}"
    2720             : //
    2721             : //        calls _DBE_expand() for each of the expressions
    2722             : //
    2723             : //           ${+ ${x} ${y}}
    2724             : //           ${& ${section} ${subsection}}
    2725             : //           ${Title}
    2726             : //
    2727             : //        and returns the string
    2728             : //
    2729             : //          "4711 Subject-1.01:   Mit den Clowns kamen die Schwaene"
    2730             : //
    2731             : //        assuming that
    2732             : //            x          = "4699"
    2733             : //            y          = "12"
    2734             : //            section    = "1."
    2735             : //            subsection = "01"
    2736             : //            title      = "Mit den Clowns kamen die Schwaene"
    2737             : //
    2738             : //      2) _DBE_expand():
    2739             : //
    2740             : //           checks for the command, i.e. the 'sign' that follows '${'
    2741             : //           divides the argument list into sub-expressions using
    2742             : //           _DBE_get_expr_list()
    2743             : //
    2744             : //           ${+ ${x} ${y}}                 -> "${x}"  "${y}"
    2745             : //           ${& ${section} ${subsection}}  -> "${section}" "${subsection}"
    2746             : //           ${Title}                       -> Nothing, variable expansion
    2747             : //
    2748             : //      3) _DBE_expression_list():
    2749             : //
    2750             : //           builds a vector of unbracketed whitespace separated strings, i.e.
    2751             : //
    2752             : //           "  ${Number}.a ${: Das Marmorbild} AB-${& Author= ${Eichendorf}-1870}"
    2753             : //
    2754             : //           is split into a vector
    2755             : //
    2756             : //              [0] ${Number}.a
    2757             : //              [1] ${: Das Marmorbild}
    2758             : //              [2] AB-${& Author= ${Eichendorf}}-1870
    2759             : //
    2760             : //           Each sub-expression is expanded using expand().
    2761             : //---------------------------------------------------------------------------
    2762             : inline std::string
    2763      136300 : GetPot::_DBE_expand_string(const std::string& str)
    2764             : {
    2765             :   // Parses for closing operators '${ }' and expands them letting
    2766             :   // white spaces and other letters as they are.
    2767      136300 :   std::string   new_string = "";
    2768        1060 :   unsigned open_brackets = 0;
    2769        1060 :   unsigned first = 0;
    2770     1593800 :   for (unsigned i = 0;  i<str.size(); i++)
    2771             :     {
    2772     3862504 :       if (i + 2 < str.size() && str.substr(i, 2) == "${")
    2773             :         {
    2774           0 :           if (open_brackets == 0)
    2775           0 :             first = i+2;
    2776           0 :           open_brackets++;
    2777             :         }
    2778     1457500 :       else if (str[i] == '}' && open_brackets > 0)
    2779             :         {
    2780           0 :           open_brackets -= 1;
    2781           0 :           if (open_brackets == 0)
    2782             :             {
    2783           0 :               const std::string Replacement = _DBE_expand(str.substr(first, i - first));
    2784           0 :               new_string += Replacement;
    2785             :             }
    2786             :         }
    2787     1457500 :       else if (open_brackets == 0)
    2788     1457500 :         new_string += str[i];
    2789             :     }
    2790      136300 :   return new_string;
    2791             : }
    2792             : 
    2793             : 
    2794             : 
    2795             : inline STRING_VECTOR
    2796           0 : GetPot::_DBE_get_expr_list(const std::string& str_, const unsigned ExpectedNumber)
    2797             : {
    2798             :   // ensures that the resulting vector has the expected number
    2799             :   // of arguments, but they may contain an error message
    2800           0 :   std::string str = str_;
    2801             :   // Separates expressions by non-bracketed whitespaces, expands them
    2802             :   // and puts them into a list.
    2803             : 
    2804           0 :   unsigned i=0;
    2805             :   // (1) eat initial whitespaces
    2806           0 :   for (; i < str.size(); i++)
    2807           0 :     if (!std::isspace(str[i]))
    2808           0 :       break;
    2809             : 
    2810           0 :   STRING_VECTOR   expr_list;
    2811           0 :   unsigned         open_brackets = 0;
    2812           0 :   std::vector<unsigned> start_idx;
    2813           0 :   unsigned         start_new_string = i;
    2814           0 :   unsigned         l = (unsigned)(str.size());
    2815             : 
    2816             :   // (2) search for ${ } expressions ...
    2817           0 :   while (i < l)
    2818             :     {
    2819           0 :       const char letter = str[i];
    2820             :       // whitespace -> end of expression
    2821           0 :       if (std::isspace(letter) && open_brackets == 0)
    2822             :         {
    2823           0 :           expr_list.push_back(str.substr(start_new_string, i - start_new_string));
    2824           0 :           bool no_breakout_f = true;
    2825           0 :           for (i++; i < l ; i++)
    2826             :             {
    2827           0 :               if (!std::isspace(str[i]))
    2828             :                 {
    2829           0 :                   no_breakout_f = false;
    2830           0 :                   start_new_string = i;
    2831           0 :                   break;
    2832             :                 }
    2833             :             }
    2834             : 
    2835           0 :           if (no_breakout_f)
    2836             :             {
    2837             :               // end of expression list
    2838           0 :               if (expr_list.size() < ExpectedNumber)
    2839             :                 {
    2840           0 :                   const std::string   pre_tmp("<< ${ }: missing arguments>>");
    2841           0 :                   STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
    2842           0 :                   expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
    2843           0 :                 }
    2844           0 :               return expr_list;
    2845             :             }
    2846             :         }
    2847             : 
    2848             :       // dollar-bracket expression
    2849           0 :       if (str.length() >= i+2 && str.substr(i, 2) == "${")
    2850             :         {
    2851           0 :           open_brackets++;
    2852           0 :           start_idx.push_back(i+2);
    2853             :         }
    2854             : 
    2855           0 :       else if (letter == '}' && open_brackets > 0)
    2856             :         {
    2857           0 :           int start = start_idx[start_idx.size()-1];
    2858           0 :           start_idx.pop_back();
    2859           0 :           const std::string Replacement = _DBE_expand(str.substr(start, i-start));
    2860           0 :           if (start - 3 < (int)0)
    2861           0 :             str = Replacement + str.substr(i+1);
    2862             :           else
    2863           0 :             str = str.substr(0, start-2) + Replacement + str.substr(i+1);
    2864           0 :           l = (int)(str.size());
    2865           0 :           i = start + (int)(Replacement.size()) - 3;
    2866           0 :           open_brackets--;
    2867             :         }
    2868           0 :       i++;
    2869             :     }
    2870             : 
    2871             :   // end of expression list
    2872           0 :   expr_list.push_back(str.substr(start_new_string, i-start_new_string));
    2873             : 
    2874           0 :   if (expr_list.size() < ExpectedNumber)
    2875             :     {
    2876           0 :       const std::string   pre_tmp("<< ${ }: missing arguments>>");
    2877           0 :       STRING_VECTOR tmp(ExpectedNumber - expr_list.size(), pre_tmp);
    2878           0 :       expr_list.insert(expr_list.end(), tmp.begin(), tmp.end());
    2879           0 :     }
    2880             : 
    2881           0 :   return expr_list;
    2882           0 : }
    2883             : 
    2884             : 
    2885             : 
    2886             : inline const GetPot::variable*
    2887           0 : GetPot::_DBE_get_variable(const std::string& VarName)
    2888             : {
    2889           0 :   static GetPot::variable ev;
    2890           0 :   std::string secure_Prefix = prefix;
    2891             : 
    2892           0 :   prefix = section;
    2893             :   // (1) first search in currently active section
    2894           0 :   const GetPot::variable* var = _request_variable(VarName.c_str());
    2895           0 :   if (var != 0)
    2896             :     {
    2897           0 :       prefix = secure_Prefix;
    2898           0 :       return var;
    2899             :     }
    2900             : 
    2901             :   // (2) search in root name space
    2902           0 :   prefix = "";
    2903           0 :   var = _request_variable(VarName.c_str());
    2904           0 :   if (var != 0)
    2905             :     {
    2906           0 :       prefix = secure_Prefix;
    2907           0 :       return var;
    2908             :     }
    2909             : 
    2910           0 :   prefix = secure_Prefix;
    2911             : 
    2912             :   // error occurred => variable name == ""
    2913           0 :   ev.original = "<<${ } variable '";
    2914           0 :   ev.original += VarName + "' undefined>>";
    2915           0 :   return &ev;
    2916             : }
    2917             : 
    2918             : 
    2919             : 
    2920             : inline std::string
    2921           0 : GetPot::_DBE_expand(const std::string& expr)
    2922             : {
    2923             :   // ${: } pure text
    2924           0 :   if (expr[0] == ':')
    2925           0 :     return expr.substr(1);
    2926             : 
    2927             :   // ${& expr expr ... } text concatenation
    2928           0 :   else if (expr[0] == '&')
    2929             :     {
    2930           0 :       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 1);
    2931             : 
    2932           0 :       STRING_VECTOR::const_iterator it = A.begin();
    2933           0 :       std::string result = *it++;
    2934           0 :       for (; it != A.end(); ++it) result += *it;
    2935             : 
    2936           0 :       return result;
    2937           0 :     }
    2938             : 
    2939             :   // ${<-> expr expr expr} text replacement
    2940           0 :   else if (expr.length() >= 3 && expr.substr(0, 3) == "<->")
    2941             :     {
    2942           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(3), 3);
    2943           0 :       size_t tmp = 0;
    2944           0 :       const size_t L = A[1].length();
    2945             : 
    2946           0 :       while ((tmp = A[0].find(A[1])) != std::string::npos)
    2947           0 :         A[0].replace(tmp, L, A[2]);
    2948             : 
    2949           0 :       return A[0];
    2950           0 :     }
    2951             : 
    2952             :   // ${=func [expr...] } function evaluation
    2953           0 :   else if (expr.length() >= 2 &&
    2954           0 :            expr.substr(0, 1) == "=" &&
    2955           0 :            expr.substr(0, 2) != "==")
    2956             :     {
    2957           0 :       size_t funcnamestart = expr.find_first_not_of(" \t", 1);
    2958           0 :       if (funcnamestart != std::string::npos)
    2959             :         {
    2960           0 :           size_t funcnameend = expr.find_first_of(" \t",funcnamestart);
    2961             :           std::string funcname = expr.substr(funcnamestart,
    2962           0 :                                              funcnameend-funcnamestart);
    2963           0 :           if (funcname == "log")
    2964             :             {
    2965             :               STRING_VECTOR A =
    2966           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2967           0 :               double arg = _convert_to_type(A[0], 0.0);
    2968           0 :               return _convert_from_type(std::log(arg));
    2969           0 :             }
    2970           0 :           else if (funcname == "log10")
    2971             :             {
    2972             :               STRING_VECTOR A =
    2973           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2974           0 :               double arg = _convert_to_type(A[0], 0.0);
    2975           0 :               return _convert_from_type(std::log10(arg));
    2976           0 :             }
    2977           0 :           else if (funcname == "exp")
    2978             :             {
    2979             :               STRING_VECTOR A =
    2980           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2981           0 :               double arg = _convert_to_type(A[0], 0.0);
    2982           0 :               return _convert_from_type(std::exp(arg));
    2983           0 :             }
    2984           0 :           else if (funcname == "sin")
    2985             :             {
    2986             :               STRING_VECTOR A =
    2987           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2988           0 :               double arg = _convert_to_type(A[0], 0.0);
    2989           0 :               return _convert_from_type(std::sin(arg));
    2990           0 :             }
    2991           0 :           else if (funcname == "cos")
    2992             :             {
    2993             :               STRING_VECTOR A =
    2994           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    2995           0 :               double arg = _convert_to_type(A[0], 0.0);
    2996           0 :               return _convert_from_type(std::cos(arg));
    2997           0 :             }
    2998           0 :           else if (funcname == "tan")
    2999             :             {
    3000             :               STRING_VECTOR A =
    3001           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3002           0 :               double arg = _convert_to_type(A[0], 0.0);
    3003           0 :               return _convert_from_type(std::tan(arg));
    3004           0 :             }
    3005           0 :           else if (funcname == "asin")
    3006             :             {
    3007             :               STRING_VECTOR A =
    3008           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3009           0 :               double arg = _convert_to_type(A[0], 0.0);
    3010           0 :               return _convert_from_type(std::asin(arg));
    3011           0 :             }
    3012           0 :           else if (funcname == "acos")
    3013             :             {
    3014             :               STRING_VECTOR A =
    3015           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3016           0 :               double arg = _convert_to_type(A[0], 0.0);
    3017           0 :               return _convert_from_type(std::acos(arg));
    3018           0 :             }
    3019           0 :           else if (funcname == "atan")
    3020             :             {
    3021             :               STRING_VECTOR A =
    3022           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3023           0 :               double arg = _convert_to_type(A[0], 0.0);
    3024           0 :               return _convert_from_type(std::atan(arg));
    3025           0 :             }
    3026           0 :           else if (funcname == "atan2")
    3027             :             {
    3028             :               STRING_VECTOR A =
    3029           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
    3030           0 :               double arg1 = _convert_to_type(A[0], 0.0);
    3031           0 :               double arg2 = _convert_to_type(A[1], 0.0);
    3032           0 :               return _convert_from_type(std::atan2(arg1, arg2));
    3033           0 :             }
    3034           0 :           else if (funcname == "sinh")
    3035             :             {
    3036             :               STRING_VECTOR A =
    3037           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3038           0 :               double arg = _convert_to_type(A[0], 0.0);
    3039           0 :               return _convert_from_type(std::sinh(arg));
    3040           0 :             }
    3041           0 :           else if (funcname == "cosh")
    3042             :             {
    3043             :               STRING_VECTOR A =
    3044           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3045           0 :               double arg = _convert_to_type(A[0], 0.0);
    3046           0 :               return _convert_from_type(std::cosh(arg));
    3047           0 :             }
    3048           0 :           else if (funcname == "tanh")
    3049             :             {
    3050             :               STRING_VECTOR A =
    3051           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3052           0 :               double arg = _convert_to_type(A[0], 0.0);
    3053           0 :               return _convert_from_type(std::tanh(arg));
    3054           0 :             }
    3055             : #ifdef HAVE_INVERSE_HYPERBOLIC_SINE
    3056           0 :           else if (funcname == "asinh")
    3057             :             {
    3058             :               STRING_VECTOR A =
    3059           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3060           0 :               double arg = _convert_to_type(A[0], 0.0);
    3061           0 :               return _convert_from_type(std::asinh(arg));
    3062           0 :             }
    3063             : #endif
    3064             : #ifdef HAVE_INVERSE_HYPERBOLIC_COSINE
    3065           0 :           else if (funcname == "acosh")
    3066             :             {
    3067             :               STRING_VECTOR A =
    3068           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3069           0 :               double arg = _convert_to_type(A[0], 0.0);
    3070           0 :               return _convert_from_type(std::acosh(arg));
    3071           0 :             }
    3072             : #endif
    3073             : #ifdef HAVE_INVERSE_HYPERBOLIC_TANGENT
    3074           0 :           else if (funcname == "atanh")
    3075             :             {
    3076             :               STRING_VECTOR A =
    3077           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3078           0 :               double arg = _convert_to_type(A[0], 0.0);
    3079           0 :               return _convert_from_type(std::atanh(arg));
    3080           0 :             }
    3081             : #endif
    3082           0 :           else if (funcname == "sqrt")
    3083             :             {
    3084             :               STRING_VECTOR A =
    3085           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3086           0 :               double arg = _convert_to_type(A[0], 0.0);
    3087           0 :               return _convert_from_type(std::sqrt(arg));
    3088           0 :             }
    3089           0 :           else if (funcname == "abs")
    3090             :             {
    3091             :               STRING_VECTOR A =
    3092           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3093           0 :               double arg = _convert_to_type(A[0], 0.0);
    3094           0 :               return _convert_from_type(std::abs(arg));
    3095           0 :             }
    3096           0 :           else if (funcname == "max")
    3097             :             {
    3098             :               STRING_VECTOR A =
    3099           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3100           0 :               STRING_VECTOR::const_iterator it = A.begin();
    3101           0 :               double result = _convert_to_type(*it++, 0.0);
    3102           0 :               for (; it != A.end(); ++it)
    3103           0 :                 result = std::max(result, _convert_to_type(*it, 0.0));
    3104           0 :               return _convert_from_type(result);
    3105           0 :             }
    3106           0 :           else if (funcname == "min")
    3107             :             {
    3108             :               STRING_VECTOR A =
    3109           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3110           0 :               STRING_VECTOR::const_iterator it = A.begin();
    3111           0 :               double result = _convert_to_type(*it++, 0.0);
    3112           0 :               for (; it != A.end(); ++it)
    3113           0 :                 result = std::min(result, _convert_to_type(*it, 0.0));
    3114           0 :               return _convert_from_type(result);
    3115           0 :             }
    3116           0 :           else if (funcname == "ceil")
    3117             :             {
    3118             :               STRING_VECTOR A =
    3119           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3120           0 :               double arg = _convert_to_type(A[0], 0.0);
    3121           0 :               return _convert_from_type(std::ceil(arg));
    3122           0 :             }
    3123           0 :           else if (funcname == "floor")
    3124             :             {
    3125             :               STRING_VECTOR A =
    3126           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3127           0 :               double arg = _convert_to_type(A[0], 0.0);
    3128           0 :               return _convert_from_type(std::floor(arg));
    3129           0 :             }
    3130           0 :           else if (funcname == "fmod")
    3131             :             {
    3132             :               STRING_VECTOR A =
    3133           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 2);
    3134           0 :               double arg1 = _convert_to_type(A[0], 0.0);
    3135           0 :               double arg2 = _convert_to_type(A[1], 0.0);
    3136           0 :               return _convert_from_type(std::fmod(arg1, arg2));
    3137           0 :             }
    3138           0 :           else if (funcname == "srand")
    3139             :             {
    3140             :               STRING_VECTOR A =
    3141           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3142           0 :               unsigned int arg = _convert_to_type(A[0], 0u);
    3143           0 :               std::srand(arg);
    3144           0 :               return A[0];
    3145           0 :             }
    3146             :           // ${=rand range} with default range==RAND_MAX
    3147           0 :           else if (funcname == "rand")
    3148             :             {
    3149           0 :               if (funcnameend >= expr.length() ||
    3150           0 :                   expr.find_first_not_of(" \t", funcnameend) == std::string::npos)
    3151           0 :                 return _convert_from_type(std::rand());
    3152             : 
    3153             :               STRING_VECTOR A =
    3154           0 :                 _DBE_get_expr_list(expr.substr(funcnameend), 1);
    3155           0 :               unsigned int range = _convert_to_type(A[0],0u);
    3156           0 :               if (!range)
    3157           0 :                 return _convert_from_type(0);
    3158           0 :               const unsigned int x = (RAND_MAX + 1u) / range;
    3159           0 :               const unsigned int y = x * range;
    3160             :               unsigned int returnval;
    3161           0 :               do
    3162             :                 {
    3163           0 :                   returnval = rand();
    3164           0 :                 } while (returnval >= y);
    3165           0 :               return _convert_from_type(returnval / x);
    3166           0 :             }
    3167           0 :           else if (funcname == "time")
    3168           0 :             return _convert_from_type(std::time(NULL));
    3169             :           else
    3170             :             {
    3171           0 :               getpot_cerr << "ERROR: unrecognized function "
    3172           0 :                           << funcname << std::endl;
    3173           0 :               getpot_error();
    3174             :             }
    3175             :         }
    3176             :     }
    3177             : 
    3178             :   // ${+ ...}, ${- ...}, ${* ...}, ${/ ...} expressions
    3179           0 :   else if (expr[0] == '+')
    3180             :     {
    3181           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3182           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3183           0 :       double result = _convert_to_type(*it++, 0.0);
    3184           0 :       for (; it != A.end(); ++it)
    3185           0 :         result += _convert_to_type(*it, 0.0);
    3186             : 
    3187           0 :       return _convert_from_type(result);
    3188           0 :     }
    3189           0 :   else if (expr[0] == '-')
    3190             :     {
    3191           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3192           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3193           0 :       double result = _convert_to_type(*it++, 0.0);
    3194           0 :       for (; it != A.end(); ++it)
    3195           0 :         result -= _convert_to_type(*it, 0.0);
    3196             : 
    3197           0 :       return _convert_from_type(result);
    3198           0 :     }
    3199           0 :   else if (expr[0] == '*')
    3200             :     {
    3201           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3202           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3203           0 :       double result = _convert_to_type(*it++, 0.0);
    3204           0 :       for (; it != A.end(); ++it)
    3205           0 :         result *= _convert_to_type(*it, 0.0);
    3206             : 
    3207           0 :       return _convert_from_type(result);
    3208           0 :     }
    3209           0 :   else if (expr[0] == '/')
    3210             :     {
    3211           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3212           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3213           0 :       double result = _convert_to_type(*it++, 0.0);
    3214           0 :       if (result == 0)
    3215           0 :         return "0.0";
    3216             : 
    3217           0 :       for (; it != A.end(); ++it)
    3218             :         {
    3219           0 :           const double Q = _convert_to_type(*it, 0.0);
    3220           0 :           result /= Q;
    3221             :         }
    3222           0 :       return _convert_from_type(result);
    3223           0 :     }
    3224             : 
    3225             :   // ${^ ... } power expressions
    3226           0 :   else if (expr[0] == '^')
    3227             :     {
    3228           0 :       STRING_VECTOR A = _DBE_get_expr_list(expr.substr(1), 2);
    3229           0 :       STRING_VECTOR::const_iterator it = A.begin();
    3230           0 :       double result = _convert_to_type(*it++, 0.0);
    3231           0 :       for (; it != A.end(); ++it)
    3232           0 :         result = pow(result, _convert_to_type(*it, 0.0));
    3233           0 :       return _convert_from_type(result);
    3234           0 :     }
    3235             : 
    3236             :   // ${==  } ${<=  } ${>= } comparisons (return the number of the first 'match'
    3237           0 :   else if (expr.length() >= 2 &&
    3238           0 :            (expr.substr(0,2) == "==" || expr.substr(0,2) == ">=" ||
    3239           0 :             expr.substr(0,2) == "<=" || expr[0] == '>'           || expr[0] == '<'))
    3240             :     {
    3241             :       // differentiate between two and one sign operators
    3242           0 :       unsigned op = 0;
    3243             :       enum { EQ, GEQ, LEQ, GT, LT };
    3244             : 
    3245           0 :       if (expr.substr(0, 2) == "==")
    3246           0 :         op = EQ;
    3247             : 
    3248           0 :       else if (expr.substr(0, 2) == ">=")
    3249           0 :         op = GEQ;
    3250             : 
    3251           0 :       else if (expr.substr(0, 2) == "<=")
    3252           0 :         op = LEQ;
    3253             : 
    3254           0 :       else if (expr[0] == '>')
    3255           0 :         op = GT;
    3256             : 
    3257             :       else
    3258           0 :         op = LT;
    3259             : 
    3260           0 :       STRING_VECTOR a;
    3261           0 :       if (op == GT || op == LT)
    3262           0 :         a = _DBE_get_expr_list(expr.substr(1), 2);
    3263             : 
    3264             :       else
    3265           0 :         a = _DBE_get_expr_list(expr.substr(2), 2);
    3266             : 
    3267           0 :       std::string   x_orig = a[0];
    3268           0 :       double   x = _convert_to_type(x_orig, 1e37);
    3269           0 :       unsigned i = 1;
    3270             : 
    3271           0 :       STRING_VECTOR::const_iterator y_orig = a.begin();
    3272           0 :       for (y_orig++; y_orig != a.end(); ++y_orig)
    3273             :         {
    3274           0 :           double y = _convert_to_type(*y_orig, 1e37);
    3275             : 
    3276             :           // set the strings as reference if one wasn't a number
    3277           0 :           if (x == 1e37 || y == 1e37)
    3278             :             {
    3279             :               // it's a string comparison
    3280           0 :               if ((op == EQ  && x_orig == *y_orig) || (op == GEQ && x_orig >= *y_orig) ||
    3281           0 :                   (op == LEQ && x_orig <= *y_orig) || (op == GT  && x_orig >  *y_orig) ||
    3282           0 :                   (op == LT  && x_orig <  *y_orig))
    3283           0 :                 return _convert_from_type(i);
    3284             :             }
    3285             :           else
    3286             :             {
    3287             :               // it's a number comparison
    3288           0 :               if ((op == EQ  && x == y) || (op == GEQ && x >= y) ||
    3289           0 :                   (op == LEQ && x <= y) || (op == GT  && x >  y) ||
    3290           0 :                   (op == LT  && x <  y))
    3291           0 :                 return _convert_from_type(i);
    3292             :             }
    3293           0 :           i++;
    3294             :         }
    3295             : 
    3296             :       // nothing fulfills the condition => return 0
    3297           0 :       return "0";
    3298           0 :     }
    3299             : 
    3300             :   // ${?? expr expr} select
    3301           0 :   else if (expr.length() >= 2 && expr.substr(0, 2) == "??")
    3302             :     {
    3303           0 :       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(2), 2);
    3304           0 :       double x = _convert_to_type(a[0], 1e37);
    3305             : 
    3306             :       // last element is always the default argument
    3307           0 :       if (x == 1e37 || x < 0 || x >= double(a.size() - 1))
    3308           0 :         return a[a.size()-1];
    3309             : 
    3310             :       // round x to closest integer
    3311           0 :       return a[int(x+0.5)];
    3312           0 :     }
    3313             : 
    3314             :   // ${? expr expr expr} if then else conditions
    3315           0 :   else if (expr[0] == '?')
    3316             :     {
    3317           0 :       STRING_VECTOR a = _DBE_get_expr_list(expr.substr(1), 2);
    3318             : 
    3319           0 :       if (_convert_to_type(a[0], 0.0) == 1.0)
    3320           0 :         return a[1];
    3321             : 
    3322           0 :       else if (a.size() > 2)
    3323           0 :         return a[2];
    3324           0 :     }
    3325             :   // ${! expr} maxro expansion
    3326           0 :   else if (expr[0] == '!')
    3327             :     {
    3328           0 :       const GetPot::variable* Var = _DBE_get_variable(expr.substr(1));
    3329             :       // error
    3330           0 :       if (Var->name == "")
    3331           0 :         return std::string(Var->original);
    3332             : 
    3333           0 :       const STRING_VECTOR A = _DBE_get_expr_list(Var->original, 2);
    3334           0 :       return A[0];
    3335           0 :     }
    3336             :   // ${@: } - string subscription
    3337           0 :   else if (expr.length() >= 2 && expr.substr(0,2) == "@:")
    3338             :     {
    3339           0 :       const STRING_VECTOR A = _DBE_get_expr_list(expr.substr(2), 2);
    3340           0 :       double x = _convert_to_type(A[1], 1e37);
    3341             : 
    3342             :       // last element is always the default argument
    3343           0 :       if (x == 1e37 || x < 0 || x >= double(A[0].size() - 1))
    3344           0 :         return "<<1st index out of range>>";
    3345             : 
    3346           0 :       if (A.size() > 2)
    3347             :         {
    3348           0 :           double y = _convert_to_type(A[2], 1e37);
    3349           0 :           if (y != 1e37 && y > 0 && y <= double(A[0].size() - 1) && y > x)
    3350           0 :             return A[0].substr(int(x+0.5), int(y+1.5) - int(x+0.5));
    3351             : 
    3352           0 :           else if (y == -1)
    3353           0 :             return A[0].substr(int(x+0.5));
    3354             : 
    3355           0 :           return "<<2nd index out of range>>";
    3356             :         }
    3357             :       else
    3358             :         {
    3359           0 :           char* tmp = new char[2];
    3360           0 :           tmp[0] = A[0][int(x+0.5)]; tmp[1] = '\0';
    3361           0 :           std::string result(tmp);
    3362           0 :           delete [] tmp;
    3363           0 :           return result;
    3364             :         }
    3365           0 :     }
    3366             :   // ${@ } - vector subscription
    3367           0 :   else if (expr[0] == '@')
    3368             :     {
    3369           0 :       STRING_VECTOR          A   = _DBE_get_expr_list(expr.substr(1), 2);
    3370           0 :       const GetPot::variable* Var = _DBE_get_variable(A[0]);
    3371             :       // error
    3372           0 :       if (Var->name == "")
    3373             :         {
    3374             :           // make a copy of the string if an error occurred
    3375             :           // (since the error variable is a static variable inside get_variable())
    3376           0 :           return std::string(Var->original);
    3377             :         }
    3378             : 
    3379           0 :       double x = _convert_to_type(A[1], 1e37);
    3380             : 
    3381             :       // last element is always the default argument
    3382           0 :       if (x == 1e37 || x < 0 || x >= double(Var->value.size()))
    3383           0 :         return "<<1st index out of range>>";
    3384             : 
    3385           0 :       if (A.size() > 2)
    3386             :         {
    3387           0 :           double y = _convert_to_type(A[2], 1e37);
    3388           0 :           int    begin = int(x+0.5);
    3389           0 :           int    end = 0;
    3390           0 :           if (y != 1e37 && y > 0 && y <= double(Var->value.size()) && y > x)
    3391           0 :             end = int(y+1.5);
    3392           0 :           else if (y == -1)
    3393           0 :             end = int(Var->value.size());
    3394             :           else
    3395           0 :             return "<<2nd index out of range>>";
    3396             : 
    3397           0 :           std::string result = *(Var->get_element(begin));
    3398           0 :           for (int i = begin+1; i < end; i++)
    3399           0 :             result += std::string(" ") + *(Var->get_element(i));
    3400           0 :           return result;
    3401             :         }
    3402             :       else
    3403           0 :         return *(Var->get_element(int(x+0.5)));
    3404           0 :     }
    3405             : 
    3406           0 :   const STRING_VECTOR    A = _DBE_get_expr_list(expr, 1);
    3407           0 :   const GetPot::variable* B = _DBE_get_variable(A[0]);
    3408             : 
    3409             :   // make a copy of the string if an error occurred
    3410             :   // (since the error variable is a static variable inside get_variable())
    3411           0 :   if (B->name == "")
    3412           0 :     return std::string(B->original);
    3413             : 
    3414             :   // ([email protected] mentioned to me the warning MSVC++6.0 produces
    3415             :   //  with:  else return B->original (thanks))
    3416           0 :   return B->original;
    3417           0 : }
    3418             : 
    3419             : 
    3420             : 
    3421             : ///////////////////////////////////////////////////////////////////////////////
    3422             : // (*) unidentified flying objects
    3423             : //.............................................................................
    3424             : //
    3425             : inline bool
    3426             : GetPot::_search_string_vector(const STRING_VECTOR& VecStr, const std::string& Str) const
    3427             : {
    3428             :   victorate(std::string, VecStr, itk)
    3429             :     {
    3430             :       if (*itk == Str)
    3431             :         return true;
    3432             :     }
    3433             :   return false;
    3434             : }
    3435             : 
    3436             : 
    3437             : 
    3438             : inline STRING_VECTOR
    3439             : GetPot::unidentified_arguments(unsigned Number,
    3440             :                                const char* KnownArgument1, ...) const
    3441             : {
    3442             :   std::set<std::string> known_arguments;
    3443             : 
    3444             :   // (1) create a vector of known arguments
    3445             :   if (Number == 0)
    3446             :     return STRING_VECTOR();
    3447             : 
    3448             :   va_list ap;
    3449             :   va_start(ap, KnownArgument1);
    3450             :   known_arguments.insert(std::string(KnownArgument1));
    3451             :   for (unsigned i=1; i<Number; i++)
    3452             :     known_arguments.insert(std::string(va_arg(ap, char *)));
    3453             :   va_end(ap);
    3454             : 
    3455             :   return unidentified_arguments(known_arguments);
    3456             : }
    3457             : 
    3458             : 
    3459             : 
    3460             : inline STRING_VECTOR
    3461             : GetPot::unidentified_arguments() const
    3462             : {
    3463             :   return unidentified_arguments(_requested_arguments);
    3464             : }
    3465             : 
    3466             : 
    3467             : 
    3468             : inline STRING_VECTOR
    3469             : GetPot::unidentified_arguments(const std::vector<std::string>& Knowns) const
    3470             : {
    3471             :   // We use set for efficiency, but want to support vector inputs for
    3472             :   // backwards compatibility.
    3473             :   return unidentified_arguments(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3474             : }
    3475             : 
    3476             : 
    3477             : 
    3478             : inline STRING_VECTOR
    3479             : GetPot::unidentified_arguments(const std::set<std::string>& Knowns) const
    3480             : {
    3481             :   STRING_VECTOR ufos;
    3482             :   STRING_VECTOR::const_iterator it = argv.begin();
    3483             :   ++it; // forget about argv[0] (application or filename)
    3484             :   for (; it != argv.end(); ++it)
    3485             :     {
    3486             :       // -- argument belongs to prefixed section ?
    3487             :       const std::string arg = _get_remaining_string(*it, prefix);
    3488             :       if (arg == "")
    3489             :         continue;
    3490             : 
    3491             :       // -- check if in list
    3492             :       if (Knowns.find(arg) == Knowns.end())
    3493             :         ufos.push_back(*it);
    3494             :     }
    3495             :   return ufos;
    3496             : }
    3497             : 
    3498             : 
    3499             : 
    3500             : inline STRING_VECTOR
    3501             : GetPot::unidentified_options(unsigned Number,
    3502             :                              const char* KnownOption1, ...) const
    3503             : {
    3504             :   std::set<std::string> known_options;
    3505             : 
    3506             :   // (1) create a vector of known arguments
    3507             :   if (Number == 0)
    3508             :     return STRING_VECTOR();
    3509             : 
    3510             :   va_list ap;
    3511             :   va_start(ap, KnownOption1);
    3512             :   known_options.insert(std::string(KnownOption1));
    3513             :   for (unsigned i=1; i<Number; i++)
    3514             :     known_options.insert(std::string(va_arg(ap, char *)));
    3515             :   va_end(ap);
    3516             : 
    3517             :   return unidentified_options(known_options);
    3518             : }
    3519             : 
    3520             : 
    3521             : 
    3522             : inline STRING_VECTOR
    3523             : GetPot::unidentified_options() const
    3524             : {
    3525             :   // -- every option is an argument.
    3526             :   // -- the set of requested arguments contains the set of requested options.
    3527             :   // -- IF the set of requested arguments contains unrequested options,
    3528             :   //    THEN they were requested as 'follow' and 'next' arguments and not as real options.
    3529             :   //
    3530             :   // => it is not necessary to separate requested options from the list
    3531             :   return unidentified_arguments(_requested_arguments);
    3532             : }
    3533             : 
    3534             : 
    3535             : 
    3536             : inline STRING_VECTOR
    3537             : GetPot::unidentified_options(const std::vector<std::string>& Knowns) const
    3538             : {
    3539             :   // We use set for efficiency, but want to support vector inputs for
    3540             :   // backwards compatibility.
    3541             :   return unidentified_options(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3542             : }
    3543             : 
    3544             : 
    3545             : 
    3546             : inline STRING_VECTOR
    3547             : GetPot::unidentified_options(const std::set<std::string>& Knowns) const
    3548             : {
    3549             :   STRING_VECTOR ufos;
    3550             :   STRING_VECTOR::const_iterator it = argv.begin();
    3551             :   ++it; // forget about argv[0] (application or filename)
    3552             :   for (; it != argv.end(); ++it)
    3553             :     {
    3554             :       // -- argument belongs to prefixed section ?
    3555             :       const std::string arg = _get_remaining_string(*it, prefix);
    3556             :       if (arg == "")
    3557             :         continue;
    3558             : 
    3559             :       // is argument really an option (starting with '-') ?
    3560             :       if (arg.length() < 1 || arg[0] != '-')
    3561             :         continue;
    3562             : 
    3563             :       if (Knowns.find(arg) == Knowns.end())
    3564             :         ufos.push_back(*it);
    3565             :     }
    3566             : 
    3567             :   return ufos;
    3568             : }
    3569             : 
    3570             : 
    3571             : 
    3572             : // Two modes:
    3573             : //  ArgumentNumber >= 0 check specific argument
    3574             : //  ArgumentNumber == -1 check all options starting with one '-'
    3575             : //                       for flags
    3576             : inline std::string
    3577             : GetPot::unidentified_flags(const char* KnownFlagList, int ArgumentNumber=-1) const
    3578             : {
    3579             :   std::string         ufos;
    3580             :   // STRING_VECTOR known_arguments;
    3581             :   std::string         KFL(KnownFlagList);
    3582             : 
    3583             :   // (2) iteration over '-' arguments (options)
    3584             :   if (ArgumentNumber == -1)
    3585             :     {
    3586             :       STRING_VECTOR::const_iterator it = argv.begin();
    3587             :       ++it; // forget about argv[0] (application or filename)
    3588             :       for (; it != argv.end(); ++it)
    3589             :         {
    3590             :           // -- argument belongs to prefixed section ?
    3591             :           const std::string arg = _get_remaining_string(*it, prefix);
    3592             :           if (arg == "") continue;
    3593             : 
    3594             :           // -- does arguments start with '-' (but not '--')
    3595             :           if (arg.length() < 2)
    3596             :             continue;
    3597             : 
    3598             :           else if (arg[0] != '-')
    3599             :             continue;
    3600             : 
    3601             :           else if (arg[1] == '-')
    3602             :             continue;
    3603             : 
    3604             :           // -- check out if flags inside option are contained in KnownFlagList
    3605             :           const char* p=arg.c_str();
    3606             :           p++; // skip starting minus
    3607             :           for (; *p != '\0' ; p++)
    3608             :             if (KFL.find(*p) == std::string::npos) ufos += *p;
    3609             :         }
    3610             :     }
    3611             :   // (1) check specific argument
    3612             :   else
    3613             :     {
    3614             :       // -- only check arguments that start with prefix
    3615             :       int no_matches = 0;
    3616             :       for (unsigned i=1; i<argv.size(); i++)
    3617             :         {
    3618             :           const std::string Remain = _get_remaining_string(argv[i], prefix);
    3619             :           if (Remain != "")
    3620             :             {
    3621             :               no_matches++;
    3622             :               if (no_matches == ArgumentNumber)
    3623             :                 {
    3624             :                   // -- the right argument number inside the section is found
    3625             :                   // => check it for flags
    3626             :                   const char* p = Remain.c_str();
    3627             :                   p++; // skip starting minus
    3628             :                   for (; *p != '\0' ; p++)
    3629             :                     if (KFL.find(*p) == std::string::npos) ufos += *p;
    3630             :                   return ufos;
    3631             :                 }
    3632             :             }
    3633             :         }
    3634             :     }
    3635             :   return ufos;
    3636             : }
    3637             : 
    3638             : 
    3639             : 
    3640             : inline STRING_VECTOR
    3641             : GetPot::unidentified_variables(unsigned Number,
    3642             :                                const char* KnownVariable1, ...) const
    3643             : {
    3644             :   std::set<std::string> known_variables;
    3645             : 
    3646             :   // create vector of known arguments
    3647             :   if (Number == 0)
    3648             :     return STRING_VECTOR();
    3649             : 
    3650             :   va_list ap;
    3651             :   va_start(ap, KnownVariable1);
    3652             :   known_variables.insert(std::string(KnownVariable1));
    3653             :   for (unsigned i=1; i<Number; i++)
    3654             :     known_variables.insert(std::string(va_arg(ap, char *)));
    3655             :   va_end(ap);
    3656             : 
    3657             :   return unidentified_variables(known_variables);
    3658             : }
    3659             : 
    3660             : 
    3661             : 
    3662             : inline STRING_VECTOR
    3663             : GetPot::unidentified_variables(const std::vector<std::string>& Knowns) const
    3664             : {
    3665             :   // We use set for efficiency, but want to support vector inputs for
    3666             :   // backwards compatibility.
    3667             :   return unidentified_variables(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3668             : }
    3669             : 
    3670             : 
    3671             : 
    3672             : inline STRING_VECTOR
    3673             : GetPot::unidentified_variables(const std::set<std::string>& Knowns) const
    3674             : {
    3675             :   STRING_VECTOR ufos;
    3676             : 
    3677             :   victorate(GetPot::variable, variables, it)
    3678             :     {
    3679             :       // -- check if variable has specific prefix
    3680             :       const std::string var_name = _get_remaining_string((*it).name, prefix);
    3681             :       if (var_name == "")
    3682             :         continue;
    3683             : 
    3684             :       // -- check if variable is known
    3685             :       if (Knowns.find(var_name) == Knowns.end())
    3686             :         ufos.push_back((*it).name);
    3687             :     }
    3688             :   return ufos;
    3689             : }
    3690             : 
    3691             : 
    3692             : 
    3693             : inline STRING_VECTOR
    3694             : GetPot::unidentified_variables() const
    3695             : {
    3696             :   return unidentified_variables(_requested_variables);
    3697             : }
    3698             : 
    3699             : 
    3700             : 
    3701             : inline STRING_VECTOR
    3702             : GetPot::unidentified_sections(unsigned Number,
    3703             :                               const char* KnownSection1, ...) const
    3704             : {
    3705             :   std::set<std::string> known_sections;
    3706             : 
    3707             :   // (1) create a vector of known arguments
    3708             :   if (Number == 0)
    3709             :     return STRING_VECTOR();
    3710             : 
    3711             :   va_list ap;
    3712             :   va_start(ap, KnownSection1);
    3713             :   known_sections.insert(std::string(KnownSection1));
    3714             :   for (unsigned i=1; i<Number; i++)
    3715             :     {
    3716             :       std::string tmp = std::string(va_arg(ap, char *));
    3717             : 
    3718             :       if (tmp.length() == 0)
    3719             :         continue;
    3720             : 
    3721             :       if (tmp[tmp.length()-1] != '/')
    3722             :         tmp += '/';
    3723             : 
    3724             :       known_sections.insert(tmp);
    3725             :     }
    3726             :   va_end(ap);
    3727             : 
    3728             :   return unidentified_sections(known_sections);
    3729             : }
    3730             : 
    3731             : 
    3732             : 
    3733             : inline STRING_VECTOR
    3734             : GetPot::unidentified_sections() const
    3735             : {
    3736             :   return unidentified_sections(_requested_sections);
    3737             : }
    3738             : 
    3739             : 
    3740             : 
    3741             : inline STRING_VECTOR
    3742             : GetPot::unidentified_sections(const std::vector<std::string>& Knowns) const
    3743             : {
    3744             :   // We use set for efficiency, but want to support vector inputs for
    3745             :   // backwards compatibility.
    3746             :   return unidentified_sections(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3747             : }
    3748             : 
    3749             : 
    3750             : 
    3751             : inline STRING_VECTOR
    3752             : GetPot::unidentified_sections(const std::set<std::string>& Knowns) const
    3753             : {
    3754             :   STRING_VECTOR ufos;
    3755             : 
    3756             :   victorate(std::string, section_list, it)
    3757             :     {
    3758             :       // -- check if section conform to prefix
    3759             :       const std::string sec_name = _get_remaining_string(*it, prefix);
    3760             :       if (sec_name == "")
    3761             :         continue;
    3762             : 
    3763             :       // -- check if section is known
    3764             :       if (Knowns.find(sec_name) == Knowns.end())
    3765             :         ufos.push_back(*it);
    3766             :     }
    3767             : 
    3768             :   return ufos;
    3769             : }
    3770             : 
    3771             : 
    3772             : 
    3773             : inline STRING_VECTOR
    3774             : GetPot::unidentified_nominuses(unsigned Number, const char* Known, ...) const
    3775             : {
    3776             :   std::set<std::string> known_nominuses;
    3777             : 
    3778             :   // create vector of known arguments
    3779             :   if (Number == 0)
    3780             :     return STRING_VECTOR();
    3781             : 
    3782             :   va_list ap;
    3783             :   va_start(ap, Known);
    3784             :   known_nominuses.insert(std::string(Known));
    3785             :   for (unsigned i=1; i<Number; i++)
    3786             :     {
    3787             :       std::string tmp = std::string(va_arg(ap, char *));
    3788             :       if (tmp.length() == 0)
    3789             :         continue;
    3790             :       known_nominuses.insert(tmp);
    3791             :     }
    3792             :   va_end(ap);
    3793             : 
    3794             :   return unidentified_nominuses(known_nominuses);
    3795             : }
    3796             : 
    3797             : 
    3798             : 
    3799             : inline STRING_VECTOR
    3800             : GetPot::unidentified_nominuses() const
    3801             : {
    3802             :   // -- every nominus is an argument.
    3803             :   // -- the set of requested arguments contains the set of requested nominuss.
    3804             :   // -- IF the set of requested arguments contains unrequested nominuss,
    3805             :   //    THEN they were requested as 'follow' and 'next' arguments and not as real nominuses.
    3806             :   //
    3807             :   // => it is not necessary to separate requested nominus from the list
    3808             : 
    3809             :   return unidentified_nominuses(_requested_arguments);
    3810             : }
    3811             : 
    3812             : 
    3813             : 
    3814             : inline STRING_VECTOR
    3815             : GetPot::unidentified_nominuses(const std::vector<std::string>& Knowns) const
    3816             : {
    3817             :   // We use set for efficiency, but want to support vector inputs for
    3818             :   // backwards compatibility.
    3819             :   return unidentified_nominuses(std::set<std::string> (Knowns.begin(), Knowns.end()));
    3820             : }
    3821             : 
    3822             : 
    3823             : 
    3824             : inline STRING_VECTOR
    3825             : GetPot::unidentified_nominuses(const std::set<std::string>& Knowns) const
    3826             : {
    3827             :   STRING_VECTOR ufos;
    3828             : 
    3829             :   // (2) iterate over all arguments
    3830             :   STRING_VECTOR::const_iterator it = argv.begin();
    3831             :   ++it; // forget about argv[0] (application or filename)
    3832             :   for (; it != argv.end(); ++it)
    3833             :     {
    3834             :       // -- check if nominus part of prefix
    3835             :       const std::string arg = _get_remaining_string(*it, prefix);
    3836             :       if (arg == "")
    3837             :         continue;
    3838             : 
    3839             :       if (arg.length() < 1)
    3840             :         continue;
    3841             : 
    3842             :       // option ? --> not a nomius
    3843             :       if (arg[0] == '-')
    3844             :         continue;
    3845             : 
    3846             :       // section ? --> not a real nominus
    3847             :       if (arg[0] == '[' && arg[arg.length()-1] == ']')
    3848             :         continue;
    3849             : 
    3850             :       // variable definition ? --> not a real nominus
    3851             :       bool continue_f = false;
    3852             :       for (unsigned i=0; i<arg.length() ; i++)
    3853             :         if (arg[i] == '=')
    3854             :           {
    3855             :             continue_f = true;
    3856             :             break;
    3857             :           }
    3858             : 
    3859             :       if (continue_f)
    3860             :         continue;
    3861             : 
    3862             :       // real nominuses are compared with the given list
    3863             :       if (Knowns.find(arg) == Knowns.end())
    3864             :         ufos.push_back(*it);
    3865             :     }
    3866             :   return ufos;
    3867             : }
    3868             : 
    3869             : 
    3870             : ///////////////////////////////////////////////////////////////////////////////
    3871             : // (*) Accessors for requested types
    3872             : //.............................................................................
    3873             : 
    3874             : inline
    3875             : std::set<std::string>
    3876          71 : GetPot::get_requested_arguments() const
    3877             : {
    3878          71 :   return _requested_arguments;
    3879             : }
    3880             : 
    3881             : 
    3882             : 
    3883             : inline
    3884             : std::set<std::string>
    3885          71 : GetPot::get_requested_variables() const
    3886             : {
    3887          71 :   return _requested_variables;
    3888             : }
    3889             : 
    3890             : 
    3891             : 
    3892             : inline
    3893             : std::set<std::string>
    3894          71 : GetPot::get_requested_sections() const
    3895             : {
    3896          71 :   return _requested_sections;
    3897             : }
    3898             : 
    3899             : 
    3900             : 
    3901             : ///////////////////////////////////////////////////////////////////////////////
    3902             : // (*) variable class
    3903             : //.............................................................................
    3904             : //
    3905             : inline
    3906           0 : GetPot::variable::variable()
    3907             :   : name(),
    3908             :     value(),
    3909           0 :     original()
    3910           0 : {}
    3911             : 
    3912             : 
    3913             : 
    3914             : inline
    3915        9180 : GetPot::variable::variable(const variable& Other)
    3916             : {
    3917             : #ifdef WIN32
    3918             :   operator=(Other);
    3919             : #else
    3920        8740 :   GetPot::variable::operator=(Other);
    3921             : #endif
    3922        8740 : }
    3923             : 
    3924             : 
    3925             : 
    3926             : inline
    3927        4760 : GetPot::variable::variable(const char* Name, const char* Value, const char* FieldSeparator)
    3928        4760 :   : name(Name)
    3929             : {
    3930             :   // make a copy of the 'Value'
    3931        4760 :   take(Value, FieldSeparator);
    3932        4760 : }
    3933             : 
    3934             : 
    3935             : 
    3936             : inline const std::string*
    3937           8 : GetPot::variable::get_element(unsigned Idx) const
    3938             : {
    3939        4134 :   if (Idx >= value.size())
    3940           0 :     return 0;
    3941             :   else
    3942           8 :     return &(value[Idx]);
    3943             : }
    3944             : 
    3945             : 
    3946             : 
    3947             : inline void
    3948        4760 : GetPot::variable::take(const char* Value, const char* FieldSeparator)
    3949             : {
    3950        5088 :   original = std::string(Value); // string member var
    3951        4432 :   value.clear();                 // vector<string> member var
    3952             : 
    3953             :   /*
    3954             :   // separate string by white space delimiters using 'strtok'
    3955             :   // thread safe usage of strtok (no static members)
    3956             :   char* spt = 0;
    3957             :   // make a copy of the 'Value'
    3958             :   char* copy = new char[strlen(Value)+1];
    3959             :   strcpy(copy, Value);
    3960             :   char* follow_token = strtok_r(copy, FieldSeparator, &spt);
    3961             :   while (follow_token != 0)
    3962             :   {
    3963             :   value.push_back(std::string(follow_token));
    3964             :   follow_token = strtok_r(NULL, FieldSeparator, &spt);
    3965             :   }
    3966             : 
    3967             :   delete [] copy;
    3968             :   */
    3969             : 
    3970             :   // Don't use strtok, instead tokenize the input char "Value" using std::string operations so
    3971             :   // that the results end up in the local "value" member
    3972             : 
    3973             :   // Construct std::string objects from the input char*s.  I think the only
    3974             :   // FieldSeparator recognized by GetPot is whitespace?
    3975        5088 :   std::string Value_str = std::string(Value);
    3976        5088 :   std::string delimiters = std::string(FieldSeparator);
    3977             : 
    3978             :   // Skip delimiters at beginning.
    3979         656 :   std::string::size_type lastPos = Value_str.find_first_not_of(delimiters, 0);
    3980             : 
    3981             :   // Find first "non-delimiter".
    3982         328 :   std::string::size_type pos     = Value_str.find_first_of(delimiters, lastPos);
    3983             : 
    3984             :   // Loop over the input string until all the tokens have been pushed back
    3985             :   // into the local "value" member.
    3986        9520 :   while (std::string::npos != pos || std::string::npos != lastPos)
    3987             :     {
    3988             :       // Found a token, add it to the vector.
    3989        8864 :       value.push_back(Value_str.substr(lastPos, pos - lastPos));
    3990             : 
    3991             :       // Skip delimiters.  Note the "not_of"
    3992         656 :       lastPos = Value_str.find_first_not_of(delimiters, pos);
    3993             : 
    3994             :       // Find next "non-delimiter"
    3995         328 :       pos = Value_str.find_first_of(delimiters, lastPos);
    3996             :     }
    3997             : 
    3998             :   // We're done, all the tokens should now be in the vector<string>
    3999        4760 : }
    4000             : 
    4001             : inline
    4002       15832 : GetPot::variable::~variable()
    4003       15804 : {}
    4004             : 
    4005             : 
    4006             : 
    4007             : inline GetPot::variable&
    4008        8740 : GetPot::variable::operator=(const GetPot::variable& Other)
    4009             : {
    4010        8740 :   if (&Other != this)
    4011             :     {
    4012        8740 :       name     = Other.name;
    4013        8740 :       value    = Other.value;
    4014        8740 :       original = Other.original;
    4015             :     }
    4016        8740 :   return *this;
    4017             : }
    4018             : 
    4019             : #ifdef GETPOT_NAMESPACE
    4020             : }
    4021             : #endif
    4022             : 
    4023             : #undef victorate
    4024             : 
    4025             : #endif // LIBMESH_GETPOT_H

Generated by: LCOV version 1.14