Ignore:
Timestamp:
Apr 23, 2021, 8:31:23 PM (5 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
Candidate_v1.7.0, stable
Children:
26062f
Parents:
1ca493a
git-author:
Frederik Heber <frederik.heber@…> (04/23/21 07:20:26)
git-committer:
Frederik Heber <frederik.heber@…> (04/23/21 20:31:23)
Message:

Program_options 1.63 behavior breaks.

  • in program_options with 1.63 a behaviorial change for implicit values was introduced: "-a foo" needs to be "-a=foo" if foo is an implicit value. This completely breaks with the current behavior.
  • here, we generally fix that an action whose name is identical to an option may have its value given by following right after the action name with an equality sign and the value. This now works as well (splitting off the actual open name). Before the action was then never scheduled to run.
  • using a fix from Benedek Thaler suggest on the boost mailing list to regain the old behavior.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/UIElements/CommandLineUI/CommandLineParser.cpp

    r1ca493a rb56827  
    3535//#include "CodePatterns/MemDebug.hpp"
    3636
     37#include <boost/algorithm/string.hpp>
    3738#include <boost/filesystem.hpp>
    3839#include <boost/lexical_cast.hpp>
     
    191192}
    192193
     194/**
     195 * This is a fix by Benedek Thaler given on the boost mailing list to get back
     196 * to the old behavior before the breaking change in 1.63 for
     197 * boost::program_options.
     198 *
     199 * The problem is that for an implicit value "-a foo" will not recognize the
     200 * value for "a". It now needs to read "-a=foo" to store the value "foo" for
     201 * the action "a". This broke our behavior for all action that have same-named
     202 * options.
     203 *
     204 * See https://lists.boost.org/Archives/boost/2017/01/232272.php
     205 */
     206#if BOOST_VERSION >= 106300
     207template <typename T>
     208struct greedy_implicit_value : public po::typed_value<T>
     209{
     210  using base = po::typed_value<T>;
     211
     212  greedy_implicit_value(const T& value) : base(nullptr)
     213  {
     214    base::implicit_value(value);
     215  }
     216
     217  bool adjacent_tokens_only() const override { return false; }
     218unsigned max_tokens() const override { return 1; }
     219};
     220
     221template <typename T>
     222po::typed_value<T>* implicit_value(const T& value)
     223{
     224  return new greedy_implicit_value<T>(value);
     225}
     226#else
     227template <typename T>
     228po::typed_value<T>* implicit_value(const T& value)
     229{
     230  return new po::typed_value<T>()->implicit_value(value);
     231}
     232#endif
     233
     234
    193235/** Adds an Action or Option to the CommandLineParser.
    194236 * Note that Action is derived from Option(Trait)
     
    230272            currentOption->hasDefaultValue() ?
    231273                  (_DefaultAsImplicit ?
    232                       po::value < bool >()->implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
     274                      implicit_value(bool(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
    233275                      po::value < bool >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
    234276                  po::value < bool >(),
     
    259301            currentOption->hasDefaultValue() ?
    260302                  (_DefaultAsImplicit ?
    261                       po::value < int >()->implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
     303                      implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
    262304                      po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
    263305                  po::value < int >(),
     
    279321            currentOption->hasDefaultValue() ?
    280322                  (_DefaultAsImplicit ?
    281                       po::value < unsigned int >()->implicit_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str())) :
     323                      implicit_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str())) :
    282324                      po::value < unsigned int >()->default_value(boost::lexical_cast<unsigned int>(currentOption->getDefaultValue().c_str()))) :
    283325                  po::value < unsigned int >(),
     
    299341            currentOption->hasDefaultValue() ?
    300342                  (_DefaultAsImplicit ?
    301                       po::value < double >()->implicit_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
     343                      implicit_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
    302344                      po::value < double >()->default_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str()))) :
    303345                  po::value < double >(),
     
    319361            currentOption->hasDefaultValue() ?
    320362                  (_DefaultAsImplicit ?
    321                       po::value < std::string >()->implicit_value(currentOption->getDefaultValue()) :
     363                      implicit_value(currentOption->getDefaultValue()) :
    322364                      po::value < std::string >()->default_value(currentOption->getDefaultValue())) :
    323365                  po::value < std::string >(),
     
    375417            currentOption->hasDefaultValue() ?
    376418                  (_DefaultAsImplicit ?
    377                       po::value < int >()->implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
     419                      implicit_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
    378420                      po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str()))) :
    379421                  po::value < int >(),
     
    422464            currentOption->hasDefaultValue() ?
    423465                  (_DefaultAsImplicit ?
    424                       po::value < KeyValuePair >()->implicit_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str())) :
     466                      implicit_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str())) :
    425467                      po::value < KeyValuePair >()->default_value(boost::lexical_cast< KeyValuePair >(currentOption->getDefaultValue().c_str()))) :
    426468                  po::value < KeyValuePair >(),
     
    547589      if (argv[i][1] == '-') { // .. or --
    548590        LOG(1, "Putting " << argv[i] << " into the sequence.");
    549         SequenceOfActions.push_back(&(argv[i][2]));
     591        std::vector<std::string> fields;
     592        boost::split(fields, argv[i], boost::is_any_of("="));
     593        SequenceOfActions.push_back(&(fields[0][2]));
    550594        //  .. and check that next letter is not numeric, if so insert
    551595      } else if (((argv[i][1] < '0') || (argv[i][1] > '9')) && ((argv[i][1] != '.'))) {
Note: See TracChangeset for help on using the changeset viewer.