diff --git a/TODO b/TODO index 9aeb738485dc723e09bd5f297fdbbd3ca9ddb164..0e607aecfaaf7f92032cb2fd3f9c9b849b64a1f2 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ ==== BUGS ==== -ctest -j4 fails +ctest -j4 fails [not confirmed on l2, aug17] ==== New functionality ==== @@ -13,7 +13,7 @@ convolution with function - with TOFTOF model -==== Improve extant functcionality ==== +==== Improve extant functionality ==== coord name algebra @@ -29,8 +29,6 @@ dp: output for #spec>1 is obfuscated fs: for curve-calling-external-program (cc ecr or similar) -gp: version 'gp!' <filename> ? - mfj: remove redundant doc lines oi: wenn mehrere Files mit rank=2, automatisch in einen File packen @@ -41,13 +39,11 @@ oi: wenn mehrere Files mit rank=2, automatisch in einen File packen Register all commands; transform within-command dialogs into command options - (this replaces the following "dialog generics":) - restore ask callback help for lists (prompt for list, not for string) - restore help on "?" (e.g. expression help for 'md') - default for plot range - refactor func+op registration so that registered object can be const (assemble typed function list prior to registration) @@ -87,7 +83,6 @@ history: - save every input at once (from history to logging ...) - ==== WISHLIST ==== customization @@ -99,16 +94,6 @@ allow ad-hoc addition of fit functions (plugin ? distinguish from opr-functions ?) - plot accessible Q-E-space -distribution -- include wupscat, wupsbb -- rewrite wupscat in bash instead of ruby - - -==== PROJECTS ==== - - -2d plots using pm3d # was ist das ? - ==== WAITING FOR CLUE ==== diff --git a/arch/gcode/c3.ps b/arch/gcode/c3.ps new file mode 100644 index 0000000000000000000000000000000000000000..a67bf6f174565ae9d938a1e7227c826d09afe3cf --- /dev/null +++ b/arch/gcode/c3.ps @@ -0,0 +1,14 @@ +WuGdict11a begin + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Next frame: customizable plot setup +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Clear frame: + +Resets +BoxBackground + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ecu", end of the customization section +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/share/g3.ps b/arch/gcode/g3.ps similarity index 98% rename from pub/share/g3.ps rename to arch/gcode/g3.ps index a4737749391c18b1fa035a8fd75308908345766a..768bdd2ce216fccebd780930542c818f361cec42 100644 --- a/pub/share/g3.ps +++ b/arch/gcode/g3.ps @@ -11,7 +11,7 @@ iFrame 0 eq 10 dup autolabel defsiz 1 dup geld stdred 2 -11 setnewpage newpage -1 1 13 -14 setpagegrid +2 4 13 -14 setpagegrid 2 8 24 abcset % usage: {(text)} abc /EndFrame { nextFrame end } def diff --git a/pub/share/wups11a.ps b/arch/gcode/wups11a.ps similarity index 97% rename from pub/share/wups11a.ps rename to arch/gcode/wups11a.ps index ea61fb86749d98700e8a1ed82cf48ae3e262d74d..4897bf5f685b8544619c08fcc120643e42dfad80 100644 --- a/pub/share/wups11a.ps +++ b/arch/gcode/wups11a.ps @@ -171,6 +171,20 @@ WuGdict11a begin wyd } bind def } def +/hSetCoord { % log min max | - + /whmax x def + /whmin x def + /whlog x 0 eq not def + % prepare conversion world coord -> frame coord + /whdel whmax whmin whlog { div log } { sub } ifelse def + /whd { % dx(world) | dx(frame) + whlog { log } if whdel div 10 mul + } bind def + /wh { % x(world) | x(frame) + whmin whlog { div } { sub } ifelse + whd + } bind def + } def % pair conversion /wxy { % x,y(world) -> x,y(frame) @@ -391,7 +405,7 @@ WuGdict11a begin /Encoding MyEncoding def currentdict end - definefont % define as NewFont + definefont pop % define as NewFont } def % we assume that image scripts are Latin1 encoded @@ -1244,6 +1258,16 @@ WuGdict11a begin } def +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 2D plots %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/t2d { + icCol + { fill } execRectangle3 + black +} def + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% List %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1413,7 +1437,21 @@ WuGdict11a begin grestore grestore } def -/execRectangle2 { % xl xh yl yh {proc} | - +/execRectangle3 { % xl xh yl yh {proc} | - + 5 1 roll + gsave + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + np + qqxl qqyl mv + qqxh qqyl li + qqxh qqyh li + qqxl qqyh li + cp exec grestore + } def +/execRectangle2 { % xl xh yl yh {proc} | - OBSOLETE, BOGUS (duplicate xm|ym operations) 5 1 roll gsave ym /qqyh x def @@ -1605,14 +1643,7 @@ WuGdict11a begin supsc (-1) endsc (\)) showif } bind def /inGHzr { showif (\(GHz) (-1) sp (\)) showif } def -%% home-made Angstr is obsolete; use \305 (more reliable than Ã…) -/Angstr { - showif - (A) .5 1.23 { - currentpoint fontheight .1 mul setline np - fontheight .14 mul 0 360 arc st () - } build -} bind def +/Angstr { showif (\305) showif } bind def /Angr { showif (\305) supsc (-1) endsc } bind def /inAngr { showif (\() Angr (\)) showif } bind def /Angrr { showif (\305) supsc (-2) endsc } bind def diff --git a/distrib/core/HOWTO b/distrib/core/HOWTO index 2a9204550f8b5268a12da253439ab9817e36b3a7..470c97f4ea7a4c2251d12c312b5ae2a156b742c3 100755 --- a/distrib/core/HOWTO +++ b/distrib/core/HOWTO @@ -1,17 +1,13 @@ cd /G/f2 - -### merge devel into master -# git rebase -i HEAD~99 # correct commit messages; do not go past last tag or branch from master git checkout master git pull origin master git merge --no-ff devel -git push origin master -### prepare +git push origin master vi pub/CMakeLists.txt # increment version number, remove "post-" + vi pub/CHANGELOG -### purge rm -r /G/f2/pub/build rm -r /G/f2/pub/qtbuild cd /G/f2/pub @@ -19,18 +15,16 @@ rm *~ rm */*~ rm */*/*~ rm */Doxyfile.bak - -### pack export V=2. # 2.<major>.<minor><bugfix> + export A=frida$V cd /tmp rm $A slink /G/f2/pub $A tar czvfh ~/data/tgz/$A.tgz $A/* dl ~/data/tgz/frida2.* # CHECK size -rm $A -### update git +rm $A cd /G/f2 kcom -m "This is release $V" kush @@ -38,10 +32,10 @@ k tag v$V # Yes! Our IT wants version tags to start with "v". # to delete erroneous tag: git tag -d $X; git push origin :refs/tags/$X kush --tags -### upload tgz - ssh wuttke@a mv /www/apps/src/frida/frida2.* /www/apps/src/frida/old/ + scp ~/data/tgz/$A.tgz wuttke@a:/www/apps/src/frida/ + scp /G/f2/pub/CHANGELOG wuttke@a:/www/apps/src/frida/frida2-CHANGELOG ### advertise @@ -54,16 +48,15 @@ git checkout devel git rebase master cd /G/f2/pub vi CMakeLists.txt # version becomes "post-<release>" + kcom -m "Starting post-$V" kush - -### rebuild cd /G/f2/pub mkdir build cd build cmake .. m -j7 -ctest +ctest -j7 mi ### upload man page (if changed) diff --git a/pub/CHANGELOG b/pub/CHANGELOG index eb061f0e28b779f3278a664351bcde31476fb644..bc6ee9e62591ae88f3de2340ba0a4077781e1510 100644 --- a/pub/CHANGELOG +++ b/pub/CHANGELOG @@ -1,3 +1,62 @@ +- use plot.Y.force in 2d plotting +- use wx, wy, wh in setting ticks and tacks for easier editing of PS file +- correct ticks and tacks for small log range +- correct handling of Z in oixy +- pertinent error message when calling 'a' before 'p' + +Release 2.4.0b of 21apr17: + +- Modified functionality: + - sqrt, ln, lg return NaN outside their definition range + - sqrt0, ln0, lg0 return 0 outside the definition range of the standard functions +- Bug fix: + - detection of dy==0 for fit weighing was inverted + +Release 2.4.0a of 24mar17: + +- Consolidated graphics definitions wups17a +- Practicable 2D plotting +- Bug fixes: + - Reactivated possibility to overwrite when saving files (now fs! instead of fso) + - Correct handling of i-dependent indices (-> test oxy_idep) +- Code cleanup: + - Decoupled plot window administration from the actual plotting + - Removed save_y08 + - Hard-coded debug facility in node.cpp + +Release 2.3.6c of 17mar17: + +- New command dv to display list of defined variables +- Experimental code for 2d plots + +Release 2.3.6b of 14mar17: + +- Replaced experimental/filesystem by boost/filesystem for compilation under gcc4.8 + +Release 2.3.6a of 13mar17: + +- Bug fixes: + - Restored ability to load files from outside the current working directory + - Correct handling of dy (or absence thereof) in ftv +- New functionality: + - Frida main program now has command-line options -b, -h, --version + - Command crp to restrict plot range + - New integral operations firstwith, lastwith +- Improved functionality: + - In binning (mpa, msa), computation of sampling error is now optional + - Commands gp, gf, gp!, gf!, gfa to create/overwrite/append graphic file + - Integral operations now return integers when appropriate + - Cleaner implementation of refined curve plotting +- Code cleanup: + - fname_divide replaced by functions from std::experimental::filesystem + +Release 2.3.5a of 01feb17: + +- CMake machinery now uses variables like ${library_name}_LIBRARY +- Renamed libfrida -> libfridacore, libtrivia -> libfridatrivia +- Fully relying on implicit library dependencies (frida -> libfridacore -> libfridatrivia -> GSL) +- Ensure termination of functional tests by including the one-line script "exit(1)" + Release 2.3.4d of 28jan17: - mpgi,mpgr now using NOlo::j2j for spectrum correspondence diff --git a/pub/CMakeLists.txt b/pub/CMakeLists.txt index 775fe7744ef47d16fa4b2c92ef3c9f88ef75c6e6..332629dbc8077824b83bd4ecc4feb98c5c37e5df 100644 --- a/pub/CMakeLists.txt +++ b/pub/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) project(Frida) -set(Frida_VERSION 2.3.4d) +set(Frida_VERSION post-2.4.0b) include(CTest) # equivalent to "enable_testing() ??? add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) # => 'make check' is an alias for 'ctest' @@ -22,10 +22,12 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/scripts/CTestCustom.cmake.in #option(FRIDA_MAN "Build a user manual" OFF) #option(BUILD_DEBIAN "Build a debian package" OFF) +set(destination_lib ${CMAKE_INSTALL_PREFIX}/lib) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O2 -pedantic -Wall -Wno-sign-compare -Wno-unused-result -Wno-parentheses -Wno-unknown-pragmas -Werror") # to use C99 _Complex, add -fext-numeric-literals to CXX_FLAGS -find_package(Boost REQUIRED) # used header-only modules: format algorithm +find_package(Boost REQUIRED filesystem) find_package(BISON REQUIRED) find_package(FLEX REQUIRED) find_package(Readline REQUIRED) @@ -37,7 +39,6 @@ find_package(Cerf REQUIRED) find_package(LMFit REQUIRED) find_package(Gnuplot REQUIRED) -add_subdirectory(ThirdParty/googletest) add_subdirectory(readplus) add_subdirectory(trivia) add_subdirectory(plot) @@ -45,6 +46,8 @@ add_subdirectory(lib) add_subdirectory(src) add_subdirectory(share) add_subdirectory(man) + +add_subdirectory(ThirdParty/googletest) add_subdirectory(utest) # unit tests add_subdirectory(ftest) # functional tests (run Frida with given script) diff --git a/pub/ThirdParty/tclap/Arg.h b/pub/ThirdParty/tclap/Arg.h new file mode 100644 index 0000000000000000000000000000000000000000..b28eef117c633f5e4108775cf9466a22402a9d07 --- /dev/null +++ b/pub/ThirdParty/tclap/Arg.h @@ -0,0 +1,692 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: Arg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARGUMENT_H +#define TCLAP_ARGUMENT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <cstdio> + +#if defined(HAVE_SSTREAM) +#include <sstream> +typedef std::istringstream istringstream; +#elif defined(HAVE_STRSTREAM) +#include <strstream> +typedef std::istrstream istringstream; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +#include <tclap/ArgException.h> +#include <tclap/Visitor.h> +#include <tclap/CmdLineInterface.h> +#include <tclap/ArgTraits.h> +#include <tclap/StandardTraits.h> + +namespace TCLAP { + +/** + * A virtual base class that defines the essential data for all arguments. + * This class, or one of its existing children, must be subclassed to do + * anything. + */ +class Arg +{ + private: + /** + * Prevent accidental copying. + */ + Arg(const Arg& rhs); + + /** + * Prevent accidental copying. + */ + Arg& operator=(const Arg& rhs); + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool& ignoreRestRef() { static bool ign = false; return ign; } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char& delimiterRef() { static char delim = ' '; return delim; } + + protected: + + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor* _visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v = NULL ); + + public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Defaults to '-', but + * clients can define TCLAP_FLAGSTARTCHAR to override. + */ +#ifndef TCLAP_FLAGSTARTCHAR +#define TCLAP_FLAGSTARTCHAR '-' +#endif + static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } + + /** + * The sting that indicates the beginning of a flag. Defaults to "-", but + * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same + * as TCLAP_FLAGSTARTCHAR. + */ +#ifndef TCLAP_FLAGSTARTSTRING +#define TCLAP_FLAGSTARTSTRING "-" +#endif + static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } + + /** + * The sting that indicates the beginning of a name. Defaults to "--", but + * clients can define TCLAP_NAMESTARTSTRING to override. + */ +#ifndef TCLAP_NAMESTARTSTRING +#define TCLAP_NAMESTARTSTRING "--" +#endif + static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter( char c ) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector<std::string>& args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Returns the argument flag. + */ + const std::string& getFlag() const; + + /** + * Returns the argument name. + */ + const std::string& getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches( const std::string& s ) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID( const std::string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID( const std::string& valueId = "val" ) const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag( std::string& flag, std::string& value ) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks( const std::string& s ) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel( const std::string& s ); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); +}; + +/** + * Typedef of an Arg list iterator. + */ +typedef std::list<Arg*>::iterator ArgListIterator; + +/** + * Typedef of an Arg vector iterator. + */ +typedef std::vector<Arg*>::iterator ArgVectorIterator; + +/** + * Typedef of a Visitor list iterator. + */ +typedef std::list<Visitor*>::iterator VisitorListIterator; + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * ValueLike traits use operator>> to assign the value from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) +{ + static_cast<void>(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while ( is.good() ) { + if ( is.peek() != EOF ) +#ifdef TCLAP_SETBASE_ZERO + is >> std::setbase(0) >> destVal; +#else + is >> destVal; +#endif + else + break; + + valuesRead++; + } + + if ( is.fail() ) + throw( ArgParseException("Couldn't read argument value " + "from string '" + strVal + "'")); + + + if ( valuesRead > 1 ) + throw( ArgParseException("More than one valid value parsed from " + "string '" + strVal + "'")); + +} + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * StringLike uses assignment (operator=) to assign from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, StringLike sl) +{ + static_cast<void>(sl); // Avoid warning about unused sl + SetString(destVal, strVal); +} + +////////////////////////////////////////////////////////////////////// +//BEGIN Arg.cpp +////////////////////////////////////////////////////////////////////// + +inline Arg::Arg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v) : + _flag(flag), + _name(name), + _description(desc), + _required(req), + _requireLabel("required"), + _valueRequired(valreq), + _alreadySet(false), + _visitor( v ), + _ignoreable(true), + _xorSet(false), + _acceptsMultipleValues(false) +{ + if ( _flag.length() > 1 ) + throw(SpecificationException( + "Argument flag can only be one character long", toString() ) ); + + if ( _name != ignoreNameString() && + ( _flag == Arg::flagStartString() || + _flag == Arg::nameStartString() || + _flag == " " ) ) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString() ) ); + + if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || + ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || + ( _name.find( " ", 0 ) != std::string::npos ) ) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString() ) ); + +} + +inline Arg::~Arg() { } + +inline std::string Arg::shortID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +inline std::string Arg::longID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + { + id += Arg::flagStartString() + _flag; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + id += ", "; + } + + id += Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + return id; + +} + +inline bool Arg::operator==(const Arg& a) const +{ + if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) + return true; + else + return false; +} + +inline std::string Arg::getDescription() const +{ + std::string desc = ""; + if ( _required ) + desc = "(" + _requireLabel + ") "; + +// if ( _valueRequired ) +// desc += "(value required) "; + + desc += _description; + return desc; +} + +inline const std::string& Arg::getFlag() const { return _flag; } + +inline const std::string& Arg::getName() const { return _name; } + +inline bool Arg::isRequired() const { return _required; } + +inline bool Arg::isValueRequired() const { return _valueRequired; } + +inline bool Arg::isSet() const +{ + if ( _alreadySet && !_xorSet ) + return true; + else + return false; +} + +inline bool Arg::isIgnoreable() const { return _ignoreable; } + +inline void Arg::setRequireLabel( const std::string& s) +{ + _requireLabel = s; +} + +inline bool Arg::argMatches( const std::string& argFlag ) const +{ + if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || + argFlag == Arg::nameStartString() + _name ) + return true; + else + return false; +} + +inline std::string Arg::toString() const +{ + std::string s = ""; + + if ( _flag != "" ) + s += Arg::flagStartString() + _flag + " "; + + s += "(" + Arg::nameStartString() + _name + ")"; + + return s; +} + +inline void Arg::_checkWithVisitor() const +{ + if ( _visitor != NULL ) + _visitor->visit(); +} + +/** + * Implementation of trimFlag. + */ +inline void Arg::trimFlag(std::string& flag, std::string& value) const +{ + int stop = 0; + for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ ) + if ( flag[i] == Arg::delimiter() ) + { + stop = i; + break; + } + + if ( stop > 1 ) + { + value = flag.substr(stop+1); + flag = flag.substr(0,stop); + } + +} + +/** + * Implementation of _hasBlanks. + */ +inline bool Arg::_hasBlanks( const std::string& s ) const +{ + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] == Arg::blankChar() ) + return true; + + return false; +} + +inline void Arg::forceRequired() +{ + _required = true; +} + +inline void Arg::xorSet() +{ + _alreadySet = true; + _xorSet = true; +} + +/** + * Overridden by Args that need to added to the end of the list. + */ +inline void Arg::addToList( std::list<Arg*>& argList ) const +{ + argList.push_front( const_cast<Arg*>(this) ); +} + +inline bool Arg::allowMore() +{ + return false; +} + +inline bool Arg::acceptsMultipleValues() +{ + return _acceptsMultipleValues; +} + +inline void Arg::reset() +{ + _xorSet = false; + _alreadySet = false; +} + +////////////////////////////////////////////////////////////////////// +//END Arg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif + diff --git a/pub/ThirdParty/tclap/ArgException.h b/pub/ThirdParty/tclap/ArgException.h new file mode 100644 index 0000000000000000000000000000000000000000..3411aa9543fe3643053ab2aff7c8994b3a900327 --- /dev/null +++ b/pub/ThirdParty/tclap/ArgException.h @@ -0,0 +1,200 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgException.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARG_EXCEPTION_H +#define TCLAP_ARG_EXCEPTION_H + +#include <string> +#include <exception> + +namespace TCLAP { + +/** + * A simple class that defines and argument exception. Should be caught + * whenever a CmdLine is created and parsed. + */ +class ArgException : public std::exception +{ + public: + + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException( const std::string& text = "undefined exception", + const std::string& id = "undefined", + const std::string& td = "Generic ArgException") + : std::exception(), + _errorText(text), + _argId( id ), + _typeDescription(td) + { } + + /** + * Destructor. + */ + virtual ~ArgException() throw() { } + + /** + * Returns the error text. + */ + std::string error() const { return ( _errorText ); } + + /** + * Returns the argument id. + */ + std::string argId() const + { + if ( _argId == "undefined" ) + return " "; + else + return ( "Argument: " + _argId ); + } + + /** + * Returns the arg id and error text. + */ + const char* what() const throw() + { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const + { + return _typeDescription; + } + + + private: + + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; + +}; + +/** + * Thrown from within the child Arg classes when it fails to properly + * parse the argument it has been passed. + */ +class ArgParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found while parsing " ) + + std::string( "the value the Arg has been passed." )) + { } +}; + +/** + * Thrown from CmdLine when the arguments on the command line are not + * properly specified, e.g. too many arguments, required argument missing, etc. + */ +class CmdLineParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found when the values ") + + std::string( "on the command line do not meet ") + + std::string( "the requirements of the defined ") + + std::string( "Args." )) + { } +}; + +/** + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * same flag as another Arg, same name, etc. + */ +class SpecificationException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string("Exception found when an Arg object ")+ + std::string("is improperly defined by the ") + + std::string("developer." )) + { } + +}; + +class ExitException { +public: + ExitException(int estat) : _estat(estat) {} + + int getExitStatus() const { return _estat; } + +private: + int _estat; +}; + +} // namespace TCLAP + +#endif + diff --git a/pub/ThirdParty/tclap/ArgTraits.h b/pub/ThirdParty/tclap/ArgTraits.h new file mode 100644 index 0000000000000000000000000000000000000000..0b2c18f70c68200b431794eb6bec28927b6ec9aa --- /dev/null +++ b/pub/ThirdParty/tclap/ArgTraits.h @@ -0,0 +1,87 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_ARGTRAITS_H +#define TCLAP_ARGTRAITS_H + +namespace TCLAP { + +// We use two empty structs to get compile type specialization +// function to work + +/** + * A value like argument value type is a value that can be set using + * operator>>. This is the default value type. + */ +struct ValueLike { + typedef ValueLike ValueCategory; + virtual ~ValueLike() {} +}; + +/** + * A string like argument value type is a value that can be set using + * operator=(string). Usefull if the value type contains spaces which + * will be broken up into individual tokens by operator>>. + */ +struct StringLike { + virtual ~StringLike() {} +}; + +/** + * A class can inherit from this object to make it have string like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct StringLikeTrait { + typedef StringLike ValueCategory; + virtual ~StringLikeTrait() {} +}; + +/** + * A class can inherit from this object to make it have value like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct ValueLikeTrait { + typedef ValueLike ValueCategory; + virtual ~ValueLikeTrait() {} +}; + +/** + * Arg traits are used to get compile type specialization when parsing + * argument values. Using an ArgTraits you can specify the way that + * values gets assigned to any particular type during parsing. The two + * supported types are StringLike and ValueLike. + */ +template<typename T> +struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + virtual ~ArgTraits() {} + //typedef ValueLike ValueCategory; +}; + +#endif + +} // namespace diff --git a/pub/ThirdParty/tclap/CmdLine.h b/pub/ThirdParty/tclap/CmdLine.h new file mode 100644 index 0000000000000000000000000000000000000000..0fec8d8a115910c800ff12a1fd1c41f6b8dc023f --- /dev/null +++ b/pub/ThirdParty/tclap/CmdLine.h @@ -0,0 +1,633 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: CmdLine.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINE_H +#define TCLAP_CMDLINE_H + +#include <tclap/SwitchArg.h> +#include <tclap/MultiSwitchArg.h> +#include <tclap/UnlabeledValueArg.h> +#include <tclap/UnlabeledMultiArg.h> + +#include <tclap/XorHandler.h> +#include <tclap/HelpVisitor.h> +#include <tclap/VersionVisitor.h> +#include <tclap/IgnoreRestVisitor.h> + +#include <tclap/CmdLineOutput.h> +#include <tclap/StdOutput.h> + +#include <tclap/Constraint.h> +#include <tclap/ValuesConstraint.h> + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> +#include <stdlib.h> // Needed for exit(), which isn't defined in some envs. + +namespace TCLAP { + +template<typename T> void DelPtr(T ptr) +{ + delete ptr; +} + +template<typename C> void ClearContainer(C &c) +{ + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr<value_type>); + c.clear(); +} + + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLine : public CmdLineInterface +{ + protected: + + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list<Arg*> _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list<Arg*> _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list<Visitor*> _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput* _output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string& s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg* ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor* ptr); + +private: + + /** + * Prevent accidental copying. + */ + CmdLine(const CmdLine& rhs); + CmdLine& operator=(const CmdLine& rhs); + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + + public: + + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string& message, + const char delimiter = ' ', + const std::string& version = "none", + bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add( Arg& a ); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add( Arg* a ); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd( Arg& a, Arg& b ); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd( std::vector<Arg*>& xors ); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char * const * argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * + */ + CmdLineOutput* getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput* co); + + /** + * + */ + std::string& getVersion(); + + /** + * + */ + std::string& getProgramName(); + + /** + * + */ + std::list<Arg*>& getArgList(); + + /** + * + */ + XorHandler& getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string& getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); + +}; + + +/////////////////////////////////////////////////////////////////////////////// +//Begin CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + +inline CmdLine::CmdLine(const std::string& m, + char delim, + const std::string& v, + bool help ) + : + _argList(std::list<Arg*>()), + _progName("not_set_yet"), + _message(m), + _version(v), + _numRequired(0), + _delimiter(delim), + _xorHandler(XorHandler()), + _argDeleteOnExitList(std::list<Arg*>()), + _visitorDeleteOnExitList(std::list<Visitor*>()), + _output(0), + _handleExceptions(true), + _userSetOutput(false), + _helpAndVersion(help) +{ + _constructor(); +} + +inline CmdLine::~CmdLine() +{ + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); + + if ( !_userSetOutput ) { + delete _output; + _output = 0; + } +} + +inline void CmdLine::_constructor() +{ + _output = new StdOutput; + + Arg::setDelimiter( _delimiter ); + + Visitor* v; + + if ( _helpAndVersion ) + { + v = new HelpVisitor( this, &_output ); + SwitchArg* help = new SwitchArg("h","help", + "Displays usage information and exits.", + false, v); + add( help ); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor( this, &_output ); + SwitchArg* vers = new SwitchArg("","version", + "Displays version information and exits.", + false, v); + add( vers ); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), + Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", + false, v); + add( ignore ); + deleteOnExit(ignore); + deleteOnExit(v); +} + +inline void CmdLine::xorAdd( std::vector<Arg*>& ors ) +{ + _xorHandler.add( ors ); + + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) + { + (*it)->forceRequired(); + (*it)->setRequireLabel( "OR required" ); + add( *it ); + } +} + +inline void CmdLine::xorAdd( Arg& a, Arg& b ) +{ + std::vector<Arg*> ors; + ors.push_back( &a ); + ors.push_back( &b ); + xorAdd( ors ); +} + +inline void CmdLine::add( Arg& a ) +{ + add( &a ); +} + +inline void CmdLine::add( Arg* a ) +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + if ( *a == *(*it) ) + throw( SpecificationException( + "Argument with same flag/name already exists!", + a->longID() ) ); + + a->addToList( _argList ); + + if ( a->isRequired() ) + _numRequired++; +} + + +inline void CmdLine::parse(int argc, const char * const * argv) +{ + // this step is necessary so that we have easy access to + // mutable strings. + std::vector<std::string> args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + + parse(args); +} + +inline void CmdLine::parse(std::vector<std::string>& args) +{ + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) + { + bool matched = false; + for (ArgListIterator it = _argList.begin(); + it != _argList.end(); it++) { + if ( (*it)->processArg( &i, args ) ) + { + requiredCount += _xorHandler.check( *it ); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if ( !matched && _emptyCombined( args[i] ) ) + matched = true; + + if ( !matched && !Arg::ignoreRest() ) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if ( requiredCount < _numRequired ) + missingArgsException(); + + if ( requiredCount > _numRequired ) + throw(CmdLineParseException("Too many arguments!")); + + } catch ( ArgException& e ) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + try { + _output->failure(*this,e); + } catch ( ExitException &ee ) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); +} + +inline bool CmdLine::_emptyCombined(const std::string& s) +{ + if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) + return false; + + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline void CmdLine::missingArgsException() +{ + int count = 0; + + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + { + if ( (*it)->isRequired() && !(*it)->isSet() ) + { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0,missingArgList.length()-2); + + std::string msg; + if ( count > 1 ) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; + + msg += missingArgList; + + throw(CmdLineParseException(msg)); +} + +inline void CmdLine::deleteOnExit(Arg* ptr) +{ + _argDeleteOnExitList.push_back(ptr); +} + +inline void CmdLine::deleteOnExit(Visitor* ptr) +{ + _visitorDeleteOnExitList.push_back(ptr); +} + +inline CmdLineOutput* CmdLine::getOutput() +{ + return _output; +} + +inline void CmdLine::setOutput(CmdLineOutput* co) +{ + if ( !_userSetOutput ) + delete _output; + _userSetOutput = true; + _output = co; +} + +inline std::string& CmdLine::getVersion() +{ + return _version; +} + +inline std::string& CmdLine::getProgramName() +{ + return _progName; +} + +inline std::list<Arg*>& CmdLine::getArgList() +{ + return _argList; +} + +inline XorHandler& CmdLine::getXorHandler() +{ + return _xorHandler; +} + +inline char CmdLine::getDelimiter() +{ + return _delimiter; +} + +inline std::string& CmdLine::getMessage() +{ + return _message; +} + +inline bool CmdLine::hasHelpAndVersion() +{ + return _helpAndVersion; +} + +inline void CmdLine::setExceptionHandling(const bool state) +{ + _handleExceptions = state; +} + +inline bool CmdLine::getExceptionHandling() const +{ + return _handleExceptions; +} + +inline void CmdLine::reset() +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + (*it)->reset(); + + _progName.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +//End CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + + + +} //namespace TCLAP +#endif diff --git a/pub/ThirdParty/tclap/CmdLineInterface.h b/pub/ThirdParty/tclap/CmdLineInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..1b25e9b8c950a29988bd510c9f3b3a2a6b1b3b58 --- /dev/null +++ b/pub/ThirdParty/tclap/CmdLineInterface.h @@ -0,0 +1,150 @@ + +/****************************************************************************** + * + * file: CmdLineInterface.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_COMMANDLINE_INTERFACE_H +#define TCLAP_COMMANDLINE_INTERFACE_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + + +namespace TCLAP { + +class Arg; +class CmdLineOutput; +class XorHandler; + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLineInterface +{ + public: + + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add( Arg& a )=0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add( Arg* a )=0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd( Arg& a, Arg& b )=0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd( std::vector<Arg*>& xors )=0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char * const * argv)=0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput* getOutput()=0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput* co)=0; + + /** + * Returns the version string. + */ + virtual std::string& getVersion()=0; + + /** + * Returns the program name string. + */ + virtual std::string& getProgramName()=0; + + /** + * Returns the argList. + */ + virtual std::list<Arg*>& getArgList()=0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler& getXorHandler()=0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter()=0; + + /** + * Returns the message string. + */ + virtual std::string& getMessage()=0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion()=0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset()=0; +}; + +} //namespace + + +#endif diff --git a/pub/ThirdParty/tclap/CmdLineOutput.h b/pub/ThirdParty/tclap/CmdLineOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..71ee5a3b418b4d3aaf7b2bdfd30282bc5d4e0e3b --- /dev/null +++ b/pub/ThirdParty/tclap/CmdLineOutput.h @@ -0,0 +1,74 @@ + + +/****************************************************************************** + * + * file: CmdLineOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINEOUTPUT_H +#define TCLAP_CMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +class CmdLineInterface; +class ArgException; + +/** + * The interface that any output object must implement. + */ +class CmdLineOutput +{ + + public: + + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} + + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure( CmdLineInterface& c, + ArgException& e )=0; + +}; + +} //namespace TCLAP +#endif diff --git a/pub/ThirdParty/tclap/Constraint.h b/pub/ThirdParty/tclap/Constraint.h new file mode 100644 index 0000000000000000000000000000000000000000..a92acf9a9a29e5b15f655b3d0caa6d280193f60d --- /dev/null +++ b/pub/ThirdParty/tclap/Constraint.h @@ -0,0 +1,68 @@ + +/****************************************************************************** + * + * file: Constraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CONSTRAINT_H +#define TCLAP_CONSTRAINT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +/** + * The interface that defines the interaction between the Arg and Constraint. + */ +template<class T> +class Constraint +{ + + public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const =0; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const =0; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const =0; + + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } +}; + +} //namespace TCLAP +#endif diff --git a/pub/ThirdParty/tclap/DocBookOutput.h b/pub/ThirdParty/tclap/DocBookOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..a42ca274dfbb4648adb62962773310e902151973 --- /dev/null +++ b/pub/ThirdParty/tclap/DocBookOutput.h @@ -0,0 +1,299 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: DocBookOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_DOCBOOKOUTPUT_H +#define TCLAP_DOCBOOKOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates DocBook output for usage() method for the + * given CmdLine and its Args. + */ +class DocBookOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars( std::string& s, char r, std::string& x ); + void removeChar( std::string& s, char r); + void basename( std::string& s ); + + void printShortArg(Arg* it); + void printLongArg(Arg* it); + + char theDelimiter; +}; + + +inline void DocBookOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void DocBookOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "<?xml version='1.0'?>" << std::endl; + std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl; + std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl; + + std::cout << "<refentry>" << std::endl; + + std::cout << "<refmeta>" << std::endl; + std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl; + std::cout << "<manvolnum>1</manvolnum>" << std::endl; + std::cout << "</refmeta>" << std::endl; + + std::cout << "<refnamediv>" << std::endl; + std::cout << "<refname>" << progName << "</refname>" << std::endl; + std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl; + std::cout << "</refnamediv>" << std::endl; + + std::cout << "<refsynopsisdiv>" << std::endl; + std::cout << "<cmdsynopsis>" << std::endl; + + std::cout << "<command>" << progName << "</command>" << std::endl; + + // xor + for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) + { + std::cout << "<group choice='req'>" << std::endl; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + printShortArg((*it)); + + std::cout << "</group>" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + printShortArg((*it)); + + std::cout << "</cmdsynopsis>" << std::endl; + std::cout << "</refsynopsisdiv>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Description</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Options</title>" << std::endl; + + std::cout << "<variablelist>" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "</variablelist>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Version</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << xversion << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "</refentry>" << std::endl; + +} + +inline void DocBookOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); +} + +inline void DocBookOutput::substituteSpecialChars( std::string& s, + char r, + std::string& x ) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + s.insert(p,x); + } +} + +inline void DocBookOutput::removeChar( std::string& s, char r) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + } +} + +inline void DocBookOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void DocBookOutput::printShortArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id,'<',lt); + substituteSpecialChars(id,'>',gt); + removeChar(id,'['); + removeChar(id,']'); + + std::string choice = "opt"; + if ( a->isRequired() ) + choice = "plain"; + + std::cout << "<arg choice='" << choice << '\''; + if ( a->acceptsMultipleValues() ) + std::cout << " rep='repeat'"; + + + std::cout << '>'; + if ( !a->getFlag().empty() ) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</arg>" << std::endl; + +} + +inline void DocBookOutput::printLongArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc,'<',lt); + substituteSpecialChars(desc,'>',gt); + + std::cout << "<varlistentry>" << std::endl; + + if ( !a->getFlag().empty() ) + { + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->flagStartChar() << a->getFlag(); + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + } + + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + + std::cout << "<listitem>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << desc << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</listitem>" << std::endl; + + std::cout << "</varlistentry>" << std::endl; +} + +} //namespace TCLAP +#endif diff --git a/pub/ThirdParty/tclap/HelpVisitor.h b/pub/ThirdParty/tclap/HelpVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..cc3bd070cad5903ea67b15ae38ed5d605c5ac694 --- /dev/null +++ b/pub/ThirdParty/tclap/HelpVisitor.h @@ -0,0 +1,76 @@ + +/****************************************************************************** + * + * file: HelpVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_HELP_VISITOR_H +#define TCLAP_HELP_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Visitor object that calls the usage method of the given CmdLineOutput + * object for the specified CmdLine object. + */ +class HelpVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying. + */ + HelpVisitor(const HelpVisitor& rhs); + HelpVisitor& operator=(const HelpVisitor& rhs); + + protected: + + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } + +}; + +} + +#endif diff --git a/pub/ThirdParty/tclap/IgnoreRestVisitor.h b/pub/ThirdParty/tclap/IgnoreRestVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..e328649e511eb737e098e411e17552dbc3da1b73 --- /dev/null +++ b/pub/ThirdParty/tclap/IgnoreRestVisitor.h @@ -0,0 +1,52 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_IGNORE_REST_VISITOR_H +#define TCLAP_IGNORE_REST_VISITOR_H + +#include <tclap/Visitor.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A Vistor that tells the CmdLine to begin ignoring arguments after + * this one is parsed. + */ +class IgnoreRestVisitor: public Visitor +{ + public: + + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/pub/ThirdParty/tclap/MultiArg.h b/pub/ThirdParty/tclap/MultiArg.h new file mode 100644 index 0000000000000000000000000000000000000000..34bb2d7895269cb676ff06b792bb914c79b5cc91 --- /dev/null +++ b/pub/ThirdParty/tclap/MultiArg.h @@ -0,0 +1,433 @@ +/****************************************************************************** + * + * file: MultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_ARGUMENT_H +#define TCLAP_MULTIPLE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { +/** + * An argument that allows multiple values of type T to be specified. Very + * similar to a ValueArg, except a vector of values will be returned + * instead of just one. + */ +template<class T> +class MultiArg : public Arg +{ +public: + typedef std::vector<T> container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + +protected: + + /** + * The list of values parsed from the CmdLine. + */ + std::vector<T> _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue( const std::string& val ); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; + +public: + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector<T>& getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); + +private: + /** + * Prevent accidental copying + */ + MultiArg<T>(const MultiArg<T>& rhs); + MultiArg<T>& operator=(const MultiArg<T>& rhs); + +}; + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v) : + Arg( flag, name, desc, req, true, v ), + _values(std::vector<T>()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector<T>()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +/** + * + */ +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector<T>()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector<T>()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +template<class T> +const std::vector<T>& MultiArg<T>::getValue() { return _values; } + +template<class T> +bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + // always take the first one, regardless of start string + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } + else + return false; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; +} + +/** + * Once we've matched the first value, then the arg is no longer + * required. + */ +template<class T> +bool MultiArg<T>::isRequired() const +{ + if ( _required ) + { + if ( _values.size() > 1 ) + return false; + else + return true; + } + else + return false; + +} + +template<class T> +void MultiArg<T>::_extractValue( const std::string& val ) +{ + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory()); + _values.push_back(tmp); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _values.back() ) ) + throw( CmdLineParseException( "Value '" + val + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +bool MultiArg<T>::allowMore() +{ + bool am = _allowMore; + _allowMore = true; + return am; +} + +template<class T> +void MultiArg<T>::reset() +{ + Arg::reset(); + _values.clear(); +} + +} // namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/MultiSwitchArg.h b/pub/ThirdParty/tclap/MultiSwitchArg.h new file mode 100644 index 0000000000000000000000000000000000000000..8820b641626ed8dd28fb000211076e37d14f6c33 --- /dev/null +++ b/pub/ThirdParty/tclap/MultiSwitchArg.h @@ -0,0 +1,216 @@ + +/****************************************************************************** +* +* file: MultiSwitchArg.h +* +* Copyright (c) 2003, Michael E. Smoot . +* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. +* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. +* All rights reverved. +* +* See the file COPYING in the top directory of this distribution for +* more information. +* +* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + + +#ifndef TCLAP_MULTI_SWITCH_ARG_H +#define TCLAP_MULTI_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/SwitchArg.h> + +namespace TCLAP { + +/** +* A multiple switch argument. If the switch is set on the command line, then +* the getValue method will return the number of times the switch appears. +*/ +class MultiSwitchArg : public SwitchArg +{ + protected: + + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + + public: + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init = 0, + Visitor* v = NULL); + + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init = 0, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string& val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string& val) const; + + void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ } + +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ + parser.add( this ); +} + +inline int MultiSwitchArg::getValue() { return _value; } + +inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] )) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + _checkWithVisitor(); + + return true; + } + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + // Check for more in argument and increment value. + while ( combinedSwitchesMatch( args[*i] ) ) + ++_value; + + _checkWithVisitor(); + + return false; + } + else + return false; +} + +inline std::string +MultiSwitchArg::shortID(const std::string& val) const +{ + return Arg::shortID(val) + " ... "; +} + +inline std::string +MultiSwitchArg::longID(const std::string& val) const +{ + return Arg::longID(val) + " (accepted multiple times)"; +} + +inline void +MultiSwitchArg::reset() +{ + MultiSwitchArg::_value = MultiSwitchArg::_default; +} + +////////////////////////////////////////////////////////////////////// +//END MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/OptionalUnlabeledTracker.h b/pub/ThirdParty/tclap/OptionalUnlabeledTracker.h new file mode 100644 index 0000000000000000000000000000000000000000..8174c5f624b8e208abda65a84aadfbb2da83b10e --- /dev/null +++ b/pub/ThirdParty/tclap/OptionalUnlabeledTracker.h @@ -0,0 +1,62 @@ + + +/****************************************************************************** + * + * file: OptionalUnlabeledTracker.h + * + * Copyright (c) 2005, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H +#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H + +#include <string> + +namespace TCLAP { + +class OptionalUnlabeledTracker +{ + + public: + + static void check( bool req, const std::string& argName ); + + static void gotOptional() { alreadyOptionalRef() = true; } + + static bool& alreadyOptional() { return alreadyOptionalRef(); } + + private: + + static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +}; + + +inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) +{ + if ( OptionalUnlabeledTracker::alreadyOptional() ) + throw( SpecificationException( + "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", + argName ) ); + + if ( !req ) + OptionalUnlabeledTracker::gotOptional(); +} + + +} // namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/StandardTraits.h b/pub/ThirdParty/tclap/StandardTraits.h new file mode 100644 index 0000000000000000000000000000000000000000..46d7f6fafdeda744890e223c13ef3630c9784e72 --- /dev/null +++ b/pub/ThirdParty/tclap/StandardTraits.h @@ -0,0 +1,208 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StandardTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_STANDARD_TRAITS_H +#define TCLAP_STANDARD_TRAITS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> // To check for long long +#endif + +// If Microsoft has already typedef'd wchar_t as an unsigned +// short, then compiles will break because it's as if we're +// creating ArgTraits twice for unsigned short. Thus... +#ifdef _MSC_VER +#ifndef _NATIVE_WCHAR_T_DEFINED +#define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +#endif +#endif + +namespace TCLAP { + +// ====================================================================== +// Integer types +// ====================================================================== + +/** + * longs have value-like semantics. + */ +template<> +struct ArgTraits<long> { + typedef ValueLike ValueCategory; +}; + +/** + * ints have value-like semantics. + */ +template<> +struct ArgTraits<int> { + typedef ValueLike ValueCategory; +}; + +/** + * shorts have value-like semantics. + */ +template<> +struct ArgTraits<short> { + typedef ValueLike ValueCategory; +}; + +/** + * chars have value-like semantics. + */ +template<> +struct ArgTraits<char> { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * long longs have value-like semantics. + */ +template<> +struct ArgTraits<long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Unsigned integer types +// ====================================================================== + +/** + * unsigned longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned ints have value-like semantics. + */ +template<> +struct ArgTraits<unsigned int> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned shorts have value-like semantics. + */ +template<> +struct ArgTraits<unsigned short> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned chars have value-like semantics. + */ +template<> +struct ArgTraits<unsigned char> { + typedef ValueLike ValueCategory; +}; + +// Microsoft implements size_t awkwardly. +#if defined(_MSC_VER) && defined(_M_X64) +/** + * size_ts have value-like semantics. + */ +template<> +struct ArgTraits<size_t> { + typedef ValueLike ValueCategory; +}; +#endif + + +#ifdef HAVE_LONG_LONG +/** + * unsigned long longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Float types +// ====================================================================== + +/** + * floats have value-like semantics. + */ +template<> +struct ArgTraits<float> { + typedef ValueLike ValueCategory; +}; + +/** + * doubles have value-like semantics. + */ +template<> +struct ArgTraits<double> { + typedef ValueLike ValueCategory; +}; + +// ====================================================================== +// Other types +// ====================================================================== + +/** + * bools have value-like semantics. + */ +template<> +struct ArgTraits<bool> { + typedef ValueLike ValueCategory; +}; + + +/** + * wchar_ts have value-like semantics. + */ +#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +template<> +struct ArgTraits<wchar_t> { + typedef ValueLike ValueCategory; +}; +#endif + +/** + * Strings have string like argument traits. + */ +template<> +struct ArgTraits<std::string> { + typedef StringLike ValueCategory; +}; + +template<typename T> +void SetString(T &dst, const std::string &src) +{ + dst = src; +} + +} // namespace + +#endif + diff --git a/pub/ThirdParty/tclap/StdOutput.h b/pub/ThirdParty/tclap/StdOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..35f7b99b2ccf4b626fb9926f167a34ce5a371e0a --- /dev/null +++ b/pub/ThirdParty/tclap/StdOutput.h @@ -0,0 +1,298 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StdOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_STDCMDLINEOUTPUT_H +#define TCLAP_STDCMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that isolates any output from the CmdLine object so that it + * may be easily modified. + */ +class StdOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const; + +}; + + +inline void StdOutput::version(CmdLineInterface& _cmd) +{ + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + + std::cout << std::endl << progName << " version: " + << xversion << std::endl << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface& _cmd ) +{ + std::cout << std::endl << "USAGE: " << std::endl << std::endl; + + _shortUsage( _cmd, std::cout ); + + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage( _cmd, std::cout ); + + std::cout << std::endl; + +} + +inline void StdOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + std::string progName = _cmd.getProgramName(); + + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl << std::endl; + + if ( _cmd.hasHelpAndVersion() ) + { + std::cerr << "Brief USAGE: " << std::endl; + + _shortUsage( _cmd, std::cerr ); + + std::cerr << std::endl << "For complete USAGE and HELP type: " + << std::endl << " " << progName << " --help" + << std::endl << std::endl; + } + else + usage(_cmd); + + throw ExitException(1); +} + +inline void +StdOutput::_shortUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + std::string s = progName + " "; + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + s += " {"; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + s += (*it)->shortID() + "|"; + + s[s.length()-1] = '}'; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + s += " " + (*it)->shortID(); + + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast<int>(progName.length()) + 2; + if ( secondLineOffset > 75/2 ) + secondLineOffset = static_cast<int>(75/2); + + spacePrint( os, s, 75, 3, secondLineOffset ); +} + +inline void +StdOutput::_longUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++ ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + + if ( it+1 != xorList[i].end() ) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + os << std::endl; + } + + os << std::endl; + + spacePrint( os, message, 75, 3, 0 ); +} + +inline void StdOutput::spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const +{ + int len = static_cast<int>(s.length()); + + if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) + { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while ( start < len ) + { + // find the substring length + // int stringLen = std::min<int>( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min<int>( len - start, allowedLen ); + + // trim the length so it doesn't end in middle of a word + if ( stringLen == allowedLen ) + while ( stringLen >= 0 && + s[stringLen+start] != ' ' && + s[stringLen+start] != ',' && + s[stringLen+start] != '|' ) + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if ( stringLen <= 0 ) + stringLen = allowedLen; + + // check for newlines + for ( int i = 0; i < stringLen; i++ ) + if ( s[start+i] == '\n' ) + stringLen = i+1; + + // print the indent + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + + if ( start == 0 ) + { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start,stringLen) << std::endl; + + // so we don't start a line with a space + while ( s[stringLen+start] == ' ' && start < len ) + start++; + + start += stringLen; + } + } + else + { + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + os << s << std::endl; + } +} + +} //namespace TCLAP +#endif diff --git a/pub/ThirdParty/tclap/SwitchArg.h b/pub/ThirdParty/tclap/SwitchArg.h new file mode 100644 index 0000000000000000000000000000000000000000..39161090692aebc454b10a330191cce6250a67e2 --- /dev/null +++ b/pub/ThirdParty/tclap/SwitchArg.h @@ -0,0 +1,266 @@ + +/****************************************************************************** + * + * file: SwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_SWITCH_ARG_H +#define TCLAP_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A simple switch argument. If the switch is set on the command line, then + * the getValue method will return the opposite of the default value for the + * switch. + */ +class SwitchArg : public Arg +{ + protected: + + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + + public: + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool def = false, + Visitor* v = NULL); + + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool def = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string& combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + + private: + /** + * Checks to see if we've found the last match in + * a combined string. + */ + bool lastCombined(std::string& combined); + + /** + * Does the common processing of processArg. + */ + void commonProcessing(); +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN SwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default( default_val ) +{ } + +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default(default_val) +{ + parser.add( this ); +} + +inline bool SwitchArg::getValue() { return _value; } + +inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) +{ + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( combinedSwitches[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) +{ + // make sure this is actually a combined switch + if ( combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0] ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == + Arg::nameStartString() ) + return false; + + // make sure the delimiter isn't in the string + if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( _flag.length() > 0 && + combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + //combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; +} + +inline void SwitchArg::commonProcessing() +{ + if ( _xorSet ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", toString())); + + if ( _alreadySet ) + throw(CmdLineParseException("Argument already set!", toString())); + + _alreadySet = true; + + if ( _value == true ) + _value = false; + else + _value = true; + + _checkWithVisitor(); +} + +inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + // if the whole string matches the flag or name string + if ( argMatches( args[*i] ) ) + { + commonProcessing(); + + return true; + } + // if a substring matches the flag as part of a combination + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // check again to ensure we don't misinterpret + // this as a MultiSwitchArg + if ( combinedSwitchesMatch( args[*i] ) ) + throw(CmdLineParseException("Argument already set!", + toString())); + + commonProcessing(); + + // We only want to return true if we've found the last combined + // match in the string, otherwise we return true so that other + // switches in the combination will have a chance to match. + return lastCombined( args[*i] ); + } + else + return false; +} + +inline void SwitchArg::reset() +{ + Arg::reset(); + _value = _default; +} +////////////////////////////////////////////////////////////////////// +//End SwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/UnlabeledMultiArg.h b/pub/ThirdParty/tclap/UnlabeledMultiArg.h new file mode 100644 index 0000000000000000000000000000000000000000..d5e1781060dceb3fe59c504825fcf888c930f7e8 --- /dev/null +++ b/pub/ThirdParty/tclap/UnlabeledMultiArg.h @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H +#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/MultiArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + +namespace TCLAP { + +/** + * Just like a MultiArg, except that the arguments are unlabeled. Basically, + * this Arg will slurp up everything that hasn't been matched to another + * Arg. + */ +template<class T> +class UnlabeledMultiArg : public MultiArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg<T>::_ignoreable; + using MultiArg<T>::_hasBlanks; + using MultiArg<T>::_extractValue; + using MultiArg<T>::_typeDesc; + using MultiArg<T>::_name; + using MultiArg<T>::_description; + using MultiArg<T>::_alreadySet; + using MultiArg<T>::toString; + + public: + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; +}; + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled multi arg + + + // always take the first value, regardless of the start string + _extractValue( args[(*i)] ); + + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + + return true; +} + +template<class T> +std::string UnlabeledMultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; +} + +template<class T> +std::string UnlabeledMultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; +} + +template<class T> +bool UnlabeledMultiArg<T>::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledMultiArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} + +#endif diff --git a/pub/ThirdParty/tclap/UnlabeledValueArg.h b/pub/ThirdParty/tclap/UnlabeledValueArg.h new file mode 100644 index 0000000000000000000000000000000000000000..5721d61252f20180c349bb126e582a79f939367b --- /dev/null +++ b/pub/ThirdParty/tclap/UnlabeledValueArg.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H +#define TCLAP_UNLABELED_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/ValueArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template<class T> +class UnlabeledValueArg : public ValueArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg<T>::_ignoreable; + using ValueArg<T>::_hasBlanks; + using ValueArg<T>::_extractValue; + using ValueArg<T>::_typeDesc; + using ValueArg<T>::_name; + using ValueArg<T>::_description; + using ValueArg<T>::_alreadySet; + using ValueArg<T>::toString; + + public: + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + +}; + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); + +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Implementation of processArg(). + */ +template<class T> +bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _alreadySet ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled arg + + _extractValue( args[*i] ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding longID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding operator== for specific behavior. + */ +template<class T> +bool UnlabeledValueArg<T>::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledValueArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} +#endif diff --git a/pub/ThirdParty/tclap/ValueArg.h b/pub/ThirdParty/tclap/ValueArg.h new file mode 100644 index 0000000000000000000000000000000000000000..7ac29526b94393a4b5441921307fbf5b419805fb --- /dev/null +++ b/pub/ThirdParty/tclap/ValueArg.h @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * file: ValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VALUE_ARGUMENT_H +#define TCLAP_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { + +/** + * The basic labeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when the flag/name is matched + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. + */ +template<class T> +class ValueArg : public Arg +{ + protected: + + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue( const std::string& val ); + + public: + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + Visitor* v = NULL); + + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the value of the argument. + */ + T& getValue() ; + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val = "val") const; + + virtual void reset() ; + +private: + /** + * Prevent accidental copying + */ + ValueArg<T>(const ValueArg<T>& rhs); + ValueArg<T>& operator=(const ValueArg<T>& rhs); +}; + + +/** + * Constructor implementation. + */ +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ + parser.add( this ); +} + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ + parser.add( this ); +} + + +/** + * Implementation of getValue(). + */ +template<class T> +T& ValueArg<T>::getValue() { return _value; } + +/** + * Implementation of processArg(). + */ +template<class T> +bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( _alreadySet ) + { + if ( _xorSet ) + throw( CmdLineParseException( + "Mutually exclusive argument already set!", + toString()) ); + else + throw( CmdLineParseException("Argument already set!", + toString()) ); + } + + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } + else + return false; +} + +/** + * Implementation of shortID. + */ +template<class T> +std::string ValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template<class T> +std::string ValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID( _typeDesc ); +} + +template<class T> +void ValueArg<T>::_extractValue( const std::string& val ) +{ + try { + ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory()); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _value ) ) + throw( CmdLineParseException( "Value '" + val + + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +void ValueArg<T>::reset() +{ + Arg::reset(); + _value = _default; +} + +} // namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/ValuesConstraint.h b/pub/ThirdParty/tclap/ValuesConstraint.h new file mode 100644 index 0000000000000000000000000000000000000000..cb41f645e55b7352dd85d0bb0657ad8e2c0324bf --- /dev/null +++ b/pub/ThirdParty/tclap/ValuesConstraint.h @@ -0,0 +1,148 @@ + + +/****************************************************************************** + * + * file: ValuesConstraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_VALUESCONSTRAINT_H +#define TCLAP_VALUESCONSTRAINT_H + +#include <string> +#include <vector> +#include <tclap/Constraint.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#if defined(HAVE_SSTREAM) +#include <sstream> +#elif defined(HAVE_STRSTREAM) +#include <strstream> +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +namespace TCLAP { + +/** + * A Constraint that constrains the Arg to only those values specified + * in the constraint. + */ +template<class T> +class ValuesConstraint : public Constraint<T> +{ + + public: + + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector<T>& allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const; + + protected: + + /** + * The list of valid values. + */ + std::vector<T> _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; + +}; + +template<class T> +ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed) +: _allowed(allowed), + _typeDesc("") +{ + for ( unsigned int i = 0; i < _allowed.size(); i++ ) + { + +#if defined(HAVE_SSTREAM) + std::ostringstream os; +#elif defined(HAVE_STRSTREAM) + std::ostrstream os; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + + os << _allowed[i]; + + std::string temp( os.str() ); + + if ( i > 0 ) + _typeDesc += "|"; + _typeDesc += temp; + } +} + +template<class T> +bool ValuesConstraint<T>::check( const T& val ) const +{ + if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) + return false; + else + return true; +} + +template<class T> +std::string ValuesConstraint<T>::shortID() const +{ + return _typeDesc; +} + +template<class T> +std::string ValuesConstraint<T>::description() const +{ + return _typeDesc; +} + + +} //namespace TCLAP +#endif + diff --git a/pub/ThirdParty/tclap/VersionVisitor.h b/pub/ThirdParty/tclap/VersionVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..c110d4fa009401bcf88533b9f7d7101e9735bb1d --- /dev/null +++ b/pub/ThirdParty/tclap/VersionVisitor.h @@ -0,0 +1,81 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: VersionVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VERSION_VISITOR_H +#define TCLAP_VERSION_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Vistor that will call the version method of the given CmdLineOutput + * for the specified CmdLine object and then exit. + */ +class VersionVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying + */ + VersionVisitor(const VersionVisitor& rhs); + VersionVisitor& operator=(const VersionVisitor& rhs); + + protected: + + /** + * The CmdLine of interest. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } + +}; + +} + +#endif diff --git a/pub/ThirdParty/tclap/Visitor.h b/pub/ThirdParty/tclap/Visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..38ddcbdb86107a52300b99ca1369f65b0efa1354 --- /dev/null +++ b/pub/ThirdParty/tclap/Visitor.h @@ -0,0 +1,53 @@ + +/****************************************************************************** + * + * file: Visitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VISITOR_H +#define TCLAP_VISITOR_H + +namespace TCLAP { + +/** + * A base class that defines the interface for visitors. + */ +class Visitor +{ + public: + + /** + * Constructor. Does nothing. + */ + Visitor() { } + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() { } + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() { } +}; + +} + +#endif diff --git a/pub/ThirdParty/tclap/XorHandler.h b/pub/ThirdParty/tclap/XorHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..d9dfad31f6ff6b7d18a7b045d8f8347f1118c172 --- /dev/null +++ b/pub/ThirdParty/tclap/XorHandler.h @@ -0,0 +1,166 @@ + +/****************************************************************************** + * + * file: XorHandler.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_XORHANDLER_H +#define TCLAP_XORHANDLER_H + +#include <tclap/Arg.h> +#include <string> +#include <vector> +#include <algorithm> +#include <iostream> + +namespace TCLAP { + +/** + * This class handles lists of Arg's that are to be XOR'd on the command + * line. This is used by CmdLine and you shouldn't ever use it. + */ +class XorHandler +{ + protected: + + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector< std::vector<Arg*> > _orList; + + public: + + /** + * Constructor. Does nothing. + */ + XorHandler( ) : _orList(std::vector< std::vector<Arg*> >()) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add( std::vector<Arg*>& ors ); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check( const Arg* a ); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream& os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains( const Arg* a ); + + std::vector< std::vector<Arg*> >& getXorList(); + +}; + + +////////////////////////////////////////////////////////////////////// +//BEGIN XOR.cpp +////////////////////////////////////////////////////////////////////// +inline void XorHandler::add( std::vector<Arg*>& ors ) +{ + _orList.push_back( ors ); +} + +inline int XorHandler::check( const Arg* a ) +{ + // iterate over each XOR list + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find( _orList[i].begin(), + _orList[i].end(), a ); + if ( ait != _orList[i].end() ) + { + // first check to see if a mutually exclusive switch + // has not already been set + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) && (*it)->isSet() ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", + (*it)->toString())); + + // go through and set each arg that is not a + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) ) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ( (*ait)->allowMore() ) + return 0; + else + return static_cast<int>(_orList[i].size()); + } + } + + if ( a->isRequired() ) + return 1; + else + return 0; +} + +inline bool XorHandler::contains( const Arg* a ) +{ + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a == (*it) ) + return true; + + return false; +} + +inline std::vector< std::vector<Arg*> >& XorHandler::getXorList() +{ + return _orList; +} + + + +////////////////////////////////////////////////////////////////////// +//END XOR.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/pub/ThirdParty/tclap/ZshCompletionOutput.h b/pub/ThirdParty/tclap/ZshCompletionOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..0b37fc7296c6b5f4179467318d590c350fb84832 --- /dev/null +++ b/pub/ThirdParty/tclap/ZshCompletionOutput.h @@ -0,0 +1,323 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ZshCompletionOutput.h + * + * Copyright (c) 2006, Oliver Kiddle + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H +#define TCLAP_ZSHCOMPLETIONOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <map> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates a Zsh completion function as output from the usage() + * method for the given CmdLine and its Args. + */ +class ZshCompletionOutput : public CmdLineOutput +{ + + public: + + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + void basename( std::string& s ); + void quoteSpecialChars( std::string& s ); + + std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); + void printOption( Arg* it, std::string mutex ); + void printArg( Arg* it ); + + std::map<std::string, std::string> common; + char theDelimiter; +}; + +ZshCompletionOutput::ZshCompletionOutput() +: common(std::map<std::string, std::string>()), + theDelimiter('=') +{ + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; +} + +inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl << std::endl << + "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << + "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + { + if ( (*it)->shortID().at(0) == '<' ) + printArg((*it)); + else if ( (*it)->getFlag() != "-" ) + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; +} + +inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; +} + +inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) +{ + size_t idx = s.find_last_of(':'); + while ( idx != std::string::npos ) + { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while ( idx != std::string::npos ) + { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } +} + +inline void ZshCompletionOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void ZshCompletionOutput::printArg(Arg* a) +{ + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if ( a->acceptsMultipleValues() ) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if ( !a->isRequired() ) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map<std::string, std::string>::iterator compArg = common.find(a->getName()); + if ( compArg != common.end() ) + { + std::cout << compArg->second; + } + else + { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; +} + +inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) +{ + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) + { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) + { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') + { + desc.erase(len); + } + if (len) + { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if ( a->getFlag().empty() ) + { + std::cout << name; + } + else + { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if ( theDelimiter == '=' && a->isValueRequired() ) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if ( arg.at(arg.length()-1) == ']' ) + arg.erase(arg.length()-1); + if ( arg.at(arg.length()-1) == ']' ) + { + arg.erase(arg.length()-1); + } + if ( arg.at(0) == '<' ) + { + arg.erase(arg.length()-1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if ( p != std::string::npos ) + { + do + { + arg.replace(p, 1, 1, ' '); + } + while ( (p = arg.find_first_of('|', p)) != std::string::npos ); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } + else + { + std::cout << ':' << arg; + std::map<std::string, std::string>::iterator compArg = common.find(arg); + if ( compArg != common.end() ) + { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; +} + +inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) +{ + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") + { + return "(-)"; + } + + std::ostringstream list; + if ( a->acceptsMultipleValues() ) + { + list << '*'; + } + + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++) + if ( a == (*it) ) + { + list << '('; + for ( ArgVectorIterator iu = xorList[i].begin(); + iu != xorList[i].end(); + iu++ ) + { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if ( iu != xorList[i].begin() && (notCur || hasFlag) ) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if ( notCur || hasFlag ) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' << + a->nameStartString() << a->getName() << ')'; + } + + return list.str(); +} + +} //namespace TCLAP +#endif diff --git a/pub/cmake/scripts/CTestCustom.cmake.in b/pub/cmake/scripts/CTestCustom.cmake.in index 85ee881065af6d348b71d02d7525c35000e80d58..a6cae54447a736bae3c88129627a507015391f75 100644 --- a/pub/cmake/scripts/CTestCustom.cmake.in +++ b/pub/cmake/scripts/CTestCustom.cmake.in @@ -1 +1,2 @@ +set(CTEST_CUSTOM_PRE_TEST "echo To run ctest before make install, unset LD_LIBRARY_PATH") set(CTEST_CUSTOM_POST_TEST "echo For details, see the log files in Testing/Temporary/") diff --git a/pub/ftest/CMakeLists.txt b/pub/ftest/CMakeLists.txt index 742c691c1bc256100b12d240e85d1594ca23031d..40112f1eeef198c72b656518f929ceaa678d6c20 100644 --- a/pub/ftest/CMakeLists.txt +++ b/pub/ftest/CMakeLists.txt @@ -11,13 +11,17 @@ enable_testing() file(GLOB test_sources "*.f2t") list(SORT test_sources) +# This one-line script ensures termination of the functional test. +# It is only executed if the test script terminates without reaching an 'exit' command. +set(exit1file "${CMAKE_BINARY_DIR}/exit1file.f2s") +file(WRITE ${exit1file} "exit(1)") + foreach(test_src ${test_sources}) # remove directory path and suffix, to retain just the name of the test string(REGEX REPLACE ".*/" "" test_name "${test_src}") - string(REGEX REPLACE ".f2t$" "" test_name "${test_name}") + string(REGEX REPLACE "\\.f2t$" "" test_name "${test_name}") add_test( NAME ${test_name} - COMMAND ${CMAKE_BINARY_DIR}/src/frida - ARGUMENTS ${test_src} + COMMAND ${CMAKE_BINARY_DIR}/src/frida ${test_src} ${exit1file} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach(test_src) diff --git a/pub/ftest/mpa.f2t b/pub/ftest/mpa.f2t index f88813c16b3947cd2a82684e197e24782fa56fe8..a6ad824249faf8e48ead71983ab1be38c43fbeb2 100755 --- a/pub/ftest/mpa.f2t +++ b/pub/ftest/mpa.f2t @@ -1,9 +1,12 @@ #!/usr/bin/env frida fm 9 1 h 0 oy 3+i +1 oy! y+-sqrt(y) 1 mpa 0,3 exit_unless(abs(y[2,0,0]-(3+1))<1e-15,"mpa_test11") exit_unless(abs(y[2,0,1]-(3+5.5))<1e-15,"mpa_test12") +exit_unless(dy[2,0,1]>sqrt(6)/sqrt(6),"mpa_test13") +exit_unless(dy[2,0,1]<sqrt(12)/sqrt(6),"mpa_test13") 1 mpaf 3 exit_unless(ni[3,0]==3,"mpa_test20") exit_unless(abs(y[3,0,0]-(3+1))<1e-15,"mpa_test21") @@ -12,4 +15,8 @@ exit_unless(abs(y[3,0,2]-(3+7))<1e-15,"mpa_test22") exit_unless(ni[4,0]==2,"mpa_test30") exit_unless(abs(y[4,0,0]-(3+1.5))<1e-15,"mpa_test31") exit_unless(abs(y[4,0,1]-(3+5.5))<1e-15,"mpa_test32") +1 mpas 0,3 +exit_unless(abs(y[5,0,0]-(3+1))<1e-15,"mpa_test51") +exit_unless(abs(y[5,0,1]-(3+5.5))<1e-15,"mpa_test52") +exit_unless(dy[5,0,0]>dy[2,0,0],"mpa_test53") exit(0) diff --git a/pub/ftest/oi_idxwith.f2t b/pub/ftest/oi_idxwith.f2t new file mode 100755 index 0000000000000000000000000000000000000000..99a3be4ad5028e6fd305707c6abc50c7d1077a10 --- /dev/null +++ b/pub/ftest/oi_idxwith.f2t @@ -0,0 +1,6 @@ +#!/usr/bin/env frida +fm 11 1 h +oy i^2 +exit_unless(firstwith(y>10)==4,"firstwith_wrong") +exit_unless(lastwith(y>7*sqrt(y))==8,"lastwith_wrong") +exit(0) \ No newline at end of file diff --git a/pub/ftest/oxy_idep.f2t b/pub/ftest/oxy_idep.f2t new file mode 100755 index 0000000000000000000000000000000000000000..286198e3731a057a841fc1bf214dc379291a2517 --- /dev/null +++ b/pub/ftest/oxy_idep.f2t @@ -0,0 +1,19 @@ +#!/usr/bin/env frida +# pointwise operations with i dependent indices +fm 3 3 h1 +ox! 100+j*10+i +exit_unless(x[,1,1]==111,"test1") +oy! x[,,i] +exit_unless(y[,1,1]==111,"test2") +oy! x[,,ni-1-i] +exit_unless(y[,1,0]==112,"test3") +oy! x[,,i-i] +exit_unless(y[,1,2]==110,"test4") +oy! x[,i-i,1] +exit_unless(y[,1,2]==101,"test5") +oy! x[i-i,2,0] +exit_unless(y[,1,2]==120,"test6") +oy! x[,i,j] +exit_unless(y[,1,2]==121,"test7") +exit_unless(y[,2,1]==112,"test8") +exit(0) \ No newline at end of file diff --git a/pub/itest/checkIntegrity.ps b/pub/itest/checkIntegrity.ps new file mode 100644 index 0000000000000000000000000000000000000000..d31a46fd4bb09d2a8803ab072e57b626a7b2912c --- /dev/null +++ b/pub/itest/checkIntegrity.ps @@ -0,0 +1,16 @@ + {Script run} stopped + { + (\n===> Integrity test failed: ) print Script print ( has error\n\n) print + handleerror + (ignore this error which only serves to force a return value of 1) /syntaxerror signalerror + }{ + % script passed, now check the stack + count dup 0 eq { + pop (\n===> Integrity test passed: ) print Script print ( terminated normally\n\n) print + } { + (\n===> Integrity test failed: ) print Script print ( left ) print + 3 string cvs print ( item(s) on stack\n\n) print + Script /syntaxerror signalerror + } ifelse + } ifelse + quit diff --git a/pub/itest/curveplot.f2t b/pub/itest/curveplot.f2t new file mode 100755 index 0000000000000000000000000000000000000000..b2a4287d9759d1dbde176c192f42c1a85a277772 --- /dev/null +++ b/pub/itest/curveplot.f2t @@ -0,0 +1,89 @@ +#!/usr/bin/env frida +! rm -f /tmp/P.ps +ps_setup1D="setup_wallpaper.ps" +gnc 100 +cca p0+p1*t +op0 100000 +g0 +gx 0 1 +gya +p +gp /tmp/P +op0 -.5 +gya +p +gfa /tmp/P.ps +op1 50 +op0 -.47319*p1 +p +gfa /tmp/P.ps +op0 .4 +op1 3 +p +gfa /tmp/P.ps +op0 768.34 +op1 0 +gya +p +gfa /tmp/P.ps +cr t<.52||.53<t&&t<.61||.65<t +gya +p +gfa /tmp/P.ps +cca sin(t) +gx 0 80 +gya +p +gfa /tmp/P.ps +gy -.5 .5 +p +gfa /tmp/P.ps +cca t^p0 +op0 5 +gx -2 2 +gya +p +gfa /tmp/P.ps +op0 15 +gya +p +gfa /tmp/P.ps +op0 35 +gya +p +gfa /tmp/P.ps +cca t<-2?0:t^p0 +op0 5 +gx -3 2 +gya +p +gfa /tmp/P.ps +op0 25 +gya +p +gfa /tmp/P.ps +op0 26 +gya +p +gfa /tmp/P.ps +cca p0+p1*t +cr .2<t && t<.730812 +gx 0 1 +gya +p +gfa /tmp/P.ps +gy -3 0 +p +gfa /tmp/P.ps +cca sin(t) +cr abs(f(t))<.3 +gx 0 40 +gy -1.1 .9 +p +gfa /tmp/P.ps +cca ln(abs(sin(t))) +gx 0 20 +gy -12 1 +p +gfa /tmp/P.ps +qui diff --git a/pub/itest/grid40x20.yda b/pub/itest/grid40x20.yda new file mode 100644 index 0000000000000000000000000000000000000000..cf07673ea1768555214fe74814372abda8e89be2 --- /dev/null +++ b/pub/itest/grid40x20.yda @@ -0,0 +1,94 @@ +Meta: + format: yaml/frida 2.0 + type: generic tabular data +History: + - fm 40 20 + - oy (i+j)*sin(i-j) + - "fs grid40x20.yda # 2017-03-18 Sat 10:10:24 CET" +Coord: + x: {name: x, unit: ""} + y: {name: i+j*sin(i-j), unit: ""} + z: [{name: z, unit: ""}] +RPar: + [] +Slices: + - j: 0 + z: [{val: 0}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [0, 0.8414709848078965, 1.818594853651363, 0.4233600241796016, -3.027209981231713, -4.794621373315692, -1.676492989193555, 4.598906191031523, 7.914865972987054, 3.709066367175809, -5.440211108893697, -10.99989227205774, -6.43887501600522, 5.462171478746332, 13.86850297972818, 9.754317602356753, -4.606453066641045, -16.34375736195247, -13.51777044189017, 2.847666983596095, 18.25890501455255, 17.56976840925718, -0.1947288043888853, -19.46306929602892, -21.73388068815897, -3.308793752444326, 19.82651971246967, 25.82215006692158, 7.585362072620333, -19.24538264217606, -29.64094872278585, -12.52516700501502, 17.6456537997341, 32.99709138353982, 17.98881132808081, -14.98639343236529, -35.70403872395217, -23.81091093420898, 11.26200599095664, 37.58802006507943] + - j: 1 + z: [{val: 1}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-0.8414709848078965, 0, 2.524412954423689, 3.637189707302727, 0.7056000402993361, -4.540814971847569, -6.71246992264197, -2.235323985591407, 5.912879388469102, 9.893582466233818, 4.533303337659323, -6.528253330672437, -12.99987268515915, -7.512020852006089, 6.302505552399614, 15.84971769111793, 11.05489328267099, -5.182259699971175, -18.26655234571158, -15.01974493543352, 3.147421402921999, 20.08479551600781, 19.24307968632929, -0.212431422969693, -21.15551010437927, -23.54503741217222, -3.573497252639872, 21.35163661342888, 27.73490192373059, 8.127173649236072, -20.57265041060199, -31.61701197097158, -13.33324229566115, 18.74850716221748, 34.99691510375435, 19.04697670032086, -15.84275877135759, -37.6875964308384, -25.09798720092298, 11.85474314837541] + - j: 2 + z: [{val: 2}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-1.818594853651363, -2.524412954423689, 0, 4.207354924039483, 5.45578456095409, 0.9878400564190705, -6.054419962463426, -8.630318471968247, -2.794154981989259, 7.22685258590668, 11.87229895948058, 5.357540308142836, -7.616295552451177, -14.99985309826055, -8.585166688006959, 7.142839626052895, 17.83093240250767, 12.35546896298522, -5.758066333301306, -20.18934732947069, -16.52171942897687, 3.447175822247904, 21.91068601746306, 20.9163909634014, -0.2301340415505008, -22.84795091272961, -25.35619413618547, -3.838200752835418, 22.87675351438808, 29.64765378053959, 8.668985225851809, -21.89991817902793, -33.5930752191573, -14.14131758630728, 19.85136052470086, 36.99673882396888, 20.10514207256091, -16.69912411034989, -39.67115413772463, -26.38506346763698] + - j: 3 + z: [{val: 3}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-0.4233600241796016, -3.637189707302727, -4.207354924039483, 0, 5.890296893655275, 7.274379414605454, 1.270080072538805, -7.568024953079282, -10.54816702129452, -3.35298597838711, 8.540825783344257, 13.85101545272735, 6.181777278626349, -8.704337774229916, -16.99983351136196, -9.65831252400783, 7.983173699706177, 19.81214711389741, 13.65604464329945, -6.333872966631437, -22.11214231322981, -18.02369392252022, 3.746930241573808, 23.73657651891832, 22.58970224047351, -0.2478366601313085, -24.54039172107995, -27.16735086019872, -4.102904253030964, 24.40187041534729, 31.5604056373486, 9.210796802467547, -23.22718594745387, -35.56913846734302, -14.94939287695341, 20.95421388718424, 38.99656254418342, 21.16330744480095, -17.55548944934219, -41.65471184461087] + - j: 4 + z: [{val: 4}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [3.027209981231713, -0.7056000402993361, -5.45578456095409, -5.890296893655275, 0, 7.573238863271069, 9.092974268256818, 1.552320088658539, -9.081629943695138, -12.4660155706208, -3.911816974784962, 9.854798980781837, 15.82973194597411, 7.006014249109862, -9.792379996008655, -18.99981392446337, -10.7314583600087, 8.823507773359459, 21.79336182528715, 14.95662032361369, -6.909679599961567, -24.03493729698892, -19.52566841606358, 4.046684660899714, 25.56246702037357, 24.26301351754563, -0.2655392787121163, -26.23283252943029, -28.97850758421196, -4.36760775322651, 25.92698731630649, 33.4731574941576, 9.752608379083286, -24.5544537158798, -37.54520171552875, -15.75746816759954, 22.05706724966763, 40.99638626439796, 22.221472817041, -18.41185478833449] + - j: 5 + z: [{val: 5}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [4.794621373315692, 4.540814971847569, -0.9878400564190705, -7.274379414605454, -7.573238863271069, 0, 9.256180832886862, 10.91156912190818, 1.834560104778274, -10.59523493431099, -14.38386411994708, -4.470647971182814, 11.16877217821941, 17.80844843922087, 7.830251219593375, -10.88042221778739, -20.99979433756477, -11.80460419600957, 9.663841847012741, 23.77457653667689, 16.25719600392792, -7.485486233291698, -25.95773228074803, -21.02764290960693, 4.346439080225618, 27.38835752182883, 25.93632479461774, -0.283241897292924, -27.92527333778063, -30.78966430822521, -4.632311253422056, 27.4521042172657, 35.38590935096661, 10.29441995569902, -25.88172148430574, -39.52126496371447, -16.56554345824567, 23.15992061215101, 42.99620998461249, 23.27963818928105] + - j: 6 + z: [{val: 6}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [1.676492989193555, 6.71246992264197, 6.054419962463426, -1.270080072538805, -9.092974268256818, -9.256180832886862, 0, 10.93912280250265, 12.73016397555954, 2.116800120898008, -12.10883992492685, -16.30171266927335, -5.029478967580665, 12.48274537565699, 19.78716493246764, 8.654488190076888, -11.96846443956614, -22.99977475066618, -12.87775003201044, 10.50417592066602, 25.75579124806663, 17.55777168424216, -8.061292866621828, -27.88052726450715, -22.52961740315028, 4.646193499551523, 29.21424802328409, 27.60963607168985, -0.3009445158737318, -29.61771414613097, -32.60082103223846, -4.897014753617603, 28.9772211182249, 37.29866120777562, 10.83623153231476, -27.20898925273167, -41.4973282119002, -17.3736187488918, 24.26277397463438, 44.99603370482702] + - j: 7 + z: [{val: 7}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-4.598906191031523, 2.235323985591407, 8.630318471968247, 7.568024953079282, -1.552320088658539, -10.91156912190818, -10.93912280250265, 0, 12.62206477211845, 14.54875882921091, 2.399040137017743, -13.62244491554271, -18.21956121859963, -5.588309963978517, 13.79671857309457, 21.7658814257144, 9.478725160560401, -13.05650666134487, -24.99975516376759, -13.95089586801131, 11.3445099943193, 27.73700595945637, 18.85834736455639, -8.637099499951958, -29.80332224826626, -24.03159189669363, 4.945947918877427, 31.04013852473934, 29.28294734876196, -0.3186471344545395, -31.31015495448131, -34.41197775625171, -5.161718253813148, 30.50233801918411, 39.21141306458463, 11.3780431089305, -28.5362570211576, -43.47339146008592, -18.18169403953793, 25.36562733711777] + - j: 8 + z: [{val: 8}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-7.914865972987054, -5.912879388469102, 2.794154981989259, 10.54816702129452, 9.081629943695138, -1.834560104778274, -12.73016397555954, -12.62206477211845, 0, 14.30500674173424, 16.36735368286227, 2.681280153137477, -15.13604990615856, -20.13740976792591, -6.147140960376369, 15.11069177053215, 23.74459791896116, 10.30296213104391, -14.14454888312361, -26.99973557686899, -15.02404170401218, 12.18484406797259, 29.71822067084611, 20.15892304487062, -9.21290613328209, -31.72611723202537, -25.53356639023698, 5.245702338203332, 32.8660290261946, 30.95625862583407, -0.3363497530353473, -33.00259576283165, -36.22313448026495, -5.426421754008694, 32.02745492014331, 41.12416492139363, 11.91985468554624, -29.86352478958354, -45.44945470827165, -18.98976933018406] + - j: 9 + z: [{val: 9}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-3.709066367175809, -9.893582466233818, -7.22685258590668, 3.35298597838711, 12.4660155706208, 10.59523493431099, -2.116800120898008, -14.54875882921091, -14.30500674173424, 0, 15.98794871135003, 18.18594853651364, 2.963520169257211, -16.64965489677442, -22.05525831725219, -6.705971956774221, 16.42466496796973, 25.72331441220793, 11.12719910152743, -15.23259110490235, -28.9997159899704, -16.09718754001305, 13.02517814162587, 31.69943538223585, 21.45949872518485, -9.788712766612221, -33.64891221578449, -27.03554088378034, 5.545456757529236, 34.69191952764985, 32.62956990290618, -0.354052371616155, -34.69503657118199, -38.0342912042782, -5.69112525420424, 33.55257182110252, 43.03691677820264, 12.46166626216198, -31.19079255800947, -47.42551795645737] + - j: 10 + z: [{val: 10}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [5.440211108893697, -4.533303337659323, -11.87229895948058, -8.540825783344257, 3.911816974784962, 14.38386411994708, 12.10883992492685, -2.399040137017743, -16.36735368286227, -15.98794871135003, 0, 17.67089068096583, 20.004543390165, 3.245760185376946, -18.16325988739028, -23.97310686657846, -7.264802953172072, 17.73863816540731, 27.70203090545469, 11.95143607201094, -16.32063332668109, -30.99969640307181, -17.17033337601392, 13.86551221527915, 33.68065009362559, 22.76007440549909, -10.36451939994235, -35.5717071995436, -28.53751537732369, 5.845211176855141, 36.51781002910511, 34.3028811799783, -0.3717549901969628, -36.38747737953233, -39.84544792829145, -5.955828754399787, 35.07768872206172, 44.94966863501164, 13.00347783877771, -32.51806032643541] + - j: 11 + z: [{val: 11}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [10.99989227205774, 6.528253330672437, -5.357540308142836, -13.85101545272735, -9.854798980781837, 4.470647971182814, 16.30171266927335, 13.62244491554271, -2.681280153137477, -18.18594853651364, -17.67089068096583, 0, 19.35383265058162, 21.82313824381636, 3.52800020149668, -19.67686487800613, -25.89095541590474, -7.823633949569924, 19.05261136284488, 29.68074739870145, 12.77567304249445, -17.40867554845983, -32.99967681617321, -18.24347921201479, 14.70584628893243, 35.66186480501533, 24.06065008581332, -10.94032603327248, -37.49450218330271, -30.03948987086704, 6.144965596181046, 38.34370053056036, 35.97619245705041, -0.3894576087777706, -38.07991818788268, -41.6566046523047, -6.220532254595333, 36.60280562302093, 46.86242049182065, 13.54528941539345] + - j: 12 + z: [{val: 12}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [6.43887501600522, 12.99987268515915, 7.616295552451177, -6.181777278626349, -15.82973194597411, -11.16877217821941, 5.029478967580665, 18.21956121859963, 15.13604990615856, -2.963520169257211, -20.004543390165, -19.35383265058162, 0, 21.03677462019741, 23.64173309746772, 3.810240217616415, -21.19046986862199, -27.80880396523101, -8.382464945967776, 20.36658456028246, 31.65946389194822, 13.59991001297797, -18.49671777023857, -34.99965722927463, -19.31662504801566, 15.54618036258571, 37.64307951640507, 25.36122576612756, -11.51613266660261, -39.41729716706183, -31.54146436441039, 6.444720015506951, 40.16959103201562, 37.64950373412253, -0.4071602273585783, -39.77235899623302, -43.46776137631795, -6.485235754790878, 38.12792252398013, 48.77517234862965] + - j: 13 + z: [{val: 13}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-5.462171478746332, 7.512020852006089, 14.99985309826055, 8.704337774229916, -7.006014249109862, -17.80844843922087, -12.48274537565699, 5.588309963978517, 20.13740976792591, 16.64965489677442, -3.245760185376946, -21.82313824381636, -21.03677462019741, 0, 22.71971658981321, 25.46032795111909, 4.092480233736149, -22.70407485923785, -29.72665251455729, -8.941295942365628, 21.68055775772004, 33.63818038519498, 14.42414698346148, -19.58475999201731, -36.99963764237603, -20.38977088401653, 16.386514436239, 39.62429422779481, 26.66180144644179, -12.09193929993274, -41.34009215082094, -33.04343885795375, 6.744474434832855, 41.99548153347087, 39.32281501119463, -0.4248628459393861, -41.46479980458336, -45.2789181003312, -6.749939254986424, 39.65303942493934] + - j: 14 + z: [{val: 14}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-13.86850297972818, -6.302505552399614, 8.585166688006959, 16.99983351136196, 9.792379996008655, -7.830251219593375, -19.78716493246764, -13.79671857309457, 6.147140960376369, 22.05525831725219, 18.16325988739028, -3.52800020149668, -23.64173309746772, -22.71971658981321, 0, 24.402658559429, 27.27892280477045, 4.374720249855883, -24.2176798498537, -31.64450106388357, -9.500126938763479, 22.99453095515762, 35.61689687844174, 15.24838395394499, -20.67280221379605, -38.99961805547743, -21.4629167200174, 17.22684850989228, 41.60550893918455, 27.96237712675602, -12.66774593326287, -43.26288713458005, -34.5454133514971, 7.04422885415876, 43.82137203492613, 40.99612628826674, -0.4425654645201938, -43.15724061293371, -47.09007482434444, -7.014642755181971] + - j: 15 + z: [{val: 15}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-9.754317602356753, -15.84971769111793, -7.142839626052895, 9.65831252400783, 18.99981392446337, 10.88042221778739, -8.654488190076888, -21.7658814257144, -15.11069177053215, 6.705971956774221, 23.97310686657846, 19.67686487800613, -3.810240217616415, -25.46032795111909, -24.402658559429, 0, 26.08560052904479, 29.09751765842181, 4.656960265975618, -25.73128484046956, -33.56234961320985, -10.05895793516133, 24.30850415259519, 37.59561337168851, 16.07262092442851, -21.76084443557479, -40.99959846857885, -22.53606255601827, 18.06718258354556, 43.58672365057429, 29.26295280707026, -13.243552566593, -45.18568211833917, -36.04738784504045, 7.343983273484665, 45.64726253638138, 42.66943756533886, -0.4602680831010015, -44.84968142128405, -48.90123154835769] + - j: 16 + z: [{val: 16}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [4.606453066641045, -11.05489328267099, -17.83093240250767, -7.983173699706177, 10.7314583600087, 20.99979433756477, 11.96846443956614, -9.478725160560401, -23.74459791896116, -16.42466496796973, 7.264802953172072, 25.89095541590474, 21.19046986862199, -4.092480233736149, -27.27892280477045, -26.08560052904479, 0, 27.76854249866058, 30.91611251207318, 4.939200282095353, -27.24488983108542, -35.48019816253612, -10.61778893155918, 25.62247735003277, 39.57432986493527, 16.89685789491202, -22.84888665735353, -42.99957888168025, -23.60920839201914, 18.90751665719884, 45.56793836196404, 30.56352848738449, -13.81935919992313, -47.10847710209828, -37.5493623385838, 7.64373769281057, 47.47315303783664, 44.34274884241097, -0.4779707016818093, -46.54212222963439] + - j: 17 + z: [{val: 17}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [16.34375736195247, 5.182259699971175, -12.35546896298522, -19.81214711389741, -8.823507773359459, 11.80460419600957, 22.99977475066618, 13.05650666134487, -10.30296213104391, -25.72331441220793, -17.73863816540731, 7.823633949569924, 27.80880396523101, 22.70407485923785, -4.374720249855883, -29.09751765842181, -27.76854249866058, 0, 29.45148446827638, 32.73470736572454, 5.221440298215087, -28.75849482170127, -37.3980467118624, -11.17661992795703, 26.93645054747035, 41.55304635818204, 17.72109486539553, -23.93692887913227, -44.99955929478165, -24.68235422802001, 19.74785073085212, 47.54915307335378, 31.86410416769872, -14.39516583325327, -49.0312720858574, -39.05133683212716, 7.943492112136474, 49.29904353929189, 46.01606011948309, -0.4956733202626171] + - j: 18 + z: [{val: 18}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [13.51777044189017, 18.26655234571158, 5.758066333301306, -13.65604464329945, -21.79336182528715, -9.663841847012741, 12.87775003201044, 24.99975516376759, 14.14454888312361, -11.12719910152743, -27.70203090545469, -19.05261136284488, 8.382464945967776, 29.72665251455729, 24.2176798498537, -4.656960265975618, -30.91611251207318, -29.45148446827638, 0, 31.13442643789217, 34.55330221937591, 5.503680314334821, -30.27209981231713, -39.31589526118868, -11.73545092435489, 28.25042374490793, 43.5317628514288, 18.54533183587905, -25.02497110091101, -46.99953970788307, -25.75550006402088, 20.58818480450541, 49.53036778474352, 33.16467984801296, -14.9709724665834, -50.95406706961651, -40.55331132567051, 8.243246531462379, 51.12493404074715, 47.6893713965552] + - j: 19 + z: [{val: 19}] + x: [0, 0.02564102564102564, 0.05128205128205128, 0.07692307692307693, 0.1025641025641026, 0.1282051282051282, 0.1538461538461539, 0.1794871794871795, 0.2051282051282051, 0.2307692307692308, 0.2564102564102564, 0.282051282051282, 0.3076923076923077, 0.3333333333333333, 0.358974358974359, 0.3846153846153846, 0.4102564102564102, 0.4358974358974359, 0.4615384615384616, 0.4871794871794872, 0.5128205128205128, 0.5384615384615384, 0.5641025641025641, 0.5897435897435898, 0.6153846153846154, 0.6410256410256411, 0.6666666666666666, 0.6923076923076923, 0.717948717948718, 0.7435897435897436, 0.7692307692307693, 0.7948717948717948, 0.8205128205128205, 0.8461538461538461, 0.8717948717948718, 0.8974358974358975, 0.9230769230769231, 0.9487179487179487, 0.9743589743589743, 1] + y: [-2.847666983596095, 15.01974493543352, 20.18934732947069, 6.333872966631437, -14.95662032361369, -23.77457653667689, -10.50417592066602, 13.95089586801131, 26.99973557686899, 15.23259110490235, -11.95143607201094, -29.68074739870145, -20.36658456028246, 8.941295942365628, 31.64450106388357, 25.73128484046956, -4.939200282095353, -32.73470736572454, -31.13442643789217, 0, 32.81736840750796, 36.37189707302727, 5.785920330454556, -31.78570480293298, -41.23374381051495, -12.29428192075274, 29.56439694234551, 45.51047934467556, 19.36956880636256, -26.11301332268975, -48.99952012098447, -26.82864590002175, 21.42851887815869, 51.51158249613326, 34.46525552832719, -15.54677909991353, -52.87686205337562, -42.05528581921386, 8.543000950788283, 52.9508245422024] \ No newline at end of file diff --git a/pub/itest/p2D.f2t b/pub/itest/p2D.f2t new file mode 100755 index 0000000000000000000000000000000000000000..e86ada7923a297dc2e112bca99c027e9ca85389b --- /dev/null +++ b/pub/itest/p2D.f2t @@ -0,0 +1,5 @@ +#!/usr/bin/env frida +fl grid40x20 +gt+ +p +qui diff --git a/pub/itest/setup_wallpaper.ps b/pub/itest/setup_wallpaper.ps new file mode 100644 index 0000000000000000000000000000000000000000..f78e8cc66a8275121eee8c2c318fb9541088264e --- /dev/null +++ b/pub/itest/setup_wallpaper.ps @@ -0,0 +1,49 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Customizable plot setup, copied from g3.ps (editör: use latin-1) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict17a begin + +12 dup autolabel defsiz +.4 dup geld stdred + +2 -11 setnewpage newpage +3 8 13 -12 setpagegrid + +2 8 24 abcset % usage: {(text)} abc +/EndFrame { nextFrame end } def + +1 1 language +0 infSet % plot info block? +1 dup 2 SymGSet % srad slin serr(2=from pset) : graph symbols, global preset +% /setboxbackgroundcolor { 0.93 setgray } def % default is white +% setPalatino + +{ 8 aCol5 iColA } /ipCol x bind def % number of colours and colour style +/pStyles [ + { 11 0 0 1. 1. pset 0 ipCol } + { 12 1 0 1. 1. pset 1 ipCol } + { 13 1 0 1. 1. pset 2 ipCol } + { 1 0 0 1. 1. pset 3 ipCol } + { 1 1 0 .7 1. pset 4 ipCol } + { 3 0 0 1. 1. pset 5 ipCol } + { 3 1 0 .7 1. pset 6 ipCol } + { 4 0 0 1. 1. pset 7 ipCol } + { 4 1 0 .7 1. pset 0 ipCol } + { 5 0 0 1. 1. pset 1 ipCol } + { 5 1 0 .7 1. pset 2 ipCol } + { 2 0 0 1. 1. pset 3 ipCol } + { 2 1 0 .7 1. pset 4 ipCol } + ] def + +{ 8 aCol2 iColA } /icCol x bind def % number of colours and colour style +/cStyles [ + { 1. [] lset siemensred } + ] def + +Resets +BoxBackground + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ecu", end of the customization section +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/lib/CMakeLists.txt b/pub/lib/CMakeLists.txt index 8bb758396f4cdb21f31863be993f5ae1d092ee10..d57ae7585b41850096a756c74e717ef6953ed1f6 100644 --- a/pub/lib/CMakeLists.txt +++ b/pub/lib/CMakeLists.txt @@ -1,5 +1,9 @@ # frida: lib/CMakeLists.txt +set(library_name fridacore) +set(${library_name}_LIBRARY ${library_name} PARENT_SCOPE) +set(${library_name}_LIBRARY_TYPE SHARED) + bison_target(xaxyacc xax_yacc.ypp ${CMAKE_CURRENT_BINARY_DIR}/xax_yacc.cpp COMPILE_FLAGS "-p xax -y" ) flex_target(xaxlex @@ -81,25 +85,23 @@ set(inc_files xax_lex.hpp ) -add_library(libfrida SHARED +add_library(${library_name} SHARED ${src_files} ${BISON_xaxyacc_OUTPUTS} ${FLEX_xaxlex_OUTPUTS} ) -set_target_properties(libfrida PROPERTIES OUTPUT_NAME frida) - -target_link_libraries(libfrida - libreadplus - libtrivia - libfridaplot +target_link_libraries(${library_name} + ${readplus_LIBRARY} + ${fridatrivia_LIBRARY} + ${fridaplot_LIBRARY} pthread - ${GSL_LIBRARIES} ${FFTW_LIBRARIES} ${KWW_LIBRARIES} ${Cerf_LIBRARIES} - ${YAMLCPP_LIBRARY} ${LMFit_LIBRARIES} ) -install(TARGETS libfrida DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +set_target_properties(${library_name} PROPERTIES OUTPUT_NAME ${library_name}) + +install(TARGETS ${library_name} LIBRARY DESTINATION ${destination_lib} COMPONENT Libraries) diff --git a/pub/lib/commands.cpp b/pub/lib/commands.cpp index fb239c859c21534f2418d0dc608bd9c130479ee5..96032ff539b7931f2148b085fc31b3d17eedbe69 100644 --- a/pub/lib/commands.cpp +++ b/pub/lib/commands.cpp @@ -11,6 +11,7 @@ #include "ptr.hpp" #include <cstring> +#include <boost/filesystem.hpp> #include "../plot/dualplot.hpp" #include "../plot/plowin.hpp" @@ -38,9 +39,13 @@ #include "reduce_spec.hpp" #include "rssm.hpp" #include "special.hpp" +#include "variables.hpp" #include "commands.hpp" +namespace fs = boost::filesystem; + + //! Executes cmd if is a Frida command, and returns true when successful. bool frida_command(string cmd) @@ -84,7 +89,7 @@ bool frida_command(string cmd) " hic dimension-reducing functionals of curves\n" " ho operators by precedence\n" " hr handling resolution functions (convolution, Dirac delta function)\n" - " hv variables\n" + " hp parameters\n" " \\h meta commands and macros\n"; } else if (cmd == "hc") { @@ -117,8 +122,8 @@ bool frida_command(string cmd) " - use command 'cv' to provide resolution file reference\n" "If function f has a sharp peak (strong variation within one resolution bin):\n" " - use 'pconv(F(t,...))', where F is the primitive of f\n"; - } else if (cmd == "hv") { - cout << "Variables for use in expressions\n" + } else if (cmd == "hp") { + cout << "Parameters for use in expressions\n" " t dummy argument in curve definition\n" " k index running over files in online memory\n" " j index running over slices (spectra or curves) in a file\n" @@ -148,7 +153,6 @@ bool frida_command(string cmd) " cm modify function\n" " cd set data file to fit\n" " cv set file to convolute with (cv-: no convolution)\n" - " cr set fit range restriction\n" " cf fit\n" " cfs fit, allow slow convolution\n" " cp print parameters\n" @@ -164,6 +168,7 @@ bool frida_command(string cmd) " cwvc weighing: reciprocal variance, curve only\n" " cgd+ graphics: take x points from data reference file\n" " cgd- graphics: create x points by dividing the plot window\n" + " cr set restrictions for plot range\n" "Frida-wide settings:\n" " cs? show fit parameters, and indicate commands to modify them\n" " cn? show parameters for numeric integration, and indicate commands to modify " @@ -184,7 +189,7 @@ bool frida_command(string cmd) NCurveFile::set_file_reference(cmd.substr(1)); } else if (cmd == "cr") { - NCurveFile::change_range(); + NCurveFile::change_prange(); } else if (cmd == "cp") { NCurveFile::show_pars(); @@ -207,28 +212,31 @@ bool frida_command(string cmd) } else if (cmd == "d") { cout << "Directory commands: inspect internal files\n" - " df list of files\n" - " dz z-values and spectral ranges\n" - " dp x|y-values\n" - " dy y-values\n" - " dr real parameters\n" - " dc coordinate names and units\n" - " dd doc lines\n"; + " dc coordinate names and units\n" + " dd doc lines\n" + " df list of files\n" + " dp x|y-values\n" + " dr real parameters\n" + " dv variables\n" + " dy y-values\n" + " dz z-values and spectral ranges\n"; + } else if (cmd == "dc") { + NEdif::show_coord(); + } else if (cmd == "dd") { + NEdif::show_doc(); } else if (cmd == "df") { NEdif::show_files(); - } else if (cmd == "dz") { - NEdif::show_spectra(); } else if (cmd == "dp") { NOperate::show("xyd"); - } else if (cmd == "dy") { - NOperate::show("y"); } else if (cmd == "dr") { NEdif::show_numpars(); - } else if (cmd == "dc") { - NEdif::show_coord(); - } else if (cmd == "dd") { - NEdif::show_doc(); + } else if (cmd == "dv") { + SVariRegistry::instance()->display_all(); + } else if (cmd == "dy") { + NOperate::show("y"); + } else if (cmd == "dz") { + NEdif::show_spectra(); } else if (cmd == "e") { cout << "Edit commands:\n" @@ -247,9 +255,7 @@ bool frida_command(string cmd) } else if (cmd == "f") { cout << "File commands:\n" " fl load from disk\n" - " fs save to disk\n" - " fso save to disk, allow overwrite\n" - " fe0 export to old y08 format (obsolete!)\n" + " fs save to disk (use modifier ! to overwrite)\n" " fe1 export (only z and y, one line per spectrum)\n" " fe2 export (one block per spectrum: z header and x-y lines)\n" " fc copy\n" @@ -268,13 +274,7 @@ bool frida_command(string cmd) } else if (cmd == "fl") { NFileIn::load(); } else if (cmd == "fs") { - NFileOut::save("yda"); - } else if (cmd == "fso") { - NFileOut::save("yda", true); - } else if (cmd == "fe0") { - NFileOut::save("y08"); - } else if (cmd == "fe0o") { - NFileOut::save("y08", true); + NFileOut::save("yda", SMem::instance()->overwrite); } else if (cmd == "fe1") { NFileOut::save("csv"); } else if (cmd == "fe2") { @@ -303,18 +303,23 @@ bool frida_command(string cmd) " gd graphic dialog (feed commands to gnuplot)\n" "Save for print:\n" " gp plot to complete .ps file\n" - " gf plot to short .psX file\n" + " gf plot to short .psa file\n" + " gfa append plot to existing .ps or .psa file\n" "Change window:\n" " gw list of plot windows\n" " g<n> switch to plot window <n>\n" "Set axes:\n" + " gt 2D plot (toggle; or use gt+ gt-)\n" " gx set x range\n" - " gy set x range\n" + " gy set y range\n" + " gz set z range (for 2D plots)\n" " ga auto-ranges\n" " gxa x auto-range\n" " gya y auto-range\n" + " gza z auto-range (for 2D plots)\n" " gxl log x (toggle; or use gxl+ gxl-)\n" " gyl log y\n" + " gzl log z\n" " gxf force x into frame (toggle; or use gxf+ gxf-)\n" " gyf force y into frame (toggle; or use gyf+ gyf-)\n" "Other setup:\n" @@ -329,14 +334,20 @@ bool frida_command(string cmd) SPloWin::instance()->current()->X.ask_and_set("Plot x range"); } else if (cmd == "gy") { SPloWin::instance()->current()->Y.ask_and_set("Plot y range"); + } else if (cmd == "gz") { + SPloWin::instance()->current()->Z.ask_and_set("Plot z range"); } else if (cmd == "ga") { SPloWin::instance()->current()->X.set_auto(); SPloWin::instance()->current()->Y.set_auto(); + SPloWin::instance()->current()->Z.set_auto(); } else if (cmd == "gxa") { SPloWin::instance()->current()->X.set_auto(); } else if (cmd == "gya") { SPloWin::instance()->current()->Y.set_auto(); - } else if (cmd.substr(0, 2) == "gx" || cmd.substr(0, 2) == "gy" || cmd.substr(0, 2) == "ge") { + } else if (cmd == "gza") { + SPloWin::instance()->current()->Z.set_auto(); + } else if (cmd.substr(0, 2) == "gx" || cmd.substr(0, 2) == "gy" || cmd.substr(0, 2) == "gz" + || cmd.substr(0, 2) == "ge" || cmd.substr(0, 2) == "gt") { SPloWin::instance()->current()->set_aux(cmd); } else if (cmd == "gnd") { SPloWin::instance()->current()->maxpoints = iask( @@ -349,11 +360,29 @@ bool frida_command(string cmd) SPloWin::instance()->current()->refine = bask( "Allow iterative refinement for curve plotting", SPloWin::instance()->current()->refine); - } else if (cmd == "gp" || cmd == "gf") { - string ps_outdir = CNode::eval("psdir")->to_s(); - string ps_head = CNode::eval("pshead")->to_s(); - string ps_dict = cmd == "gp" ? CNode::eval("psdict")->to_s() : ""; - SPloWin::instance()->current()->write_postscript(ps_outdir, ps_head, ps_dict); + } else if (cmd == "gp" || cmd == "gf" || cmd == "gfa") { + bool withDefs = cmd.substr(0,2)=="gp"; + const string ext = string(".") + (withDefs ? "ps" : "psa"); + static string fname = ""; + string mode; + if (cmd != "gfa") { + fs::path defaultname = triv::next_tmp_file( + CNode::eval("ps_outdir")->to_s() + (withDefs ? "L" : "l") + "%i" + ext); + defaultname.replace_extension(""); + fname = sask("Graphic file name (without extension "+ext+")", defaultname.string()); + if (fname=="") + return false; + if (fs::path(fname).extension().string()=="") + fname += ext; + mode = SMem::instance()->overwrite ? "overwrite" : "create"; + } else { // gfa + fname = sask("Graphic file name", fname); + mode = "append"; + } + if (fname != "") + SPloWin::instance()->current()->write_postscript( + triv::wordexp_unique(fname), mode, withDefs, + SVariRegistry::instance()->to_sMap()); } else if (cmd == "gw") { SPloWin::instance()->display_list(); } else if (sscanf(cmd.c_str(), "g%i", &i) == 1) { @@ -404,23 +433,44 @@ bool frida_command(string cmd) " md generic delete\n" " mr generic retain\n" "Per point:\n" + " mp? command list\n" + "Per slice (spectrum/curve):\n" + " ms? command list\n" + "Per file:\n" + " mfj merge (\"join\")\n" + " mfj+ merge, adding z=number-of-input-file\n" + " mfjp merge pointwise\n" + " mr- remove real par\n" + "Histogram operations:\n" + " mhm bin data\n"; + + } else if (cmd == "mp?") { + cout << "Pointwise manipulations:\n" " mpd delete\n" " mpr retain\n" - " mpa average (=bin), list controlled\n" - " mpaf average, reduce number of points by fixed factor\n" - " mpaea average according to error bound (absolute)\n" - " mpaer average according to error bound (relative)\n" + " mpa? average (rebin) command list\n" " mpbf break into spectra by fixed factor\n" " mpo sort\n" - " mpq average when x equal\n" " mpsym symmetrize: map -x -> x, then average\n" " mpe- remove error bar\n" " mpgi interpolate to given x grid\n" - " mpgr redistribute histogram intensity to given x grid\n" - "Per spectrum:\n" + " mpgr redistribute histogram intensity to given x grid\n"; + + } else if (cmd == "mpa?") { + cout << "Commands to average (rebin) adjacent channels:\n" + " mpa[d|f|e|r][s]\n" + " d only bin channels with duplicate x\n" + " f bin size given by fixed factor\n" + " e bring absolute error below some bound\n" + " r bring relative error below some bound\n" + " s error estimate includes sampling error\n"; + + } else if (cmd == "ms?") { + cout << "Pointwise manipulations:\n" " msd delete\n" " msr retain\n" " msa average\n" + " msas average, error estimate includes sampling error\n" " msb break into files\n" " msj join\n" " ms* spawn spectra\n" @@ -428,14 +478,7 @@ bool frida_command(string cmd) " mso sort by expression\n" " msoz sort by z-values\n" " mzx exchange / rotate z coordinates\n" - " mz- delete z coordinate\n" - "Per file:\n" - " mfj merge (\"join\")\n" - " mfj+ merge, adding z=number-of-input-file\n" - " mfjp merge pointwise\n" - " mr- remove real par\n" - "Histogram operations:\n" - " mhm bin data\n"; + " mz- delete z coordinate\n"; } else if (cmd == "m/") { NManip::freeze_slices(); @@ -450,17 +493,23 @@ bool frida_command(string cmd) } else if (cmd == "mpr") { NManip::points_select(false); } else if (cmd == "mpa") { - NManip::points_rebin(); + NManip::points_rebin(false); + } else if (cmd == "mpas") { + NManip::points_rebin(true); + } else if (cmd == "mpad") { + NManip::points_rebin_duplicates(); } else if (cmd == "mpaf") { - NManip::points_rebin_by_factor(); - } else if (cmd.substr(0, 4) == "mpae") { - NManip::points_rebin_by_err(cmd.substr(4)); + NManip::points_rebin_by_factor(false); + } else if (cmd == "mpafs") { + NManip::points_rebin_by_factor(true); + } else if (cmd == "mpae") { + NManip::points_rebin_by_err(true); + } else if (cmd == "mpar") { + NManip::points_rebin_by_err(false); } else if (cmd == "mpbf") { NManip::points_break_by_factor(); } else if (cmd == "mpo") { NManip::points_sort(); - } else if (cmd == "mpq") { - NManip::points_rebin_duplicates(); } else if (cmd == "mpsym") { NManip::points_symmetrize(); } else if (cmd == "mpe-") { @@ -474,7 +523,9 @@ bool frida_command(string cmd) } else if (cmd == "msr") { NManip::slices_select(false); } else if (cmd == "msa") { - NManip::slices_rebin(); + NManip::slices_rebin(false); + } else if (cmd == "msas") { + NManip::slices_rebin(true); } else if (cmd == "msb") { NManip::slices_break(); } else if (cmd == "msj") { diff --git a/pub/lib/curve.cpp b/pub/lib/curve.cpp index ece8756db0c0dd31a2b48db572c8769b607f0363..7fd003f2663cbcc4a9820a5634dd479bfc8dd6ce 100644 --- a/pub/lib/curve.cpp +++ b/pub/lib/curve.cpp @@ -53,7 +53,7 @@ void NCurveFile::create_fitcurve() fout->RPar = fd->RPar; fout->log_action("cc " + fc->expr + " # z from " + fd->name); fout->weighing = COlc::_VAR; - if (fd->has_nonzero_dy()) { + if (!fd->dy_are_all_nonzero()) { fout->weighing = COlc::_LIN; cout << "Constant weight since there are data points with dy=0\n"; } @@ -203,22 +203,20 @@ void NCurveFile::set_par_attr(char attr) } -//! Queries and sets fit range restrictions. +//! Queries and sets plot range restrictions. -void NCurveFile::change_range() +void NCurveFile::change_prange() { FileIterator fiter(SFSel::instance()->selC()); - string expr = sask("Expression restricting the fit range"); + string query = "Expression in t, f(t) to restrict the plot range"; + string expr = sask(query); // TODO: default if only one file while (COlc* fc = fiter.nextC()) { - fc->range_expr = expr; + RNode T = expr!="" ? user_xaxparse(expr.c_str()) : nullptr; fc->log_action("cr " + expr); - if (expr == "") { - fc->range_T = nullptr; - continue; - } - fc->range_T = user_xaxparse(expr.c_str()); + fc->prange_expr = expr; + fc->prange_T = T; } } diff --git a/pub/lib/curve.hpp b/pub/lib/curve.hpp index 9b0c781bd45818679b24090a52b6cfefe7521603..df3fedfbbf5f082c2ecc63df724289890d5993b2 100644 --- a/pub/lib/curve.hpp +++ b/pub/lib/curve.hpp @@ -20,7 +20,7 @@ namespace NCurveFile void create_fitcurve(); void create_freecurve(); void change_expr(); -void change_range(); +void change_prange(); void set_file_reference(const string& which); void set_properties(string which); diff --git a/pub/lib/defs.hpp b/pub/lib/defs.hpp index f0824e2ed1754108853d6152ae50ab7d9aa29b24..9bf1447fa1aecb117c16624b5a7820b9b1e2633d 100644 --- a/pub/lib/defs.hpp +++ b/pub/lib/defs.hpp @@ -12,14 +12,12 @@ #include "../trivia/string_convs.hpp" #include <iostream> -#include <map> #include <vector> #define S(a) triv::strg((a)) #define SQR(a) ((a) * (a)) -using std::map; using std::string; using std::vector; using std::cout; diff --git a/pub/lib/expr.hpp b/pub/lib/expr.hpp index d5a1ff1975b7f460699fb9b1c3e47ec8eba6098b..fd996fe3b0884614ec6bb8e53cf37a50bf747d32 100644 --- a/pub/lib/expr.hpp +++ b/pub/lib/expr.hpp @@ -79,7 +79,6 @@ public: class CNode { -private: public: virtual ~CNode() {} diff --git a/pub/lib/fbase.cpp b/pub/lib/fbase.cpp index 2c08f6c335d525b1b2391f63f0bf8509d71ae025..2a9362f89ad2b347405d682a125f72a6b4cd71e1 100644 --- a/pub/lib/fbase.cpp +++ b/pub/lib/fbase.cpp @@ -51,8 +51,8 @@ void func_neg(double& r, double& dr, double v, double dv) dr = dv; } -double func_ln(double v) { return v > 0 ? log(v) : 0; } -void func_ln(double& r, double& dr, double v, double dv) +double func_ln0(double v) { return v > 0 ? log(v) : 0; } +void func_ln0(double& r, double& dr, double v, double dv) { if (v > 0) { r = log(v); @@ -63,8 +63,15 @@ void func_ln(double& r, double& dr, double v, double dv) } } -double func_lg(double v) { return v > 0 ? log10(v) : 0; } -void func_lg(double& r, double& dr, double v, double dv) +double func_ln(double v) { return log(v); } +void func_ln(double& r, double& dr, double v, double dv) +{ + r = log(v); + dr = dv / v; +} + +double func_lg0(double v) { return v > 0 ? log10(v) : 0; } +void func_lg0(double& r, double& dr, double v, double dv) { if (v > 0) { r = log10(v); @@ -75,8 +82,15 @@ void func_lg(double& r, double& dr, double v, double dv) } } -double func_sqrt(double v) { return v >= 0 ? sqrt(v) : 0; } -void func_sqrt(double& r, double& dr, double v, double dv) +double func_lg(double v) { return log10(v); } +void func_lg(double& r, double& dr, double v, double dv) +{ + r = log10(v); + dr = dv / v / log(10); +} + +double func_sqrt0(double v) { return v >= 0 ? sqrt(v) : 0; } +void func_sqrt0(double& r, double& dr, double v, double dv) { if (v > 0) { r = sqrt(v); @@ -87,6 +101,13 @@ void func_sqrt(double& r, double& dr, double v, double dv) } } +double func_sqrt(double v) { return sqrt(v); } +void func_sqrt(double& r, double& dr, double v, double dv) +{ + r = sqrt(v); + dr = dv / 2 / r; +} + double func_abs(double v) { return fabs(v); } int func_abs(int v) { return abs(v); } void func_abs(double& r, double& dr, double v, double dv) @@ -541,6 +562,28 @@ double func_ornuhl(double _w, double _a, double _b) return -9; // too many terms } +double func_sears_forward(double t, double rho, double z) +{ + double k = rho<1 ? sqrt(1-rho*rho) : 0; + double a = k*(1-z)/2; + if (t*a>100) + return 1; + else if (t*k>200) + return 0; + double J = k>0 ? (k*cosh(t*a)+sinh(t*a))/(k*cosh(t*k)+sinh(t*k)) : (1+t*a)/(1+t); + return J; // *exp(t*k*(1+z)/2); +} + +double func_sears_backward(double t, double rho, double z) +{ + double k = rho<1 ? sqrt(1-rho*rho) : 0; + double a = k*(1-z)/2; + if (t*a>30) + return rho/(k+1); + double J = k>0 ? rho*sinh(t*a)/(k*cosh(t*k)+sinh(t*k)) : rho*t/(1+t); + return J; // *exp(t*k*(1+z)/2); +} + //************************************************************************************************** //* Registration //************************************************************************************************** @@ -630,15 +673,24 @@ void fbase_initialize() G->register_fct_0_s(m, func_pop); m = { "exit", 1, "(x): exit(x)" }; G->register_fct_i_i(m, func_exit); - m = { "ln", 1, "(x): natural logarithm of x, or 0 if x<=0" }; + m = { "ln", 1, "(x): natural logarithm of x" }; G->register_fct_d_d(m, func_ln); G->register_fct_e_e(m, func_ln); - m = { "lg", 1, "(x): decadic logarithm of x, or 0 if x<=0" }; + m = { "ln0", 1, "(x): natural logarithm of x, or 0 if x<=0" }; + G->register_fct_d_d(m, func_ln0); + G->register_fct_e_e(m, func_ln0); + m = { "lg", 1, "(x): decadic logarithm of x" }; G->register_fct_d_d(m, func_lg); G->register_fct_e_e(m, func_lg); - m = { "sqrt", 1, "(x): square root of x, or 0 if x<0" }; + m = { "lg0", 1, "(x): decadic logarithm of x, or 0 if x<=0" }; + G->register_fct_d_d(m, func_lg0); + G->register_fct_e_e(m, func_lg0); + m = { "sqrt", 1, "(x): square root of x" }; G->register_fct_d_d(m, func_sqrt); G->register_fct_e_e(m, func_sqrt); + m = { "sqrt0", 1, "(x): square root of x, or 0 if x<0" }; + G->register_fct_d_d(m, func_sqrt0); + G->register_fct_e_e(m, func_sqrt0); m = { "abs", 1, "(x): absolute value of x" }; G->register_fct_i_i(m, func_abs); G->register_fct_d_d(m, func_abs); @@ -798,4 +850,9 @@ void fbase_initialize() G->register_fct_d_ddd(m, func_ornuhl); m = { "rotdiff", 3, "(w,tau,qb: rotational diffusion spectrum)" }; G->register_fct_d_ddd(m, func_rotdiff); + + m = { "sears_forward", 3, "(tau,rho,zeta: Current U+)" }; + G->register_fct_d_ddd(m, func_sears_forward); + m = { "sears_backward", 3, "(tau,rho,zeta: Current U-)" }; + G->register_fct_d_ddd(m, func_sears_backward); } diff --git a/pub/lib/file_in.cpp b/pub/lib/file_in.cpp index b8d27c805b704b8d516c27e940d80b32dc2fc2cf..2c356c38b2f394bc51c94a1c5d076a7b403d67c4 100644 --- a/pub/lib/file_in.cpp +++ b/pub/lib/file_in.cpp @@ -11,7 +11,7 @@ #include <fstream> #include <string.h> - +#include <boost/filesystem.hpp> #include <yaml-cpp/yaml.h> #include "../readplus/ask.hpp" @@ -24,14 +24,15 @@ #include "olf.hpp" #include "slice.hpp" +namespace fs = boost::filesystem; + namespace NFileIn { -void Load_yda(std::ifstream& F_in, string fnam); -void Load_08(std::ifstream& F_in, string flong); -void Load_01(FILE* F_in, string flong); +void Load_yda(std::ifstream& F_in, string fshort); +void Load_01(FILE* F_in, string fshort); void LoadSpec_01(FILE* F_in, PSpec& sout, int nz); -void Load_96(FILE* F_in, string flong); +void Load_96(FILE* F_in, string fshort); } @@ -41,29 +42,31 @@ void NFileIn::load(void) { string pattern = sask("Load file(s)"); vector<string> fNames = triv::glob_file_list(pattern, "yda y08 a01 i96"); + if (!fNames.size()) + throw "Found no file that matches '" + pattern + "'"; for (string fnam : fNames) { try { - string fdir, fshort, fext; - triv::fname_divide(fnam, &fdir, &fshort, &fext); - if (fext == "y08" || fext == "yda") { + string fext = fs::path(fnam).extension().string(); + string fshort = fs::path(fnam).filename().stem().string(); + if (fext == ".y08" || fext == ".yda") { std::ifstream FS(fnam.c_str(), std::ios_base::in); if (FS.fail()) throw string("cannot open file"); cout << ".. loading file " << fnam << "\n"; Load_yda(FS, fshort); FS.close(); - } else if (fext == "a01" || fext == "i96") { + } else if (fext == ".a01" || fext == ".i96") { FILE* F_in; if (!(F_in = fopen(fnam.c_str(), "r"))) throw "cannot open file " + fnam; - if (fext == "a01") { - Load_01(F_in, fnam.c_str()); - } else if (fext == "i96") { - Load_96(F_in, fnam.c_str()); + if (fext == ".a01") { + Load_01(F_in, fshort); + } else if (fext == ".i96") { + Load_96(F_in, fshort); } fclose(F_in); } else - throw "unknown extension " + fext; + throw "unknown extension '" + fext + "'"; } catch (string& ex) { throw "Cannot load " + fnam + ": " + ex; } catch (std::exception& ex) { @@ -74,7 +77,7 @@ void NFileIn::load(void) //! Load a YAML file in yda format. -void NFileIn::Load_yda(std::ifstream& FS, string fnam) +void NFileIn::Load_yda(std::ifstream& FS, string fshort) { const YAML::Node doc = YAML::Load(FS); if (doc.Type() != YAML::NodeType::Map) @@ -349,7 +352,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam) } } - fout->name = fnam; + fout->name = fshort; fout->as_on_disk = true; SMem::instance()->mem_store(move(fout)); } @@ -357,15 +360,13 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam) //! Load a .a01 formatted file. -void NFileIn::Load_01(FILE* F_in, string flong) +void NFileIn::Load_01(FILE* F_in, string fshort) { - string lin, key, val, fdir, fshort, fext; + string lin, key, val; int iz, nj = 0, j; CCoord co; POld fout(new COld); - triv::fname_divide(flong, &fdir, &fshort, &fext); - if (triv::freadln(F_in, &lin) <= 0) throw "file empty or starting with empty line"; if (lin != string("ASCII-01 JWu")) @@ -484,16 +485,15 @@ void NFileIn::LoadSpec_01(FILE* F_in, PSpec& sout, int nz) //! Load a .i96 formatted file. -void NFileIn::Load_96(FILE* F_in, string flong) +void NFileIn::Load_96(FILE* F_in, string fshort) { - string lin, key, val, fdir, fshort, fext; + string lin, key, val; double r0, r1, r2; int n, nspec, ival; POld fout(new COld); CCoord co; PSpec sout; - triv::fname_divide(flong, &fdir, &fshort, &fext); fout->name = fshort; if (!triv::freadln(F_in, &lin)) diff --git a/pub/lib/file_out.cpp b/pub/lib/file_out.cpp index ecc0a6c1907f6f7c9c0d2961da4a6db9816ab6e0..8055b0b7a309520e4d6f90c2e019c0e2c13e441a 100644 --- a/pub/lib/file_out.cpp +++ b/pub/lib/file_out.cpp @@ -13,6 +13,7 @@ #include <yaml-cpp/yaml.h> #include "../readplus/ask.hpp" +#include "../trivia/file_ops.hpp" #include "../trivia/yaml_out.hpp" #include "file_out.hpp" @@ -25,7 +26,6 @@ namespace NFileOut { void save_yda(std::ofstream& ofs, const COlo* f); -void save_y08(FILE* file, const COlo* f); void save_csv(FILE* file, const COlo* f); void save_tab(FILE* file, const COlo* f); } @@ -47,13 +47,8 @@ void NFileOut::save(string fmt, bool allow_overwrite) // document file save f->log_action("fs " + outfnam + " # " + triv::time2strg(time(0))); // prevent unintended overwriting - if (!allow_overwrite) { - FILE* file; - if ((file = fopen(outfnam.c_str(), "r"))) { - fclose(file); - throw "file " + outfnam + " exists, use fso to overwrite"; - } - } + if (!allow_overwrite && triv::file_exists(outfnam)) + throw "file " + outfnam + " exists, use command modifier '!' to overwrite"; // save file if (fmt == "yda") { std::ofstream ofs; @@ -64,9 +59,7 @@ void NFileOut::save(string fmt, bool allow_overwrite) FILE* file; if (!(file = fopen(outfnam.c_str(), "w"))) throw "cannot write to file " + outfnam; - if (fmt == "y08") { - save_y08(file, f); - } else if (fmt == "csv") { + if (fmt == "csv") { save_csv(file, f); } else if (fmt == "tab") { save_tab(file, f); @@ -166,79 +159,6 @@ void NFileOut::save_yda(std::ofstream& ofs, const COlo* f) } -//! Writes a file in format y08. - -void NFileOut::save_y08(FILE* file, const COlo* f) -{ - const COld* fd = dynamic_cast<const COld*>(f); - const COlc* fc = dynamic_cast<const COlc*>(f); - - fprintf( - file, "Meta:\n" - " format: frida/y08 for yaml1\n" - " type: %s\n", - fd ? "generic tabular data" : "frida2 curve"); - - fprintf(file, "History:\n"); - for (string lin : f->lDoc) - fprintf(file, "- %s\n", triv::yaml(lin).c_str()); - - fprintf(file, "Coord:\n"); - fprintf( - file, " x:\n name: %s\n unit: %s\n", triv::yaml(f->xco.name).c_str(), - triv::yaml(f->xco.unit).c_str()); - fprintf( - file, " y:\n name: %s\n unit: %s\n", triv::yaml(f->yco.name).c_str(), - triv::yaml(f->yco.unit).c_str()); - for (int i = 0; i < f->ZCo.size(); i++) - fprintf( - file, " z%i:\n name: %s\n unit: %s\n", i, triv::yaml(f->ZCo[i].name).c_str(), - triv::yaml(f->ZCo[i].unit).c_str()); - - fprintf(file, "Param:\n"); - for (int i = 0; i < f->RPar.size(); i++) - fprintf( - file, " -\n name: %s\n unit: %s\n value: %20.15g\n", - triv::yaml(f->RPar[i].Co.name).c_str(), triv::yaml(f->RPar[i].Co.unit).c_str(), - f->RPar[i].val); - - if (fc) { - fprintf(file, "Formula: %s\n", fc->expr.c_str()); - } - - fprintf(file, "Tables: # %i tables follow\n", f->nJ()); - - for (int j = 0; j < f->nJ(); j++) { - fprintf(file, " - # table %i\n", j); - CSlice* s = f->V[j].get(); - for (int i = 0; i < f->nZ(); i++) { - if (RObjNum pz = PCAST<const CObjNum>(s->z[i])) { - fprintf(file, " z%i: %18.10g\n", i, pz->to_r()); - if (RObjNum pdz = PCAST<const CObjEnu>(s->z[i])) - fprintf(file, " dz%i: %18.10g\n", i, pdz->to_dr()); - } else - fprintf(file, " z%i: %s\n", i, s->z[i]->to_s().c_str()); - } - if (fd) { - const CSpec* s = fd->VS(j); - if (s->dy.size()) { - fprintf(file, " xyd: |2 # %i entries\n", (int)s->size()); - for (int i = 0; i < s->size(); i++) - fprintf(file, " %20.15g %20.15g %20.15g\n", s->x[i], s->y[i], s->dy[i]); - } else { - fprintf(file, " xy: |2 # %i entries\n", (int)s->size()); - for (int i = 0; i < s->size(); i++) - fprintf(file, " %20.15g %20.15g\n", s->x[i], s->y[i]); - } - } else { - CCurve* s = fc->VC(j); - for (int i = 0; i < fc->nP; i++) - fprintf(file, " p%i: %18.10g\n", i, s->P[i]); - } - } -} - - //! Writes y as tab-separated table. void NFileOut::save_csv(FILE* file, const COlo* f) diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp index 492474808faeab85b525de9d21101a4bed11b23c..96b033c486e83bd41303a004a763da31744a65cc 100644 --- a/pub/lib/fit.cpp +++ b/pub/lib/fit.cpp @@ -19,6 +19,7 @@ #include "fsel.hpp" #include "loop.hpp" #include "mem.hpp" +#include "expr.hpp" #include "obj.hpp" #include "olf.hpp" #include "slice.hpp" @@ -514,7 +515,7 @@ void NCurveFit::fit(bool _allow_slow_conv) for (int j = 0; j < fc->nJ(); ++j) fc->VC(j)->assert_attr(); - const COld* fd = SMem::instance()->mem_get_D(fc->kd); + COld* fd = SMem::instance()->mem_get_D(fc->kd); if (fc->nJ() != fd->nJ()) throw S("data file and curve file have different number of spectra"); if (!fc->nJ()) @@ -522,32 +523,6 @@ void NCurveFit::fit(bool _allow_slow_conv) if ((fc->weighing == COlc::_VAR || fc->weighing == COlc::_VARD) && !fd->VS(0)->has_dy()) throw S("Data have no error bars, cannot apply chosen fit weights"); - if (fc->range_T) { - throw S("TODO: restore range evaluation"); - /* - // overwrite fd with data that obye the range restriction: - POld fdr( fd->new_POld() ); - for ( int j=0; j<fc->nJ(); j++ ) { - const CSpec *sin = fd->VS(j); - PSpec sout = PSpec( new CSpec ); - sout->z = sin->z; - vector<double> range( sin->size() ); - fc->range_T->tree_vec_val( &range, 0, fc->kd, j ); - bool with_dy = sin->has_dy(); - for ( int i=0; i<sin->size(); i++ ) { - if ( range[i] ) { - if( with_dy ) - sout->push_xyd( sin->x[i], sin->y[i], sin->dy[i] ); - else - sout->push_xy( sin->x[i], sin->y[i] ); - } - } - fdr->V.push_back( sout ); - } - fd.swap( fdr ); // TODO can we simplify ? - */ - } - control.epsilon = Epsilon; control.stepbound = Factor; control.patience = nCall; diff --git a/pub/lib/fsel.cpp b/pub/lib/fsel.cpp index c0c041682fda80de5bb8e41cba63d7727243af11..d5feb77bec0dd481edbe9f261af9cfd81dc8a276 100644 --- a/pub/lib/fsel.cpp +++ b/pub/lib/fsel.cpp @@ -58,6 +58,17 @@ int SFSel::nJ_max() const return ret; } +//! Return the one and only D file in the current selection. +const COld* SFSel::theOneD() const +{ + vector<int> ksel = selD(); + if (ksel.size()==0) + throw "No data file selected"; + else if (ksel.size()>1) + throw "More than one data file selected"; + return dynamic_cast<const COld*>(SMem::instance()->mem_get(ksel[0])); +} + //************************************************************************************************** //* Write to online file selection //************************************************************************************************** diff --git a/pub/lib/fsel.hpp b/pub/lib/fsel.hpp index 7d40e930521552b156014900c387d38bb3189cb8..028e994e1a2845e7032bbb56567deab6065e3adb 100644 --- a/pub/lib/fsel.hpp +++ b/pub/lib/fsel.hpp @@ -31,6 +31,7 @@ public: vector<int> selC() const; COlo* sel_first() const; int nJ_max() const; + const COld* theOneD() const; // Modify file selection: void sel_delete(); diff --git a/pub/lib/import.cpp b/pub/lib/import.cpp index 921a052ff347e88ef28ef7f3cf533eb1ace4ebb0..57bd224d88b0f6b07675ce95bc16cf419eaaaa97 100644 --- a/pub/lib/import.cpp +++ b/pub/lib/import.cpp @@ -7,8 +7,9 @@ //! \file import.cpp //! \brief NImport: import tables or make data ex nihilo -#include "defs.hpp" +#include <boost/filesystem.hpp> +#include "defs.hpp" #include "../readplus/ask.hpp" #include "../trivia/file_ops.hpp" @@ -20,6 +21,8 @@ #include "olf.hpp" #include "slice.hpp" +namespace fs = boost::filesystem; + //! Create a new online file from table. @@ -63,7 +66,6 @@ void NImport::read_tab(string qualif) } FILE* fd; - string fdir, fshort, fext; for (int iF = 0; iF < inFiles.size(); ++iF) { if (!(fd = fopen(inFiles[iF].c_str(), "r"))) throw "cannot open file " + inFiles[iF]; @@ -73,9 +75,8 @@ void NImport::read_tab(string qualif) fout->log_action("ft" + qualif + " " + script); fout->name = script; } else { - triv::fname_divide(inFiles[iF], &fdir, &fshort, &fext); fout->log_action("ft" + qualif + " " + inFiles[iF]); - fout->name = fshort; + fout->name = fs::path(inFiles[iF]).filename().stem().string(); if (choosecol) { fout->log_action("y from column " + S(iycol)); fout->name += "_" + S(iycol); @@ -141,7 +142,7 @@ void NImport::read_tab(string qualif) } if (!horizontal) { s = PSpec(new CSpec); - s->z.resize(nz); + s->z.resize(nzdat); for (int iz = 0; iz < nzdat; ++iz) s->z[iz] = RObjDbl(new CObjDbl(zdat[iz])); } @@ -182,12 +183,12 @@ void NImport::read_tab(string qualif) if (dat.size() != (with_d ? 3 : 2)) { throw "line " + S(n_in) + " (line " + S(nline) + " in block " + S(nblock) + ") [" + lin + "] contains " + S(dat.size()) + " values; " - + "at present, exactly " + S(with_d ? 3 : 2) + " are required"; + + " exactly " + S(with_d ? 3 : 2) + " are required"; } if (with_d) - s->push_xy(dat[0], dat[1]); - else s->push_xyd(dat[0], dat[1], dat[2]); + else + s->push_xy(dat[0], dat[1]); } } ++nline; diff --git a/pub/lib/manip.cpp b/pub/lib/manip.cpp index 0d7ce66a07d4242ea40f0212113f5ee36709dccf..3c71184fa4c4e0c0cc133599ef2cb2b2e3d28b6a 100644 --- a/pub/lib/manip.cpp +++ b/pub/lib/manip.cpp @@ -77,7 +77,7 @@ void NManip::unfreeze_all_slices() //! Delete (or retain) points according to list of indices. -void NManip::points_select(bool sel_del) +void NManip::points_select(const bool sel_del) { FileIterator fiter(SFSel::instance()->selD()); static string sel = ""; @@ -116,7 +116,7 @@ void NManip::points_select(bool sel_del) //! Bin points. -void NManip::points_rebin() +void NManip::points_rebin(const bool sampling_err) { FileIterator fiter(SFSel::instance()->selD()); @@ -142,7 +142,7 @@ void NManip::points_rebin() throw S("First bin must start at 0"); breaks.push_back(sin->size()); - PSpec sout = sin->binned(breaks); + PSpec sout = sin->binned(breaks, sampling_err); fout->V.push_back(move(sout)); } @@ -153,7 +153,7 @@ void NManip::points_rebin() //! Bin points. -void NManip::points_rebin_by_factor() +void NManip::points_rebin_by_factor(const bool sampling_err) { FileIterator fiter(SFSel::instance()->selD()); static int ng = 2; @@ -175,7 +175,7 @@ void NManip::points_rebin_by_factor() for (int iout = 0; iout < nout + 1; ++iout) breaks[iout] = iout * ng; - PSpec sout = sin->binned(breaks); + PSpec sout = sin->binned(breaks, sampling_err); fout->V.push_back(move(sout)); } @@ -186,16 +186,9 @@ void NManip::points_rebin_by_factor() //! Bin points to keep errors below a certain bound. -void NManip::points_rebin_by_err(const string& subcmd) +void NManip::points_rebin_by_err(const bool absolute) { FileIterator fiter(SFSel::instance()->selD()); - bool mode_abs; - if (subcmd == "a") - mode_abs = true; - else if (subcmd == "r") - mode_abs = false; - else - throw S("invalid subcommand"); static double errbound; errbound = dask("Keep error below", errbound); @@ -212,15 +205,15 @@ void NManip::points_rebin_by_err(const string& subcmd) double xg = 0, yg = 0, vg = 0; int ng = 0, istart = 0; for (int i = 0; i < sin->size(); ++i) { - if (!mode_abs && sin->y[i] < 0) + if (!absolute && sin->y[i] < 0) throw("negative counts not compatible with relative error bounds"); xg += sin->x[i]; yg += sin->y[i]; vg += SQR(sin->dy[i]); ++ng; double dg = sqrt(vg); - if ((mode_abs && dg / ng < errbound) - || (!mode_abs && yg > 0 && dg / yg < errbound)) { + if ((absolute && dg / ng < errbound) + || (!absolute && yg > 0 && dg / yg < errbound)) { sout->push_xyd(xg / ng, yg / ng, dg / ng); groupinfo += S(istart) + ","; xg = 0; @@ -233,7 +226,7 @@ void NManip::points_rebin_by_err(const string& subcmd) if (sout->size()) fout->V.push_back(move(sout)); } - string docline = "mpae" + subcmd + " " + S(errbound); + string docline = S("mpa") + (absolute ? "e" : "r") + " " + S(errbound); if (fin->nJ() == 1) docline += " #=> groups " + groupinfo.substr(0, groupinfo.size() - 1); fout->log_action(docline); @@ -580,7 +573,7 @@ void NManip::ScaRemoveConstantZ(COlo* fio) //! Delete (or retain) spectra according to list of indices. -void NManip::slices_select(bool sel_del) +void NManip::slices_select(const bool sel_del) { vector<int> JSel, JSelSorted; static string jSel = ""; @@ -604,7 +597,7 @@ void NManip::slices_select(bool sel_del) //! Bin spectra. -void NManip::slices_rebin() +void NManip::slices_rebin(const bool sampling_err) { FileIterator fiter(SFSel::instance()->sel()); vector<int> JSel; @@ -646,7 +639,7 @@ void NManip::slices_rebin() if (fd) { PSpec sout(new CSpec()); bool in_with_dy = fd->VS(ji)->has_dy(); - bool out_with_dy = in_with_dy || mj > 1; + bool out_with_dy = in_with_dy || (sampling_err && mj > 1); int n = fd->nPts(ji); sout->resize(n, out_with_dy); // x grids must be equal: @@ -684,10 +677,11 @@ void NManip::slices_rebin() for (int jj = ji; jj < jf; jj++) { if (fd->VS(jj)->has_dy()) vm_src += SQR(fd->VS(jj)->dy[i]); - vm_grp += SQR(fd->VS(jj)->y[i] - ym); + if (sampling_err) + vm_grp += SQR(fd->VS(jj)->y[i] - ym); } double vm = vm_src / mj / mj; - if (mj > 1) + if (sampling_err && mj > 1) vm += vm_grp / (mj - 1); sout->dy[i] = sqrt(vm); } diff --git a/pub/lib/manip.hpp b/pub/lib/manip.hpp index 350895313b3a3c97a86f23f7ee4dcec6d8bf4e9b..6d9f399b836e9e8b4d9714aee8ab92d010158a58 100644 --- a/pub/lib/manip.hpp +++ b/pub/lib/manip.hpp @@ -16,19 +16,19 @@ namespace NManip { void freeze_slices(); void unfreeze_all_slices(); -void points_select(bool sel_del); -void points_rebin(); -void points_rebin_by_factor(); -void points_rebin_by_err(const string& subcmd); +void points_select(const bool sel_del); +void points_rebin(const bool sampling_err); void points_rebin_duplicates(); +void points_rebin_by_factor(const bool sampling_err); +void points_rebin_by_err(const bool absolute); void points_break_by_factor(); void points_sort(); void points_symmetrize(); void points_remove_err(); void points_interpolate(); void points_redistribute(); -void slices_select(bool sel_del); -void slices_rebin(); +void slices_select(const bool sel_del); +void slices_rebin(const bool sampling_err); void slices_merge(); void slices_break(); void slices_spawn(); diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp index 658f99480d46cd962c0d8e464375951514c02615..2fc89f8c5a90f487b93d1ba9f5b91b1973ae0ae3 100644 --- a/pub/lib/node.cpp +++ b/pub/lib/node.cpp @@ -26,6 +26,7 @@ extern bool allow_slow_conv; // set in curve.cpp +const int debug = 0; //************************************************************************************************** //* CNodeWithArgs @@ -33,12 +34,18 @@ extern bool allow_slow_conv; // set in curve.cpp bool CNodeWithArgs::has_dummy() const { - return std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->has_dummy(); }); + bool ret = std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->has_dummy(); }); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.has_dummy -> " + S(ret) + "\n"); + return ret; } bool CNodeWithArgs::has_conv() const { - return std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->has_conv(); }); + bool ret = std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->has_conv(); }); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.has_conv -> " + S(ret) + "\n"); + return ret; } int CNodeWithArgs::npar() const @@ -47,22 +54,33 @@ int CNodeWithArgs::npar() const for (RNode a : arg) if (a) ret = std::max(ret, a->npar()); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.npar -> " + S(ret) + "\n"); return ret; } bool CNodeWithArgs::k_dependent() const { - return std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->k_dependent(); }); + bool ret = std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->k_dependent(); }); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.k_dep -> " + S(ret) + "\n"); + return ret; } bool CNodeWithArgs::j_dependent() const { - return std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->j_dependent(); }); + bool ret = std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->j_dependent(); }); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.j_dep -> " + S(ret) + "\n"); + return ret; } bool CNodeWithArgs::i_dependent() const { - return std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->i_dependent(); }); + bool ret = std::any_of(arg.begin(), arg.end(), [](RNode a) { return a && a->i_dependent(); }); + if (debug) + std::cerr << ("CNodeWithArgs{" + tree_info() + "}.i_dep -> " + S(ret) + "\n"); + return ret; } @@ -70,12 +88,19 @@ bool CNodeWithArgs::i_dependent() const //* CNodeFun: function/operator node //************************************************************************************************** -CNodeFun1::CNodeFun1(const CFunc* _fu, RNode _a0) : CNodeFun(1, _fu) { arg[0] = _a0; } +CNodeFun1::CNodeFun1(const CFunc* _fu, RNode _a0) : CNodeFun(1, _fu) +{ + arg[0] = _a0; + if (debug) + std::cerr << ("CNodeFun1 := " + tree_info() + "\n"); +} CNodeFun2::CNodeFun2(const CFunc* _fu, RNode _a0, RNode _a1) : CNodeFun(2, _fu) { arg[0] = _a0; arg[1] = _a1; + if (debug) + std::cerr << ("CNodeFun2 := " + tree_info() + "\n"); } CNodeFun3::CNodeFun3(const CFunc* _fu, RNode _a0, RNode _a1, RNode _a2) : CNodeFun(3, _fu) @@ -83,12 +108,16 @@ CNodeFun3::CNodeFun3(const CFunc* _fu, RNode _a0, RNode _a1, RNode _a2) : CNodeF arg[0] = _a0; arg[1] = _a1; arg[2] = _a2; + if (debug) + std::cerr << ("CNodeFun1 := " + tree_info() + "\n"); } //! Returns the result of function evaluation for given arguments. RObj CNodeFun::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeFun{" + tree_info() + "}.tree_val ...\n"); string basetypes; const CTypedFunc* tf = nullptr; try { @@ -276,11 +305,16 @@ RObj CNodeFun::tree_val(const CContext& ctx) const } -CCoord CNodeFun1::node_coord(int k) const { return fu->coord(arg[0]->node_coord(k)); } +CCoord CNodeFun1::node_coord(int k) const +{ + return fu->coord(arg[0]->node_coord(k)); +} + CCoord CNodeFun2::node_coord(int k) const { return fu->coord(arg[0]->node_coord(k), arg[1]->node_coord(k)); } + CCoord CNodeFun3::node_coord(int k) const { return fu->coord(arg[0]->node_coord(k), arg[1]->node_coord(k), arg[2]->node_coord(k)); @@ -288,7 +322,10 @@ CCoord CNodeFun3::node_coord(int k) const //! Returns string representation of this node. -string CNodeFun1::tree_info() const { return fu->tag + "(" + arg[0]->tree_info() + ")"; } +string CNodeFun1::tree_info() const +{ + return fu->tag + "(" + arg[0]->tree_info() + ")"; +} //! Returns string representation of this node. @@ -310,11 +347,12 @@ string CNodeFun3::tree_info() const //* CNodeRange: range node //************************************************************************************************** - //! Evaluates the range in context, and returns a vector object pointer. RObj CNodeRange::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeRange{" + tree_info() + "}.tree_val ...\n"); // evaluate arguments, determine types, assert they are scalar. vector<RObj> pa(narg); bool all_int = true; @@ -348,7 +386,10 @@ RObj CNodeRange::tree_val(const CContext& ctx) const } } -CCoord CNodeRange::node_coord(int k) const { return CCoord("range", ""); } +CCoord CNodeRange::node_coord(int k) const +{ + return CCoord("range", ""); +} //! Returns string representation of this node. @@ -363,7 +404,6 @@ string CNodeRange::tree_info() const //* CNodeList //************************************************************************************************** - CNodeList::CNodeList(RNode _incremand, RNode _increment) : CNodeWithArgs(1) { if (auto old = PCAST<const CNodeList>(_incremand)) { @@ -381,6 +421,8 @@ CNodeList::CNodeList(RNode _incremand, RNode _increment) : CNodeWithArgs(1) RObj CNodeList::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeList{" + tree_info() + "}.tree_val ...\n"); // evaluate arguments, determine types vector<RObj> pa(narg); bool all_int = true; @@ -469,6 +511,8 @@ CNodeGeni::CNodeGeni(const class CGeni* _geni, RRef _ref) : CNodeWithArgs(_geni- arg[iarg] = RNode(new CNodePointX(ref)); else if (geni->default_args[iarg] == "y") arg[iarg] = RNode(new CNodePointY(ref)); + else if (geni->default_args[iarg] == "expr") + throw S("syntax error: functional(expr) does not have default argument"); else throw S("BUG: unexpected default arg"); } @@ -495,6 +539,8 @@ CNodeGeni::CNodeGeni(const class CGeni* _geni, RNode _a0, RNode _a1) : CNodeWith RObj CNodeGeni::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeGeni{" + tree_info() + "}.tree_val ...\n"); try { if (ctx.dim == CContext::_VT) throw "Unexpected evaluation in curve context {context: " + ctx.context_info() + "}"; @@ -517,12 +563,11 @@ RObj CNodeGeni::tree_val(const CContext& ctx) const throw S("vector arguments have different size"); } // Now evaluate the function. - double val; - geni->eval(&val, nullptr, n, pav); // TODO: compute errors + RObjNum val = geni->eval(n, pav); // TODO: compute errors if (ctx.dim == CContext::_1) - return RObjDbl(new CObjDbl(val)); + return val; else if (ctx.dim == CContext::_VI) - return RObjVecDbl(new CObjVecDbl(ctx.nv, val)); + return val->to_vec(ctx.nv); else throw "BUG: unforeseen dimension {context: " + ctx.context_info() + "}"; @@ -593,6 +638,8 @@ CNodeCvin::CNodeCvin(const class CCvin* _cvin, RRef _ref, RNode _a0, RNode _a1) RObj CNodeCvin::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeCvin{" + tree_info() + "}.tree_val ...\n"); try { if (ctx.dim != CContext::_1) throw "Unexpected is_vec() {context: " + ctx.context_info() + "}"; @@ -660,7 +707,11 @@ CNodeVal::CNodeVal(int _val) : val(PObjInt(new CObjInt(_val))) {} bool CNodeVal::looks_like_indices() const { return PCAST<const CObjInt>(val) != nullptr; } -RObj CNodeVal::tree_val(const CContext& ctx) const { return val; } +RObj CNodeVal::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeVal{" + tree_info() + "}.tree_val -> " + val->to_s() + "\n"); + return val; +} CCoord CNodeVal::node_coord(int k) const { return CCoord(val->to_s(), ""); } @@ -677,21 +728,40 @@ RObj CNodeIdxI::tree_val(const CContext& ctx) const if (ctx.dim == CContext::_1) { if (ctx.i == -1) throw S("missing index i"); - return RObjInt(new CObjInt(ctx.i)); + RObjInt ret(new CObjInt(ctx.i)); + if (debug) + std::cerr << ("CNodeIdxI{" + tree_info() + "}.tree_val[dim=1] -> " + + ret->to_s() + "\n"); + return ret; } else if (ctx.dim == CContext::_VI) { PObjVecInt pret(new CObjVecInt(ctx.nv)); for (int i = 0; i < ctx.nv; ++i) pret->v[i] = i; + if (debug) + std::cerr << ("CNodeIdxI{" + tree_info() + "}.tree_val[dim=VI] -> " + + pret->to_s() + "\n"); return pret; } else throw S("index i not defined in this context"); } -RObj CNodeIdxJ::tree_val(const CContext& ctx) const { return RObjInt(new CObjInt(ctx.j)); } +RObj CNodeIdxJ::tree_val(const CContext& ctx) const +{ + RObj ret = RObjInt(new CObjInt(ctx.j)); + if (debug) + std::cerr << ("CNodeIdxJ{" + tree_info() + "}.tree_val -> " + ret->to_s() + "\n"); + return ret; +} -RObj CNodeIdxK::tree_val(const CContext& ctx) const { return RObjInt(new CObjInt(ctx.k)); } +RObj CNodeIdxK::tree_val(const CContext& ctx) const +{ + RObj ret = RObjInt(new CObjInt(ctx.k)); + if (debug) + std::cerr << ("CNodeIdxK{" + tree_info() + "}.tree_val -> " + ret->to_s() + "\n"); + return ret; +} //************************************************************************************************** @@ -700,7 +770,10 @@ RObj CNodeIdxK::tree_val(const CContext& ctx) const { return RObjInt(new CObjInt RObj CNodeSessionNK::tree_val(const CContext& ctx) const { - return RObjInt(new CObjInt(SMem::instance()->mem_size())); + RObj ret = RObjInt(new CObjInt(SMem::instance()->mem_size())); + if (debug) + std::cerr << ("CNodeNK{" + tree_info() + "}.tree_val -> " + ret->to_s() + "\n"); + return ret; } @@ -710,6 +783,8 @@ RObj CNodeSessionNK::tree_val(const CContext& ctx) const RObj CNodeFile::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeFile{" + tree_info() + "}.tree_val ...\n"); if (ctx.dim == CContext::_VI) { CContext myctx = ctx; myctx.dim = CContext::_1; @@ -741,12 +816,16 @@ CCoord CNodeFile::node_coord(int _k) const RObj CNodeFileNJ::tree_val_scalar(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeFileNJ{" + tree_info() + "}.tree_val_scalar ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); return RObjInt(new CObjInt(f->nJ())); } RObj CNodeFileR::tree_val_scalar(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeFileR{" + tree_info() + "}.tree_val_scalar ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); if (num < 0 || num >= f->RPar.size()) throw "file has no parameter r" + S(num); @@ -768,6 +847,8 @@ CCoord CNodeFileR::file_coord(const COlo* f) const RObj CNodeSliceZ::tree_val_scalar(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeSliceZ{" + tree_info() + "}.tree_val_scalar ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); int j = PCAST<const CRef2>(ref)->get_j(ctx, f->nJ()); const CSlice* s = f->V[j].get(); @@ -786,6 +867,8 @@ CCoord CNodeSliceZ::file_coord(const COlo* f) const RObj CNodeSpecNI::tree_val_scalar(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeSpecNI{" + tree_info() + "}.tree_val_scalar ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); const COld* fd = dynamic_cast<const COld*>(f); if (!fd) @@ -796,6 +879,8 @@ RObj CNodeSpecNI::tree_val_scalar(const CContext& ctx) const RObj CNodeCurve::tree_val_scalar(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeCurve{" + tree_info() + "}.tree_val_scalar ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); const COlc* fc = dynamic_cast<const COlc*>(f); if (!fc) @@ -807,6 +892,8 @@ RObj CNodeCurve::tree_val_scalar(const CContext& ctx) const RObj CNodeCurveP::curve_val_scalar(const CCurve* c) const { + if (debug) + std::cerr << ("CNodeCurveP{" + tree_info() + "}.tree_val_scalar ...\n"); if (num < 0 || num >= c->P.size()) throw "curve has no p" + S(num); return RObjDbl(new CObjDbl(c->P[num])); @@ -842,11 +929,14 @@ RObj CNodeCurveR2::curve_val_scalar(const CCurve* c) const RObj CNodePoint::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodePoint{" + tree_info() + "}.tree_val ...\n"); auto ref3 = PCAST<const CRef3>(ref); if (!ref3) throw S("BUG: NodePoint has no Ref3"); if (ctx.dim == CContext::_VI) { - if (ref->k_depends_on_i() || ref3->j_depends_on_i()) { + if (ref->k_depends_on_i() || ref3->j_depends_on_i() + || (ref3->ti && ref3->ti->i_dependent())) { if (ctx.nv < 0) throw S("BUG: i-dependent K or J with unspecified return array length"); if (!ref3->ti) // Could be easily supported, but is forbidden to prevent accidental use @@ -858,17 +948,37 @@ RObj CNodePoint::tree_val(const CContext& ctx) const myctx.i = i; tmp->v.push_back(tree_val_point(myctx, ref3->ti->tree_val_idx(myctx, "i"))); } - return tmp->to_vecnum(); - } else if (!ref3->ti || ref3->ti->i_dependent()) { - return tree_val_vector(ctx); + RObj ret = tmp->to_vecnum(); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val[dim=VI,i2j||i2k] -> " + + ret->to_s() + "\n"); + return ret; + } else if (!ref3->ti) { + RObj ret = tree_val_vector(ctx); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val[dim=VI,i2nil] -> " + + ret->to_s() + "\n"); + return ret; } else { - return tree_val_point(ctx, ref3->ti->tree_val_idx(ctx, "i")); + RObj ret = tree_val_point(ctx, ref3->ti->tree_val_idx(ctx, "i")); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val[dim=VI,i2i] -> " + + ret->to_s() + "\n"); + return ret; } } else { if (ref3->ti) { - return tree_val_point(ctx, ref3->ti->tree_val_idx(ctx, "i")); + RObj ret = tree_val_point(ctx, ref3->ti->tree_val_idx(ctx, "i")); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val[dim!=VI,ti] -> " + + ret->to_s() + "\n"); + return ret; } else { - return tree_val_point(ctx, ctx.i); + RObj ret = tree_val_point(ctx, ctx.i); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val[dim!=VI,!ti] -> " + + ret->to_s() + "\n"); + return ret; } } } @@ -876,6 +986,8 @@ RObj CNodePoint::tree_val(const CContext& ctx) const RObj CNodePoint::tree_val_point(const CContext& ctx, int i) const { + if (debug) + std::cerr << ("CNodePoint{" + tree_info() + "}.tree_val_point -> ...\n"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); const COld* fd = dynamic_cast<const COld*>(f); if (!fd) @@ -884,12 +996,18 @@ RObj CNodePoint::tree_val_point(const CContext& ctx, int i) const const CSpec* s = fd->VS(j); if (i < 0 || i >= s->size()) throw "invalid data point index " + S(i) + ", spectrum has length " + S(s->size()); - return spec_val_point(s, i, ctx.want_error); + RObj ret = spec_val_point(s, i, ctx.want_error); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val_point -> " + + ret->to_s() + "\n"); + return ret; } RObj CNodePoint::tree_val_vector(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodePoint{" + tree_info() + "}.tree_val_vector ...\n"); if (ctx.dim != CContext::_VI) throw S("BUG: unexpected context in tree_val_vector"); const COlo* f = SMem::instance()->mem_get(ref->get_k(ctx)); @@ -904,18 +1022,28 @@ RObj CNodePoint::tree_val_vector(const CContext& ctx) const else if (n > s->size()) throw "requested " + S(n) + " points while spectrum " + S(j) + " only has " + S(s->size()) + " points"; - return spec_val_vector(s, n, ctx.want_error); + RObj ret = spec_val_vector(s, n, ctx.want_error); + if (debug) + std::cerr << ("... CNodePoint{" + tree_info() + "}.tree_val_vector -> " + + ret->to_s() + "\n"); + return ret; } RObj CNodePointX::spec_val_point(const CSpec* s, int i, bool want_error) const { - return RObjDbl(new CObjDbl(s->x[i])); + RObj ret = RObjDbl(new CObjDbl(s->x[i])); + if (debug) + std::cerr << ("CNodePointX{" + tree_info() + "}.spec_val_point -> " + ret->to_s() + "\n"); + return ret; } RObj CNodePointX::spec_val_vector(const CSpec* s, int n, bool want_error) const { - return RObjVecDbl(new CObjVecDbl(vector<double>(s->x.begin(), s->x.begin() + n))); + RObj ret = RObjVecDbl(new CObjVecDbl(vector<double>(s->x.begin(), s->x.begin() + n))); + if (debug) + std::cerr << ("CNodePointX{" + tree_info() + "}.spec_val_vector -> " + ret->to_s() + "\n"); + return ret; } CCoord CNodePointX::file_coord(const COlo* f) const @@ -929,17 +1057,24 @@ CCoord CNodePointX::file_coord(const COlo* f) const RObj CNodePointY::spec_val_point(const CSpec* s, int i, bool want_error) const { - return want_error && s->has_dy() ? RObjEnu(new CObjEnu(s->y[i], s->dy[i])) - : RObjDbl(new CObjDbl(s->y[i])); + RObj ret = want_error && s->has_dy() + ? RObjEnu(new CObjEnu(s->y[i], s->dy[i])) + : RObjDbl(new CObjDbl(s->y[i])); + if (debug) + std::cerr << ("CNodePointY{" + tree_info() + "}.spec_val_point -> " + ret->to_s() + "\n"); + return ret; } RObj CNodePointY::spec_val_vector(const CSpec* s, int n, bool want_error) const { - return want_error && s->has_dy() + RObj ret = want_error && s->has_dy() ? RObjVecEnu(new CObjVecEnu( vector<double>(s->y.begin(), s->y.begin() + n), vector<double>(s->dy.begin(), s->dy.begin() + n))) : RObjVecDbl(new CObjVecDbl(vector<double>(s->y.begin(), s->y.begin() + n))); + if (debug) + std::cerr << ("CNodePointY{" + tree_info() + "}.spec_val_vector -> " + ret->to_s() + "\n"); + return ret; } CCoord CNodePointY::file_coord(const COlo* f) const @@ -953,14 +1088,20 @@ CCoord CNodePointY::file_coord(const COlo* f) const RObj CNodePointDY::spec_val_point(const CSpec* s, int i, bool want_error) const { - return RObjDbl(new CObjDbl(s->dy[i])); + RObj ret = RObjDbl(new CObjDbl(s->dy[i])); + if (debug) + std::cerr << ("CNodePointDY{" + tree_info() + "}.spec_val_point -> " + ret->to_s() + "\n"); + return ret; } RObj CNodePointDY::spec_val_vector(const CSpec* s, int n, bool want_error) const { if (!s->has_dy()) throw S("requested dy does not exist"); - return RObjVecDbl(new CObjVecDbl(vector<double>(s->dy.begin(), s->dy.begin() + n))); + RObj ret = RObjVecDbl(new CObjVecDbl(vector<double>(s->dy.begin(), s->dy.begin() + n))); + if (debug) + std::cerr << ("CNodePointDY{" + tree_info() + "}.spec_val_vector -> " + ret->to_s() + "\n"); + return ret; } CCoord CNodePointDY::file_coord(const COlo* f) const @@ -983,6 +1124,8 @@ RObj CNodeIdf::tree_val(const CContext& ctx) const PObj ret = SVariRegistry::instance()->find(idf); if (!ret) throw "uninitialized variable " + idf; + if (debug) + std::cerr << ("CNodeIdf{" + tree_info() + "}.tree_val -> " + ret->to_s() + "\n"); return ret; } @@ -1013,6 +1156,8 @@ RObj CNodeDummy::tree_val(const CContext& ctx) const RObj CNodeCev::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeCev{" + tree_info() + "}.tree_val ...\n"); try { // get k, curve, j from context: int k = ref->get_k(ctx); @@ -1043,6 +1188,8 @@ CCoord CNodeCev::node_coord(int k) const { return CCoord("c", ""); } // primitiv RObj CNodeMixin::tree_val(const CContext& ctx) const { + if (debug) + std::cerr << ("CNodeMixin{" + tree_info() + "}.tree_val ...\n"); // Shift: RObj res_shift = shift->tree_val(ctx); RObjNum par = PCAST<const CObjNum>(res_shift); @@ -1324,4 +1471,7 @@ RObjVecDbl CNodeDirac::convolve( return ret; } -CCoord CNodeDirac::node_coord(int k) const { return CCoord("resol", ""); } +CCoord CNodeDirac::node_coord(int k) const +{ + return CCoord("resol", ""); +} diff --git a/pub/lib/node.hpp b/pub/lib/node.hpp index 230dcd22ea0f103710f8a193c00b6b67625be645..ff2db06879b7e65756912bf2fe0d77e8f799cee5 100644 --- a/pub/lib/node.hpp +++ b/pub/lib/node.hpp @@ -22,6 +22,7 @@ protected: vector<RNode> arg; public: + CNodeWithArgs() = delete; CNodeWithArgs(int _narg) : narg(_narg) { arg.resize(narg); } int npar() const; bool k_dependent() const; @@ -41,6 +42,7 @@ protected: const class CFunc* fu; public: + CNodeFun() = delete; CNodeFun(int _narg, const class CFunc* _fu) : CNodeWithArgs(_narg), fu(_fu) {} RObj tree_val(const CContext& ctx) const; virtual CCoord node_coord(int k) const = 0; @@ -53,6 +55,7 @@ public: class CNodeFun1 : public CNodeFun { public: + CNodeFun1() = delete; CNodeFun1(const class CFunc* _fu, RNode a0); CCoord node_coord(int k) const; string tree_info() const; @@ -64,6 +67,7 @@ public: class CNodeFun2 : public CNodeFun { public: + CNodeFun2() = delete; CNodeFun2(const class CFunc* _fu, RNode a0, RNode a1); CCoord node_coord(int k) const; string tree_info() const; @@ -75,6 +79,7 @@ public: class CNodeFun3 : public CNodeFun { public: + CNodeFun3() = delete; CNodeFun3(const class CFunc* _fu, RNode a0, RNode a1, RNode a2); CCoord node_coord(int k) const; string tree_info() const; @@ -89,6 +94,7 @@ private: bool inclusive_end; public: + CNodeRange() = delete; CNodeRange( bool _inclusive_end, RNode _beg = nullptr, RNode _end = nullptr, RNode _step = nullptr) : CNodeWithArgs(3), inclusive_end(_inclusive_end) @@ -109,6 +115,7 @@ public: class CNodeList : public CNodeWithArgs { public: + CNodeList() = delete; CNodeList(RNode _list, RNode _incr); vector<RNode> args() const { return arg; } RObj tree_val(const CContext& ctx) const; @@ -126,6 +133,7 @@ private: const class CGeni* geni; public: + CNodeGeni() = delete; CNodeGeni(const class CGeni* _geni, RRef _ref = nullptr); CNodeGeni(const class CGeni* _geni, RNode a0); CNodeGeni(const class CGeni* _geni, RNode a0, RNode a1); @@ -145,6 +153,7 @@ private: RRef ref; public: + CNodeCvin() = delete; CNodeCvin(const class CCvin* _cvin, RRef _ref, RNode a0, RNode a1); bool k_dependent() const { return true; } RObj tree_val(const CContext& ctx) const; @@ -161,6 +170,7 @@ private: RObj val; public: + CNodeVal() = delete; CNodeVal(RObj _val) : val(_val) {} CNodeVal(double _val); CNodeVal(int _val); @@ -240,6 +250,7 @@ protected: RRef ref; public: + CNodeFile() = delete; CNodeFile(RRef _ref) : ref(_ref) {} void set_ref(RRef& _ref) { ref = _ref; }; bool k_dependent() const { return true; } @@ -255,6 +266,7 @@ public: class CNodeFileNJ : public CNodeFile { public: + CNodeFileNJ() = delete; CNodeFileNJ(RRef _ref) : CNodeFile(_ref) {} string name() const { return "nj"; } RObj tree_val_scalar(const CContext& ctx) const; @@ -269,6 +281,7 @@ private: int num; public: + CNodeFileR() = delete; CNodeFileR(int _num, RRef _ref) : CNodeFile(_ref), num(_num) {} CCoord file_coord(const COlo* f) const; string name() const { return "r" + S(num); } @@ -281,6 +294,7 @@ public: class CNodeSlice : public CNodeFile { public: + CNodeSlice() = delete; CNodeSlice(RRef _ref) : CNodeFile(_ref) {} }; @@ -293,6 +307,7 @@ private: int num; public: + CNodeSliceZ() = delete; CNodeSliceZ(int _num, RRef _ref) : CNodeSlice(_ref), num(_num) {} CCoord file_coord(const COlo* f) const; string name() const { return "z" + S(num); } @@ -305,6 +320,7 @@ public: class CNodeSpecNI : public CNodeSlice { public: + CNodeSpecNI() = delete; CNodeSpecNI(RRef _ref) : CNodeSlice(_ref) {} string name() const { return "ni"; } RObj tree_val_scalar(const CContext& ctx) const; @@ -316,6 +332,7 @@ public: class CNodeCurve : public CNodeSlice { public: + CNodeCurve() = delete; CNodeCurve(RRef _ref) : CNodeSlice(_ref) {} RObj tree_val_scalar(const CContext& ctx) const; virtual RObj curve_val_scalar(const CCurve* c) const = 0; @@ -330,6 +347,7 @@ private: int num; public: + CNodeCurveP() = delete; CNodeCurveP(int _num, RRef _ref) : CNodeCurve(_ref), num(_num) {} CCoord file_coord(const COlo* f) const; string name() const { return "p" + S(num); } @@ -343,6 +361,7 @@ public: class CNodeCurveOutcome : public CNodeCurve { public: + CNodeCurveOutcome() = delete; CNodeCurveOutcome(RRef _ref) : CNodeCurve(_ref) {} string name() const { return "oc"; } RObj curve_val_scalar(const CCurve* c) const; @@ -354,6 +373,7 @@ public: class CNodeCurveChi2 : public CNodeCurve { public: + CNodeCurveChi2() = delete; CNodeCurveChi2(RRef _ref) : CNodeCurve(_ref) {} string name() const { return "chi2"; } RObj curve_val_scalar(const CCurve* c) const; @@ -365,6 +385,7 @@ public: class CNodeCurveR2 : public CNodeCurve { public: + CNodeCurveR2() = delete; CNodeCurveR2(RRef _ref) : CNodeCurve(_ref) {} string name() const { return "R2"; } RObj curve_val_scalar(const CCurve* c) const; @@ -394,6 +415,7 @@ public: class CNodePointX : public CNodePoint { public: + CNodePointX() = delete; CNodePointX(RRef _ref) : CNodePoint(_ref) {} CCoord file_coord(const COlo* f) const; string name() const { return "x"; } @@ -407,6 +429,7 @@ public: class CNodePointY : public CNodePoint { public: + CNodePointY() = delete; CNodePointY(RRef _ref) : CNodePoint(_ref) {} CCoord file_coord(const COlo* f) const; string name() const { return "y"; } @@ -420,6 +443,7 @@ public: class CNodePointDY : public CNodePoint { public: + CNodePointDY() = delete; CNodePointDY(RRef _ref) : CNodePoint(_ref) {} CCoord file_coord(const COlo* f) const; string name() const { return "dy"; } @@ -436,6 +460,7 @@ private: string idf; public: + CNodeIdf() = delete; CNodeIdf(string _s); RObj tree_val(const CContext& ctx) const; CCoord node_coord(int k) const; @@ -468,6 +493,7 @@ private: RNode arg; public: + CNodeCev() = delete; CNodeCev(RRef _ref, RNode _arg) : ref(_ref), arg(_arg) {} bool k_dependent() const { return true; } bool has_dummy() const { return arg->has_dummy(); } @@ -486,6 +512,7 @@ protected: RNode shift; public: + CNodeMixin() = delete; CNodeMixin(const RNode& _shift) : shift(_shift) {} int npar() const { return shift->npar(); } bool k_dependent() const { return shift->k_dependent(); } @@ -507,9 +534,9 @@ protected: RNode theory; public: - CNodeConvBase(const RNode& _theory, const RNode& _shift) : CNodeMixin(_shift), theory(_theory) - { - } + CNodeConvBase() = delete; + CNodeConvBase(const RNode& _theory, const RNode& _shift) + : CNodeMixin(_shift), theory(_theory) {} int npar() const { return std::max(shift->npar(), theory->npar()); } bool k_dependent() const { return theory->k_dependent() || shift->k_dependent(); } bool j_dependent() const { return theory->j_dependent() || shift->j_dependent(); } @@ -524,10 +551,9 @@ public: class CNodeConv : public CNodeConvBase { public: + CNodeConv() = delete; CNodeConv(const RNode& _theory, const RNode& _shift = RNode(new CNodeVal(0.0))) - : CNodeConvBase(_theory, _shift) - { - } + : CNodeConvBase(_theory, _shift) {} RObj copy_theory(const CContext& ctx, double theshift) const; RObjVecDbl convolve( const CContext& ctx, double theshift, const CSpec* sv, double conv_norm, @@ -544,8 +570,9 @@ public: class CNodePConv : public CNodeConvBase { public: + CNodePConv() = delete; CNodePConv(const RNode& _theory, const RNode& _shift = RNode(new CNodeVal(0.0))) - : CNodeConvBase(_theory, _shift){}; + : CNodeConvBase(_theory, _shift) {}; RObj copy_theory(const CContext& ctx, double theshift) const; RObjVecDbl convolve( const CContext& ctx, double theshift, const CSpec* sv, double conv_norm, diff --git a/pub/lib/obj.cpp b/pub/lib/obj.cpp index 63d107d6989800f49d8b8da57af065fe58b7cd30..d60a1987e4f1704ff95ff37fbd56b3e3a4af0292 100644 --- a/pub/lib/obj.cpp +++ b/pub/lib/obj.cpp @@ -40,6 +40,10 @@ string CObjInt::to_s(int maxlen, int minlen, int prec) const return ret; } +RObjVecNum CObjInt::to_vec(int repetitions) const +{ + return RObjVecInt(new CObjVecInt(vector<int>(repetitions, val))); +} //************************************************************************************************** // CObjDbl @@ -65,6 +69,11 @@ string CObjDbl::result_info() const return "CObjDbl(" + to_s() + ")"; } +RObjVecNum CObjDbl::to_vec(int repetitions) const +{ + return RObjVecDbl(new CObjVecDbl(vector<double>(repetitions, val))); +} + //************************************************************************************************** // CObjEnu @@ -84,6 +93,12 @@ string CObjEnu::result_info() const return "CObjDbl(" + to_s() + ")"; } +RObjVecNum CObjEnu::to_vec(int repetitions) const +{ + return RObjVecEnu(new CObjVecEnu(vector<double>(repetitions, val), + vector<double>(repetitions, err))); +} + //************************************************************************************************** // CObjVec @@ -134,12 +149,21 @@ RObj CObjVecObj::to_vecnum() const string CObjVecObj::to_s(int maxlen, int minlen, int prec) const { - string ret; + string ret = "["; for (int i = 0; i < v.size(); ++i) { ret += v[i]->to_s(); if (i < v.size() - 1) ret += ","; } + ret += "]"; + return ret; +} + +vector<double> CObjVecObj::to_rvec() const +{ + vector<double> ret(size()); + for (int i = 0; i < v.size(); ++i) + ret[i] = v[i]->to_r(); return ret; } @@ -151,12 +175,13 @@ string CObjVecObj::to_s(int maxlen, int minlen, int prec) const string CObjVecInt::to_s(int maxlen, int minlen, int prec) const { - string ret; + string ret = "["; for (int i = 0; i < v.size(); ++i) { ret += S(v[i]); if (i < v.size() - 1) ret += ","; } + ret += "]"; return ret; } @@ -174,12 +199,13 @@ string CObjVecInt::result_info() const { return to_s(); } string CObjVecDbl::to_s(int maxlen, int minlen, int prec) const { - string ret; + string ret = "["; for (int i = 0; i < v.size(); ++i) { ret += S(v[i]); if (i < v.size() - 1) ret += ","; } + ret += "]"; return ret; } diff --git a/pub/lib/obj.hpp b/pub/lib/obj.hpp index acfcea515ea140339e0cf8ed72d90c3b7563e9bd..616c831ce25353cb1c967021167fc2009a02acf3 100644 --- a/pub/lib/obj.hpp +++ b/pub/lib/obj.hpp @@ -20,7 +20,6 @@ class CObj { public: virtual ~CObj() {} - // virtual PObj clone() const =0; virtual bool is_vec() const = 0; virtual bool has_err() const = 0; virtual char base_type() const = 0; @@ -50,6 +49,7 @@ public: bool is_vec() const { return false; } virtual double to_dr() const { return 0.; } virtual double to_dr(int i) const { return 0.; } + virtual RObjVecNum to_vec(int repetitions) const = 0; }; //! Data container holding a single integer number. @@ -59,7 +59,6 @@ class CObjInt : public CObjNum public: int val; //!< Scalar value. CObjInt(int _val) : CObjNum(), val(_val) {} - // PObj clone() const { return PObjInt( new CObjInt( *this ) ); } inline bool has_err() const { return false; } inline char base_type() const { return 'i'; } string result_info() const { return "CObjInt(" + S(val) + ")"; } @@ -69,6 +68,7 @@ public: inline int to_i(int i) const { return val; } string to_s(int maxlen = 12, int minlen = 1, int prec = 6) const; inline bool to_b() const { return val; } + RObjVecNum to_vec(int repetitions) const final; }; //! Data container holding a single floating-point number. @@ -78,7 +78,6 @@ class CObjDbl : public CObjNum public: double val; //!< Scalar value. CObjDbl(double _val = NAN) : CObjNum(), val(_val) {} - // PObj clone() const { return PObjDbl( new CObjDbl( *this ) ); } inline bool has_err() const { return false; } inline char base_type() const { return 'd'; } string result_info() const; @@ -86,17 +85,16 @@ public: inline double to_r(int i) const { return val; } string to_s(int maxlen = 12, int minlen = 1, int prec = 6) const; bool to_b() const { return val; } + virtual RObjVecNum to_vec(int repetitions) const; }; //! Data container holding a single floating-point number with its error bar. -// STILL UNUSED! class CObjEnu : public CObjDbl { public: double err; //!< Error of scalar value. CObjEnu(double _val = NAN, double _err = NAN) : CObjDbl(_val), err(_err) {} - // PObj clone() const { return PObjEnu( new CObjEnu( *this ) ); } inline bool has_err() const { return true; } inline char base_type() const { return 'e'; } string result_info() const; @@ -106,6 +104,7 @@ public: inline double to_dr(int i) const { return err; } string to_s(int maxlen = 12, int minlen = 1, int prec = 6) const; bool to_b() const { return val; } + RObjVecNum to_vec(int repetitions) const final; }; //! Data container holding a string. @@ -115,7 +114,6 @@ class CObjStr : public CObj public: string val; CObjStr(string _val) : CObj(), val(_val) {} - // PObj clone() const { return PObjStr( new CObjStr( *this ) ); } bool is_vec() const { return false; } bool has_err() const { return false; } char base_type() const { return 's'; } @@ -150,6 +148,7 @@ public: inline string result_info() const { return to_s(); } inline RObj to_obj(int i) const { return v[i]; } string to_s(int maxlen = 12, int minlen = 1, int prec = 6) const; + vector<double> to_rvec() const; RObj to_vecnum() const; }; @@ -169,10 +168,9 @@ class CObjVecInt : public CObjVecNum { public: vector<int> v; //!< The data. - CObjVecInt(int n = 0) : CObjVecNum(), v(n, -1) {} + CObjVecInt(int n=0, int val=0) : CObjVecNum(), v(n, val) {} CObjVecInt(const vector<int>& _v) : CObjVecNum(), v(_v) {} inline int size() const { return v.size(); } - // PObj clone() const { return PObjVecInt( new CObjVecInt( *this ) ); } bool has_err() const { return false; } char base_type() const { return 'i'; } string result_info() const; @@ -191,7 +189,6 @@ public: CObjVecDbl(int n = 0, double val = NAN) : CObjVecNum(), v(n, val) {} CObjVecDbl(const vector<double>& _v) : CObjVecNum(), v(_v) {} inline int size() const { return v.size(); } - // PObj clone() const { return PObjVecDbl( new CObjVecDbl( *this ) ); } bool has_err() const { return false; } char base_type() const { return 'd'; } string result_info() const; @@ -209,7 +206,6 @@ public: CObjVecEnu(int n = 0) : CObjVecDbl(n), dv(n, NAN) {} CObjVecEnu(const vector<double>& _v, const vector<double>& _dv) : CObjVecDbl(_v), dv(_dv) {} inline int size() const { return v.size(); } - // PObj clone() const { return PObjVecEnu( new CObjVecEnu( *this ) ); } bool has_err() const { return true; } char base_type() const { return 'e'; } string result_info() const; diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp index 23008a1d8dfe6e8472869dd6d5aa16966c785a72..1a2c7a0a64a28ddbd3c450d5b897a9c3fb1ff453 100644 --- a/pub/lib/olf.cpp +++ b/pub/lib/olf.cpp @@ -102,6 +102,14 @@ void COlo::check_integrity() const RObj COlo::z(int j, int iz) const { return V[j]->z[iz]; } +//! Return vector of iz-th z-variables. + +RObjVecObj COlo::zvec(int iz) const { + PObjVecObj ret(new CObjVecObj(nJ())); + for (size_t j=0; j<nJ(); ++j) + ret->v[j] = V[j]->z[iz]; + return ret; +} //************************************************************************************************** //* COld/COlc (member functions that are similar for both classes) @@ -127,8 +135,8 @@ void COlc::copy_meta_C_from_other(const COlc* other) kd = other->kd; weighing = other->weighing; plot_to_grid = other->plot_to_grid; - range_expr = other->range_expr; - range_T = other->range_T; + prange_expr = other->prange_expr; + prange_T = other->prange_T; chi2 = other->chi2; } @@ -375,11 +383,13 @@ int COld::nPts() const //! Returns true if all data points have nonzero dy. -bool COld::has_nonzero_dy() const +bool COld::dy_are_all_nonzero() const { - return std::all_of(V.cbegin(), V.cend(), [](const PSlice& s) { - return dynamic_cast<const CSpec*>(s.get())->has_nonzero_dy(); - }); + for (int j = 0; j < nJ(); ++j) { + if (!VS(j)->dy_are_all_nonzero()) + return false; + } + return true; } //************************************************************************************************** @@ -637,14 +647,35 @@ RObjVec COlc::eval_curve(const vector<double>& vt, int k, int j, bool want_error RObj COlc::eval_curve_scalar(double arg, int k, int j, bool want_error) const { - vector<double> vt(1, arg); - RObjVec cu = eval_curve(vt, k, j, want_error); + RObjVec cu = eval_curve({arg}, k, j, want_error); if (cu->size() != 1) throw "BUG: vector has " + S(cu->size()) + " elements while exactly one was expected"; return cu->to_obj(0); } +//! Vectorial evaluation of a curve's prange given by an expression tree. + +RObjVecInt COlc::eval_prange(const vector<double>& vt, int k, int j) const +{ + if (!prange_T) + return RObjVecInt( new CObjVecInt(vt.size(), 1) ); + CContext ctx(k, j); + ctx.want_error = false; + RObj ret; + if (!prange_T->has_dummy()) { // curve does not depend on t + ret = prange_T->tree_val(ctx); + } else { + ctx.request_VT(&vt); + ret = prange_T->tree_val(ctx); + } + RObjVecInt ret2 = PCAST<const CObjVecInt>(ret); + if (!ret2) + throw S("BUG in eval_prange_expr: result is not an integer vector"); + return ret2; +} + + //************************************************************************************************** //* class COlc - inspect //************************************************************************************************** @@ -667,6 +698,8 @@ vector<string> COlc::info_settings() const txt += "conv file: " + S(kconv) + ", "; txt += "weighing: " + weight_str(); ret.push_back(txt); + if (prange_expr!="") + ret.push_back("plot range: " + prange_expr); if (chi2 > 0) ret.push_back("global fit result: " + S(chi2)); return ret; diff --git a/pub/lib/olf.hpp b/pub/lib/olf.hpp index e343cb38ed3a9ddf9a61dbd503c0ee88489a7cef..6fa957fba33e896ada1c9197aa4e8d0a55e94a66 100644 --- a/pub/lib/olf.hpp +++ b/pub/lib/olf.hpp @@ -47,6 +47,7 @@ public: int nJ() const { return V.size(); } int nZ() const { return ZCo.size(); } RObj z(int j, int iz) const; + RObjVecObj zvec(int iz) const; virtual PSlice copy_slice(int j) const = 0; virtual POlo new_POlo() const = 0; virtual CCoord coord(const CGenus& genus) const = 0; @@ -80,7 +81,7 @@ public: int nPts(int j) const; int nPts() const; // 0 unless all spectra j have same nPts(j) - bool has_nonzero_dy() const; + bool dy_are_all_nonzero() const; virtual string type() const { return "data"; } }; @@ -118,8 +119,8 @@ public: static string wgtNames[]; static TWgt name2wgt(string name); bool plot_to_grid; ///< Use grid from file 'kd' ? - string range_expr; ///< Restricts points to be fitted. - RNode range_T; ///< Parsed range_expr. + string prange_expr; ///< Restricts points to be plotted. + RNode prange_T; ///< Parsed range_expr. double chi2; ///< Global chi^2 COlc() @@ -130,7 +131,7 @@ public: , kd(-1) , weighing(_VAR) , plot_to_grid(false) - , range_expr("") + , prange_expr("") , chi2(0) { } @@ -161,6 +162,7 @@ public: void curve_query(const string& quest); RObjVec eval_curve(const vector<double>& vt, int k, int j, bool want_error) const; RObj eval_curve_scalar(double arg, int k, int j, bool want_error) const; + RObjVecInt eval_prange(const vector<double>& vt, int k, int j) const; virtual string type() const { return "curve"; } }; diff --git a/pub/lib/opr.cpp b/pub/lib/opr.cpp index fabae83fd1dc0b20fac1f8f96b753579715bf4ff..0b325e7c0f530b079dd0588388151e1b2557fc3e 100644 --- a/pub/lib/opr.cpp +++ b/pub/lib/opr.cpp @@ -283,9 +283,9 @@ void NOperate::Integral() else fout = POld((dynamic_cast<const COld*>(fin))->new_POld()); fout->log_action("oi " + expr); - fout->ZCo.pop_back(); fout->xco = fin->ZCo.back(); fout->yco = T->node_coord(k); + fout->ZCo.pop_back(); sout = PSpec(new CSpec); sout->z = fin->V[0]->z; sout->z.pop_back(); @@ -300,14 +300,14 @@ void NOperate::Integral() cout << "result: " << res->to_s() << "\n"; continue; } - xval = fin->V[j]->z[nz - 1]->to_r(); + xval = fin->V[j]->z[nz-1]->to_r(); sout->push_xyd(xval, res->to_r(), res->to_dr()); - if (nz >= 2) { // new spectrum if jump in other z values - double zval = fin->V[j]->z[nz - 2]->to_r(); - if (j + 1 < fin->nJ() && fin->V[j + 1]->z[nz - 2]->to_r() != zval) { + if (nz > 1) { // new spectrum if jump in other z values + if (j+1 < fin->nJ() + && fin->V[j+1]->z[nz-2]->to_r() != fin->V[j]->z[nz-2]->to_r()) { fout->V.push_back(move(sout)); sout = PSpec(new CSpec); - sout->z = fin->V[j + 1]->z; + sout->z = fin->V[j+1]->z; sout->z.pop_back(); } } @@ -350,8 +350,6 @@ void NOperate::IntXY(string mode) if (icold < 0) return; } - xco = CCoord("x", ""); - yco = CCoord("y", ""); while (const COld* fin = fiter.nextD()) { int nz = fin->ZCo.size(); @@ -362,10 +360,15 @@ void NOperate::IntXY(string mode) lin += " " + S(icold); fout->log_action(lin); - fout->xco = xco; - fout->yco = yco; + fout->xco = CCoord("x", ""); + fout->yco = CCoord("y", ""); + if (nz) + fout->ZCo.pop_back(); PSpec sout(new CSpec); + sout->z = fin->V[0]->z; + if (nz) + sout->z.pop_back(); for (int j = 0; j < fin->nJ(); j++) { int n = fin->nPts(j); @@ -376,11 +379,14 @@ void NOperate::IntXY(string mode) else sout->push_xy(fin->VS(j)->y[icolx], fin->VS(j)->y[icoly]); sout->z = fin->VS(j)->z; - if (nz > 2) { // new spectrum if jump in other z value - if (j + 1 < fin->nJ() - && fin->V[j + 1]->z[nz - 2]->to_r() != fin->V[j]->z[nz - 2]->to_r()) { + if (nz > 1) { // new spectrum if jump in other z value + if (j+1 < fin->nJ() + && fin->V[j+1]->z[nz-2]->to_r() != fin->V[j]->z[nz-2]->to_r()) { fout->V.push_back(move(sout)); sout = PSpec(new CSpec); + sout->z = fin->V[j+1]->z; + if (nz) + sout->z.pop_back(); } } } @@ -389,7 +395,6 @@ void NOperate::IntXY(string mode) } } - //************************************************************************************************** //* functional operations //************************************************************************************************** diff --git a/pub/lib/plot.cpp b/pub/lib/plot.cpp index 098bca7a635d9ecefd2d9d18d08cc4c4dc64f2e8..bbd42fe7065af275e01736b45f50ca2792c70214 100644 --- a/pub/lib/plot.cpp +++ b/pub/lib/plot.cpp @@ -7,502 +7,608 @@ //! \file plot.cpp //! \brief NPlot: plot data and curves. -#include "defs.hpp" +#include <cmath> +#include <algorithm> +#include <boost/format.hpp> +#include "defs.hpp" -#include "../plot/dualplot.hpp" #include "../trivia/vector_ops.hpp" +#include "../trivia/file_ops.hpp" // TODO rm file creation from plot2D +#include "../plot/dualplot.hpp" +#include "config.hpp" #include "curve.hpp" #include "fsel.hpp" #include "jsel.hpp" #include "loop.hpp" +#include "expr.hpp" #include "mem.hpp" #include "obj.hpp" #include "olf.hpp" #include "plot.hpp" #include "slice.hpp" +#include "variables.hpp" +using boost::format; + +namespace { + void determine_Xrange(CPlot* plot, vector<int>& JSel); + void determine_Yrange(CPlot* plot, vector<int>& JSel); + int plot_data(CPlot* plot, const COld* fd, int k, int j, int pstyle); + int plot_curve_convolved(CPlot* plot, const COlc* fc, int k, int j, int cstyle); + int plot_curve_to_grid(CPlot* plot, const COlc* fc, int k, int j, int cstyle); + int plot_curve_equidist(CPlot* plot, const COlc* fc, int k, int j, int cstyle); + int plot_curve_refine(CPlot* plot, const COlc* fc, int k, int j, int cstyle); + void plot1D(class CPlot* plot, bool add, const string& mode); + void plot2D(class CPlot* plot); //************************************************************************************************** //* Subroutines: determine data ranges //************************************************************************************************** - //! Loop over selected data files to determine x range. -void determine_Xrange(CPlot* plot, vector<int>& JSel) -{ - double inf, sup; - FileIterator fiter(SFSel::instance()->selD()); - const vector<double>* vx; - bool first = true; - while (const COld* fd = fiter.nextD()) { - // JSel->evaluate( 0, fd->nJ()-1 ); - for (int iv = 0; iv < JSel.size(); ++iv) { - vx = &(fd->VS(JSel[iv])->x); - for (int i = 0; i < vx->size(); ++i) { - if (plot->X.logflag && (*vx)[i] <= 0) - continue; - if (first) { - inf = (*vx)[i]; - sup = (*vx)[i]; - first = false; - } else { - if ((*vx)[i] < inf) + void determine_Xrange(CPlot* plot, vector<int>& JSel) + { + double inf, sup; + FileIterator fiter(SFSel::instance()->selD()); + const vector<double>* vx; + bool first = true; + while (const COld* fd = fiter.nextD()) { + // JSel->evaluate( 0, fd->nJ()-1 ); + for (int iv = 0; iv < JSel.size(); ++iv) { + vx = &(fd->VS(JSel[iv])->x); + for (int i = 0; i < vx->size(); ++i) { + if (plot->X.logflag && (*vx)[i] <= 0) + continue; + if (first) { inf = (*vx)[i]; - if ((*vx)[i] > sup) sup = (*vx)[i]; + first = false; + } else { + if ((*vx)[i] < inf) + inf = (*vx)[i]; + if ((*vx)[i] > sup) + sup = (*vx)[i]; + } } } } + if (first) + throw S("x range is empty"); + plot->X.set_rounded_limits(inf, sup); } - if (first) - throw S("x range is empty"); - plot->X.set_rounded_limits(inf, sup); -} //! Loop over selected files to determine y range for current x range. -void determine_Yrange(CPlot* plot, vector<int>& JSel) -{ - double inf = INFINITY, sup = -INFINITY; - FileIterator fiter(SFSel::instance()->sel()); - while (const COlo* f = fiter.next()) { - int k = fiter.k(); - const COlc* fc = dynamic_cast<const COlc*>(f); - if (fc && fc->kconv != -1) - continue; - const COld* fd = dynamic_cast<const COld*>(f); - // JSel->evaluate( 0, f->nJ()-1 ); - for (int iv = 0; iv < JSel.size(); ++iv) { - int j = JSel[iv]; - CSpec* s; - if (fd) { - s = fd->VS(j); - } else { - PSpec tmp(new CSpec); - s = tmp.get(); - plot->X.set_xgrid(s->x, 97); - RObjVec cu = fc->eval_curve(s->x, k, j, false); - s->y.resize(s->x.size()); - for (int i = 0; i < s->size(); ++i) - s->y[i] = cu->to_r(i); - } - for (int i = 0; i < s->size(); i++) { - if (!plot->X.contains(s->x[i])) - continue; - if (plot->Y.logflag && s->y[i] <= 0) - continue; - if (s->y[i] < inf) - inf = s->y[i]; - if (s->y[i] > sup) - sup = s->y[i]; + void determine_Yrange(CPlot* plot, vector<int>& JSel) + { + double inf = INFINITY, sup = -INFINITY; + FileIterator fiter(SFSel::instance()->sel()); + while (const COlo* f = fiter.next()) { + int k = fiter.k(); + const COlc* fc = dynamic_cast<const COlc*>(f); + if (fc && fc->kconv != -1) + continue; + const COld* fd = dynamic_cast<const COld*>(f); + // JSel->evaluate( 0, f->nJ()-1 ); + for (int iv = 0; iv < JSel.size(); ++iv) { + int j = JSel[iv]; + CSpec* s; + if (fd) { + s = fd->VS(j); + } else { + PSpec tmp(new CSpec); + s = tmp.get(); + plot->X.set_xgrid(s->x, 97); + RObjVec cu = fc->eval_curve(s->x, k, j, false); + s->y.resize(s->x.size()); + for (int i = 0; i < s->size(); ++i) + s->y[i] = cu->to_r(i); + } + for (int i = 0; i < s->size(); i++) { + if (!plot->X.contains(s->x[i])) + continue; + if (plot->Y.logflag && s->y[i] <= 0) + continue; + if (s->y[i] < inf) + inf = s->y[i]; + if (s->y[i] > sup) + sup = s->y[i]; + } } } + if (inf == INFINITY || sup == -INFINITY) + throw S("y range is empty"); + plot->Y.set_rounded_limits(inf, sup); } - if (inf == INFINITY || sup == -INFINITY) - throw S("y range is empty"); - plot->Y.set_rounded_limits(inf, sup); -} //************************************************************************************************** //* Subroutines: plot one scan //************************************************************************************************** - -//! Plot scan j of data file fd; return number of points plotted. - -int plot_data(CPlot* plot, const COld* fd, int k, int j, int pstyle) -{ - const CSpec* s = fd->VS(j); - int n = s->x.size(); - if (n != s->y.size()) - throw S("BUG: plot: x.size<>y.size"); - // Filter: x,y -> xp,yp if inside frame - int np = 0, nxl = 0, nxh = 0, nyl = 0, nyh = 0; - vector<double> xp, yp, dyp; - for (int i = 0; i < n; i++) { - double x = s->x[i]; - if (!plot->X.contains(x)) { - if (x <= plot->X.inf) { - x = plot->X.inf; - nxl++; +//! Plot slice j of data file fd; return number of points plotted. + + int plot_data(CPlot* plot, const COld* fd, int k, int j, int pstyle) + { + const CSpec* s = fd->VS(j); + int n = s->x.size(); + if (n != s->y.size()) + throw S("BUG: plot: x.size<>y.size"); + // Filter: x,y -> xp,yp if inside frame + int np = 0, nxl = 0, nxh = 0, nyl = 0, nyh = 0; + vector<double> xp, yp, dyp; + for (int i = 0; i < n; i++) { + double x = s->x[i]; + if (!plot->X.contains(x)) { + if (x <= plot->X.inf) { + x = plot->X.inf; + nxl++; + } + if (x >= plot->X.sup) { + x = plot->X.sup; + nxh++; + } + if (!plot->X.force) + continue; } - if (x >= plot->X.sup) { - x = plot->X.sup; - nxh++; + double y = s->y[i]; + if (!plot->Y.contains(y)) { + if (y <= plot->Y.inf) { + y = plot->Y.inf; + nyl++; + } + if (y >= plot->Y.sup) { + y = plot->Y.sup; + nyh++; + } + if (!plot->Y.force) + continue; } - if (!plot->X.force) - continue; + if (np == plot->maxpoints && np < n) + cout << "reached maxpoints at " << s->x[i] << "\n"; + xp.push_back(x); + yp.push_back(y); + if (s->has_dy()) + dyp.push_back(s->dy[i]); + np = xp.size(); + if (np > plot->maxpoints) // continue in large steps + i += plot->maxpoints; } - double y = s->y[i]; - if (!plot->Y.contains(y)) { - if (y <= plot->Y.inf) { - y = plot->Y.inf; - nyl++; - } - if (y >= plot->Y.sup) { - y = plot->Y.sup; - nyh++; - } - if (!plot->Y.force) - continue; + if (np == 0) { + cout << "file " << k << " spec " << j << " all " << n << " points outside plot range:\n"; + if (nxl) + cout << " " << nxl << " points < xmin\n"; + if (nxh) + cout << " " << nxh << " points > xmax\n"; + if (nyl) + cout << " " << nyl << " points < ymin\n"; + if (nyh) + cout << " " << nyh << " points > ymax\n"; + } else { + plot->add_spec( + false, true, pstyle, xp, yp, dyp, fd->V[j]->z_str(), fd->xco.str_std(), + fd->yco.str_std(), "data file " + S(k) + " spectrum " + S(j)); } - if (np == plot->maxpoints && np < n) - cout << "reached maxpoints at " << s->x[i] << "\n"; - xp.push_back(x); - yp.push_back(y); - if (s->has_dy()) - dyp.push_back(s->dy[i]); - np = xp.size(); - if (np > plot->maxpoints) // continue in large steps - i += plot->maxpoints; + return np; } - if (np == 0) { - cout << "file " << k << " spec " << j << " all " << n << " points outside plot range:\n"; - if (nxl) - cout << " " << nxl << " points < xmin\n"; - if (nxh) - cout << " " << nxh << " points > xmax\n"; - if (nyl) - cout << " " << nyl << " points < ymin\n"; - if (nyh) - cout << " " << nyh << " points > ymax\n"; - } else { - plot->add_spec( - false, true, pstyle, xp, yp, dyp, fd->V[j]->z_str(), fd->xco.str_std(), - fd->yco.str_std(), "data file " + S(k) + " spectrum " + S(j)); - } - return np; -} -//! Plot scan j of convolved curve file fc; return number of points plotted. +//! Plot slice j of convolved curve file fc; return number of points plotted. -int plot_curve_convolved(CPlot* plot, const COlc* fc, int k, int j, int cstyle) -{ - vector<double> novec; - int kconv, jconv; - const CSpec* sconv; - NCurveFile::get_conv(&sconv, &kconv, &jconv, k, j); - vector<double> xp; - for (int i = 0; i < sconv->size(); ++i) { - double x = sconv->x[i]; - if (plot->X.contains(x)) - xp.push_back(x); - } - RObjVec cu = fc->eval_curve(xp, k, j, false); - vector<double> xo, yo; - for (int i = 0; i < xp.size(); ++i) { - double yp = cu->to_r(i); - if (!(plot->X.contains(xp[i]) && plot->Y.contains(yp))) - continue; - xo.push_back(xp[i]); - yo.push_back(yp); - } - if (xo.size() == 0) { - cout << "curve k=" << S(k) << ", j=" << S(j) << " has no points in plot window\n"; + int plot_curve_convolved(CPlot* plot, const COlc* fc, int k, int j, int cstyle) + { + vector<double> novec; + int kconv, jconv; + const CSpec* sconv; + NCurveFile::get_conv(&sconv, &kconv, &jconv, k, j); + vector<double> xp; + for (int i = 0; i < sconv->size(); ++i) { + double x = sconv->x[i]; + if (plot->X.contains(x)) + xp.push_back(x); + } + RObjVec cu = fc->eval_curve(xp, k, j, false); + vector<double> xo, yo; + for (int i = 0; i < xp.size(); ++i) { + double yp = cu->to_r(i); + if (!(plot->X.contains(xp[i]) && plot->Y.contains(yp))) + continue; + xo.push_back(xp[i]); + yo.push_back(yp); + } + if (xo.size() == 0) { + cout << "curve k=" << S(k) << ", j=" << S(j) << " has no points in plot window\n"; + } + plot->add_spec( + true, true, cstyle, xo, yo, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), + "curve file " + S(k) + " spectrum " + S(j)); + return xo.size(); } - plot->add_spec( - true, true, cstyle, xo, yo, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), - "curve file " + S(k) + " spectrum " + S(j)); - return xo.size(); -} -//! Plot scan j of curve file fc, using grid from file kd. - -int plot_curve_to_grid(CPlot* plot, const COlc* fc, int k, int j, int cstyle) -{ - if (fc->kd == -1) - throw S("data reference not set, incompatible with cg+"); - const COld* fd = SMem::instance()->mem_get_D(fc->kd); - if (!fd) - throw S("data reference not found"); - if (j >= fd->nJ()) - throw S("number of spectra does not match"); - vector<double>* xc = &(fd->VS(j)->x); - vector<double> novec, xp, yp; - RObjVec cu = fc->eval_curve(*xc, k, j, false); - for (int i = 0; i < xc->size(); ++i) { - double yc = cu->to_r(i); - if (plot->X.contains((*xc)[i]) && plot->Y.contains(yc)) { - xp.push_back((*xc)[i]); - yp.push_back(yc); +//! Plot slice j of curve file fc, using grid from file kd. + + int plot_curve_to_grid(CPlot* plot, const COlc* fc, int k, int j, int cstyle) + { + if (fc->kd == -1) + throw S("data reference not set, incompatible with cg+"); + const COld* fd = SMem::instance()->mem_get_D(fc->kd); + if (!fd) + throw S("data reference not found"); + if (j >= fd->nJ()) + throw S("number of spectra does not match"); + vector<double>* xc = &(fd->VS(j)->x); + vector<double> novec, xp, yp; + RObjVec cu = fc->eval_curve(*xc, k, j, false); + for (int i = 0; i < xc->size(); ++i) { + double yc = cu->to_r(i); + if (plot->X.contains((*xc)[i]) && plot->Y.contains(yc)) { + xp.push_back((*xc)[i]); + yp.push_back(yc); + } } + plot->add_spec( + true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), + "curve file " + S(k) + " spectrum " + S(j)); + return xp.size(); } - plot->add_spec( - true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), - "curve file " + S(k) + " spectrum " + S(j)); - return xp.size(); -} -//! Plot scan j of non-convolved curve file fc on equidistant grid; return number of points plotted. +//! Plot slice j of non-convolved curve file fc on equidistant grid; return number of points plotted. -int plot_curve_equidist(CPlot* plot, const COlc* fc, int k, int j, int cstyle) -{ - vector<double> novec; - // equidistant grid - - int npts = plot->equipoints; - vector<double> xc, xp, yp; - plot->X.set_xgrid(xc, npts); - RObjVec cu = fc->eval_curve(xc, k, j, false); - for (int i = 0; i < npts; ++i) { - double yc = cu->to_r(i); - if (plot->X.contains(xc[i]) && plot->Y.contains(yc)) { - xp.push_back(xc[i]); - yp.push_back(yc); + int plot_curve_equidist(CPlot* plot, const COlc* fc, int k, int j, int cstyle) + { + vector<double> novec; + // equidistant grid + + int npts = plot->equipoints; + vector<double> xc, xp, yp; + plot->X.set_xgrid(xc, npts); + RObjVec cu = fc->eval_curve(xc, k, j, false); + for (int i = 0; i < npts; ++i) { + double yc = cu->to_r(i); + if (plot->X.contains(xc[i]) && plot->Y.contains(yc)) { + xp.push_back(xc[i]); + yp.push_back(yc); + } } + plot->add_spec( + true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), + "curve file " + S(k) + " spectrum " + S(j)); + return xp.size(); } - plot->add_spec( - true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(), fc->xco.str_std(), fc->yco.str_std(), - "curve file " + S(k) + " spectrum " + S(j)); - return xp.size(); -} - -//! Plots scan j of non-convolved curve file fc, refining the grid where necessary; return number of -//! points plotted. -int plot_curve_refine(CPlot* plot, const COlc* fc, int k, int j, int cstyle) -{ - // refinement cares to: - // - stop/start line when leaving/reentering/crossing(TODO) the frame - // - TODO interpolate when crossing the horizontal border - // - interpolate at discontinuities - - vector<double> xc, yc, xn, yn; - vector<double> novec; - - // start with equidistant grid: - int npts = plot->equipoints; - plot->X.set_xgrid(xc, npts); - - // refinement loop: - for (int iref = 0;; ++iref) { - if (!xc.size()) { - if (!iref) - throw S("BUG: plot_curve_refine called with xc.size()=0"); - break; // regular exit - } - // evaluate curve for grid xc: - RObjVecDbl cu = PCAST<const CObjVecDbl>(fc->eval_curve(xc, k, j, false)); - for (int i = 0; i < xc.size(); ++i) - yc = cu->v; - - // merge xc,yc and xn,yn: - if (iref == 0) { - xn = xc; - yn = yc; - } else { - vector<double> xa, ya; - int ic = 0, in = 0; - for (; ic < xc.size() && in < xn.size();) { - if (plot->X.close_enough(xc[ic], xn[ic], 1e-7)) { - ++in; // skip new point - } else if (xc[ic] < xn[in]) { - xa.push_back(xc[ic]); - ya.push_back(yc[ic]); - ++ic; - } else { - xa.push_back(xn[in]); - ya.push_back(yn[in]); - ++in; +//! Plots slice j of non-convolved curve file fc, refining the grid where necessary; +//! return number of points plotted. + + int plot_curve_refine(CPlot* plot, const COlc* fc, int k, int j, int cstyle) + { + class CP2 { + public: + double x; + double y; + CP2 operator-(const CP2 other) { + return { x-other.x, y-other.y }; }; + double operator*(const CP2 other) { + return x*other.x + y*other.y; }; + }; + + class CPt { + public: + double xd; // data point + double yd; + int code; // -1=nan 0=valid, 1=below, 2=above, 3=off_range + CP2 P; // plot point + }; + + auto x2p = [&](const vector<double>& x) -> vector<CPt> + { + vector<double> y = PCAST<const CObjVecDbl>(fc->eval_curve(x, k, j, false))->v; + vector<int> inRange = fc->eval_prange(x, k, j)->v; + vector<CPt> ret(x.size()); + for (size_t i=0; i<x.size(); ++i) { + double xp = plot->X.pc(x[i]); + if (std::isnan(y[i])) + ret[i] = {x[i], y[i], 1, {xp, NAN}}; + else if (y[i]<plot->Y.inf) + ret[i] = {x[i], y[i], 1, {xp, NAN}}; + else if (y[i]>plot->Y.sup) + ret[i] = {x[i], y[i], 2, {xp, NAN}}; + else if (!inRange[i]) + ret[i] = {x[i], y[i], 3, {xp, NAN}}; + else + ret[i] = {x[i], y[i], 0, {xp, plot->Y.pc(y[i])}}; } - } - for (; ic < xc.size(); ++ic) { - xa.push_back(xc[ic]); - ya.push_back(yc[ic]); - } - for (; in < xn.size(); ++in) { - xa.push_back(xn[in]); - ya.push_back(yn[in]); - } - xn = xa; - yn = ya; - } - if (iref >= 10 || xn.size() >= plot->maxpoints) - break; // alternate exit: too many refinements or too many points - - // eliminate points outside y range (except border points): - vector<double> xa, ya; - xa.push_back(xn[0]); - ya.push_back(yn[0]); - for (int i = 1; i < xn.size() - 1; ++i) { - new_segment: - xa.push_back(xn[i]); - ya.push_back(yn[i]); - if (!plot->Y.contains(yn[i])) { - for (int ii = i + 1; ii < xn.size() - 1; ++ii) { - if (plot->Y.contains(yn[ii])) { - if (ii - 1 > i) { - xa.push_back(xn[ii - 1]); - ya.push_back(yn[ii - 1]); + return ret; + }; + + auto pt_order = [](const CPt a, const CPt b) -> bool + { return a.xd<=b.xd; }; + + auto nonlinearity = [](const vector<CPt>::iterator b) -> double + { + auto a = b-1; + auto c = b+1; + CP2 BA = a->P-b->P; + CP2 AC = c->P-a->P; + // squared deviation from linearity: + return BA*BA - pow(BA*AC,2)/(AC*AC); + }; + + // start with equidistant grid: + vector<double> xn; + plot->X.set_xgrid(xn, plot->equipoints); + + // refinement loop: + vector<CPt> pp; + for (int iref=0; iref<49 && pp.size() < plot->maxpoints; ++iref) { + vector<CPt> pn = x2p(xn); + pp = triv::merge_sorted(pp, pn, pt_order); + xn.clear(); + + for (auto b = pp.begin()+1; b<pp.end(); ++b) { + auto a = b-1; + if (a->code!=0 || b->code!=0) { + if (a->code!=b->code) { + xn.push_back( (b->xd + a->xd)/2 ); + } + } else { // valid data + auto c = b+1; + if (c<pp.end() && c->code==0) { + // squared deviation from linearity: + if ( nonlinearity(b) > 1e-8 ) { + double dx = std::min(b->xd - a->xd, c->xd - b->xd)/2; + xn.push_back( b->xd - dx ); + xn.push_back( b->xd + dx ); } - i = ii; - goto new_segment; } } } + if (!xn.size()) + break; + xn = std::vector<double>( xn.begin(), std::unique(xn.begin(), xn.end()) ); } - xa.push_back(xn.back()); - ya.push_back(yn.back()); - xn = xa; - yn = ya; - - // set additional base points: - bool insert_next = false; - xc.clear(); - for (int i = 1; i < xn.size() - 1; ++i) { - if (i < xn.size() - 2) { - double yi = ((xn[i + 1] - xn[i]) * yn[i - 1] + (xn[i] - xn[i - 1]) * yn[i + 1]) - / (xn[i + 1] - xn[i - 1]); - if (!plot->Y.close_enough(yn[i], yi, 0.005)) { - xc.push_back((xn[i - 1] + xn[i]) / 2); - insert_next = true; - continue; - } - } - if (insert_next) { - xc.push_back((xn[i - 1] + xn[i]) / 2); - insert_next = false; - continue; - } - if ((plot->Y.contains(yn[i]) && !plot->Y.contains(yn[i - 1])) - || (!plot->Y.contains(yn[i]) && plot->Y.contains(yn[i - 1]))) { - xc.push_back((xn[i - 1] + xn[i]) / 2); - continue; + + // remove points in straight lines + vector<CPt> po; + size_t nout = 0; + for (int iref=0; iref<49; ++iref) { + po.clear(); + po.push_back( *pp.begin() ); + bool even = false; + for (auto b = pp.begin()+1; b<pp.end()-1; ++b) { + if (even || b->code!=(b-1)->code!=0 || b->code!=(b+1)->code!=0 + || b->code==0 && nonlinearity(b)>1e-9) + po.push_back(*b); + even = !even; } + po.push_back( *(pp.end()-1) ); + if (po.size()==nout) + break; + nout = po.size(); + pp = po; } - // temporary check - if (xc.size()) - for (int i = 0; i < xc.size() - 1; ++i) - if (xc[i + 1] <= xc[i]) - throw "BUG: new base points not sorted at " + S(i) + ": " + S(xc[i]) + " " - + S(xc[i + 1]); - } - // divide into segments and plot: - vector<double> xa, ya; - bool first_seg = true; - npts = 0; - for (int i = 0; i < xn.size(); ++i) { - if (plot->Y.contains(yn[i])) { - xa.push_back(xn[i]); - ya.push_back(yn[i]); + // divide into segments + vector<vector<CPt>> segments; + vector<CPt> seg; + for (CPt p: po) { + if (p.code==0) + seg.push_back(p); + else if (seg.size()) { + segments.push_back(seg); + seg.clear(); + } } - if (!plot->Y.contains(yn[i]) || i == xn.size() - 1) { - npts += xa.size(); - if (xa.size()) { - plot->add_spec( - true, first_seg, cstyle, xa, ya, novec, fc->V[j]->z_str(), fc->xco.str_std(), - fc->yco.str_std(), "curve file " + S(k) + " spectrum " + S(j)); - xa.clear(); - ya.clear(); - first_seg = false; + if (seg.size()) + segments.push_back(seg); + + // plot segments + size_t npts = 0; + for (size_t is=0; is<segments.size(); ++is) { + vector<double> xf, yf; + for (CPt p: segments[is]) { + xf.push_back(p.xd); + yf.push_back(p.yd); } + plot->add_spec( + true, is==0, cstyle, xf, yf, vector<double>(), fc->V[j]->z_str(), fc->xco.str_std(), + fc->yco.str_std(), "curve file " + S(k) + " spectrum " + S(j)); + npts += segments[is].size(); } - } - return npts; -} + return npts; + } //************************************************************************************************** -//* Plot routine is accessible from the main menu +//* plot1D //************************************************************************************************** -//! Plot set of spectra, or add to open plot. + //! Plot set of spectra, or add to open plot. -void NPlot::plot(class CPlot* plot, bool add, const string& mode) -{ - FileIterator fiter(SFSel::instance()->sel()); + void plot1D(class CPlot* plot, bool add, const string& mode) + { + FileIterator fiter(SFSel::instance()->sel()); - static vector<int> JSel; - static int pstyle = 1, cstyle = 1; - static string jSel = ""; + static vector<int> JSel; + static int pstyle = 1, cstyle = 1; + static string jSel = ""; + if (mode == "ask") { + JSelAsk("Plot which spectra", JSel); + } else { + if (mode == "next") { + triv::increment_indices(JSel, +1, SFSel::instance()->nJ_max()); + } else if (mode == "prev") { + triv::increment_indices(JSel, -1, SFSel::instance()->nJ_max()); + } else + throw "unexpected mode " + mode; + if (!JSel.size()) + throw S("no spectra in range"); + cout << "plotting spectra " << triv::indices_to_s(JSel) << "\n"; + } - if (mode == "ask") { - JSelAsk("Plot which spectra", JSel); - } else { - if (mode == "next") { - triv::increment_indices(JSel, +1, SFSel::instance()->nJ_max()); - } else if (mode == "prev") { - triv::increment_indices(JSel, -1, SFSel::instance()->nJ_max()); - } else - throw "unexpected mode " + mode; - if (!JSel.size()) - throw S("no spectra in range"); - cout << "plotting spectra " << triv::indices_to_s(JSel) << "\n"; - } + if (!add) { // prepare frame (ranges, labels) + pstyle = 1; + cstyle = 1; + if (!plot->X.finite()) + determine_Xrange(plot, JSel); + if (!plot->Y.finite()) + determine_Yrange(plot, JSel); - if (!add) { // prepare frame (ranges, labels) - pstyle = 1; - cstyle = 1; - if (!plot->X.finite()) - determine_Xrange(plot, JSel); - if (!plot->Y.finite()) - determine_Yrange(plot, JSel); + // build label: (zur Zeit nur vom ersten File; definiere +=) + CCoord xCo = SFSel::instance()->sel_first()->xco; + CCoord yCo = SFSel::instance()->sel_first()->yco; - // build label: (zur Zeit nur vom ersten File; definiere +=) - CCoord xCo = SFSel::instance()->sel_first()->xco; - CCoord yCo = SFSel::instance()->sel_first()->yco; + // draw new frame: + plot->start_frame1D("Frida version " VERSION, xCo.str_ps(), yCo.str_ps()); + } else + plot->reopen_frame1D(); + + // plot: + while (const COlo* f = fiter.next()) { + int k = fiter.k(); + const COld* fd = dynamic_cast<const COld*>(f); + const COlc* fc = dynamic_cast<const COlc*>(f); + + plot->doc_TxLine(f->name); + for (int i = 0; i < f->lDoc.size(); i++) + plot->doc_TxLine(" " + f->lDoc[i]); + if (fc) { + for (string line : fc->info_settings()) + plot->doc_TxLine(" " + line); + plot->doc_TxLine(" " + fc->info_table_header()); + } - // draw new frame: - plot->clear_frame(); - plot->plot_frame(xCo.str_ps(), yCo.str_ps()); - } + // JSel.evaluate( 0, f->nJ()-1 ); + for (int iv = 0; iv < JSel.size(); ++iv) { + int j = JSel[iv]; - // plot: - while (const COlo* f = fiter.next()) { - int k = fiter.k(); - const COld* fd = dynamic_cast<const COld*>(f); - const COlc* fc = dynamic_cast<const COlc*>(f); - - plot->doc_TxLine(f->name); - for (int i = 0; i < f->lDoc.size(); i++) - plot->doc_TxLine(" " + f->lDoc[i]); - if (fc) { - for (string line : fc->info_settings()) - plot->doc_TxLine(" " + line); - plot->doc_TxLine(" " + fc->info_table_header()); + if (fd) { + if (!plot_data(plot, fd, k, j, pstyle)) + continue; + plot->doc_PtTxLine(" " + f->info_line(j), pstyle); + ++pstyle; + + } else if (fc) { + if (fc->kconv != -1) { + if (!plot_curve_convolved(plot, fc, k, j, cstyle)) + continue; + } else if (fc->plot_to_grid) { + if (!plot_curve_to_grid(plot, fc, k, j, cstyle)) + continue; + } else if (!plot->refine) { + if (!plot_curve_equidist(plot, fc, k, j, cstyle)) + continue; + } else { + if (!plot_curve_refine(plot, fc, k, j, cstyle)) + continue; + } + plot->doc_CvTxLine(" " + f->info_line(j), cstyle); + ++cstyle; + } + } } + plot->show_specs(); + } - // JSel.evaluate( 0, f->nJ()-1 ); - for (int iv = 0; iv < JSel.size(); ++iv) { - int j = JSel[iv]; +//************************************************************************************************** +//* plot2D +//************************************************************************************************** - if (fd) { - if (!plot_data(plot, fd, k, j, pstyle)) - continue; - } else if (fc) { - if (fc->kconv != -1) { - if (!plot_curve_convolved(plot, fc, k, j, cstyle)) - continue; - } else if (fc->plot_to_grid) { - if (!plot_curve_to_grid(plot, fc, k, j, cstyle)) - continue; - } else if (!plot->refine) { - if (!plot_curve_equidist(plot, fc, k, j, cstyle)) - continue; - } else { - if (!plot_curve_refine(plot, fc, k, j, cstyle)) - continue; + //! Plot all spectra as 2D color plot + + void plot2D(class CPlot* plot) + { // EMBEDDED DIALOG + const COld* fd = SFSel::instance()->theOneD(); + + size_t m = fd->nJ(); + if (m<2) + throw "2d plot requires at least 2 slices"; + // determine bin limits + vector<double> zval = fd->zvec(0)->to_rvec(); + vector<double> zlim = triv::histogram_limits(zval); + vector<double> xlim = triv::histogram_limits(fd->VS(0)->x); + double xinf = xlim.front(); + double xsup = xlim.back(); + double yinf, ysup; + if (plot->Y.logflag) + triv::getPosminMax(fd->VS(0)->y, yinf, ysup); + else + triv::getMinMax(fd->VS(0)->y, yinf, ysup); + for (size_t j=1; j<m; ++j) { + xlim = triv::histogram_limits(fd->VS(j)->x); + xinf = std::min(xinf, xlim.front()); + xsup = std::max(xsup, xlim.back()); + double yyinf, yysup; + if (plot->Y.logflag) + triv::getPosminMax(fd->VS(j)->y, yyinf, yysup); + else + triv::getMinMax(fd->VS(j)->y, yyinf, yysup); + yinf = std::min(yinf, yyinf); + ysup = std::max(ysup, yysup); + } + if (!plot->X.finite()) + plot->X.set_limits(xinf, xsup); + if (!plot->Z.finite()) + plot->Z.set_limits(zlim.front(), zlim.back()); + if (plot->Y.logflag && !(std::isfinite(yinf) && std::isfinite(ysup))) + throw "No nonzero y values"; + if (!plot->Y.finite()) + plot->Y.set_limits(yinf-1e-4*std::abs(yinf), ysup+1e-4*std::abs(ysup)); + // plot + plot->start_frame2D("Frida version " VERSION); + bool recent_empty_line = false; + for (size_t j=0; j<m; ++j) { + const CSpec* s = fd->VS(j); + vector<double> xlim = triv::histogram_limits(s->x); + for (size_t i=0; i<s->size(); ++i) { + if ( (plot->Y.force || plot->Y.contains(s->y[i])) + && plot->X.contains(xlim[i]) && plot->X.contains(xlim[i+1]) + && plot->Z.contains(zlim[j]) && plot->Z.contains(zlim[j+1])) { + plot->ps_line( + str(format("%13.7g wx %13.7g wx %13.7g wy %13.7g wy %13.7g wH t2d") + % xlim[i] % xlim[i+1] % zlim[j] % zlim[j+1] % s->y[i] ) ); + recent_empty_line = false; } - } else - throw S("PROGRAM ERROR plot: unexpected file type"); - - if (fd) { - plot->doc_PtTxLine(" " + f->info_line(j), pstyle); - ++pstyle; - } else if (fc) { - plot->doc_CvTxLine(" " + f->info_line(j), cstyle); - ++cstyle; + } + if (!recent_empty_line) { + plot->ps_line(""); + recent_empty_line = true; } } + plot->close_frame2D(fd->xco.str_ps(), fd->ZCo[0].str_ps(), fd->yco.str_ps()); + // doclines + plot->doc_TxLine(fd->name); + for (int i = 0; i < fd->lDoc.size(); i++) + plot->doc_TxLine(" " + fd->lDoc[i]); + // plot -> file + static string fname = "/tmp/P.ps"; + plot->write_postscript( + triv::wordexp_unique(fname), "overwrite", true, SVariRegistry::instance()->to_sMap()); + cout << "Plotted to " << fname << "\n"; + PObj pViewer = SVariRegistry::instance()->find("ps_viewer"); + if (pViewer) + system((pViewer->to_s()+" "+fname+"&").c_str()); } - plot->show_specs(); + +} // anonymous namespace + +//************************************************************************************************** +//* Main plot routine accessible from the main menu +//************************************************************************************************** + +void NPlot::plot(class CPlot* plot, bool add, const string& mode) +{ + if (plot->p2D) { + if (add) + throw "Cannot 'add' to 2D plot"; + if (mode=="next" || mode=="prev") + throw "Cannot scroll through 2D plot"; + ::plot2D(plot); + } else + ::plot1D(plot, add, mode); } diff --git a/pub/lib/plot.hpp b/pub/lib/plot.hpp index 74849502c1941638ed96ed1a053c4e9e0a6db13d..c83a9fc87689ff5b0398d23726a4e284e392728f 100644 --- a/pub/lib/plot.hpp +++ b/pub/lib/plot.hpp @@ -10,11 +10,11 @@ #ifndef PLOT_H #define PLOT_H - //! Plot data and curves. namespace NPlot { -void plot(class CPlot* plot, bool add, const string& mode = "ask"); + void plot(class CPlot* plot, bool add, const string& mode = "ask"); } + #endif // PLOT_H diff --git a/pub/lib/reduce_curv.cpp b/pub/lib/reduce_curv.cpp index 69fb19b9dad764d608d2bbb8cdcbf288257cbfcc..b0abd50ebc3623b60c491f98806396e59a3584b3 100644 --- a/pub/lib/reduce_curv.cpp +++ b/pub/lib/reduce_curv.cpp @@ -10,6 +10,7 @@ #include "defs.hpp" #include <boost/format.hpp> +#include <map> #include "../readplus/ask.hpp" #include "../trivia/integrate.hpp" @@ -114,8 +115,8 @@ void cvin_integrate(double* r, double* dr, const COlc* fc, int k, int j, const v namespace NCvin { // internals: -map<string, const CCvin*> hmap; // unsorted hash, for expression evaluation -vector<const CCvin*> hlist; // sorted array, for help text + std::map<string, const CCvin*> hmap; // unsorted hash, for expression evaluation + vector<const CCvin*> hlist; // sorted array, for help text } diff --git a/pub/lib/reduce_spec.cpp b/pub/lib/reduce_spec.cpp index aa43360860855fccad2f20cb7ca44c2793bde774..807d4b462042e94ea50347c9a69a098df8e2c26d 100644 --- a/pub/lib/reduce_spec.cpp +++ b/pub/lib/reduce_spec.cpp @@ -10,6 +10,7 @@ #include "defs.hpp" #include <boost/format.hpp> +#include <map> #include "../trivia/string_ops.hpp" @@ -26,39 +27,37 @@ using boost::format; //! Compute minimum value of a vector. -void geni_valmin(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_valmin(int n, const vector<RObjVecNum>& a) { - int idx = 0; - *r = a[0]->to_r(0); + double r = a[0]->to_r(0); + double dr = a[0]->to_dr(0); for (int i = 1; i < n; ++i) { - if (a[0]->to_r(i) < *r) { - *r = a[0]->to_r(i); - idx = i; + if (a[0]->to_r(i) < r) { + r = a[0]->to_r(i); + dr = a[0]->to_dr(i); } } - if (dr) - *dr = a[0]->to_dr(idx); + return RObjEnu(new CObjEnu(r,dr)); } //! Compute maximum value of a vector. -void geni_valmax(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_valmax(int n, const vector<RObjVecNum>& a) { - int idx = 0; - *r = a[0]->to_r(0); + double r = a[0]->to_r(0); + double dr = a[0]->to_dr(0); for (int i = 1; i < n; ++i) { - if (a[0]->to_r(i) > *r) { - *r = a[0]->to_r(i); - idx = i; + if (a[0]->to_r(i) > r) { + r = a[0]->to_r(i); + dr = a[0]->to_dr(i); } } - if (dr) - *dr = a[0]->to_dr(idx); + return RObjEnu(new CObjEnu(r,dr)); } //! Return x[i] with i for which y[i] is minimal. -void geni_argmin(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_argmin(int n, const vector<RObjVecNum>& a) { int idx = 0; double extr = a[1]->to_r(0); @@ -68,14 +67,12 @@ void geni_argmin(double* r, double* dr, int n, const vector<RObjVecNum>& a) idx = i; } } - *r = a[0]->to_r(idx); - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(a[0]->to_r(idx))); } //! Return x[i] with i for which y[i] is maximal. -void geni_argmax(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_argmax(int n, const vector<RObjVecNum>& a) { int idx = 0; double extr = a[1]->to_r(0); @@ -85,14 +82,12 @@ void geni_argmax(double* r, double* dr, int n, const vector<RObjVecNum>& a) idx = i; } } - *r = a[0]->to_r(idx); - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(a[0]->to_r(idx))); } //! Return i for which x[i] is minimal. -void geni_idxmin(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_idxmin(int n, const vector<RObjVecNum>& a) { int idx = 0; double extr = a[0]->to_r(0); @@ -102,14 +97,12 @@ void geni_idxmin(double* r, double* dr, int n, const vector<RObjVecNum>& a) idx = i; } } - *r = idx; - if (dr) - *dr = 0; // TODO better estimate + return RObjInt(new CObjInt(idx)); } //! Return i for which x[i] is maximal. -void geni_idxmax(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_idxmax(int n, const vector<RObjVecNum>& a) { int idx = 0; double extr = a[0]->to_r(0); @@ -119,39 +112,36 @@ void geni_idxmax(double* r, double* dr, int n, const vector<RObjVecNum>& a) idx = i; } } - *r = idx; - if (dr) - *dr = 0; // TODO better estimate + return RObjInt(new CObjInt(idx)); } //! Sum. -void geni_sum(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_sum(int n, const vector<RObjVecNum>& a) { - *r = 0; + double r = 0; for (int i = 0; i < n; i++) - *r += a[0]->to_r(i); - if (dr) - *dr = 0; // TODO better estimate + r += a[0]->to_r(i); + return RObjNum(new CObjDbl(r)); + // TODO error estimate } //! Average. -void geni_avge(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_avge(int n, const vector<RObjVecNum>& a) { - *r = 0; + double r = 0; if (!n) throw S("Cannot compute average of empty vector"); for (int i = 0; i < n; i++) - *r += a[0]->to_r(i); - *r /= n; - if (dr) - *dr = 0; // TODO better estimate + r += a[0]->to_r(i); + return RObjNum(new CObjDbl(r/n)); + // TODO error estimate } //! Sample variance. -void geni_variance(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_variance(int n, const vector<RObjVecNum>& a) { if (n < 2) throw S("Cannot compute sample variance for sample size < 2"); @@ -161,52 +151,49 @@ void geni_variance(double* r, double* dr, int n, const vector<RObjVecNum>& a) q += (a[0]->to_r(i) - p) * (a[0]->to_r(i) - pp); p = pp; } - *r = q / (n - 1); - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(q / (n - 1))); + // TODO error estimate } //! Sample standard deviation. -void geni_stdv(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_stdv(int n, const vector<RObjVecNum>& a) { - geni_variance(r, dr, n, a); - *r = sqrt(*r); - if (dr) - *dr = 0; // TODO better estimate + RObjNum var = geni_variance(n, a); + return RObjDbl(new CObjDbl(var->to_r())); + // TODO error estimate } //! Integral. -void geni_integral(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_integral(int n, const vector<RObjVecNum>& a) { - *r = 0; + double r = 0; for (int i = 0; i < n - 1; i++) { if (a[0]->to_r(i + 1) <= a[0]->to_r(i)) throw S("a not sorted"); - *r += (a[0]->to_r(i + 1) - a[0]->to_r(i)) * (a[1]->to_r(i + 1) + a[1]->to_r(i)) / 2; + r += (a[0]->to_r(i + 1) - a[0]->to_r(i)) * (a[1]->to_r(i + 1) + a[1]->to_r(i)) / 2; } - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(r)); + // TODO error estimate } //! Center of gravity in x, weighed by y. -void geni_cog(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_cog(int n, const vector<RObjVecNum>& a) { double r0 = 0, r1 = 0; for (int i = 0; i < n; i++) { r0 += a[1]->to_r(i); r1 += a[1]->to_r(i) * a[0]->to_r(i); } - *r = r0 > 0 ? r1 / r0 : 0; - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(r0 > 0 ? r1 / r0 : 0)); + // TODO error estimate } //! Standard deviation in x, weighed by y. -void geni_width(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_width(int n, const vector<RObjVecNum>& a) { double r0 = 0, r1 = 0, r2 = 0; for (int i = 0; i < n; i++) { @@ -219,13 +206,12 @@ void geni_width(double* r, double* dr, int n, const vector<RObjVecNum>& a) for (int i = 0; i < n; i++) { r2 += a[1]->to_r(i) * SQR(a[0]->to_r(i) - center); } - *r = sqrt(r2 / r0); - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl(sqrt(r2 / r0))); + // TODO error estimate } //! Correlation coefficient. -void geni_corr(double* r, double* dr, int n, const vector<RObjVecNum>& a) +RObjNum geni_corr(int n, const vector<RObjVecNum>& a) { double r0 = 0, r1 = 0, s0 = 0, s1 = 0, v = 0; for (int i = 0; i < n; i++) { @@ -237,9 +223,26 @@ void geni_corr(double* r, double* dr, int n, const vector<RObjVecNum>& a) s1 += SQR(a[1]->to_r(i) - r1) / n; v += (a[0]->to_r(i) - r0) * (a[1]->to_r(i) - r1) / n; } - *r = v / sqrt(s0 * s1); - if (dr) - *dr = 0; // TODO better estimate + return RObjDbl(new CObjDbl( v / sqrt(s0 * s1) )); + // TODO error estimate +} + +//! First index for which expr is true. +RObjNum geni_firstwith(int n, const vector<RObjVecNum>& a) +{ + for (int i = 0; i < n; ++i) + if (a[0]->to_i(i)) + return RObjInt(new CObjInt(i)); + return RObjInt(new CObjInt(-1)); +} + +//! Last index for which expr is true. +RObjNum geni_lastwith(int n, const vector<RObjVecNum>& a) +{ + for (int i = n-1; i>= 0; --i) + if (a[0]->to_i(i)) + return RObjInt(new CObjInt(i)); + return RObjInt(new CObjInt(-1)); } @@ -249,8 +252,8 @@ void geni_corr(double* r, double* dr, int n, const vector<RObjVecNum>& a) namespace NGeni { // internals: -map<string, const CGeni*> gmap; // unsorted hash, for expression evaluation -vector<const CGeni*> glist; // sorted array, for help text + std::map<string, const CGeni*> gmap; // unsorted hash, for expression evaluation + vector<const CGeni*> glist; // sorted array, for help text } CGeni::CGeni( @@ -308,4 +311,8 @@ void SGeniRegistry::initialize() "corr", 2, "x,y", geni_corr, "?", // TODO: unit? "correlation coefficient of x and y")) ->register_me(); + (new CGeni("firstwith", 1, "expr", geni_firstwith, "-", + "first index for which expr is true"))->register_me(); + (new CGeni("lastwith", 1, "expr", geni_firstwith, "-", + "last index for which expr is true"))->register_me(); } diff --git a/pub/lib/reduce_spec.hpp b/pub/lib/reduce_spec.hpp index eda55bb9c35ecf65971444a9fe20594b698bc14f..6404344faf3949d71b3109a30fcc46e9fe726887 100644 --- a/pub/lib/reduce_spec.hpp +++ b/pub/lib/reduce_spec.hpp @@ -14,7 +14,7 @@ //! Function type: Evaluate generalized integral for given vector(s). -typedef void (*geni_eval)(double*, double*, int, const vector<RObjVecNum>&); +typedef RObjNum (*geni_eval)(int, const vector<RObjVecNum>&); //! A wrapper holding a functional. diff --git a/pub/lib/registry.hpp b/pub/lib/registry.hpp index 27eec53cf7e8b059f8d63774adf34b49fc0f3a73..5dd25570908b6eeec662c567cba29f04077655ae 100644 --- a/pub/lib/registry.hpp +++ b/pub/lib/registry.hpp @@ -10,6 +10,7 @@ #ifndef IREGISTRY_H #define IREGISTRY_H +#include <map> #include "../trivia/singleton.hpp" //! Mixin interface for registries holding objects of type T; temporary version for SFuncRegistry. @@ -18,7 +19,7 @@ template <class T> class IRegistryTmp { protected: virtual string type_name() const = 0; - map<string, /*const*/ T*> FMap; //! unsorted hash, for expression evaluation + std::map<string, /*const*/ T*> FMap; //! unsorted hash, for expression evaluation vector<const T*> FList; //! sorted array, for help text public: virtual ~IRegistryTmp() @@ -53,7 +54,7 @@ template <class T> class IRegistry { protected: virtual string type_name() const = 0; - map<string, const T*> FMap; //! unsorted hash, for expression evaluation + std::map<string, const T*> FMap; //! unsorted hash, for expression evaluation vector<const T*> FList; //! sorted array, for help text public: virtual ~IRegistry() diff --git a/pub/lib/rssm.cpp b/pub/lib/rssm.cpp index c45e4ae7e24fccbdf04efb83fd927eb552c63cb4..1e83eae4472c5c0bcc42ea41270a1b3b754c6ead 100644 --- a/pub/lib/rssm.cpp +++ b/pub/lib/rssm.cpp @@ -11,11 +11,10 @@ #include <cstring> #include <fstream> - +#include <boost/filesystem.hpp> #include <yaml-cpp/yaml.h> #include "../readplus/ask.hpp" -#include "../trivia/file_ops.hpp" #include "../trivia/string_ops.hpp" #include "mem.hpp" @@ -24,6 +23,8 @@ #include "rssm.hpp" #include "slice.hpp" +namespace fs = boost::filesystem; + //! All relevant information extracted from one raw-data file from SPHERES. @@ -223,8 +224,7 @@ void NRSSM::read_spec(int flag) // 16 no normalization { - string file_f, name; - file_f = wask("Read SPHERES data from file"); + string file_f = wask("Read SPHERES data from file"); CRawfileSpheres R; std::ifstream F_in; @@ -247,7 +247,7 @@ void NRSSM::read_spec(int flag) olf[iolf]->yco = CCoord("cts", "sec-1"); olf[iolf]->ZCo.push_back(CCoord("det", "")); } - triv::fname_divide(file_f, 0, &name, 0); + string name = fs::path(file_f).filename().stem().string(); olf[0]->name = name + "left"; olf[1]->name = name + "right"; olf[2]->name = name + "open_left"; @@ -379,7 +379,7 @@ void NRSSM::read_series(int flag) { char tstrg[30]; - string fser, fnam, name; + string fser, fnam; time_t t; int isub; vector<CRawfileSpheres> RR; @@ -446,7 +446,7 @@ void NRSSM::read_series(int flag) olf[iolf]->ZCo.push_back(CCoord("#sub", "")); olf[iolf]->ZCo.push_back(CCoord("det", "")); } - triv::fname_divide(fser, 0, &name, 0); + string name = fs::path(fser).filename().stem().string(); olf[0]->name = name; olf[1]->name = name + "open"; olf[0]->log_action("refl, average over both halfspaces"); diff --git a/pub/lib/slice.cpp b/pub/lib/slice.cpp index 4ca860e4a4e623bd67f82599539e32f1fc908406..f735b467d348dc05470f75c49797cfd6162467bb 100644 --- a/pub/lib/slice.cpp +++ b/pub/lib/slice.cpp @@ -243,14 +243,14 @@ string CSpec::info_line() const //! Returns true if all data points have nonzero dy. -bool CSpec::has_nonzero_dy() const +bool CSpec::dy_are_all_nonzero() const { if (!has_dy()) return false; return std::all_of(dy.cbegin(), dy.cend(), [](double dv) { return dv > 0; }); } -PSpec CSpec::binned(const vector<int>& breaks) const +PSpec CSpec::binned(const vector<int>& breaks, const bool sampling_error) const { PSpec sout(new CSpec()); sout->z = z; @@ -269,10 +269,11 @@ PSpec CSpec::binned(const vector<int>& breaks) const for (int i = igi; i < igf; ++i) { if (has_dy()) vg_src += SQR(dy[i]); - vg_grp += SQR(y[i] - yg); + if (sampling_error) + vg_grp += SQR(y[i] - yg); } double vg = vg_src / ng / ng; - if (ng > 1) + if (sampling_error && ng > 1) vg += vg_grp / (ng - 1); sout->push_xyd(xg, yg, sqrt(vg)); } diff --git a/pub/lib/slice.hpp b/pub/lib/slice.hpp index 3f2fada86d569a5b692f2973cd237a541169e41a..1ff7a6a4506fcd0af071cb49eff0d1fc67ca1ad4 100644 --- a/pub/lib/slice.hpp +++ b/pub/lib/slice.hpp @@ -47,8 +47,8 @@ public: bool has_step(double step) const; string info_line() const; inline bool has_dy() const { return dy.size() != 0; } - bool has_nonzero_dy() const; - PSpec binned(const vector<int>& breaks) const; + bool dy_are_all_nonzero() const; + PSpec binned(const vector<int>& breaks, const bool sampling_error) const; }; diff --git a/pub/lib/special.cpp b/pub/lib/special.cpp index cf8eba150c371b191203fbd038e3c0f6e71ebde9..389c89dee40ce677caa5c463351686e63d99d4dc 100644 --- a/pub/lib/special.cpp +++ b/pub/lib/special.cpp @@ -9,10 +9,14 @@ #include "defs.hpp" - +#include <fstream> +#include <vector> #include <fftw3.h> +#include <boost/format.hpp> - +#include "../trivia/file_ops.hpp" +#include "../trivia/vector_ops.hpp" +#include "../readplus/ask.hpp" #include "fsel.hpp" #include "loop.hpp" #include "mem.hpp" @@ -21,6 +25,9 @@ #include "slice.hpp" #include "special.hpp" +using boost::format; +using std::vector; + namespace NSpecial { void q_eval(double* par, int m_dat, double* fvec, void* data, int* info); diff --git a/pub/lib/toplevel.cpp b/pub/lib/toplevel.cpp index 9b5d6ec27dbfe401ec601a4c6704ac6af24915da..350192fbf93eeaacb3277cc311689de6f3f05e92 100644 --- a/pub/lib/toplevel.cpp +++ b/pub/lib/toplevel.cpp @@ -58,7 +58,7 @@ void atexit_handler() {} //! Executes one Frida command. -void CFrida::execute_cmd(const string cmdline) +void CFrida::execute_cmd(const string& cmdline) { // Empty input, comment lines. if (cmdline == "" || cmdline[0] == '#') { @@ -178,6 +178,10 @@ void CFrida::interactive() string cmdline; try { cmdline = NMacro::readln(triv::indices_to_s(SFSel::instance()->sel()) + " > "); + if (cmdline=="EOF") { + cout << "\n"; + exit(0); + } execute_cmd(cmdline); } catch (string& ex) { cout << "'" << cmdline << "' failed:\n " << ex << "\n"; @@ -199,7 +203,7 @@ void CFrida::interactive() //! Reads a script file and executes it line by line. -void CFrida::execute_file(const string fnam) +void CFrida::execute_file(const string& fnam, bool batchMode) { int lineno = 0; try { @@ -212,7 +216,19 @@ void CFrida::execute_file(const string fnam) try { execute_cmd(cmdline); } catch (string& ex) { - throw "'" + cmdline + "':\n " + ex; + string msg = "'" + cmdline + "':\n " + ex; + if (batchMode) { + std::cerr << msg << "\n"; + exit(1); + } + throw msg; + } catch (...) { + string msg = "'" + cmdline + "':\n unforeseen exception type"; + if (batchMode) { + std::cerr << msg << "\n"; + exit(1); + } + throw msg; } } } catch (string& ex) { diff --git a/pub/lib/toplevel.hpp b/pub/lib/toplevel.hpp index 2e347a0b7a649bd056b674bbac6fdbcac198c782..78511f004d058799b39d3681d6cd3dea5ceb02b6 100644 --- a/pub/lib/toplevel.hpp +++ b/pub/lib/toplevel.hpp @@ -16,7 +16,7 @@ class CFrida { private: - void execute_cmd(const std::string cmdline); + void execute_cmd(const std::string& cmdline); // Time spent in frida, for optimizing numerical routines: clock_t clock_start; clock_t clock_cmd_i; @@ -25,7 +25,7 @@ private: public: CFrida(); static std::string prompt(); - void execute_file(const std::string fname); + void execute_file(const std::string& fname, bool batchMode); void interactive(); }; diff --git a/pub/lib/variables.cpp b/pub/lib/variables.cpp index b7d5c761bd42fdc85c6bfb70e5477d3088d91ab6..9e6068eb64ccd9607c55aec284c61b581cc13acc 100644 --- a/pub/lib/variables.cpp +++ b/pub/lib/variables.cpp @@ -7,18 +7,21 @@ //! \file variables.cpp //! \brief Implements class SVariRegistry. +#include <algorithm> + #include "variables.hpp" #include "defs.hpp" +#include "obj.hpp" #include "ptr.hpp" -PObj SVariRegistry::find(string key) const +PObj SVariRegistry::find(const string& key) const { auto pos = Map.find(key); return pos == Map.end() ? nullptr : pos->second; } -PObj SVariRegistry::find_or_fail(string key) const +PObj SVariRegistry::find_or_fail(const string& key) const { PObj ret = find(key); if (!ret) @@ -27,36 +30,21 @@ PObj SVariRegistry::find_or_fail(string key) const } -void SVariRegistry::display_functions() const +void SVariRegistry::display_all() const { - /* - // this implementation works only, if flist is strictly ordered: - // first operators by precedence, then functions. - - cout << "Operators by precedence:\n"; - int precedence = -1; - for( int i=0; i<FList.size(); ++i ){ - const CFunc *f; - f = FList[i]; - if( f->precedence ) { // operators - if( f->precedence!=precedence ) - cout << "\n "; - cout << " " << f->key; - } else { // functions - if( f->precedence!=precedence ) - cout << "\nBuilt-in functions:\n"; - cout << " " << f->key << f->explanation << "\n"; - } - precedence = f->precedence; - } - */ + vector<string> keys; + for (const auto& it: Map) + keys.push_back(it.first); + sort(keys.begin(), keys.end()); + for (const string& key: keys) + cout << " " << key << " = " << Map.at(key)->to_s() << "\n"; } -void SVariRegistry::register_scalar(string key, PObj val) { Map[key] = val; } +void SVariRegistry::register_scalar(const string& key, PObj val) { Map[key] = val; } //! Undefines a key (removes entry from registry); returns true unless the key wasn't defined. -bool SVariRegistry::undef(string key) +bool SVariRegistry::undef(const string& key) { auto pos = Map.find(key); if (pos == Map.end()) @@ -64,3 +52,12 @@ bool SVariRegistry::undef(string key) Map.erase(pos); return true; } + +std::map<const string, string> SVariRegistry::to_sMap() const +{ + std::map<const string, string> ret; + for (const auto& it: Map) { + ret[it.first] = it.second->to_s(); + } + return ret; +} diff --git a/pub/lib/variables.hpp b/pub/lib/variables.hpp index 96b3a7432c685674df89dc68aaa803660a9f36c1..f05ef77f0844b60e33125213145c22df5b83691b 100644 --- a/pub/lib/variables.hpp +++ b/pub/lib/variables.hpp @@ -10,8 +10,8 @@ #ifndef VARIABLES_H #define VARIABLES_H +#include <map> #include "../trivia/singleton.hpp" - #include "defs.hpp" #include "ptr.hpp" @@ -20,16 +20,17 @@ class SVariRegistry : public triv::ISingleton<SVariRegistry> { private: - map<string, PObj> Map; //! unsorted hash, for expression evaluation + std::map<const string, PObj> Map; //! unsorted hash, for expression evaluation public: - PObj find(string key) const; - PObj find_or_fail(string key) const; + PObj find(const string& key) const; + PObj find_or_fail(const string& key) const; - void display_functions() const; + void display_all() const; - void register_scalar(string key, PObj val); - bool undef(string key); + void register_scalar(const string& key, PObj val); + bool undef(const string& key); + std::map<const string, string> to_sMap() const; }; #endif // VARIABLES_H diff --git a/pub/plot/CMakeLists.txt b/pub/plot/CMakeLists.txt index a00656e46c995849c0685ecd998e3374c76dfc2b..9f68fe7e486aa515ae261fa906fafb9fe252047d 100644 --- a/pub/plot/CMakeLists.txt +++ b/pub/plot/CMakeLists.txt @@ -1,23 +1,31 @@ # frida: trivia/CMakeLists.txt +set(library_name fridaplot) +set(${library_name}_LIBRARY ${library_name} PARENT_SCOPE) +set(${library_name}_LIBRARY_TYPE SHARED) + include_directories(${Frida_SOURCE_DIR}/plot ${CMAKE_CURRENT_BINARY_DIR}) set(src_files -axis.cpp -dualplot.cpp -plowin.cpp -) + axis.cpp + dualplot.cpp + gnuplotter.cpp + ps_plotter.cpp + plowin.cpp + ) set(inc_files -axis.hpp -dualplot.hpp -plowin.hpp -) + axis.hpp + dualplot.hpp + gnuplotter.hpp + ps_plotter.hpp + plowin.hpp + ) -add_library(libfridaplot SHARED ${src_files}) +add_library(${library_name} SHARED ${src_files}) -set_target_properties(libfridaplot PROPERTIES OUTPUT_NAME fridaplot) +set_target_properties(${library_name} PROPERTIES OUTPUT_NAME ${library_name}) -target_link_libraries(libfridaplot) +target_link_libraries(${library_name} ${Readline_LIBRARIES}) -install(TARGETS libfridaplot DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +install(TARGETS ${library_name} LIBRARY DESTINATION ${destination_lib}) diff --git a/pub/plot/axis.cpp b/pub/plot/axis.cpp index 82dfe64c2a6e5e958d8be6f59e53c207f8ba1b35..01a50438a7f894c204bbd94d4f634c87480eb7c1 100644 --- a/pub/plot/axis.cpp +++ b/pub/plot/axis.cpp @@ -165,7 +165,6 @@ void CAxis::set_rounded_limits(double _inf, double _sup) if (inf2 < 0 && inf > 0) inf2 = 0; mydigits += 0.1; - // printf("DEB [%g,%g] -> [%g,%g] (%g)\n", inf, sup, inf2, sup2, mydigits); if (mydigits > 17) { std::cerr << std::setprecision(17) << "PLEASE REPORT THIS BUG: escaping from endless loop in Axis::" @@ -309,116 +308,150 @@ double CAxis::pc(double v) const { return 10 * value2plotcoord(v); } double CAxis::pcerr(double v, double dv) const { return 10 * value2ploterror(v, dv); } -//! Sets Tacks, *ntpt, *ticklim to a nice division of the plot range. +//! Sets Tacks, ntpt, nt4t, *ticklim to a nice division of the plot range. -void CAxis::calc_ticks(vector<double>& Tacks, int* ntpt, double* ticklim) const +void CAxis::calc_ticks(vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const { - if (inf >= sup) - throw "BUG detected by calc_ticks: inf=" + S(inf) + " >= sup=" + S(sup); + if (logflag) + calc_logticks(Tacks, ntpt, nt4t, ticklim); + else + calc_linticks(Tacks, ntpt, nt4t, ticklim); +} + + +//! Sets Tacks, ntpt, nt4t, *ticklim to a nice division of the plot range. + +void CAxis::calc_linticks(vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const +{ + double dtack; + calc_lintacks(Tacks, ntpt, dtack); + if (!Tacks.size()) + throw "Empty Tack vector for "+name+" axis ["+S(inf)+","+S(sup)+"]"; + ticklim[0] = Tacks.front() - dtack; + ticklim[1] = Tacks.back() + dtack; + nt4t = Tacks.size() + 2; +} + +//! Sets Tacks, *ntpt, and dtack + +void CAxis::calc_lintacks(vector<double>& Tacks, int& ntpt, double& dtack) const +{ + double range = sup-inf; + if (range <= 0) + throw "BUG detected by calc_linticks: inf=" + S(inf) + " >= sup=" + S(sup); + double r = log10(range); + int ir = (int)((r < 0) ? r - 1 : r); + double rd = r - ir; // fractional part of r + double rdr = pow(10., rd); + if (rdr > 9.99999) { + dtack = 2.5 * pow(10., ir); // spacing between tacks + ntpt = 5; // ticks per tack + } else if (rdr > 5.00001) { + dtack = 2 * pow(10., ir); + ntpt = 4; + } else if (rdr > 2.500005) { + dtack = 1 * pow(10., ir); + ntpt = 5; + } else if (rdr > 1.600003) { + dtack = .5 * pow(10., ir); + ntpt = 5; + } else if (rdr > 1.250002) { + dtack = .4 * pow(10., ir); + ntpt = 4; + } else { + dtack = .25 * pow(10., ir); + ntpt = 5; + } + // Sets tack vector, taking extra precaution to avoid rounding errors. Tacks.clear(); + double dlow = dtack * (floor(inf/dtack)-1); + double dhig = dtack * (ceil(sup/dtack)+1); + double drange = dhig-dlow; + int nTacks = drange/dtack + 1.5; + if (nTacks<2) + throw "BUG: calc_lintacks -> nTacks<2"; + for (int i=0; i<nTacks; ++i) { + double d = (i*dhig + (nTacks-1-i)*dlow)/(nTacks-1); + if (std::abs(d)<1e-15*drange) + d = 0; + if (inf-1e-4*range <= d && d <= sup+1e-4*range) + Tacks.push_back(d); + } +} - if (!logflag) { - double r = log10(sup - inf); - int ir = (int)((r < 0) ? r - 1 : r); - double rd = r - ir; // fractional part of r - double rdr = pow(10., rd); - double dtack; - if (rdr > 9.99999) { - dtack = 2.5 * pow(10., ir); // spacing between tacks - *ntpt = 5; // ticks per tack - } else if (rdr > 5.00001) { - dtack = 2 * pow(10., ir); - *ntpt = 4; - } else if (rdr > 2.500005) { - dtack = 1 * pow(10., ir); - *ntpt = 5; - } else if (rdr > 1.600003) { - dtack = .5 * pow(10., ir); - *ntpt = 5; - } else if (rdr > 1.250002) { - dtack = .4 * pow(10., ir); - *ntpt = 4; - } else { - dtack = .25 * pow(10., ir); - *ntpt = 5; - } - double d = inf / dtack; - double tack0 = dtack * (int)(d <= 0 ? d - 1 : d); - d = sup / dtack; - double tackn = dtack * ((int)(d < 0 ? d - 1 : d) + 1); - double vsub = inf - (sup - inf) * 1.e-4; - double vsup = sup + (sup - inf) * 1.e-4; - int nt = (int)((tackn - tack0) / dtack) + 3; // allocate enough - for (int i = 0; i < nt; i++) { - d = tack0 + i * dtack; - if (vsub <= d && d <= vsup) - Tacks.push_back(d); - } - int ntack = Tacks.size(); - ticklim[0] = tack0; - ticklim[1] = Tacks[ntack - 1] + dtack; +//! Sets Tacks, ntpt, nt4t, *ticklim to a nice division of the plot range. + +void CAxis::calc_logticks(vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const +{ + if (inf >= sup) + throw "BUG detected by calc_logticks: inf=" + S(inf) + " >= sup=" + S(sup); + if (inf <= 0) + throw S("BUG detected by calc_logticks: negative log argument"); - } else { // log scale - static double eins = 1 + 1e-6 - 1e-12; + static double eins = 1 + 1e-6 - 1e-12; - if (inf <= 0) - throw S("BUG in CAxis::calc_ticks: negative log argument"); + double rlgmin = log10(inf); + double rlgmax = log10(sup); + double rlgrel = rlgmax - rlgmin; + if (!std::isfinite(rlgrel) || rlgrel > 100) + throw "Excessive log range " + S(inf) + " .. " + S(sup); - double rlgmin = log10(inf); - double rlgmax = log10(sup); - double rlgrel = rlgmax - rlgmin; - if (rlgrel > 100) - throw S("Excessive log range"); + int incr; // -> decades per tack + if (rlgrel <= 10) { + incr = 1; + } else { + incr = (int)(rlgrel / 7 + 1); + if (incr > 3) + incr = 3 * (incr / 3); // preferred values 3, 6, ... + } - // incr := #decades per tack - int incr; - if (rlgrel <= 10) { - incr = 1; - } else { - incr = (int)(rlgrel / 7 + 1); - if (incr > 3) - incr = 3 * (incr / 3); // preferred values 3, 6, ... - } + // first and last tack + int minexp = (int)(rlgmin > 0 ? rlgmin + 1e-6 : rlgmin - 1e-6 - 1); + int maxexp = (int)(rlgmax > 0 ? rlgmax + 1e-6 : rlgmax - 1e-6 - 1); + if (incr > 1) { + minexp -= minexp % incr; + maxexp -= maxexp % incr; + } - // first and last tack - int minexp = (int)(rlgmin > 0 ? rlgmin + 1e-6 : rlgmin - 1e-6 - 1); - int maxexp = (int)(rlgmax > 0 ? rlgmax + 1e-6 : rlgmax - 1e-6 - 1); - if (incr > 1) { - minexp -= minexp % incr; - maxexp -= maxexp % incr; - } + // set Tacks + double d1 = inf / eins; + double d2 = sup * eins; + Tacks.clear(); + for (int i = minexp; i <= maxexp; i += incr) { + double r0 = pow(10., i); + if (d1 <= r0 && r0 <= d2) + Tacks.push_back(r0); + } + nt4t = Tacks.size() + 2; - // set Tacks - double d1 = inf / eins; - double d2 = sup * eins; - for (int i = minexp; i <= maxexp; i += incr) { - double r0 = pow(10., i); - if (d1 <= r0 && r0 <= d2) - Tacks.push_back(r0); - } + // set tick limits (may exceed actual tick range) + int ntack = Tacks.size(); + if (ntack >= 1) { + ticklim[0] = Tacks.front() / pow(10., incr); + ticklim[1] = Tacks.back() * pow(10., incr); + } else { + // untested. just to allow plots when no tacks in window + ticklim[0] = pow(10., minexp); + ticklim[1] = pow(10., maxexp + 1); + } - // set tick limits (may exceed actual tick range) - int ntack = Tacks.size(); - if (ntack >= 1) { - ticklim[0] = Tacks[0] / pow(10., incr); - ticklim[1] = Tacks[ntack - 1] * pow(10., incr); - } else { - // untested. just to allow plots when no tacks in window - ticklim[0] = pow(10., minexp); - ticklim[1] = pow(10., maxexp + 1); - } + // determine #ticks / tack + if (incr == 1) { + if (rlgrel <= 3) + ntpt = 9; + else if (rlgrel <= 7) + ntpt = 3; // 1-2-5-10 - Schritte + else + ntpt = 1; + } else { + ntpt = -incr; // this one has special semantics: it means 'incr' ticks per tack + } - // determine #ticks / tack - if (incr == 1 && rlgrel <= 3) { - *ntpt = 9; - } else if (incr == 1 && rlgrel <= 7) { - *ntpt = 3; // 1-2-5-10 - Schritte - } else if (incr == 1) { - *ntpt = 1; - } else { - *ntpt = -incr; - // this one has special semantics: it means 'incr' ticks per tack - } + // for narrow ranges, overwrite tacks + if (ntack<2) { + double dtack; + int ntpt_dummy; + calc_lintacks(Tacks, ntpt_dummy, dtack); } } diff --git a/pub/plot/axis.hpp b/pub/plot/axis.hpp index 3aea8cdcb4db2a716d62a5b42c47d9494e1f3e48..e01fbc45c71b8deff4a01396d168f81b6276b9d9 100644 --- a/pub/plot/axis.hpp +++ b/pub/plot/axis.hpp @@ -7,6 +7,9 @@ //! \file axis.hpp //! \brief CAxis: One axis of a coordinate frame. +#include <string> +#include <vector> + //! One axis of a coordinate frame, for use in plotting. class CAxis @@ -40,5 +43,9 @@ public: void set_xgrid(std::vector<double>& x, int n) const; double pc(double v) const; double pcerr(double v, double dv) const; - void calc_ticks(std::vector<double>& Tacks, int* ntpt, double* ticklim) const; + void calc_ticks(std::vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const; +private: + void calc_linticks(std::vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const; + void calc_lintacks(std::vector<double>& Tacks, int& ntpt, double& dtack) const; + void calc_logticks(std::vector<double>& Tacks, int& ntpt, int& nt4t, double* ticklim) const; }; diff --git a/pub/plot/dualplot.cpp b/pub/plot/dualplot.cpp index 7c1667947f870dc81e903cf85648859bf8d1fe2b..b4ec369a678a66a6167e3991ac0f396eccb35dc4 100644 --- a/pub/plot/dualplot.cpp +++ b/pub/plot/dualplot.cpp @@ -5,94 +5,52 @@ //************************************************************************************************** //! \file dualplot.cpp -//! \brief Collection NPlot of plot frames CPlot. +//! \brief Implements class CPlot. -#include <boost/format.hpp> -#include <cmath> -#include <cstring> -#include <fcntl.h> #include <iostream> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> -#include "../trivia/file_ops.hpp" #include "../trivia/string_convs.hpp" - #include "dualplot.hpp" +#include "gnuplotter.hpp" +#include "ps_plotter.hpp" + +#define S(a) triv::strg((a)) using std::string; using std::vector; using std::cout; -using boost::format; - -#define S(a) triv::strg((a)) - -static const int mLin = 80; // max num of chars in PostScript line - //! Constructor for plot window: setup for gnuplot and postscript. -CPlot::CPlot(int _iPlot, bool _logx, bool _logy) +CPlot::CPlot(int _iPlot, bool _logx, bool _logy, bool _p2D, bool _logz) : iPlot(_iPlot) , X("x", _logx) , Y("y", _logy) + , Z("UNUSED", _logz) , maxpoints(20000) , with_errors(true) - , equipoints(49) + , equipoints(120) , refine(true) + , gnuPlotter(new CGnuPlotter(iPlot)) + , ps_Plotter(new CPS_Plotter) { - // == Initialization for Gnuplot == - - // Create a named pipe (FIFO) that will transmit our commands to Gnuplot. - string fn_fifo = "/tmp/gnuplot-" + S(getpid()); - triv::system("rm -f " + fn_fifo); - if (mkfifo(fn_fifo.c_str(), 0666)) - throw "SYSTEM ERROR cannot make fifo " + fn_fifo + ": will not be able to print"; - - // Check that Gnuplot supports X11. - string out = triv::system_read("gnuplot -e 'help X11' 2>&1 < /dev/null"); - if (out.substr(0, 5) == "Sorry" || out.length() < 80) { - cout << "Gnuplot seems not to support X11\n"; - exit(1); - } - - // Start a Gnuplot that will read from our pipe. - triv::system("gnuplot -title " + S(iPlot) + " -noraise < " + fn_fifo + "&"); - - // Open our pipe so that we can write commands to it - // (we use 'open' instead of 'fopen' or 'ofstream', because we need non-blocking mode). - if ((gp_fifo = open(fn_fifo.c_str(), O_WRONLY)) == -1) - throw "SYSTEM ERROR: cannot open fifo " + fn_fifo + " (" + strerror(errno) + ")"; - fcntl(gp_fifo, F_SETFL, O_NONBLOCK); - - // Now the initialization _within_ Gnuplot. - gp_write(string("set terminal x11")); - - // == Initialization for PostScript == - ps_fnum = 0; + set_dims(_p2D); } +//! Sets 1D or 2D; sets axis names accordingly. -//! Clear plot frame and buffer. - -void CPlot::clear_frame() +void CPlot::set_dims(const bool _p2D) { - // clear gnuplot tmp files - gp_fno = 0; - gp_fnames = ""; - - // reset buffers for postscript output - string cmd; - ps_accu.clear(); - ps_accu.push_back("\n%% output created by frida2\n"); - ps_snum = 0; - ps_pnum = 0; - ps_cnum = 0; - ps_Doc.clear(); + p2D = _p2D; + if (p2D) { + Y.name = "h"; + Z.name = "y"; + } else { + Y.name = "y"; + Z.name = "UNUSED"; + } } - //! Change one setup parameter per command. void CPlot::set_aux(const string& cmd) @@ -104,6 +62,7 @@ void CPlot::set_aux(const string& cmd) X.set_log(true); else if (cmd == "gxl-") X.set_log(false); + else if (cmd == "gyl") { Y.set_log(!Y.logflag); printf("set y %s\n", Y.logflag ? "log" : "lin"); @@ -111,6 +70,15 @@ void CPlot::set_aux(const string& cmd) Y.set_log(true); else if (cmd == "gyl-") Y.set_log(false); + + else if (cmd == "gzl") { + Z.set_log(!Z.logflag); + printf("set z %s\n", Z.logflag ? "log" : "lin"); + } else if (cmd == "gzl+") + Z.set_log(true); + else if (cmd == "gzl-") + Z.set_log(false); + else if (cmd == "gxf") { X.force = !X.force; printf("force x %s\n", X.force ? "on" : "off"); @@ -125,184 +93,98 @@ void CPlot::set_aux(const string& cmd) Y.force = true; else if (cmd == "gyf-") Y.force = false; + else if (cmd == "ge") with_errors = !with_errors; else if (cmd == "ge+") with_errors = true; else if (cmd == "ge-") with_errors = false; + + else if (cmd == "gt") + set_dims(!p2D); + else if (cmd == "gt+") + set_dims(true); + else if (cmd == "gt-") + set_dims(false); + else throw "unknown command " + cmd; } +//! Clear 1D plot canvas, and plot coordinate frame (axes, ticks, labels). + +void CPlot::start_frame1D(const string& caller, const string& xlabel, const string& ylabel) +{ + gnuPlotter->start_frame(X, Y); + ps_Plotter->start_frame1D(caller, X, Y, xlabel, ylabel); + open1D = true; +} + +//! Start adding to plot. + +void CPlot::reopen_frame1D() +{ + if (!open1D) + throw S("plot frame is not open for adding"); +} + +//! Clear 2D plot canvas, and print coordinate ranges + +void CPlot::start_frame2D(const string& caller) +{ + ps_Plotter->start_frame2D(caller, X, Z, Y); +} + + //! Plot coordinate frame (axes, ticks, labels). -void CPlot::plot_frame(const string& xlabel, const string& ylabel) +void CPlot::close_frame2D(const string& xlabel, const string& zlabel, const string& ylabel) { - gp_write("set nologscale"); - string whichlog = ""; - if (X.logflag) - whichlog += "x"; - if (Y.logflag) - whichlog += "y"; - if (whichlog != "") - gp_write("set logscale " + whichlog); - - // wups: - char outlin[mLin]; - snprintf(outlin, mLin, "\n%i %g %g xSetCoord\n", X.logflag, X.inf, X.sup); - ps_accu.push_back(outlin); - snprintf(outlin, mLin, "%i %g %g ySetCoord\n", Y.logflag, Y.inf, Y.sup); - ps_accu.push_back(outlin); - snprintf(outlin, mLin, "%% %i %g %g %i zSetCoord\n\n", 0, 0., 0., 0); - ps_accu.push_back(outlin); - - int ntpt; - double ticklim[2]; - vector<double> Tacks; - ps_accu.push_back("\n/xPlotFrame {\n"); - if (X.logflag && X.inf <= 0) - throw "BUG: x log incompatible with limits " + X.str(); - X.calc_ticks(Tacks, &ntpt, ticklim); - ps_ticktack(Tacks, ntpt, ticklim, &X); - snprintf(outlin, mLin - 4, " {(%s", xlabel.c_str()); - strncat(outlin, ")}\n", mLin); - ps_accu.push_back(outlin); - ps_accu.push_back(" 0 10 0 0 0 90 " - "OneAxx Axx Tic Tac xNumL %% low x axis\n"); - ps_accu.push_back(" 0 10 0 10 0 270 " - "OneAxx Axx Tic Tac %% top x axis\n"); - ps_accu.push_back(" xCL\n"); - ps_accu.push_back("} def\n"); - - ps_accu.push_back("\n/yPlotFrame {\n"); - if (Y.logflag && Y.inf <= 0) - throw "BUG: y log incompatible with limits " + Y.str(); - Y.calc_ticks(Tacks, &ntpt, ticklim); - ps_ticktack(Tacks, ntpt, ticklim, &Y); - snprintf(outlin, mLin - 4, " {(%s", ylabel.c_str()); - strncat(outlin, ")}\n", mLin); - ps_accu.push_back(outlin); - ps_accu.push_back(" 0 10 0 0 90 0 " - "OneAxx Axx Tic Tac yNumL %% left y axis\n"); - ps_accu.push_back(" 0 10 10 0 90 180 " - "OneAxx Axx Tic Tac %% right y axis\n"); - ps_accu.push_back(" yCL\n"); - ps_accu.push_back("} def\n"); - ps_accu.push_back("\n%% modeDD\nplotbefore\n"); + ps_Plotter->close_frame2D(X, Z, Y, xlabel, zlabel, ylabel); } //! Plot one spectrum. void CPlot::add_spec( - bool as_line, bool new_style, int style_no, const vector<double>& xp, const vector<double>& yp, - const vector<double>& dyp, const vector<string>& z, const string& xco, const string& yco, - const string& info) + bool as_line, bool new_slice, int style_no, const vector<double>& xp, const vector<double>& yp, + const vector<double>& dyp, const vector<string>& zentries, + const string& xco, const string& yco, const string& info) { - static const int mColor = 6; - static int color[mColor] = { 0x880000, 0x008800, 0x000088, 0x006666, 0x660066, 0x666600 }; - // Checks: - int np = xp.size(); - if (!np) - throw S("invalid call to CPLot::addSpec: no data points"); - if (np != yp.size()) - throw S("invalid call to CPLot::addSpec: x.size<>y.size"); - - // Prepare for live display, to be shown by showSpecs(): - string gp_fnam = str(format("/tmp/%s-%i-%03i.gnu") % getenv("LOGNAME") % iPlot % gp_fno++); - if (gp_fnames != "") - gp_fnames += ", "; - gp_fnames += string("\"") + gp_fnam + "\" notitle"; - if (as_line) - gp_fnames += str(format(" with lines lt 1 lc rgb \"#%6x\"") % color[style_no % mColor]); - else if (with_errors && dyp.size()) - gp_fnames += " with errorbars"; - FILE* gp_fd; - if (!(gp_fd = fopen(gp_fnam.c_str(), "w"))) - throw "cannot save gnuplot data to " + gp_fnam; - int nout = 0; - try { - for (int i = 0; i < np; i++) { - if (std::isinf(xp[i]) || std::isinf(yp[i])) - throw "Data point number " + S(i) + " is invalid: x=" + S(xp[i]) + ", y=" - + S(yp[i]); - if (xp[i] < X.inf || xp[i] > X.sup) - throw "CPlot::addSpec: x[" + S(i) + "]=" + S(xp[i]) + " out of range"; - if (yp[i] < Y.inf || yp[i] > Y.sup) - throw "CPlot::addSpec: y[" + S(i) + "]=" + S(yp[i]) + " out of range"; - if (with_errors && dyp.size()) - fprintf(gp_fd, "%20.13g %20.13g %20.13g\n", xp[i], yp[i], dyp[i]); - else - fprintf(gp_fd, "%20.13g %20.13g\n", xp[i], yp[i]); - nout++; - } - } catch (string& s) { - fclose(gp_fd); - throw s; - } catch (...) { - fclose(gp_fd); - throw "BUG: unexpected exception type"; - } - fclose(gp_fd); - if (!nout) - throw "no points in frame: " + info; - - // Postscript copy: - char outlin[mLin]; - if (new_style) { - snprintf(outlin, mLin, "\n%3u [", ++ps_snum); - ps_accu.push_back(outlin); - for (int i = 0; i < z.size(); i++) { - snprintf(outlin, mLin, " %s", z[i].c_str()); - ps_accu.push_back(outlin); - } - snprintf(outlin, mLin, " ] zValues\n"); - ps_accu.push_back(outlin); - if (as_line) - snprintf(outlin, mLin, "%2i cstyle", style_no); - else - snprintf(outlin, mLin, "%2i pstyle", style_no); - ps_accu.push_back(outlin); - snprintf(outlin, mLin - 2, " %% (%s -> %s)", xco.c_str(), yco.c_str()); - strncat(outlin, "\n", mLin); - ps_accu.push_back(outlin); - } else { - ps_accu.push_back("\n"); - } - for (int i = 0; i < np; i++) { - snprintf( - outlin, mLin, "%8.5f %8.5f %8.5f t%c %% %13.7g wx %13.7g wy\n", X.pc(xp[i]), - Y.pc(yp[i]), dyp.size() ? Y.pcerr(yp[i], dyp[i]) : 0, - i == 0 ? 'i' : i == np - 1 ? 'f' : ' ', xp[i], yp[i]); - ps_accu.push_back(outlin); - } + gnuPlotter->add_spec( + as_line, new_slice, with_errors, + style_no, xp, yp, dyp, zentries, xco, yco, info); + ps_Plotter->add_spec( + as_line, new_slice, + style_no, xp, yp, dyp, zentries, xco, yco, info); } - -//! Live display as prepared by addSpec. +//! Plot one bin of 2D plot. +void CPlot::ps_line(const string& line) +{ + ps_Plotter->main_line(line); +} void CPlot::show_specs() { - if (gp_fnames != "") - gp_write( - "plot " - + str(format("[%12.8g:%12.8g] [%12.8g:%12.8g] ") % X.inf % X.sup % Y.inf % Y.sup) - + gp_fnames); + gnuPlotter->show_specs(); } - //! Add documentation line to postscript output. -void CPlot::doc_TxLine(const string& line) { ps_Doc.push_back(" {(" + line + ")} TxLine"); } +void CPlot::doc_TxLine(const string& line) +{ + ps_Plotter->doc_line(" {(" + line + ")} TxLine"); +} //! Add documentation line explaining a plot symbol to postscript output. void CPlot::doc_PtTxLine(const string& line, int num) { - ps_Doc.push_back(" " + S(num) + " {(" + line + ")} PtTxLine"); + ps_Plotter->doc_line(" " + S(num) + " {(" + line + ")} PtTxLine"); } @@ -310,65 +192,27 @@ void CPlot::doc_PtTxLine(const string& line, int num) void CPlot::doc_CvTxLine(const string& line, int num) { - ps_Doc.push_back(" " + S(num) + " {(" + line + ")} CvTxLine"); + ps_Plotter->doc_line(" " + S(num) + " {(" + line + ")} CvTxLine"); } //! Write buffered plot to postscript file. -void CPlot::write_postscript(const string& ps_outdir, const string& ps_head, const string& ps_dict) +void CPlot::write_postscript( + const string& fname, const string& mode, const bool withDefs, + std::map<const string, string>&& settings) { - // construct output file name: - FILE* pssav; - string cmd, outf; - while (1) { - if (ps_fnum >= 999) - throw S("graph file number overflow"); - outf = triv::wordexp_unique( - ps_outdir + str(format("l%i") % ++ps_fnum) + "." + (ps_dict == "" ? "psa" : "ps")); - if (!triv::file_exists(outf.c_str())) - break; // legal exit - } - cout << "save plot in " << outf << "\n"; - - // copy headers to output file: - cmd = string("cat ") + ps_dict + " " + // ps_dict may be "" - ps_head + " > " + outf + "\n"; - triv::system(cmd); - - // append specific output to output file: - if (!(pssav = fopen(outf.c_str(), "a+"))) - throw "cannot append contents to file " + outf; - for (string lin : ps_accu) { - // fprintf does not work here because output line may contain "%" - fwrite(lin.c_str(), 1, lin.size(), pssav); - } - - // additional output (do not append this to ps_accu to allow - // further incrementation of ps_accu): - fprintf(pssav, "\n{ black 0 -4 13 1.65 NewList\n"); - for (string lin : ps_Doc) - fprintf(pssav, "%s\n", lin.c_str()); - fprintf(pssav, "} oooinfo 1 eq { exec } { pop } ifelse\n"); - - fprintf( - pssav, "\n{(%s)} /filename exch def 10 -2.8 18 showfilename\n\n" - " EndFrame\n", - outf.c_str()); - - // output completed: - fclose(pssav); + ps_Plotter->copy_header(fname, mode, withDefs, settings); + ps_Plotter->write_data(fname); } - //! Info line to characterize this plot window. string CPlot::info() const { - string ret; - ret = "x: " + X.info(); - ret += " y: " + Y.info(); - return ret; + if ( p2D ) + return "2D x: " + X.info() + " z: " + Z.info() + " y: " + Y.info(); + return "1D x: " + X.info() + " y: " + Y.info(); } @@ -376,40 +220,5 @@ string CPlot::info() const void CPlot::gp_write(const string& in) { - string out = in + "\n"; - // cout << "monitor gnuplot driver: '" << out << "'\n"; - if (write(gp_fifo, out.c_str(), out.size()) <= 0) - throw S("could not write to gp_fifo"); -} - - -//! Format ticks and tacks for postscript file. - -void CPlot::ps_ticktack( - const vector<double>& Tacks, int ntpt, const double* ticklim, const CAxis* A) -{ - char outlin[mLin]; - int i, ntack; - ntack = Tacks.size(); - if (ntack > 0) { - ps_accu.push_back(" [\n"); - if (A->logflag && (Tacks[0] < 1e-3 || Tacks[ntack - 1] > 1e3)) { - for (i = 0; i < ntack; i++) { - snprintf( - outlin, mLin, " %9.6f {(10)(%i)sp()} %%{(%g)}\n", A->pc(Tacks[i]), - (int)(log10(Tacks[i])), (float)Tacks[i]); - ps_accu.push_back(outlin); - } - } else { - for (i = 0; i < ntack; i++) { - snprintf(outlin, mLin, " %9.6f {(%g)}\n", A->pc(Tacks[i]), (float)Tacks[i]); - ps_accu.push_back(outlin); - } - } - ps_accu.push_back(" ] SetTacVec\n"); - } - snprintf( - outlin, mLin, " %g %g %i %i SetTicVec%s\n", A->pc(ticklim[0]), A->pc(ticklim[1]), - ntack + 2, ntpt, (A->logflag ? "Log" : "Lin")); - ps_accu.push_back(outlin); + gnuPlotter->write(in); } diff --git a/pub/plot/dualplot.hpp b/pub/plot/dualplot.hpp index ad1bc784fa5a43d48db4a182c8a04bcf140729d5..ea79c7afb80e7b8c8710861db01fe494c9f24d66 100644 --- a/pub/plot/dualplot.hpp +++ b/pub/plot/dualplot.hpp @@ -5,19 +5,28 @@ //************************************************************************************************** //! \file dualplot.hpp -//! \brief Collection NPlot of plot frames CPlot. +//! \brief Declares class CPlot. +#include <map> +#include <memory> #include "axis.hpp" - //! One plot frame. class CPlot { public: + CPlot(int _iPlot, bool _logx, bool _logy, bool _p2D, bool _logz); + CPlot(int _iPlot, bool _logx, bool _logy) : CPlot(_iPlot, _logx, _logy, false, false) {} + CPlot(int _iPlot) : CPlot(_iPlot, false, false) {} + CPlot(CPlot const&) = delete; + CPlot& operator=(CPlot const&) = delete; + int iPlot; //!< The index of this frame in NPloWin::Plots. + bool p2D; //!< Two-dimensional color plot? CAxis X; //!< Limits, log flag &c for x axis. CAxis Y; //!< Limits, log flag &c for y axis. + CAxis Z; //!< Limits, log flag &c for z axis in 2D plot. // For data plotting: int maxpoints; //!< Maximum # points to be plotted without reduction. bool with_errors; //!< Plot error bars? @@ -25,38 +34,33 @@ public: int equipoints; //!< Start curve plot with this # grid points. bool refine; //!< Refine curve plot when appropriate? - CPlot(int _iPlot, bool _logx, bool _logy); + void set_dims(const bool _p2D); + void set_aux(const std::string& cmd); void gp_write(const std::string& in); - void clear_frame(); - void plot_frame(const std::string& xlabel, const std::string& ylabel); + void start_frame1D( + const std::string& caller, const std::string& xlabel, const std::string& ylabel); + void reopen_frame1D(); + void start_frame2D(const std::string& caller); + void close_frame2D( + const std::string& xlabel, const std::string& zlabel, const std::string& ylabel); void add_spec( - bool as_line, bool new_style, int style_no, const std::vector<double>& xp, + bool as_line, bool new_slice, int style_no, const std::vector<double>& xp, const std::vector<double>& yp, const std::vector<double>& dyp, - const std::vector<std::string>& z, const std::string& xco, const std::string& yco, + const std::vector<std::string>& zentries, const std::string& xco, const std::string& yco, const std::string& info); + void ps_line(const std::string& line); void show_specs(); void doc_TxLine(const std::string& line); void doc_PtTxLine(const std::string& line, int num); void doc_CvTxLine(const std::string& line, int num); void write_postscript( - const std::string& ps_outdir, const std::string& ps_head, const std::string& ps_dict); - void set_aux(const std::string& cmd); + const std::string& fname, const std::string& mode, const bool withDefs, + std::map<const std::string, std::string>&& settings); std::string info() const; private: - // TODO: some of this could be made local static, if class instances - // are created anew instead of calling clearFrame(). - int gp_fifo; //!< Pipe to Gnuplot. - int gp_fno; //!< Number of Gnuplot input file. - std::string gp_fnames; //!< List of currently plotted Gnuplot input file names. - - int ps_fnum; //!< Postscript output file number. - int ps_snum; //!< Slice number in Postscript file. - int ps_pnum; //!< Spectrum number, for setting pstyle. - int ps_cnum; //!< Curve number, for setting cstyle. - void - ps_ticktack(const std::vector<double>& Tacks, int ntpt, const double* ticklim, const CAxis* A); - std::vector<std::string> ps_accu; //!< Main Postscript cache. - std::vector<std::string> ps_Doc; //!< Special Postscript cache for doc lines ?. + std::shared_ptr<class CGnuPlotter> gnuPlotter; + std::shared_ptr<class CPS_Plotter> ps_Plotter; + bool open1D = false; }; diff --git a/pub/plot/gnuplotter.cpp b/pub/plot/gnuplotter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..346942b05650da619c5f4cb7a225aec112e2fa2d --- /dev/null +++ b/pub/plot/gnuplotter.cpp @@ -0,0 +1,146 @@ +//************************************************************************************************** +//* FRIDA: fast reliable interactive data analysis +//* (C) Joachim Wuttke 1990-, v2(C++) 2001- +//* http://apps.jcns.fz-juelich.de/frida +//************************************************************************************************** + +//! \file gnuplotter.cpp +//! \brief Implements class CGnuPlotter. + +#include <cmath> +#include <cstring> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <boost/format.hpp> + +#include "../trivia/file_ops.hpp" +#include "../trivia/string_convs.hpp" + +#include "axis.hpp" +#include "gnuplotter.hpp" + +#define S(a) triv::strg((a)) + +using std::string; +using std::vector; +using boost::format; + + +CGnuPlotter::CGnuPlotter(int _iPlot) + : iPlot(_iPlot) +{ + // Create a named pipe (FIFO) that will transmit our commands to Gnuplot. + string fn_fifo = "/tmp/gnuplot-" + S(getpid()); + triv::system("rm -f " + fn_fifo); + if (mkfifo(fn_fifo.c_str(), 0666)) + throw "SYSTEM ERROR cannot make fifo " + fn_fifo + ": will not be able to print"; + + // Check that Gnuplot supports X11. + string out = triv::system_read("gnuplot -e 'help X11' 2>&1 < /dev/null"); + if (out.substr(0, 5) == "Sorry" || out.length() < 80) + throw "Gnuplot seems not to support X11"; + + // Start a Gnuplot that will read from our pipe. + triv::system("gnuplot -title " + S(iPlot) + " -noraise < " + fn_fifo + "&"); + + // Open our pipe so that we can write commands to it + // (we use 'open' instead of 'fopen' or 'ofstream', because we need non-blocking mode). + if ((gp_fifo = open(fn_fifo.c_str(), O_WRONLY)) == -1) + throw "SYSTEM ERROR: cannot open fifo " + fn_fifo + " (" + strerror(errno) + ")"; + fcntl(gp_fifo, F_SETFL, O_NONBLOCK); + + // Now the initialization _within_ Gnuplot. + write("set terminal x11"); +} + +//! Send one line to gnuplot fifo. + +void CGnuPlotter::write(const string& in) +{ + string out = in + "\n"; + if (::write(gp_fifo, out.c_str(), out.size()) <= 0) + throw S("could not write to gp_fifo"); +} + +void CGnuPlotter::start_frame(const CAxis& _X, const CAxis& _Y) +{ + X = &_X; + Y = &_Y; + gp_fno = 0; + gp_fnames = ""; + write("set nologscale"); + string whichlog = ""; + if (X->logflag) + whichlog += "x"; + if (Y->logflag) + whichlog += "y"; + if (whichlog != "") + write("set logscale " + whichlog); +} + +void CGnuPlotter::add_spec( + bool as_line, bool new_slice, bool plot_errorbars, int style_no, + const vector<double>& xp, const vector<double>& yp, const vector<double>& dyp, + const vector<string>& zentries, + const string& xco, const string& yco, const string& info) +{ + static const int mColor = 6; + static int color[mColor] = { 0x880000, 0x008800, 0x000088, 0x006666, 0x660066, 0x666600 }; + // Checks: + int np = xp.size(); + if (!np) + throw S("invalid call to CPLot::addSpec: no data points"); + if (np != yp.size()) + throw S("invalid call to CPLot::addSpec: x.size<>y.size"); + + // Prepare for live display, to be shown by showSpecs(): + string gp_fnam = str(format("/tmp/%s-%i-%03i.gnu") % getenv("LOGNAME") % iPlot % gp_fno++); + if (gp_fnames != "") + gp_fnames += ", "; + gp_fnames += string("\"") + gp_fnam + "\" notitle"; + if (as_line) + gp_fnames += str(format(" with lines lt 1 lc rgb \"#%6x\"") % color[style_no % mColor]); + else if (plot_errorbars && dyp.size()) + gp_fnames += " with errorbars"; + FILE* gp_fd; + if (!(gp_fd = fopen(gp_fnam.c_str(), "w"))) + throw "cannot save gnuplot data to " + gp_fnam; + int nout = 0; + try { + for (int i = 0; i < np; i++) { + if (std::isinf(xp[i]) || std::isinf(yp[i])) + throw "Data point number " + S(i) + " is invalid: x=" + S(xp[i]) + ", y=" + + S(yp[i]); + if (xp[i] < X->inf || xp[i] > X->sup) + throw "CPlot::addSpec: x[" + S(i) + "]=" + S(xp[i]) + " out of range"; + if (yp[i] < Y->inf || yp[i] > Y->sup) + throw "CPlot::addSpec: y[" + S(i) + "]=" + S(yp[i]) + " out of range"; + if (plot_errorbars && dyp.size()) + fprintf(gp_fd, "%20.13g %20.13g %20.13g\n", xp[i], yp[i], dyp[i]); + else + fprintf(gp_fd, "%20.13g %20.13g\n", xp[i], yp[i]); + nout++; + } + } catch (string& s) { + fclose(gp_fd); + throw s; + } catch (...) { + fclose(gp_fd); + throw "BUG: unexpected exception type"; + } + fclose(gp_fd); + if (!nout) + throw "no points in frame: " + info; +} + +//! Live display as prepared by addSpec. + +void CGnuPlotter::show_specs() +{ + if (gp_fnames == "") + return; + write(str(format("plot [%12.8g:%12.8g] [%12.8g:%12.8g] ") % X->inf % X->sup % Y->inf % Y->sup) + + gp_fnames); +} diff --git a/pub/plot/gnuplotter.hpp b/pub/plot/gnuplotter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c214c03a93483ee9c7af16c504f28f0512ac7436 --- /dev/null +++ b/pub/plot/gnuplotter.hpp @@ -0,0 +1,35 @@ +//************************************************************************************************** +//* FRIDA: fast reliable interactive data analysis +//* (C) Joachim Wuttke 1990-, v2(C++) 2001- +//* http://apps.jcns.fz-juelich.de/frida +//************************************************************************************************** + +//! \file gnuplotter.hpp +//! \brief Declares class CGnuPlotter + +#include <string> +#include <vector> + +class CAxis; + +class CGnuPlotter { +public: + CGnuPlotter(int _iPlot); + CGnuPlotter(CGnuPlotter const&) = delete; + CGnuPlotter& operator=(CGnuPlotter const&) = delete; + void write(const std::string& in); + void start_frame(const CAxis& _X, const CAxis& _Y); + void add_spec( + bool as_line, bool new_slice, bool plot_errorbars, int style_no, + const std::vector<double>& xp, const std::vector<double>& yp, + const std::vector<double>& dyp, const std::vector<std::string>& zentries, + const std::string& xco, const std::string& yco, const std::string& info); + void show_specs(); +private: + const CAxis* X; + const CAxis* Y; + int iPlot; + int gp_fifo; //!< Pipe to Gnuplot. + int gp_fno; //!< Number of Gnuplot input file. + std::string gp_fnames; //!< List of currently plotted Gnuplot input file names. +}; diff --git a/pub/plot/plowin.cpp b/pub/plot/plowin.cpp index 9bba7e13504091af26cedcca980888aeda1bc68e..73d1efda7d53504249f1e9df62098cc1753c7306 100644 --- a/pub/plot/plowin.cpp +++ b/pub/plot/plowin.cpp @@ -25,6 +25,7 @@ void SPloWin::initialize() m->Plots.push_back(new CPlot(m->nPlot(), true, false)); m->Plots.push_back(new CPlot(m->nPlot(), false, true)); m->Plots.push_back(new CPlot(m->nPlot(), true, true)); + m->Plots.push_back(new CPlot(m->nPlot(), false, false, true, false)); m->iPlot = 0; // current plot window } @@ -36,7 +37,7 @@ void SPloWin::select(int i) iPlot = i; else if (i == nPlot()) { iPlot = i; - Plots.push_back(new CPlot(nPlot(), false, false)); + Plots.push_back(new CPlot(nPlot())); } else throw std::string("invalid graphic window number"); } diff --git a/pub/plot/ps_plotter.cpp b/pub/plot/ps_plotter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..caf204fa120e8cef35256f161fccbe4c916da932 --- /dev/null +++ b/pub/plot/ps_plotter.cpp @@ -0,0 +1,284 @@ +//************************************************************************************************** +//* FRIDA: fast reliable interactive data analysis +//* (C) Joachim Wuttke 1990-, v2(C++) 2001- +//* http://apps.jcns.fz-juelich.de/frida +//************************************************************************************************** + +//! \file gnuplotter.cpp +//! \brief Implements class CPS_Plotter. + +#include <cmath> +#include <fstream> +#include <iostream> +#include <boost/format.hpp> + +#include "../trivia/file_ops.hpp" +#include "../trivia/string_convs.hpp" + +#include "axis.hpp" +#include "ps_plotter.hpp" + +using std::string; +using std::vector; +using boost::format; + +namespace { + string ps_ticktack(const CAxis* A); + string ps_coord(const CAxis* A); + string ps_axis(const CAxis* A); + string ps_horiz(const string& label); + string ps_verti(const string& label); + string ps_colorscale(const string& label); + string ps_slice_header( + bool as_line, int slice_no, int style_no, const vector<string>& zentries, + const string& xco, const string& yco); + string ps_data_block( + const CAxis* X, const CAxis* Y, + const vector<double>& xp, const vector<double>& yp, const vector<double>& dyp); + string ps_footer( + const string& fname, const string& doc_lines); +} + +void CPS_Plotter::start_frame1D( + const string& caller, const CAxis& _X, const CAxis& _Y, + const string& xlabel, const string& ylabel) +{ + p2D = false; + X = &_X; + Y = &_Y; + ps_snum = 0; + ps_Doc = ""; + ps_accu = "\n%% output created by " + caller + "\n\n"; + ps_accu += ps_coord(X); + ps_accu += ps_coord(Y); + ps_accu += "\n"; + ps_accu += ps_axis(X) + ps_horiz(xlabel); + ps_accu += ps_axis(Y) + ps_verti(ylabel); + ps_accu += "\n"; +} + +void CPS_Plotter::start_frame2D( + const std::string& caller, const CAxis& _X, const CAxis& _Z, const CAxis& _Y) +{ + p2D = true; + X = &_X; + Z = &_Z; + Y = &_Y; + ps_snum = 0; + ps_Doc = ""; + ps_accu = "\n%% output created by " + caller + "\n\n"; + ps_accu += ps_coord(X); + ps_accu += ps_coord(Z); + ps_accu += ps_coord(Y); + ps_accu += "\n%% 2D image begin\n"; +} + +void CPS_Plotter::close_frame2D( + const CAxis& _X, const CAxis& _Z, const CAxis& _Y, + const std::string& xlabel, const std::string& zlabel, const std::string& ylabel) +{ + ps_accu += "%% 2D image end\n\n"; + ps_accu += "/linsetTic {white 1 setline} def\n"; + ps_accu += "/linsetTac {white 1.3 setline} def\n\n"; + + ps_accu += ps_axis(X) + ps_horiz(xlabel); + ps_accu += ps_axis(Z) + ps_verti(zlabel); + ps_accu += ps_axis(Y) + ps_colorscale(ylabel); +} + +void CPS_Plotter::add_spec( + bool as_line, bool new_slice, int style_no, + const vector<double>& xp, const vector<double>& yp, + const vector<double>& dyp, const vector<string>& zentries, + const string& xco, const string& yco, const string& info) +{ + + // Postscript copy: + if (new_slice) + ps_accu += ps_slice_header(as_line, ++ps_snum, style_no, zentries, xco, yco); + else + ps_accu += "\n"; + + ps_accu += ps_data_block(X, Y, xp, yp, dyp); +} + +void CPS_Plotter::main_line(const string& line) +{ + ps_accu += line + "\n"; +} + +void CPS_Plotter::doc_line(const string& line) +{ + ps_Doc += line + "\n"; +} + +void CPS_Plotter::copy_header( + const string& fname, const string& mode, const bool withDefs, + std::map<const string, string>& settings) +{ + // copy headers to output file + string cmd; + if (mode=="append") { + if (!triv::file_exists(fname)) + throw "Cannot append graphic: file " + fname + " not found"; + cmd = "cat " + settings.at("ps_continuation") + " >> " + fname; + } else { + if (mode=="create") { + if (triv::file_exists(fname)) + throw "File " + fname + " already exists. " + + "Use command suffix '!' to overwrite"; + } else if (mode=="overwrite") { + } else + throw "BUG: unexpected mode"; + cmd = "cat "; + if (withDefs) + cmd += settings.at("ps_definitions") + " "; + cmd += settings.at(string("ps_setup") + (p2D ? "2" : "1") + "D") + " > " + fname; + } + triv::system(cmd); +} + +void CPS_Plotter::write_data(const string& fname) +{ + // append specific output to output file: + if (!triv::file_exists(fname)) + throw "BUG: after copying headers, graphic output file " + fname + " still doesn't exist"; + std::fstream fs(fname, std::fstream::out | std::fstream::app); + fs << ps_accu; + fs << ps_footer(fname, ps_Doc); + fs.close(); +} + +//************************************************************************************************** +// static functions +//************************************************************************************************** + +namespace { + + //! Format ticks and tacks for postscript file. + string ps_ticktack(const CAxis* A) + { + vector<double> Tacks; + int ticks_per_tack; + int ntacks4ticks; + double ticklim[2]; + A->calc_ticks(Tacks, ticks_per_tack, ntacks4ticks, ticklim); + + string ret; + int ntack = Tacks.size(); + ret += "[\n"; + if (!ntack) + ; // do nothing + else if (A->logflag && (Tacks.front() < 1e-3 || Tacks.back() > 1e3)) { + for (int i = 0; i < ntack; i++) + ret += str(format(" %g w%s {(10)(%i)sp()} %%{(%g)}\n") + % (float)Tacks[i] + % A->name + % (int)(log10(Tacks[i])) + % (float)Tacks[i]); + } else { + for (int i = 0; i < ntack; i++) + ret += str(format(" %g w%s {(%g)}\n") + % (float)Tacks[i] + % A->name + % (float)Tacks[i]); + } + ret += " ] SetTacVec\n"; + ret += str(format("%g w%s %g w%s %i %i SetTicVec%s\n") + % (float)ticklim[0] + % A->name + % (float)ticklim[1] + % A->name + % ntacks4ticks + % ticks_per_tack + % (A->logflag ? "Log" : "Lin")); + return ret; + } + + string ps_coord(const CAxis* A) + { + return str(format("%1i %g %g %cSetCoord\n") + % A->logflag % A->inf % A->sup % A->name); + } + + string ps_axis(const CAxis* A) + { + string ret = "% " + A->name + " axis:\n"; + if (A->logflag && A->inf <= 0) + throw "BUG: log incompatible with limits " + A->str(); + ret += ps_ticktack(A); + return ret; + } + + string ps_horiz(const string& label) + { + return + " 0 10 0 0 0 90 OneAxx Axx Tic Tac xNumL %% low x axis\n" + " 0 10 0 10 0 270 OneAxx Axx Tic Tac %% top x axis\n" + "{(" + label + ")} xCL\n\n"; + } + + string ps_verti(const string& label) + { + return + " 0 10 0 0 90 0 OneAxx Axx Tic Tac yNumL %% left y axis\n" + " 0 10 10 0 90 180 OneAxx Axx Tic Tac %% right y axis\n" + "{(" + label + ")} yCL\n\n"; + } + + string ps_colorscale(const string& label) + { + return + "ColorLegend\n" + " hxlow hxhig 0 0 0 90 OneAxx Axx %% low x line\n" + " hxlow hxhig 0 10 0 90 OneAxx Axx %% low x line\n" + " 0 10 hxlow 0 90 0 OneAxx Tic Tac Axx %% left y axis\n" + " 0 10 hxhig 0 90 180 OneAxx Tic Tac Axx yNumH %% right y axis\n" + "{(" + label + ")} hxhig YCH\n\n"; + } + + string ps_slice_header( + bool as_line, int slice_no, int style_no, const vector<string>& zentries, + const string& xco, const string& yco) + { + string ret; + ret += str(format("%3u [") % slice_no); + for (string zentry: zentries) + ret += " " + zentry; + ret += " ] zValues\n"; + ret += str(format("%2i %cstyle %% (%s -> %s)\n") + % style_no + % (as_line ? 'c' : 'p') + % xco + % yco); + return ret; + } + + string ps_data_block( + const CAxis* X, const CAxis* Y, + const vector<double>& xp, const vector<double>& yp, const vector<double>& dyp) + { + string ret; + int np = xp.size(); + for (int i = 0; i < np; i++) + ret += str(format("%8.5f %8.5f %8.5f t%c %% %13.7g wx %13.7g wy\n") + % X->pc(xp[i]) + % Y->pc(yp[i]) + % (dyp.size() ? Y->pcerr(yp[i], dyp[i]) : 0) + % (i == 0 ? 'i' : i == np - 1 ? 'f' : ' ') + % xp[i] + % yp[i]); + ret += "\n"; + return ret; + } + + string ps_footer(const string& fname, const string& doc_lines) + { + return "{ black 0 -3 13 1.65 NewList\n" + + doc_lines + + " {(plot -> " + fname + ")} TxLine\n" + + "} oooinfo 1 eq { exec } { pop } ifelse\n\n" + + "EndFrame\n"; + } + +} // anonymous namespace diff --git a/pub/plot/ps_plotter.hpp b/pub/plot/ps_plotter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..edc39be074064a123d01d459ee919fbc58bb92a2 --- /dev/null +++ b/pub/plot/ps_plotter.hpp @@ -0,0 +1,48 @@ +//************************************************************************************************** +//* FRIDA: fast reliable interactive data analysis +//* (C) Joachim Wuttke 1990-, v2(C++) 2001- +//* http://apps.jcns.fz-juelich.de/frida +//************************************************************************************************** + +//! \file ps_plotter.hpp +//! \brief Declares class CPS_Plotter + +#include <map> +#include <string> +#include <vector> + +class CAxis; + +class CPS_Plotter { +public: + CPS_Plotter() {} + CPS_Plotter(CPS_Plotter const&) = delete; + CPS_Plotter& operator=(CPS_Plotter const&) = delete; + void start_frame1D( + const std::string& caller, const CAxis& _X, const CAxis& _Y, + const std::string& xlabel, const std::string& ylabel); + void start_frame2D( + const std::string& caller, const CAxis& _X, const CAxis& _Z, const CAxis& _Y); + void close_frame2D( + const CAxis& _X, const CAxis& _Z, const CAxis& _Y, + const std::string& xlabel, const std::string& zlabel, const std::string& ylabel); + void add_spec( + bool as_line, bool new_slice, int style_no, + const std::vector<double>& xp, const std::vector<double>& yp, + const std::vector<double>& dyp, const std::vector<std::string>& zentries, + const std::string& xco, const std::string& yco, const std::string& info); + void main_line(const std::string& line); + void doc_line(const std::string& line); + void copy_header( + const std::string& fname, const std::string& mode, const bool withDefs, + std::map<const std::string, std::string>& settings); + void write_data(const std::string& fname); +private: + bool p2D; + const CAxis* X; + const CAxis* Y; + const CAxis* Z; + int ps_snum; //!< Slice number in Postscript file. + std::string ps_accu; //!< Main Postscript cache. + std::string ps_Doc; //!< Special Postscript cache for doc lines ?. +}; diff --git a/pub/readplus/CMakeLists.txt b/pub/readplus/CMakeLists.txt index b710eefa48576d9a6e9f1c4fece375b12fb691fc..45d7b4c348782d40b1b87cc89f75207101f57979 100644 --- a/pub/readplus/CMakeLists.txt +++ b/pub/readplus/CMakeLists.txt @@ -1,23 +1,27 @@ # frida: readplus/CMakeLists.txt +set(library_name readplus) +set(${library_name}_LIBRARY ${library_name} PARENT_SCOPE) +set(${library_name}_LIBRARY_TYPE SHARED) + include_directories(${Frida_SOURCE_DIR}/readplus READLINE_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) set(src_files -ask.cpp -macro.cpp -readln.cpp -) + ask.cpp + macro.cpp + readln.cpp + ) set(inc_files -ask.hpp -macro.hpp -readln.hpp -) + ask.hpp + macro.hpp + readln.hpp + ) -add_library(libreadplus SHARED ${src_files}) +add_library(${library_name} SHARED ${src_files}) -set_target_properties(libreadplus PROPERTIES OUTPUT_NAME readplus) +set_target_properties(${library_name} PROPERTIES OUTPUT_NAME ${library_name}) -target_link_libraries(libreadplus ${Readline_LIBRARIES}) +target_link_libraries(${library_name} ${Readline_LIBRARIES}) -install(TARGETS libreadplus DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +install(TARGETS ${library_name} LIBRARY DESTINATION ${destination_lib} COMPONENT Libraries) diff --git a/pub/readplus/readln.cpp b/pub/readplus/readln.cpp index 52f62087a75864f0412f6438159f7a824e2f0fc7..7d77d6788e90f1b25ae789f6e90c2f0813bb1607 100644 --- a/pub/readplus/readln.cpp +++ b/pub/readplus/readln.cpp @@ -103,7 +103,9 @@ string NReadln::readline(const string& prompt) char* inp; string ret; inp = ::readline(prompt.c_str()); // from libreadline - if (inp && *inp) + if (!inp) + return "EOF"; + if (*inp) add_history(inp); // from libhistory ret = inp; free(inp); diff --git a/pub/share/CMakeLists.txt b/pub/share/CMakeLists.txt index 6530debb965f05eafae0562a2f2c9627c429ae89..6868d3575fdb3f87a3b2bc1630071fde1327c462 100644 --- a/pub/share/CMakeLists.txt +++ b/pub/share/CMakeLists.txt @@ -1,4 +1,10 @@ configure_file(frida.ini.in frida.ini) -set(share_files ${CMAKE_CURRENT_BINARY_DIR}/frida.ini g3.ps wups11a.ps gnuplot-default-symbols.eps) +set(share_files + ${CMAKE_CURRENT_BINARY_DIR}/frida.ini + wups17a.ps + setup1D.ps + setup2D.ps + continuation.ps + gnuplot-default-symbols.eps + ) install(FILES ${share_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/frida) - diff --git a/pub/share/continuation.ps b/pub/share/continuation.ps new file mode 100644 index 0000000000000000000000000000000000000000..b445711a3a7e9ee8ad3edfbb8a10c8d527ecf797 --- /dev/null +++ b/pub/share/continuation.ps @@ -0,0 +1,12 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Next frame: customizable plot setup +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict17a begin + +Resets +BoxBackground + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ecu", end of the customization section +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/share/frida.ini.in b/pub/share/frida.ini.in index 2c6e0013b5fa53a3f771d121361d23b4109deebc..7981537aafecc16aaf6833deaf9ccddec4695275 100644 --- a/pub/share/frida.ini.in +++ b/pub/share/frida.ini.in @@ -1,8 +1,11 @@ pop($silent=1) -psdir="~/gnew/" -pshead="${CMAKE_INSTALL_PREFIX}/share/frida/g3.ps" -psdict="${CMAKE_INSTALL_PREFIX}/share/frida/wups11a.ps" +ps_outdir="~/gnew/" +ps_setup1D="${CMAKE_INSTALL_PREFIX}/share/frida/setup1D.ps" +ps_setup2D="${CMAKE_INSTALL_PREFIX}/share/frida/setup2D.ps" +ps_continuation="${CMAKE_INSTALL_PREFIX}/share/frida/continuation.ps" +ps_definitions="${CMAKE_INSTALL_PREFIX}/share/frida/wups17a.ps" psgsym="${CMAKE_INSTALL_PREFIX}/share/frida/gnuplot-default-symbols.eps" +ps_viewer="evince" FK01="pv" FK02="pn" -undef("$silent") \ No newline at end of file +undef("$silent") diff --git a/pub/share/setup1D.ps b/pub/share/setup1D.ps new file mode 100644 index 0000000000000000000000000000000000000000..de913f620ed9569e910bc1c477f0050b55b46b6e --- /dev/null +++ b/pub/share/setup1D.ps @@ -0,0 +1,49 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Customizable plot setup, copied from g4.ps (editör: use latin-1) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict17a begin + +8 dup autolabel defsiz +1 dup geld stdred +2 -11 setnewpage newpage + +2 4 12.6 -12.6 setpagegrid +2 8 24 abcset % usage: {(text)} abc +/EndFrame { nextFrame end } def + +1 1 language +1 infSet % plot info block? +1 dup 2 SymGSet % srad slin serr(2=from pset) : graph symbols, global preset +% /setboxbackgroundcolor { 0.93 setgray } def % default is white +% setPalatino + +{ 7 aCol5 iColA } /ipCol x bind def % number of colours and colour style +/pStyles [ + { 11 0 0 1. 1. pset 0 ipCol } + { 12 1 0 1. 1. pset 1 ipCol } + { 13 1 0 1. 1. pset 2 ipCol } + { 1 0 0 1. 1. pset 3 ipCol } + { 1 1 0 .7 1. pset 4 ipCol } + { 3 0 0 1. 1. pset 5 ipCol } + { 3 1 0 .7 1. pset 6 ipCol } + { 4 0 0 1. 1. pset 7 ipCol } + { 4 1 0 .7 1. pset 0 ipCol } + { 5 0 0 1. 1. pset 1 ipCol } + { 5 1 0 .7 1. pset 2 ipCol } + { 2 0 0 1. 1. pset 3 ipCol } + { 2 1 0 .7 1. pset 4 ipCol } + ] def + +{ 8 aCol2 iColA } /icCol x bind def % number of colours and colour style +/cStyles [ + { 1. [] lset black } + { 1. [] lset 0 icCol } + ] def + +Resets +BoxBackground + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ecu", end of the customization section +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/share/setup2D.ps b/pub/share/setup2D.ps new file mode 100644 index 0000000000000000000000000000000000000000..70d226ada703328fb41ba5f81d6f3b4507d0482a --- /dev/null +++ b/pub/share/setup2D.ps @@ -0,0 +1,31 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Customizable plot setup, copied from g4.ps (editör: use latin-1) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict17a begin + +10 dup autolabel defsiz +1 dup geld stdred +2 -11 setnewpage newpage + +2 4 13 -14 setpagegrid +2 8 24 abcset % usage: {(text)} abc +/EndFrame { nextFrame end } def + +1 1 language +1 infSet % plot info block? +1 dup 2 SymGSet % srad slin serr(2=from pset) : graph symbols, global preset +/setboxbackgroundcolor { black } def +% setPalatino + +{ 10 aCol6 {black} {white} iColAA } /icCol x bind def % number of colours and colour style + +/hxlow 11.3 def +/hxhig 12.3 def + +Resets +BoxBackground + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ecu", end of the customization section +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/share/wups17a.ps b/pub/share/wups17a.ps new file mode 100644 index 0000000000000000000000000000000000000000..4336be936504ad6d02248761e1b5e79c38554d64 --- /dev/null +++ b/pub/share/wups17a.ps @@ -0,0 +1,1484 @@ +%!PS-Adobe-2.0 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% FRIDA: fast reliable interactive data analysis %% +%% wups17a.ps: graphic macros %% +%% (C) Joachim Wuttke 1990-2017 %% +%% http://www.messen-und-deuten.de/frida %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/WuGdict17a 400 dict def +WuGdict17a begin + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Generic and math operators +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Shortcuts: + +/np { newpath } bind def +/mv { moveto } bind def +/rm { rmoveto } bind def +/rl { rlineto } bind def +/li { lineto } bind def +/cp { closepath } bind def +/st { stroke } bind def +/x { exch } bind def +/gs { gsave } bind def +/gr { grestore } bind def +/G { gsave exec grestore } bind def + +/F false def +/T true def + +%% Math operators: + +/twopi { 6.2831853072 } def + +/rnd { rand cvr 1 30 bitshift div 2 div 0 max 1 min } def % -> between 0 and 1 + +/min { 2 copy gt { x } if pop } def +/max { 2 copy lt { x } if pop } def + +/tan { dup sin x cos div } def +/cot { dup cos x sin div } def +/pol2xy{ 2 copy cos mul 3 1 roll sin mul } def % r phi | x y + +/eexp { 2.71828 x exp } def % "exp" is x^y, eexp is e^x +/tanh { 2.71828 x 2 copy exp 3 1 roll neg exp 2 copy sub 3 1 roll add div } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Page coordinates +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/pt { .018567 mul} bind def % for line widths and font sizes, reason unclear +/cm {28.346456 mul} bind def % typographic_point -> cm + +/cmtranslate { % x y cmtranslate | - + cm x cm x translate } bind def + +% Move origin from lower left (PostScript default) to upper left +/setnewpage { % xoff yoff + /yoffnewpage x def + /xoffnewpage x def +} def +/originUpperLeft_A4{ .7 28.3 cmtranslate } bind def +/goffsetA4 { ungscale originUpperLeft_A4 gscale } def +/newpage { + goffsetA4 + xoffnewpage yoffnewpage offset +} def + +% Set absolute global scale and relative symbol size +/defsiz { % size(cm) symbolsize(rel) | - + /ftot x def + /gsiz x cm 10 div def + gscale % within 'size', coordinates run from 0 to 10 + } def +/gscale { + gsiz dup scale + } def +/ungscale { + 1 gsiz div dup scale + } def + +% Symbol (and label?) size as sublinear function of figure size +/autolabel { % size(cm) | symbolsize(rel) + dup 7 div 2 add 4 mul % the simplest sublinear increase + x div % anticipate overall rescaling + } def + +% Aspect ratios +/gyld {0.447214 mul} bind def /Gyld {0.447214 div} bind def % sqrt(5) +/guld {0.547723 mul} bind def /Guld {0.547723 div} bind def % sqrt(3) +/gold {0.618034 mul} bind def /Gold {0.618034 div} bind def % goldener Schnitt +/gild {0.707107 mul} bind def /Gild {0.707107 div} bind def % sqrt(2) : DIN +/geld {0.759836 mul} bind def /Geld {0.759836 div} bind def % sqrt(sqrt(3)) +/gald {0.817765 mul} bind def /Gald {0.817765 div} bind def % sqrt sqrt sqrt 5 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Several frames per page +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/setpagegrid { % ncol nrow xoffnewframe yoffnewframe + /yoffnewframe x def + /xoffnewframe x def + /nrowpage x def + /ncolpage x def +} def +/iFrame 0 def +/nextFrame { + /iFrame iFrame 1 add def + iFrame nrowpage ncolpage mul mod 0 eq { + showpage gscale newpage + } { + iFrame ncolpage mod 0 eq { + xoffnewframe ncolpage 1 sub neg mul yoffnewframe offset + } { + xoffnewframe 0 offset + } ifelse + } ifelse + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Frame coordinates +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/defred { % x_reduction y_reduction label_reduction | - + /fmm x ftot mul def + /ymm x def + /xmm x def + + % conversion frame_coordinate -> global_coord + /xm {xmm mul} bind def + /ym {ymm mul} bind def + /fm {fmm mul} bind def + /xym {ym x xm x} bind def + + % prefer rescaling over explicit conversion (make more use of this !) + /mmscale { xmm ymm scale } bind def + /mmunscale { 1 xmm div 1 ymm div scale } bind def + + % graphic commands in frame coordinates + /offset { xym translate } bind def + /currentxy { currentpoint ymm div x xmm div x } bind def + /setline { pt fm setlinewidth [] 0 setdash } bind def + } def + +/stdred { % x_reduction y_reduction | - + 2 copy mul sqrt defred + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% World (= user application) coordinates +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/xSetCoord { % log min max | - + /wxmax x def + /wxmin x def + /wxlog x 0 eq not def + /wxdel wxmax wxmin wxlog { div log } { sub } ifelse def + /wxd { % dx(world) | dx(frame) + wxlog { log } if wxdel div 10 mul + } bind def + /wx { % x(world) | x(frame) + wxmin wxlog { div } { sub } ifelse + wxd + } bind def + } def +/ySetCoord { % log min max | - + /wymax x def + /wymin x def + /wylog x 0 eq not def + /wydel wymax wymin wylog { div log } { sub } ifelse def + /wyd { % dy(world) | dy(frame) + wylog { log } if wydel div 10 mul + } bind def + /wy { % y(world) | y(frame) + wymin wylog { div } { sub } ifelse + wyd + } bind def + } def +/hSetCoord { % log min max | - % for use in 2D plot + /whmax x def + /whmin x def + /whlog x 0 eq not def + /wH { % h(world) | h(col) + dup whmin lt { + pop -1 + } { + dup whmax gt { + pop 11 + } { + wh + } ifelse + } ifelse + } bind def + whlog { + /whdel whmax whmin div log def + /wh { whmin div log whdel div 10 mul } bind def % h(world) | h(col) + } { + /whdel whmax whmin sub def + /wh { whmin sub whdel div 10 mul } bind def % h(world) | h(col) + } ifelse + } def + +% pair conversion +/wxy { % x,y(world) -> x,y(frame) + wy x wx x + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Colors %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Color operators: + +/setRGBcolor { + 3 { 255 div 3 1 roll } repeat setrgbcolor + } def + +/colormix { % weight(0..1) col1(R|G|B) col2(R|G|B) | col(R|G|B) + 7 -1 roll dup /weightA x def /weightB x 1 x sub def + 4 -1 roll weightA mul x weightB mul add 5 1 roll + 3 -1 roll weightA mul x weightB mul add 4 1 roll + 2 -1 roll weightA mul x weightB mul add 3 1 roll + } def + +/relcol { % i_col n_col | rel(0..1) : for one-dimensional choices + 1 sub div 0 max 1 min + } def + +%% Named colors: + +/black { 0 setgray } bind def +/white { 1 setgray } bind def + +/red { 255 0 0 setRGBcolor } bind def + +/siemensorange { 255 153 0 setRGBcolor } bind def +/siemensblue { 0 102 153 setRGBcolor } bind def +/siemenstext { 0 51 102 setRGBcolor } bind def +/siemensred { 165 0 33 setRGBcolor } bind def +/siemenspink { 221 102 102 setRGBcolor } bind def +/siemensgrey { 221 221 221 setRGBcolor } bind def +/siemensdark { 102 102 102 setRGBcolor } bind def +/siemensgreen { 33 153 102 setRGBcolor } bind def +/siemensyellow { 255 221 0 setRGBcolor } bind def + + +%% One-dimensional linear color choices: + +/iCol1 { % i i_max | - : default -2010, round the circle, RGBR + relcol dup 1 x % rel 1 rel + 360 mul 255 add cos 1 add dup mul neg .053 mul 1 add % modulate saturation + sethsbcolor + } def +/iCol2 { % i i_max | - : cyan - yellow - magenta + relcol 3 mul + dup 1 le { + dup 1 sub neg 0 3 2 roll } { + dup 2 le { + 1 sub dup 1 sub neg 0 3 1 roll } { + 2 sub dup 1 sub neg 0 3 0 roll } ifelse + } ifelse + 0 setcmykcolor + } def +/iCol3 { % i i_max | - : siemens + div /icnow x def + 165 1 icnow sub mul + 102 icnow mul + 33 120 icnow mul add setRGBcolor + } def +/iCol4 { % i i_max | - : red to blue (subsequence of old scheme iCol1) + relcol + 3 x sub 3 div 1 iCol1 + } def + + +%% One-dimensional color choice from given array: + +/iColA { % i i_max arr | - + /aCol x def + relcol + aCol length 1 sub mul % position within array + dup cvi dup 3 1 roll % idx pos idx + sub x % offset idx + 0 max aCol length 1 sub min % offset safe_idx + dup 1 add aCol length 1 sub min % offset i i+1 + aCol x get exec + 4 3 roll aCol x get exec colormix setRGBcolor + } def + +%% ditto with discontinuous values for h<0 and h>1 + +/iColAA { % i i_max arr {low_col} {hig_col} | - + 5 3 roll + div + dup 0 lt { + pop pop x pop exec + } { + dup 1 gt { + pop 3 1 roll pop pop exec + } { + 1 % arr {l} {h} i i_max + 5 2 roll pop pop + x 1 add x % ad-hoc correction for legacy definition of relcol + iColA + } ifelse + } ifelse + } def + +%% Color arrays for non-linear one-dimensional choices: + +/aCol1 [ % red-blue + { 255 0 0 } % 1 + { 240 10 10 } % 2 + { 220 40 40 } % 3 + { 205 65 90 } % 4 + { 195 80 130 } % 5 + { 180 110 180 } % 6 + { 165 120 185 } % 7 + { 150 130 190 } % 8 + { 130 150 210 } % 9 + { 110 125 220 } % 10 + { 85 105 230 } % 11 + { 70 90 255 } % 12 + { 0 0 255 } % 13 + ] def +/aCol2 [ % orange-red-blue-darkblue + { 255 180 0 } + { 255 160 0 } + { 255 120 0 } + { 255 70 0 } + { 255 0 0 } + { 220 30 30 } + { 220 70 60 } + { 220 100 110 } + { 200 130 130 } + { 200 130 160 } + { 180 110 180 } + { 165 110 185 } + { 150 130 190 } + { 130 150 210 } + { 100 120 220 } + { 85 105 230 } + { 70 90 255 } + { 0 0 255 } + { 0 0 180 } + { 10 10 150 } + { 30 30 130 } + ] def +/aCol3 [ % [fixed size: max_i=8] siemenscolors + { 165 0 33 } % siemensred + { 33 153 102 } % siemensgreen + { 0 102 153 } % siemensblue + { 0 51 102 } % siemenstext + { 255 153 0 } % siemensorange + { 102 102 102 } % siemensdark + { 255 221 0 } % siemensyellow + { 221 221 221 } % siemensgrey + { 221 102 102 } % siemenspink + ] def +/aCol4 [ % green-blue-brown + { 120 160 60 } + { 90 185 40 } + { 50 215 20 } + { 0 245 0 } + { 10 235 112 } + { 20 235 143 } + { 30 230 173 } + { 40 225 194 } + { 50 205 215 } + { 40 153 204 } + { 40 102 153 } + { 40 82 122 } + { 90 74 101 } + { 140 68 80 } + { 170 59 60 } + { 190 50 40 } + { 180 65 40 } + { 160 80 40 } + { 140 100 40 } + { 120 80 30 } + { 100 60 20 } + ] def +/aCol5 [ % [fixed size: max_i=7] old gnuplot default (see man gnuplot and rgb.txt) + { 255 0 0 } % red + { 0 255 0 } % green + { 0 0 255 } % blue + { 255 0 255 } % magenta + { 0 255 255 } % cyan + { 160 82 45 } % sienna + { 255 165 0 } % orange + { 255 127 80 } % coral + ] def +/aCol6 [ % heat plot + { 100 0 100 } % violet + { 60 30 130 } % dark blue + { 30 50 220 } % blue + { 50 150 100 } % green + { 150 200 100 } % green + { 215 255 50 } % green/yellow + { 255 255 0 } % yellow + { 255 125 0 } % orange + { 255 0 0 } % red + ] def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Fonts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% extend font encoding +/ReEncode { % OldFont NewFont Encoding | - + /MyEncoding x def + x findfont % select OldFont + dup length dict begin + {def} forall + /Encoding MyEncoding def + currentdict + end + definefont pop % define as NewFont + } def + +% we assume that image scripts are Latin1 encoded +/Helvetica /MyFont ISOLatin1Encoding ReEncode +/Helvetica-Oblique /MyFont-Oblique ISOLatin1Encoding ReEncode +/Helvetica-Bold /MyFont-Bold ISOLatin1Encoding ReEncode +/Helvetica-BoldOblique /MyFont-BoldOblique ISOLatin1Encoding ReEncode + +/setPalatino { + /Palatino /MyFont ISOLatin1Encoding ReEncode + /Palatino-Italic /MyFont-Oblique ISOLatin1Encoding ReEncode + /Palatino-Bold /MyFont-Bold ISOLatin1Encoding ReEncode + /Palatino-BoldItalic /MyFont-BoldOblique ISOLatin1Encoding ReEncode + } def + +%% Preset standard styles: + +% scale and set font; define fontsize, fontheight +/setfontandsize { % font size | - + dup 0 le { pop 100 } if % fontsize <= 0 not allowed ! + /fontnonnil true def + pt fm dup /fontsize x def + x findfont + x scalefont + setfont + gsave % determine fontheight - from the cookbook : + np 0 0 mv (1) true charpath flattenpath + pathbbox % low_left_x, low_left_y, up_right_x, up_right_y + x pop x pop x pop + /fontheight x def + grestore + } def + +% standard settings for labelling axes +/numlabcol { black } def +/setnum { /MyFont 24 setfontandsize numlabcol } def +/setlab { /MyFont 24 setfontandsize numlabcol } def + +% user commands (free choice of fontsize, but fixed font family) +/setown { /MyFont x setfontandsize } def +/setbol { /MyFont-Bold x setfontandsize } def +/setboq { /MyFont-BoldOblique x setfontandsize } def +/setobl { /MyFont-Oblique x setfontandsize } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Text blocks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/showif { % string | - : increment xwidth or plot string + prepare + { stringwidth pop xwidth add /xwidth x def } + { show } + ifelse + } def +/script { % matrix relpos_y | - + /yoffset x fontheight mul def + currentfont x makefont setfont + 0 yoffset rm + } def +/scred .71 def +/subsc { + showif + [scred 0 0 scred 0 0] -.2 script + } def +/supsc { + showif + [scred 0 0 scred 0 0] .6 script + } def +/endsc { + showif + regularfont setfont + 0 yoffset neg rm + } def +/grec { + showif + /Symbol findfont fontsize scalefont setfont + } def +/endgr { + showif + regularfont setfont + } def +/endall { + showif + regularfont setfont + } def +/build { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + dup showif + prepare + { pop } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/gbuild { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + /Symbol findfont fontsize scalefont setfont + dup showif + prepare + { pop regularfont setfont } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + regularfont setfont + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/hut { % ..) (<Char>) hut (.. %%% MISERABEL PROGRAMMIERT + x showif + 1.4 .6 {(\136) show ()} build + } def +/ghut { % ..) (<grec-Char>) ghut (.. %%% BREITE PASST NUR FUER Phi(t) + x showif + .8 .65 {(\136) show ()} gbuild + } def +/tilde { + x showif + 1. .6 {(~) show ()} build + } def +/gtilde { + x showif + 1. .6 {(~) show ()} gbuild + } def +/spce { % string n spce - ; insert n times ( ) + {showif ( )} repeat + } def + +% the following macros use the symbol/curve plotting mechanism +/pins { % string symins - ; symbol must be selected by pset + showif + ( ) showif ( ) .5 .5 { currentxy 0 p black ()} build ( ) showif + } def +/clenins { % string len clenins - ; curve must be selected by cset + x showif % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div def + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def +/cins { % string symins - ; curve must be selected by cset + showif 8 % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div 10 div def + % nov03, ohne zu verstehen, "10 div" eingefuegt + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def + +/block { % x y ob xrel yrel | - + /yrel x def /xrel x def /blabla x def + /ypos x ym def /xpos x xm def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall % first pass : determine xwidth + boxif { /boxwidth xwidth (M) stringwidth pop boxxr mul 2 mul add def + /boxheight fontheight 1 boxyr 2 mul add mul def + np xpos xwidth xrel mul sub boxwidth xwidth sub 2 div sub + ypos fontheight .5 boxyr add mul sub mv + boxwidth 0 rl 0 boxheight rl boxwidth neg 0 rl cp + boxproc + } if + xpos xwidth xrel mul sub ypos fontheight yrel mul sub mv + /prepare false def + blabla endall % second pass : plot + /boxif false def + } def +/rblock { % x y ang ob proc rblock - + 5 3 roll + gsave + xym translate + 3 2 roll rotate + 0 0 4 2 roll exec + grestore + } def + +/Box { % x y {exe} + /boxif true def + /boxproc x def /boxyr x def /boxxr x def + } def +/nBox { .6 .6 3 2 roll Box } def +/boxif false def +/textW { % obj | length : calculate only length. + /blabla x def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall + xwidth % has been determined + } def +/textw { % obj | y : dito, in 0..10-units + textW xmm div + } def + +% horizontal text: x y ob | - +/textLB { 0. 0. block } bind def +/textCB { .5 0. block } bind def +/textRB { 1. 0. block } bind def +/textLM { 0. .5 block } bind def +/textCM { .5 .5 block } bind def +/textRM { 1. .5 block } bind def +/textLT { 0. 1. block } bind def +/textCT { .5 1. block } bind def +/textRT { 1. 1. block } bind def + +% rotated text: x y ang ob | - +/rtextLB { {textLB} rblock } bind def +/rtextLM { {textLM} rblock } bind def +/rtextRB { {textRB} rblock } bind def +/rtextRM { {textRM} rblock } bind def +/rtextCM { {textCM} rblock } bind def + +%% Language selection: + +% preset +/language { % choose_this of_so_many | - % select current language + /langMax x def + /langChc x def + } def +1 1 language % default +% choose text from sequence +/langSel { % text_1 .. text_M | text_C : choose text, M=langMax, C=langChc + langMax dup langChc sub 1 add roll + langMax 1 sub { pop } repeat + } def +/L { langSel } bind def + +%% Text composition shortcuts: + +/g { x grec endgr} bind def +/sb { x subsc endsc} bind def +/sp { x supsc endsc} bind def +/sbgr { x grec () subsc endsc () endgr} bind def +/spgr { x grec () supsc endsc () endgr} bind def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Text macros +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/Celsius { showif (\26x)g(C) showif } bind def +/hbar { + showif + (h) 1.2 .66 { + currentpoint fontheight .11 mul setline np mv + fontheight dup .8 mul x .3 mul rl + st () + } build + } bind def + +%% for neutron scattering: + +/hbarw { hbar () grec (w) endgr } bind def +/wbar { grec (w) endgr ( / 2) grec (p) endgr } bind def +/taumean { () (\341t\361) g } bind def +/Sqw { showif (S\(q,) grec (w) endgr (\)) showif } bind def +/Sqn { showif (S\(q,) grec (n) endgr (\)) showif } bind def +/SQw { showif (S\(Q,) grec (w) endgr (\)) showif } bind def +/Sttw { showif (S\(2) grec (q) endgr (,) grec (w) endgr (\)) showif } bind def +/Sttn { showif (S\(2) grec (q) endgr (,) grec (n) endgr (\)) showif } bind def +/Xqw { grec (c) endgr (''\(q,) grec (w) endgr (\)) showif } bind def +/Xqn { grec (c) endgr (''\(q,) grec (n) endgr (\)) showif } bind def +/ueV{ grec (m) endgr (eV) showif} bind def +/inueV { showif (\() grec (m) endgr (eV\)) showif } bind def +/inmeVr { showif (\(meV) supsc (-1) endsc (\)) showif } bind def +/inueVr { showif (\() grec (m) endgr (eV) + supsc (-1) endsc (\)) showif } bind def +/inGHzr { showif (\(GHz) (-1) sp (\)) showif } def + +/Angstr { showif (\305) showif } bind def +/Angr { showif (\305) supsc (-1) endsc } bind def +/inAngr { showif (\() Angr (\)) showif } bind def +/Angrr { showif (\305) supsc (-2) endsc } bind def +/inAngrr { showif (\() Angrr (\)) showif } bind def +/wmin {grec (w) endgr () subsc (min) endsc} def +/winpi { grec (w) endgr ( / 2) grec (p) endgr } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Coordinate Frame %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Layout presets: + +/xyTicLen {0.10 fm} def +/xyTacLen {0.20 fm} def +/txllen {0.20 fm} def +/tyllen {0.20 fm} def +/linsetAxx {black 0.7 setline} def +/linsetTic {black 0.7 setline} def +/linsetTac {black 0.7 setline} def +/linsetGri {black 0.4 setline} def + +%% Start-up commands: + +/Resets { + /yNumLengthL 0 def /yNumLengthH 0 def + /xNumHeightL .3 def /xNumHeightH 0 def + /xNumHeightRel 2.4 def + /aMean 5 def + black + } def +/BoxBackground { + 0 10 0 10 rect gsave setboxbackgroundcolor fill grestore +} def +/setboxbackgroundcolor { white } def + +/zValues { pop pop } def +/whiteframe { 1 0 0 10 10 graybox } def + +/abc {abclab setown abcx abcy 3 2 roll textCM} def % usage ((a)) abc +/abcset { % x y siz abcset - : preset for abc + /abclab x def /abcy x def /abcx x def + } def + +%% Ticks: + +% set tick array - internal macros +/tiputs { % rel_pos_of_tick | pos_of_tick : innermost routine for /taproc + tastep mul taloop add + } def +/taproclin { % (#tick/tack) | - : define /taproc for use in SetVec + 1 x div /tistep x def + /taproc { 0 tistep .999 { tiputs } for } def + } def +/taproclog { % (#ticks/tacks) | - : define /taproc for use in SetVec + dup 3 gt { pop /taproc { 1 1 9 { log tiputs } for } def + }{ dup 1 gt { pop /taproc { 0 tiputs 2 log tiputs 5 log tiputs } def + }{ dup 0 gt { pop /taproc { 0 tiputs } def + }{ neg taproclin + } ifelse } ifelse } ifelse + } def +/SetVec { % tafro tatoo nta /vector | - : set /vector + 4 1 roll + /nta x def /tatoo x def /tafro x def + /tastep tatoo tafro sub nta 1 sub div def + [ + 0 1 nta { + tastep mul tafro add /taloop x def + taproc exec + } for + ] def + } def +% set tick array - user commands +/SetTicVecLin { taproclin /TicVec SetVec } def +/SetTicVecLog { taproclog /TicVec SetVec } def + +% set tack-and-number array +/SetTacVec { % [ pos {label} pos {label} ... ] | - + /TacVec x def + } def + +% define axes + % note on angles : 0 = x-axis, 90 = y-axis +/OneAxx { % fro to xpos ypos aang tang | - : presets for Axx, Tic, Tac, Num + % store arguments + /tAng x def /aAng x def + /yPos x def /xPos x def + /aTo x def /aFro x def + % set constants + /xTicLen tAng cos xyTicLen mul def /yTicLen tAng sin xyTicLen mul def + /xTacLen tAng cos xyTacLen mul def /yTacLen tAng sin xyTacLen mul def + /xAng aAng cos def /yAng aAng sin def + /aMean aFro aTo add 2 div def + } def + +% draw axis (with parameters preset by OneAxx or ArrAxx) +/Axx { % - | - + linsetAxx + gsave + xPos yPos offset + mmscale + aAng rotate + % draw a line + aFro 0 np mv + aTo 0 li st + grestore + } def + +% draw ticks (positions given by SetTicVec, parameters preset by OneAxx/..) +/Tic { % - | - : draw tick as defined in TicProc + linsetTic + TicVec { + dup dup aFro lt x aTo gt or {pop} {TicProc} ifelse + } forall + } def +/TicProc { % aPos | - : default procedure to plot one tick + np + xPos yPos xym mv + dup xAng mul x yAng mul xym rm % eat argument, go to start pos. + xTicLen yTicLen rl st + } def +/xGric { % yFro yTo | - : draw a grid line (instead of an x tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % y1 y2 x x + 4 -1 roll xym np mv % y2 x + x xym li st + } ifelse + } forall + pop pop + } def +/yGric { % xFro xTo | - : draw a grid line (instead of an y tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % x1 x2 y y + 4 -1 roll x xym np mv % x2 y + xym li st + } ifelse + } forall + pop pop + } def + +% draw tacks (positions given by SetTacVec, parameters preset by OneAxx/..) +/TacExe { % Proc | - % Execute Proc for all pairs of elements of TacVec + % (but only if inside aFro..aTo) + /TacProc x def + /ispair true def % toggle: take pos, take label, take pos, take label ... + TacVec { + ispair + { + /aPos x def + /ispair false def + } { + aPos dup aFro lt x aTo gt or + {pop} {TacProc} ifelse + /ispair true def + } ifelse + } forall + } def +/Tac { + linsetTac + { pop xPos yPos xym mv + aPos dup xAng mul x yAng mul xym rm + xTacLen yTacLen rl st + } TacExe + } def +% special tack routines, only for rectangular axes +/xTacC { % : centered tack on x axis + linsetTac + { pop aPos xm yPos ym txllen 2 div sub np mv 0 txllen rl st } TacExe + } def +/xGrid { % : rule instead of tack on x axis + linsetTac + { pop aPos xm np yPos ym mv 0 10 xym rl st } TacExe + } def +/yTacC { % : centered tack on y axis + linsetTac + { pop xPos xm tyllen 2 div sub aPos ym np mv tyllen 0 rl st } TacExe + } def +/yGrid { % : rule instead of tack on low y axis + linsetTac + { pop aPos ym np xPos xm x mv 10 0 xym rl st } TacExe + } def + +% draw numbers (pos-txt pairs given by SetTacVec) +/Num { % Generic but useless. Adjust for your application. + setnum + fontheight ymm div yDisRel mul tAng sin mul /yDist x def + { dup textW xDisRel mul tAng cos mul /xDist x def + xPos aPos xAng mul add xDist sub + yPos aPos yAng mul add yDist sub 3 2 roll textCM + } TacExe + } def +/setnumDisRel { % xDisRel yDisRel | - : adjust just a little bit + /yDisRel x def /xDisRel x def + } def +1.2 1.2 setnumDisRel % default setting +% explicit Num routines for rectangular case +/xNumL { % : numbers on low x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightL x def + -.6 mul yPos add aPos x 3 2 roll textCT + } TacExe + } def +/xNumH { % : numbers on high x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightH x def + .6 mul yPos add aPos x 3 2 roll textCB + } TacExe + } def +/yNumL { % : numbers on low y axis + setnum + { fontsize -.3 mul xmm div xPos add aPos 3 2 roll textRM + xwidth dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yNumLD { % : calculate only yNumLength (used for adjustement) + setnum + { textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yDumL { % {(..)} yDumL : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } def +/yNumH { % : numbers on high y axis + setnum + { fontsize .3 mul xmm div xPos add aPos 3 2 roll textLM + xwidth dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yNumHD { % : calculate only yNumLength (used for adjustement) + setnum + {textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yDumH { % {(..)} yDumH : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } def + +% draw labels +/xCL { % xlabel | - ; plots coordinate name below the x-axis. + setlab + aMean xNumHeightL xNumHeightRel neg mul + 3 -1 roll textCT + } def +/xCH { % xlabel | - ; plots coordinate name above the x-axis. + setlab + aMean xNumHeightH xNumHeightRel mul 10 add + 3 -1 roll textCB + } def +/yCL { % ylabel | - ; plots coordinate name to the left of the y-axis. + gsave + setlab + yNumLengthL neg fontsize -.85 mul add % yNumLengthL calculated in yN + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCB + grestore + } def +/YCH { % ylabel xpos | - ; plots coordinate name to the right of a vertical axis + gsave + setlab + yNumLengthH fontsize .85 mul add x xm add + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCT + grestore + } def +/yCH { 10 YCH } def % ylabel | - ; plots coordinate name to the right of the y-axis. +/yCF { % ylabel | - ; plots coordinate name *falling* right of the y-axis. + gsave + setlab + yNumLengthH fontsize .85 mul add 10 xm add + aMEan ym translate + 0 0 mv + -90 rotate + 0 x 0 x textCB + grestore + } def + +/knautschy { % x0 y0 y_knau y_tot knautschy - : insert an S in dived y-axis + % the total height of the generated object is y_tot + % of which y_knau(.le. y_tot) is for the real knautsch, + % the remainder is for vertical prolongations. + x ym 4 div dup /tmpy x def 5 sqrt mul /tmpx x def + /tmpa x ym tmpy 4 mul sub 2 div def + np ym x xm x mv 0 tmpa rl tmpx tmpy rl tmpx -2 mul tmpy 2 mul rl + tmpx tmpy rl 0 tmpa rl st + } def +/separy { % x0 y0 sep lng ang lin - : insert an // in dived y-axis + setline + /spang x def + /splng x def + /spsep x def + 2 copy spsep sub gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + spsep add gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Data Plotting (Symbols and Curves) %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Initializations: + +% asymmetric error bars? +/err_asy false def % overwrite this if data are quadruples x y d- d+ + +%% Presets: + +% global preset +/SymGSet { % sradglo slinglo serrglo | - + /serrglo x def % plot error bars? 0=never, 1=always, 2=as_given_in_pset + /slinglo x def % symbol linewidth multiplier + /sradglo x def % symbol size multiplier + } def + +%% Retrieve presets from style array: + +/pstyle { pStyles setstyle } def +/cstyle { cStyles setstyle } def +/setstyle { % chosen_number array | - : set p or c as predefined in array. + dup length % i A n + 3 2 roll % A n i + dup 0 le { + pop pop pop ostyle % chosen_number<=0 means: don't plot + } { + 1 sub x % A i-1 n + mod get % A(i-1) + exec + } ifelse + } def + +%% Set plot symbol: + +/pset { % styp sfill serr srad slin | - + % arg -> symbol linewidth + /slin x slinglo mul def + % arg -> symbol size + /srad x fm 0.16 mul sradglo mul def + % arg -> plot error bar? + 2 serrglo ne { pop serrglo } if % if (serrglo=2) use serr else use serrglo + /plot_errorbar x 1 eq { { errorbar } } { { pop pop pop pop } } ifelse def + % arg -> fill the symbol? (0=open, 1=full, 2=colored_with_black_border) + /sfill x def + % adjust srad: it's the _outer_ radius + % TROUBLE sfill 1 ne {/srad srad slin fm pt sub def} if + % arg -> symbol type + /ps {ps_nil} def % default: don't plot (maybe we only want an error bar) + dup 1 eq {/ps {ps_square} def} if + dup 2 eq {/ps {ps_diamond} def} if + dup 3 eq {/ps {ps_circle} def} if + dup 4 eq {/ps {ps_triangle} def} if + dup 5 eq {/ps {ps_cedez} def} if + dup 6 eq {/ps {ps_eieruhr} def} if + dup 7 eq {/ps {ps_valve} def} if + dup 8 eq {/ps {ps_tfwd} def} if + dup 9 eq {/ps {ps_tbwd} def} if + dup 10 eq {/ps {ps_pentagram} def} if + dup 11 eq {/ps {ps_plus} def} if + dup 12 eq {/ps {ps_cross} def} if + dup 13 eq {/ps {ps_star} def} if + dup 14 eq {/ps {ps_pentagon} def} if + dup 15 eq {/ps {ps_horiz} def} if + dup 16 eq {/ps {ps_verti} def} if + pop + % + /t { % x y d[- d+] | - : plot a symbol and eventually an error bar. + err_asy not { dup } if + 4 copy pop pop plot_symbol + plot_errorbar + } bind def + /ti { t } bind def + /tf { t black } bind def + } def + +%% Set curve: + +/lset { % lwidth dashes | - + 0 setdash + dup 0 gt { + pt fm setlinewidth + % pop error bar and convert frame coord -> paper coord + /txy { err_asy { pop } if pop xym } def % x y d[- d+] | x' y' + % commands to plot points (can be overwritten by nopoints): + /ti { np txy mv } def % x y d[- d+] | - : start curve + /t { txy li } def % x y d[- d+] | - : continue curve + /tf { txy li st } def % x y d[- d+] | - : terminate and plot curve + } { + ostyle + } ifelse + } def + +%% Plot nothing: + +/ostyle { % - | - + /ti { nopoint } def + /t { nopoint } def + /tf { nopoint } def +} def +/nopoint { % x y d[- d+] | - + pop pop pop err_asy { pop } if +} def + +%% Plot an asymmetric vertical error bar: + +/errorbar { % x y d- d+ | - + gsave + slin setline + 3 copy pop pop + dup 0 gt x 10 lt and { + 4 copy + x pop add 10. 2 copy gt { x } if pop ym x xm x + 2 copy x .05 sub x np mv .1 0 rl st + np mv + pop sub 0. 2 copy lt { x } if pop ym x xm x + 2 copy lineto st + x .05 sub x np mv .1 0 rl st + } { + pop pop pop pop + } ifelse + grestore +} def + +%% Plot a data symbol: + +/plot_symbol { % x y | - + gsave + offset + srad dup scale + slin srad div setline % factor 1/srad compensates "scale" + ps % the actual plot symbol, defined by 'pset' + grestore + } def + +/fill_symbol { + sfill dup + 0 eq { + pop st + } { + 1 eq { + fill + } { + gsave fill grestore + gsave black st grestore + } ifelse + } ifelse + } def + +%% The different symbols, designed for unit area (no arguments): + +/ps_nil { + } bind def + +/ps_square { + .5 .5 np mv + 0 -1 rl + -1 0 rl + 0 1 rl cp fill_symbol + } bind def + +/ps_diamond { + gsave 45 rotate ps_square grestore + } bind def + +/ps_circle { + 0 0 np .564 0 360 arc cp fill_symbol + } bind def + +/ps_triangle { + .77 dup dup 90 pol2xy np mv + 210 pol2xy li + 330 pol2xy li cp fill_symbol + } bind def + +/ps_cedez { + gsave 180 rotate ps_triangle grestore + } bind def + +/ps_tfwd { + gsave 30 rotate ps_triangle grestore + } bind def + +/ps_tbwd { + gsave 210 rotate ps_triangle grestore + } bind def + +/ps_eieruhr { + -.7 -.7 np mv + .7 -.7 li + -.7 .7 li + .7 .7 li cp fill_symbol + } bind def + +/ps_valve { + gsave 90 rotate ps_eieruhr grestore + } bind def + +/ps_pentagram { + .8 dup dup dup dup + 90 pol2xy np mv + 234 pol2xy li + 18 pol2xy li + 162 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_pentagon { + .8 dup dup dup dup + 18 pol2xy np mv + 90 pol2xy li + 162 pol2xy li + 234 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_plus { + gsave 45 rotate ps_cross grestore + } bind def + +/ps_cross { + .5 .5 np mv + -1 -1 rl st + -.5 .5 np mv + 1 -1 rl st + } bind def + +/ps_star { + .7 dup 0 pol2xy np mv 180 pol2xy li st + .7 dup 120 pol2xy np mv 300 pol2xy li st + .7 dup 240 pol2xy np mv 60 pol2xy li st + } bind def + +/ps_horiz { + -.7 0 np mv + 1.4 0 rl st + } bind def + +/ps_verti { + 0 -.7 np mv + 0 1.4 rl st + } bind def + +%% Set column plotting (use this instead of pset) +/setcolumn{ % shift width exec | % + % usage: 0 .2 { gsave { .5 setgray fill } grestore cp } setcolumn + /colexec x def + /colwidth x xm def + /colshift x xm def + /t { + pop xym + np x colshift add colwidth 2 div sub dup 3 2 roll mv + colwidth 0 rl + colwidth add 0 li + colwidth neg 0 rl + cp colexec + } def + /ti { t } bind def + /tf { t black } bind def +} def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 2D plots %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/t2d { + icCol rect fill + black +} def + +/ColorLegend { % - | - [plot color legend to rectangle hxlow hxhig 0 10] + /ncol 100 def + 1 1 ncol { + dup ncol div 10 mul icCol + dup ncol div 10 mul + x 1 sub ncol div 10 mul + hxlow hxhig 4 2 roll rect fill + } for + } def +/hColorLegend { % ditto, horizontally, to rectangle 0 10 hylow hyhig + /ncol 100 def + 1 1 ncol { + dup ncol div 10 mul icCol + dup ncol div 10 mul + x 1 sub ncol div 10 mul + hylow hyhig rect fill + } for + } def +% Usage: +% hColorLegend +% hylow hyhig 0 0 90 0 OneAxx Axx +% hylow hyhig 10 0 90 180 OneAxx Axx +% 0 10 0 hyhig 0 90 OneAxx Axx Tic Tac +% 0 10 0 0 0 90 OneAxx Axx Tic Tac xNumL +% {(intensity)} xCL + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% List %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/NewList { % xins yins size advance NewList - + /nl_advance x def setown /nl_yins x def /nl_xins x def + /nl_xshift fontsize xmm div .9 mul def + /nl_xrline 0.33 def + /nl_ystep fontheight ymm div nl_advance mul def + /newline { + /nl_yins nl_yins nl_ystep sub def + } def + /fracline { % frac | - + fontheight ymm div nl_advance mul mul /nl_yins x nl_yins x sub def + } def + } def +/newlist { 1.65 NewList } def +/TxLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textLM newline + } bind def +/TxCLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textCM newline + } bind def +/PtTxLine { % pstyle text | - + x pstyle + nl_xins nl_xshift .5 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PttttTxLine { % pstyle text | - %% chain of very small symbols + x pstyle + nl_xins nl_xshift .10 mul add nl_yins 0 t + nl_xins nl_xshift .26 mul add nl_yins 0 t + nl_xins nl_xshift .42 mul add nl_yins 0 t + nl_xins nl_xshift .58 mul add nl_yins 0 t + nl_xins nl_xshift .74 mul add nl_yins 0 t + nl_xins nl_xshift .90 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PtPtCvTxLine { % pstyle pstyle cstyle text | - + 4 3 roll pstyle nl_xins nl_yins 0 t + 3 2 roll pstyle nl_xins nl_xshift add nl_yins 0 t + x cstyle + nl_xins nl_xshift 2 mul add + dup dup nl_xshift nl_xrline mul sub nl_yins 0 ti + nl_xshift nl_xrline mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtCvTxLine { % pstyle cstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x cstyle + nl_xins nl_xshift 1 mul add + dup dup nl_xshift -.33 mul add nl_yins 0 ti + nl_xshift 0.33 mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtPtTxLine { % pstyle pstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x pstyle nl_xins nl_xshift add nl_yins 0 t + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/CvTxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul 0 mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul 3 mul add nl_yins 0 tf + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/Cv2TxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul add nl_xshift add nl_yins 0 tf + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PCTxLine { % pstyle(with plset) text | - + x pstyle + nl_xins fontsize xmm div nl_xrline 2 mul mul sub nl_yins 0 ci + nl_xins fontsize xmm div nl_xrline 2 mul mul add nl_yins 0 cf + nl_xins yins 0 t + black nl_xins + fontsize xmm div 1.9 mul % instead of xshift + add nl_yins 3 2 roll textLM + newline + } bind def +/infSet { % oooinfo | - : set whether(1) or not(0) to plot info block + /oooinfo x def + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Boxes +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/rect { % xl xh yl yh | - [path -> rectangle] + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + np + qqxl qqyl mv + qqxh qqyl li + qqxh qqyh li + qqxl qqyh li + cp + } def +/oval { % xl xh yl yh dr | - [path -> oval] + fm /qqdr x def + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + qqxl qqyl qqdr add np mv + qqxl qqyh qqdr sub li + qqxl qqdr add qqyh qqdr sub qqdr 180 90 arcn + qqxh qqdr sub qqyh li + qqxh qqdr sub qqyh qqdr sub qqdr 90 0 arcn + qqxh qqyl qqdr add li + qqxh qqdr sub qqyl qqdr add qqdr 0 -90 arcn + qqxl qqdr add qqyl li + qqxl qqdr add qqyl qqdr add qqdr -90 -180 arcn + cp + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Arrows +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +/pfeilangle 36.87 def +/pfeilspitze { % x[local] y[local] rot siz + % draw with current linestyle, as set e.g. by linsetAxx + x 4 2 roll % siz rot x y + gsave + xym translate 180 add rotate dup dup dup + [] 0 setdash + pfeilangle cos mul x pfeilangle sin mul np mv + 0 0 li pfeilangle cos mul x pfeilangle sin neg mul li st + grestore + } def +/pfeiL { % (arrow anchored at base) x y rot siz len + gsave + dup xm x ym mul sqrt % (scale len) + 5 3 roll + xym translate % (origin at base) rot siz len + 3 2 roll + rotate % (draw rightwards) siz len + dup 0 translate % (origin at head) siz len + x 0 0 0 4 3 roll pfeilspitze % len + 0 0 np mv neg 0 li st + grestore + } def +/Pfeil { % (arrow anchored at head) x y rot siz len + dup xm x ym mul sqrt 5 copy + pop pfeilspitze + x pop + x 4 2 roll % len rot x y + gsave + xym translate 180 add rotate + 0 0 np mv 0 li st + grestore + } def + +/bemasz { % x y L ang text | - %% precede by '24 setown 1 [] lset /pfeilangle 90 def' + gsave + 5 3 roll offset % consumes x and y + x rotate % consumes ang | L text + dup textw .5 mul fontheight .4 mul add /bmszDT x def % => half text width + 0 0 3 2 roll textCM % L + .5 mul /bmszDX x def % => half bemasz length + bmszDX 0 0 fontheight .67 mul bmszDX bmszDT sub Pfeil + bmszDX neg 0 180 fontheight .67 mul bmszDX bmszDT sub Pfeil + grestore + } def + +end % WuGdict... + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ewu", the end of the wups.. macro definition file %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/pub/src/CMakeLists.txt b/pub/src/CMakeLists.txt index e65bfd3b9ee32c1e0151b5fb4f11588a925d17cc..0e815c1afcd442dc74d97a9d198dc34c205c09d4 100644 --- a/pub/src/CMakeLists.txt +++ b/pub/src/CMakeLists.txt @@ -2,16 +2,16 @@ CONFIGURE_FILE ("config_src.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/config_src.hpp") -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${Frida_SOURCE_DIR}/lib) +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${Frida_SOURCE_DIR}/lib + ${Frida_SOURCE_DIR}/ThirdParty + ) set(src_files frida2.cpp) add_executable(frida frida2.cpp) -target_link_libraries(frida - libtrivia - libreadplus - ${GSL_LIBRARIES} - libfrida) +target_link_libraries(frida ${fridacore_LIBRARY}) install(TARGETS frida DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/pub/src/config_src.hpp.in b/pub/src/config_src.hpp.in index f43b33df12f93a111fe3a4333a5bae29b39681d0..5db452e7426c3fb89e46ba598ec0f12fb0e55f78 100644 --- a/pub/src/config_src.hpp.in +++ b/pub/src/config_src.hpp.in @@ -1 +1,2 @@ #define CONFDIR "@CMAKE_INSTALL_PREFIX@/share/frida" +#define VERSION "@Frida_VERSION@" diff --git a/pub/src/frida2.cpp b/pub/src/frida2.cpp index fca862ba0a7bc52eb169aba307d235947933c2ff..273df2e4a197eb9307d3f3e3a2fe8923b6e8de54 100644 --- a/pub/src/frida2.cpp +++ b/pub/src/frida2.cpp @@ -31,6 +31,8 @@ #include <string> +#include <vector> +#include <tclap/CmdLine.h> #include "config_src.hpp" #include "toplevel.hpp" @@ -38,18 +40,37 @@ int main(int argc, char* argv[]) { - // Initialize runtime environment. - CFrida frida; + try { + TCLAP::CmdLine cmd("Flexible rapid interactive data analysis", ' ', VERSION, true); + TCLAP::SwitchArg batchSwitch("b","batch","Batch mode: exit on error", cmd, false); + TCLAP::UnlabeledMultiArg<std::string> multi("script", "Script files", false, ""); + cmd.add( multi ); + cmd.parse(argc, argv); + + bool batchMode = batchSwitch.getValue(); + std::vector<std::string> scripts = multi.getValue(); + + // Initialize runtime environment. + CFrida frida; #ifdef CONFDIR - // Execute initialization script. - frida.execute_file( CONFDIR "/frida.ini" ); + // Execute initialization script. + frida.execute_file( CONFDIR "/frida.ini", batchMode ); #endif - // Execute scripts from command line (used in particular by shebang files). - for( int iarg=1; iarg<argc; ++iarg ) - frida.execute_file( argv[iarg] ); + // Execute scripts from command line (used in particular by shebang files). + for( const std::string& script: scripts ) + frida.execute_file( script, batchMode ); + + // Interactive main loop. + frida.interactive(); - // Interactive main loop. - frida.interactive(); + } catch (TCLAP::ArgException &e) { + std::cerr << "error: " << e.error() << " for arg " << e.argId() << "\n"; + exit(1); + } catch (...) { + std::cerr << "Unexpected uncatched exception in main program\n"; + exit(1); + } + exit(0); } diff --git a/pub/trivia/CMakeLists.txt b/pub/trivia/CMakeLists.txt index b2818757cf2bad12e4a69dafa0b1377a4bcf4cc8..93b95855639826ff2da6cfa04bc550cd5f743728 100644 --- a/pub/trivia/CMakeLists.txt +++ b/pub/trivia/CMakeLists.txt @@ -1,34 +1,42 @@ # frida: trivia/CMakeLists.txt +set(library_name fridatrivia) +set(${library_name}_LIBRARY ${library_name} PARENT_SCOPE) +set(${library_name}_LIBRARY_TYPE SHARED) + include_directories(${Frida_SOURCE_DIR}/trivia ${CMAKE_CURRENT_BINARY_DIR}) set(src_files -file_ops.cpp -integrate.cpp -math.cpp -rng.cpp -string_convs.cpp -string_ops.cpp -vector_ops.cpp -yaml_out.cpp -) + file_ops.cpp + integrate.cpp + math.cpp + rng.cpp + string_convs.cpp + string_ops.cpp + vector_ops.cpp + yaml_out.cpp + ) set(inc_files -file_ops.hpp -integrate.hpp -math.hpp -rng.hpp -singleton.hpp -string_convs.hpp -string_ops.hpp -vector_ops.hpp -yaml_out.hpp -) + file_ops.hpp + integrate.hpp + math.hpp + rng.hpp + singleton.hpp + string_convs.hpp + string_ops.hpp + vector_ops.hpp + yaml_out.hpp + ) -add_library(libtrivia SHARED ${src_files}) +add_library(${library_name} SHARED ${src_files}) -set_target_properties(libtrivia PROPERTIES OUTPUT_NAME trivia) +set_target_properties(${library_name} PROPERTIES OUTPUT_NAME ${library_name}) -target_link_libraries(libtrivia) +target_link_libraries(${library_name} + ${GSL_LIBRARIES} + ${YAMLCPP_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} +) -install(TARGETS libtrivia DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +install(TARGETS ${library_name} LIBRARY DESTINATION ${destination_lib} COMPONENT Libraries) diff --git a/pub/trivia/file_ops.cpp b/pub/trivia/file_ops.cpp index 3e43738c95454a8bbaf09fbf449eda8ccbd8d5f7..adee27f390d484cad2d8039d9595ff8544485b77 100644 --- a/pub/trivia/file_ops.cpp +++ b/pub/trivia/file_ops.cpp @@ -7,10 +7,11 @@ #include <sys/stat.h> #include <wordexp.h> - #include <iostream> - #include <boost/format.hpp> +#include <boost/filesystem.hpp> + +namespace fs = boost::filesystem; using boost::format; using std::string; @@ -76,29 +77,6 @@ bool triv::file_exists(const string& path) return 1; } -//! Analyses a file name: divides "dir/short.ext" into "dir", "short", "ext". - -void triv::fname_divide(const string& fname, string* fdir, string* fshort, string* fext) -// each of the three output arguments, when called with a nullptr, will not be computed -{ - size_t idir = fname.rfind("/") + 1; - if (fdir) - *fdir = fname.substr(0, idir); - - size_t iext = fname.rfind(string(".")) + 1; - if (iext <= idir) { - if (fext) - *fext = ""; - if (fshort) - *fshort = fname.substr(idir); - } else { - if (fext) - *fext = fname.substr(iext); - if (fshort) - *fshort = fname.substr(idir, iext - idir - 1); - } -} - //! Returns a unique file name obtained by Posix shell expansion of a given pattern. @@ -151,13 +129,13 @@ string triv::next_tmp_file(const string& path_format) const int tmpmax = 1024; for (int i = 0; i < tmpmax; ++i) { string fname = str(format(path_format) % i); - if (!triv::file_exists(fname)) + if (!triv::file_exists(triv::wordexp_unique(fname))) return fname; if (i == tmpmax / 2) - cerr << "WARNING: there more than " << i << " temporay files of form " << path_format - << "; please clean up soon\n"; + cerr << "WARNING: there more than " << i << " files of form '" << path_format + << "'; please clean up soon\n"; } - throw "Too many temporary files in use"; + throw "Too many files of type '" + path_format + "' in use"; } @@ -175,8 +153,7 @@ vector<string> triv::glob_file_list(const string& patterns, const string& extens throw string("empty file list"); vector<string> vExtension = split(extensions); for (string pat : vPattern) { - string fmain, fext; - fname_divide(pat, nullptr, &fmain, &fext); + string fext = fs::path(pat).extension().string(); if (fext == "" && vExtension.size()) { for (string ext : vExtension) extended_patterns += pat + "." + ext + " "; diff --git a/pub/trivia/file_ops.hpp b/pub/trivia/file_ops.hpp index ee9a1e22201f210196ad4f9abe5530f59423470c..2af595e21002aec2da096d2148f628d02b4d42f5 100644 --- a/pub/trivia/file_ops.hpp +++ b/pub/trivia/file_ops.hpp @@ -8,6 +8,9 @@ #ifndef FILE_OPS_H #define FILE_OPS_H +#include <string> +#include <vector> + namespace triv { @@ -17,8 +20,6 @@ std::string system_read(std::string cmd, bool debug = false); // File names, globbing: bool file_exists(const std::string& fname); -void fname_divide( - const std::string& fname, std::string* fdir, std::string* fshort, std::string* fext); std::vector<std::string> glob_file_list(const std::string& patterns, const std::string& extensions); std::string wordexp_unique(const std::string& s); std::vector<std::string> wordexp_multi(const std::string& s); diff --git a/pub/trivia/integrate.cpp b/pub/trivia/integrate.cpp index 3993cfb16bd72710eb7a79751441d0e8e4311a7f..f5ce5ed81df9155052e3439910e47c6955167756 100644 --- a/pub/trivia/integrate.cpp +++ b/pub/trivia/integrate.cpp @@ -52,6 +52,8 @@ double triv::integrate( case 6: rule = GSL_INTEG_GAUSS15; break; + default: + throw "Impossible case"; } // QAG adaptive integration gsl_integration_qag(&F, low, hig, epsabs, epsrel, nwork, rule, work, &val, &err); diff --git a/pub/trivia/vector_ops.cpp b/pub/trivia/vector_ops.cpp index 36f30708ecc7a4df6f4a04cdae0987e252cc7c42..49a0d6b6c27a962b103c798dff63a23286debdcd 100644 --- a/pub/trivia/vector_ops.cpp +++ b/pub/trivia/vector_ops.cpp @@ -167,3 +167,17 @@ std::string triv::indices_to_s(const vector<int>& v) } return ret; } + +//! Determines minimal positive value and maximal value in vector v. +//! Results must be tested for finiteness. +void triv::getPosminMax(const std::vector<double>& v, double& minval, double&maxval) +{ + minval = +INFINITY; + maxval = -INFINITY; + for (auto t = v.begin(); t<v.end(); ++t) { + if (*t<=0) + continue; + minval = std::min(minval, *t); + maxval = std::max(maxval, *t); + } +} diff --git a/pub/trivia/vector_ops.hpp b/pub/trivia/vector_ops.hpp index d26ccb05d064b22612fcd320f88fe4a61a0ac5e3..b47e28bb9b59d5d8dc138ec66e04e334ed9b89c4 100644 --- a/pub/trivia/vector_ops.hpp +++ b/pub/trivia/vector_ops.hpp @@ -8,25 +8,66 @@ #ifndef VECTOR_OPS_H #define VECTOR_OPS_H +#include <cmath> #include <vector> +#include <functional> +#include <algorithm> namespace triv { + void insert_in_sorted(std::vector<double>* V, double val); + void make_unique(std::vector<double>* V, double tolabs = 1e-100, double tolrel = 1e-10); + bool is_ascending(const std::vector<double>& V); + bool is_equidist(double* step, const std::vector<double>& V); + std::vector<size_t> sorted_indices(std::vector<double> const& V); + std::vector<int> iota_list(int number_of_entries); + std::vector<double> histogram_limits(const std::vector<double>& channel_centers); + void increment_indices(std::vector<int>& v, int incr, int siz); + std::string indices_to_s(const std::vector<int>& v); -void insert_in_sorted(std::vector<double>* V, double val); -void make_unique(std::vector<double>* V, double tolabs = 1e-100, double tolrel = 1e-10); -bool is_ascending(const std::vector<double>& V); -bool is_equidist(double* step, const std::vector<double>& V); -std::vector<size_t> sorted_indices(std::vector<double> const& V); -std::vector<int> iota_list(int number_of_entries); -std::vector<double> histogram_limits(const std::vector<double>& channel_centers); -void increment_indices(std::vector<int>& v, int incr, int siz); -std::string indices_to_s(const std::vector<int>& v); - -template <class A> bool contains(const std::vector<A>& v, const A e) -{ - return std::find(v.begin(), v.end(), e) != v.end(); -} + template <class T> void getMinMax(const std::vector<T>& v, T& minval, T&maxval); + void getPosminMax(const std::vector<double>& v, double& minval, double&maxval); + template <class T> bool contains(const std::vector<T>& v, const T e); + template <class T, class Pred> std::vector<T> merge_sorted( + const std::vector<T>& a, const std::vector<T>& b, Pred a_before_b); + +//************************************************************************************************** +// Template implementation +//************************************************************************************************** + + template <class T> + void getMinMax(const std::vector<T>& v, T& minval, T&maxval) + { + if (v.size()==0) + throw "BUG: attempt to determine min and max of empty vector"; + minval = v.front(); + maxval = v.front(); + for (auto t = v.begin()+1; t<v.end(); ++t) { + minval = std::min(minval, *t); + maxval = std::max(maxval, *t); + } + } + + template <class T> + bool contains(const std::vector<T>& v, const T e) + { + return std::find(v.begin(), v.end(), e) != v.end(); + } + + template <class T, class Pred> + std::vector<T> merge_sorted(const std::vector<T>& a, const std::vector<T>& b, Pred a_before_b) + { + std::vector<T> ret; + auto ia=a.begin(); + auto ib=b.begin(); + for (;ia!=a.end() && ib!=b.end();) + ret.push_back( a_before_b(*ia,*ib) ? *(ia++) : *(ib++) ); + for (;ia!=a.end();) + ret.push_back( *(ia++) ); + for (;ib!=b.end();) + ret.push_back( *(ib++) ); + return ret; + } } #endif // VECTOR_OPS_H diff --git a/pub/utest/CMakeLists.txt b/pub/utest/CMakeLists.txt index 0bb8d006fb4ffdbbf2769fc32d8d6387bf220b18..1ced2ef640c84db9166a5e1e70d1b9a98f8513bf 100644 --- a/pub/utest/CMakeLists.txt +++ b/pub/utest/CMakeLists.txt @@ -25,10 +25,7 @@ link_directories( set(test_link_libs gtest_main - libtrivia - libreadplus - ${GSL_LIBRARIES} - libfrida + ${fridacore_LIBRARY} ) # We glob test sources, though this is often considered evil. @@ -40,6 +37,6 @@ list(SORT test_sources) foreach(test_src ${test_sources}) # remove directory path and suffix, to retain just the name of the test string(REGEX REPLACE ".*/" "" test_name "${test_src}") - string(REGEX REPLACE ".cpp$" "" test_name "${test_name}") + string(REGEX REPLACE "\\.cpp$" "" test_name "${test_name}") cxx_test(${test_name} "${test_link_libs}") endforeach(test_src) diff --git a/pub/utest/test002_vecops.cpp b/pub/utest/test002_vecops.cpp index 2eeb43315cbcbd8d1a2763d8958baa0e2b1a5c3e..26dc785f8f4ffd41724ec9f412e9486dea2f557f 100644 --- a/pub/utest/test002_vecops.cpp +++ b/pub/utest/test002_vecops.cpp @@ -11,3 +11,31 @@ TEST(VecOpsTest, HistoLimits) { EXPECT_NEAR(15., l[3], 1e-14 ); EXPECT_NEAR(19., l[4], 1e-14 ); } + +TEST(VecOpsTest, InsertSorted) { + std::vector<double> A { 1.1, 1.3, 1.8 }; + std::vector<double> B { 2.1, 2.2, 2.4, 2.7 }; + auto f = [](const double a, const double b) -> bool { return (a-(long)(a))<=(b-(long(b))); }; + std::vector<double> C = triv::merge_sorted(A, B, f); + EXPECT_EQ( C[0], A[0] ); + EXPECT_EQ( C[1], B[0] ); + EXPECT_EQ( C[2], B[1] ); + EXPECT_EQ( C[3], A[1] ); + EXPECT_EQ( C[4], B[2] ); + EXPECT_EQ( C[5], B[3] ); + EXPECT_EQ( C[6], A[2] ); +} + +TEST(VecOpsTest, InsertSortedInplace) { + std::vector<double> A { 1.1, 1.3, 1.8 }; + std::vector<double> B { 2.1, 2.2, 2.4, 2.7 }; + auto f = [](const double a, const double b) -> bool { return (a-(long)(a))<=(b-(long(b))); }; + A = triv::merge_sorted(A, B, f); + EXPECT_EQ( A[0], 1.1 ); + EXPECT_EQ( A[1], B[0] ); + EXPECT_EQ( A[2], B[1] ); + EXPECT_EQ( A[3], 1.3 ); + EXPECT_EQ( A[4], B[2] ); + EXPECT_EQ( A[5], B[3] ); + EXPECT_EQ( A[6], 1.8 ); +}