From 8bb17fb2e8c1396921e242afe6400a779b797c7f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:11:46 -0400 Subject: [PATCH 01/97] CLI - CLI is a streamlined version of Parser, now that wisdom is upon us. --- src/CLI.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/CLI.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/CLI.cpp create mode 100644 src/CLI.h diff --git a/src/CLI.cpp b/src/CLI.cpp new file mode 100644 index 000000000..d918de40b --- /dev/null +++ b/src/CLI.cpp @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// 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. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +CLI::CLI () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +CLI::~CLI () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::alias (const std::string& name, const std::string& value) +{ + _aliases.insert (std::pair (name, value)); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::entity (const std::string& name, const std::string& value) +{ + _entities.insert (std::pair (name, value)); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h new file mode 100644 index 000000000..1743b24bf --- /dev/null +++ b/src/CLI.h @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// 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. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_CLI +#define INCLUDED_CLI + +#include +#include + +class CLI +{ +public: + CLI (); + ~CLI (); + void alias (const std::string&, const std::string&); + void entity (const std::string&, const std::string&); + +private: + +private: + std::multimap _entities; + std::map _aliases; +}; + +#endif + From 3b0606922f2dd192bacf08aabc78760bd2973fe8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:17:20 -0400 Subject: [PATCH 02/97] CMake - Added new CLI class. --- src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73cd46e7c..b1b76ff5f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,8 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src/columns ${TASK_INCLUDE_DIRS}) -set (task_SRCS Color.cpp Color.h +set (task_SRCS CLI.cpp CLI.h + Color.cpp Color.h Config.cpp Config.h Context.cpp Context.h DOM.cpp DOM.h From df54b8ee4393fa8a7d09d8906ef7e7e588cfc054 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:17:59 -0400 Subject: [PATCH 03/97] Context - Integrated new CLI object. - Provided aliases and entities to CLI. --- src/Context.cpp | 23 +++++++++++++++++++++++ src/Context.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/Context.cpp b/src/Context.cpp index 31b1ac8df..a1e294228 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -171,35 +171,55 @@ int Context::initialize (int argc, const char** argv) for (cmd = commands.begin (); cmd != commands.end (); ++cmd) { parser.entity ("cmd", cmd->first); + cli.entity ("cmd", cmd->first); if (cmd->first[0] == '_') + { parser.entity ("helper", cmd->first); + cli.entity ("helper", cmd->first); + } if (cmd->second->read_only ()) + { parser.entity ("readcmd", cmd->first); + cli.entity ("readcmd", cmd->first); + } else + { parser.entity ("writecmd", cmd->first); + cli.entity ("writecmd", cmd->first); + } } // Instantiate built-in column objects. Column::factory (columns); std::map ::iterator col; for (col = columns.begin (); col != columns.end (); ++col) + { parser.entity ("attribute", col->first); + cli.entity ("attribute", col->first); + } // Entities: Pseudo-attributes. Hard-coded. parser.entity ("pseudo", "limit"); + cli.entity ("pseudo", "limit"); // Entities: Modifiers. for (unsigned int i = 0; i < NUM_MODIFIER_NAMES; ++i) + { parser.entity ("modifier", modifierNames[i]); + cli.entity ("modifier", modifierNames[i]); + } // Entities: Operators. std::vector operators; Eval::getOperators (operators); std::vector ::iterator op; for (op = operators.begin (); op != operators.end (); ++op) + { parser.entity ("operator", *op); + cli.entity ("operator", *op); + } // Now the entities are loaded, parsing may resume. parser.findBinary (); // @@ -752,7 +772,10 @@ void Context::loadAliases () std::map ::iterator i; for (i = config.begin (); i != config.end (); ++i) if (i->first.substr (0, 6) == "alias.") + { parser.alias (i->first.substr (6), i->second); + cli.alias (i->first.substr (6), i->second); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Context.h b/src/Context.h index f4c8ce4de..eb34f97a4 100644 --- a/src/Context.h +++ b/src/Context.h @@ -38,6 +38,7 @@ #include #include #include +#include #include class Context @@ -84,6 +85,7 @@ private: public: std::string program; Parser parser; + CLI cli; std::string home_dir; File rc_file; Path data_dir; From 64d4d659efd35092f0f821fee250674a547130b3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:23:45 -0400 Subject: [PATCH 04/97] CLI - ::initialize captures all args. --- src/CLI.cpp | 10 ++++++++++ src/CLI.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index d918de40b..bf1fb15b1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -54,3 +54,13 @@ void CLI::entity (const std::string& name, const std::string& value) } //////////////////////////////////////////////////////////////////////////////// +// Capture the original, intact command line arguments. These will not be +// modified. +void CLI::initialize (int argc, const char** argv) +{ + _program = argv[0]; + for (int i = 1; i < argc; ++i) + _args.push_back (argv[i]); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 1743b24bf..d743d0e5f 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -27,6 +27,7 @@ #define INCLUDED_CLI #include +#include #include class CLI @@ -36,12 +37,15 @@ public: ~CLI (); void alias (const std::string&, const std::string&); void entity (const std::string&, const std::string&); + void initialize (int, const char**); private: private: std::multimap _entities; std::map _aliases; + std::string _program; + std::vector _args; }; #endif From c73e864cdda840d44b1e9baa1949bad479151ffa Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:24:08 -0400 Subject: [PATCH 05/97] Context - CLI is initialized with command line args. --- src/Context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Context.cpp b/src/Context.cpp index a1e294228..177b7cc61 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -129,6 +129,7 @@ int Context::initialize (int argc, const char** argv) Variant::searchUsingRegex = config.getBoolean ("regex"); parser.initialize (argc, argv); // task arg0 arg1 ... + cli.initialize (argc, argv); // task arg0 arg1 ... // Process 'rc:' command line override. parser.findOverrides (); // rc: rc.: From 226c143922e8840ec4278f8d356da1a2f59c2220 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:52:50 -0400 Subject: [PATCH 06/97] CLI - Override detection and extraction. --- src/CLI.cpp | 32 ++++++++++++++++++++++++++++++-- src/CLI.h | 5 ++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index bf1fb15b1..921db892d 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -54,13 +54,41 @@ void CLI::entity (const std::string& name, const std::string& value) } //////////////////////////////////////////////////////////////////////////////// -// Capture the original, intact command line arguments. These will not be -// modified. +// Capture the original, intact command line arguments. void CLI::initialize (int argc, const char** argv) { _program = argv[0]; for (int i = 1; i < argc; ++i) _args.push_back (argv[i]); + + extractOverrides (); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::extractOverrides () +{ + std::vector reconstructed; + + std::vector ::iterator i; + for (i = _args.begin (); i != _args.end (); ++i) + { + if (i->find ("rc:") == 0) + { + _rc = i->substr (3); + } + else if (i->find ("rc.") == 0) + { + std::string::size_type sep = arg.find ('=', 3); + if (sep == std::string::npos) + sep = arg.find (':', 3); + if (sep != std::string::npos) + _overrides[i->substr (3, sep - 3)] = i->substr (sep + 1); + } + else + reconstructed.push_back (*i); + } + + _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index d743d0e5f..f07379d1a 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -40,12 +40,15 @@ public: void initialize (int, const char**); private: + void extractOverrides (); -private: +public: std::multimap _entities; std::map _aliases; std::string _program; std::vector _args; + std::string _rc; + std::map _overrides; }; #endif From f4183fd6b13e1b740b237954b582325ac381bf09 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 13 Oct 2014 23:54:16 -0400 Subject: [PATCH 07/97] Context - Added CLI rc: and rc. override extraction. --- src/Context.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Context.cpp b/src/Context.cpp index 177b7cc61..fb1cf019d 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -108,6 +108,11 @@ int Context::initialize (int argc, const char** argv) // Scan command line for 'rc:' only. Parser::getOverrides (argc, argv, rc_file._data); + cli.initialize (argc, argv); // task arg0 arg1 ... +/* + std::cout << "# cli._rc=" << cli._rc << "\n"; + rc_file = cli._rc; +*/ // TASKRC environment variable overrides the command line. char* override = getenv ("TASKRC"); @@ -129,16 +134,31 @@ int Context::initialize (int argc, const char** argv) Variant::searchUsingRegex = config.getBoolean ("regex"); parser.initialize (argc, argv); // task arg0 arg1 ... - cli.initialize (argc, argv); // task arg0 arg1 ... // Process 'rc:' command line override. parser.findOverrides (); // rc: rc.: parser.getOverrides (home_dir, rc_file); // <-- +/* + home_dir = rc_file; + std::string::size_type last_slash = rc._data.rfind ("/"); + if (last_slash != std::string::npos) + home_dir = rc_file.parent (); + else + home_dir = "."; + std::cout << "# home_dir=" << home_dir << "\n"; +*/ // The data location, Context::data_dir, is determined from the assumed // location (~/.task), or set by data.location in the config file, or // overridden by rc.data.location on the command line. parser.getDataLocation (data_dir); // <-- rc.data.location= +/* + if (cli._overrides.find ("data.location") != cli._overrides.end ()) + data_dir = cli._overrides["data.location"]; + else + data_dir = config.get ("data.location"); + std::cout << "# data_dir=" << data_dir << "\n"; +*/ override = getenv ("TASKDATA"); if (override) From 9a2bcbed3e740f5f752b9072feb5a138ed6452ff Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:08:55 -0400 Subject: [PATCH 08/97] CLI - Added ::dump for diagnostics. --- src/CLI.cpp | 18 ++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 921db892d..855ca9f65 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -92,3 +93,20 @@ void CLI::extractOverrides () } //////////////////////////////////////////////////////////////////////////////// +void CLI::dump (const std::string& label) const +{ + std::cout << "# " << label << "\n" + << "# _program '" << _program << "'\n"; + + std::vector ::const_iterator i; + for (i = _args.begin (); i != _args.end (); ++i) + std::cout << "# _args '" << *i << "'\n"; + + std::cout << "# _rc '" << _rc << "'\n"; + + std::map ::const_iterator m; + for (m = _overrides.begin (); m != _overrides.end (); ++m) + std::cout << "# _overrides '" << m->first << "' --> '" << m->second << "'\n"; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index f07379d1a..f56ccf84b 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -41,6 +41,7 @@ public: private: void extractOverrides (); + void dump (const std::string&) const; public: std::multimap _entities; From 1639e6bb68823dd69cda1acde56070a1be022113 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:09:47 -0400 Subject: [PATCH 09/97] CLI - Stubbed ::aliasExpansion. - Fixed variable types. - Added ::dump calls. --- src/CLI.cpp | 12 ++++++++++-- src/CLI.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 855ca9f65..80b86d074 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -62,6 +62,7 @@ void CLI::initialize (int argc, const char** argv) for (int i = 1; i < argc; ++i) _args.push_back (argv[i]); + dump ("CLI::initialize"); extractOverrides (); } @@ -79,9 +80,9 @@ void CLI::extractOverrides () } else if (i->find ("rc.") == 0) { - std::string::size_type sep = arg.find ('=', 3); + std::string::size_type sep = i->find ('=', 3); if (sep == std::string::npos) - sep = arg.find (':', 3); + sep = i->find (':', 3); if (sep != std::string::npos) _overrides[i->substr (3, sep - 3)] = i->substr (sep + 1); } @@ -90,6 +91,13 @@ void CLI::extractOverrides () } _args = reconstructed; + dump ("CLI::extractOverrides"); +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::aliasExpansion () +{ + dump ("CLI::aliasExpansion"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index f56ccf84b..e9dacde92 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -41,6 +41,7 @@ public: private: void extractOverrides (); + void aliasExpansion (); void dump (const std::string&) const; public: From b0cf4adc4eefa79fc45e58e51dbbd78ce3f42554 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:43:50 -0400 Subject: [PATCH 10/97] CLI - Stubbed methods for further parsing. --- src/CLI.cpp | 5 +++++ src/CLI.h | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 80b86d074..2b558e6e4 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -28,12 +28,17 @@ #include #include #include +#include #include extern Context context; //////////////////////////////////////////////////////////////////////////////// CLI::CLI () +: _program ("") +, _rc ("") +, _command ("") +, _readOnly (false) { } diff --git a/src/CLI.h b/src/CLI.h index e9dacde92..9750dfd6f 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -38,10 +38,13 @@ public: void alias (const std::string&, const std::string&); void entity (const std::string&, const std::string&); void initialize (int, const char**); + void aliasExpansion (); + void categorize (); + bool exactMatch (const std::string&, const std::string&) const; + bool canonicalize (std::string&, const std::string&, const std::string&) const; private: void extractOverrides (); - void aliasExpansion (); void dump (const std::string&) const; public: @@ -51,6 +54,11 @@ public: std::vector _args; std::string _rc; std::map _overrides; + + std::string _command; + bool _readOnly; + std::vector _filter; + std::vector _modifications; }; #endif From 227e0bd8c861c810310178b8b4e7bae44183e158 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:45:04 -0400 Subject: [PATCH 11/97] CLI - Implemented ::exactMatch. --- src/CLI.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 2b558e6e4..1c5e71ccc 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -105,6 +105,29 @@ void CLI::aliasExpansion () dump ("CLI::aliasExpansion"); } +//////////////////////////////////////////////////////////////////////////////// +// Search for exact 'value' in _entities category. +bool CLI::exactMatch ( + const std::string& category, + const std::string& value) const +{ + // Find the category. + std::pair ::const_iterator, std::multimap ::const_iterator> c; + c = _entities.equal_range (category); + + // Extract a list of entities for category. + std::vector options; + std::multimap ::const_iterator e; + for (e = c.first; e != c.second; ++e) + { + // Shortcut: if an exact match is found, success. + if (value == e->second) + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { From 4d921c7920fa8b16e9a4427a1ddb554f92274561 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:45:53 -0400 Subject: [PATCH 12/97] CLI - Implemented ::canonicalize. --- src/CLI.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 1c5e71ccc..61bae23d2 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -33,6 +33,12 @@ extern Context context; +// Overridden by rc.abbreviation.minimum. +static int minimumMatchLength = 3; + +// Alias expansion limit. Any more indicates some kind of error. +static int safetyValveDefault = 10; + //////////////////////////////////////////////////////////////////////////////// CLI::CLI () : _program ("") @@ -128,6 +134,43 @@ bool CLI::exactMatch ( return false; } +//////////////////////////////////////////////////////////////////////////////// +// Search for 'value' in _entities category, return canonicalized value. +bool CLI::canonicalize ( + std::string& canonicalized, + const std::string& category, + const std::string& value) const +{ + // Find the category. + std::pair ::const_iterator, std::multimap ::const_iterator> c; + c = _entities.equal_range (category); + + // Extract a list of entities for category. + std::vector options; + std::multimap ::const_iterator e; + for (e = c.first; e != c.second; ++e) + { + // Shortcut: if an exact match is found, success. + if (value == e->second) + { + canonicalized = value; + return true; + } + + options.push_back (e->second); + } + + // Match against the options, throw away results. + std::vector matches; + if (autoComplete (value, options, matches, minimumMatchLength) == 1) + { + canonicalized = matches[0]; + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { From 58afe2395276989bf30d2986b76a32b11400113e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:47:02 -0400 Subject: [PATCH 13/97] CLI - Implemented ::aliasExpansion. --- src/CLI.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 61bae23d2..449c25f0a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,35 @@ void CLI::extractOverrides () //////////////////////////////////////////////////////////////////////////////// void CLI::aliasExpansion () { + bool action; + int counter = 0; + do + { + action = false; + std::vector reconstructed; + + std::vector ::iterator i; + for (i = _args.begin (); i != _args.end (); ++i) + { + if (_aliases.find (*i) != _aliases.end ()) + { + std::vector lexed; + Lexer::token_split (lexed, _aliases[*i]); + + std::vector ::iterator l; + for (l = lexed.begin (); l != lexed.end (); ++l) + reconstructed.push_back (*l); + + action = true; + } + else + reconstructed.push_back (*i); + } + + _args = reconstructed; + } + while (action && counter++ < safetyValveDefault); + dump ("CLI::aliasExpansion"); } From 343a79a03497e6a12f9e0c117d09b7e0f5009f48 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:49:02 -0400 Subject: [PATCH 14/97] CLI - Implemented ::categorize. --- src/CLI.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 449c25f0a..ac99092ca 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -141,6 +141,37 @@ void CLI::aliasExpansion () dump ("CLI::aliasExpansion"); } +//////////////////////////////////////////////////////////////////////////////// +void CLI::categorize () +{ + bool foundCommand = false; + + _filter.clear (); + _modifications.clear (); + _command = ""; + _readOnly = false; + + std::vector ::iterator i; + for (i = _args.begin (); i != _args.end (); ++i) + { + if (canonicalize (_command, "cmd", *i)) + { + foundCommand = true; + _readOnly = ! exactMatch ("writecmd", _command); + } + else if (foundCommand && ! _readOnly) + { + _modifications.push_back (*i); + } + else + { + _filter.push_back (*i); + } + } + + dump ("CLI::categorize"); +} + //////////////////////////////////////////////////////////////////////////////// // Search for exact 'value' in _entities category. bool CLI::exactMatch ( From c54e0d6d05b3e45c6fc589f8bd7cc1d55f1c9347 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:49:15 -0400 Subject: [PATCH 15/97] CLI - Added new data to ::dump. --- src/CLI.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index ac99092ca..462d74a2d 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -247,6 +247,13 @@ void CLI::dump (const std::string& label) const std::map ::const_iterator m; for (m = _overrides.begin (); m != _overrides.end (); ++m) std::cout << "# _overrides '" << m->first << "' --> '" << m->second << "'\n"; + + for (i = _filter.begin (); i != _filter.end (); ++i) + std::cout << "# _filter '" << *i << "'\n"; + + for (i = _modifications.begin (); i != _modifications.end (); ++i) + std::cout << "# _modifications '" << *i << "'\n"; + } //////////////////////////////////////////////////////////////////////////////// From 2c3f12ae799d298929f6cbf1c6caa420545267ac Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:59:07 -0400 Subject: [PATCH 16/97] CLI - Added more members to the ::dump method. --- src/CLI.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 462d74a2d..114b781c0 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -246,11 +246,13 @@ void CLI::dump (const std::string& label) const std::map ::const_iterator m; for (m = _overrides.begin (); m != _overrides.end (); ++m) - std::cout << "# _overrides '" << m->first << "' --> '" << m->second << "'\n"; + std::cout << "# _overrides '" << m->first << "' --> '" << m->second << "'\n"; for (i = _filter.begin (); i != _filter.end (); ++i) std::cout << "# _filter '" << *i << "'\n"; + std::cout << "# _command '" << _command << "'" << (_readOnly ? "(read)" : "(write)") << "\n"; + for (i = _modifications.begin (); i != _modifications.end (); ++i) std::cout << "# _modifications '" << *i << "'\n"; From 632cb3e194d6f966eec7e14da7abad57c2c85f61 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 00:59:33 -0400 Subject: [PATCH 17/97] Context - Now calls aliasExpansion and categorization. --- src/Context.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Context.cpp b/src/Context.cpp index fb1cf019d..97a4c3de3 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -243,6 +243,8 @@ int Context::initialize (int argc, const char** argv) } // Now the entities are loaded, parsing may resume. + cli.aliasExpansion (); + parser.findBinary (); // parser.resolveAliases (); parser.findCommand (); // @@ -252,6 +254,7 @@ int Context::initialize (int argc, const char** argv) staticInitialization (); // Decouple code from Context. parser.parse (); // Parse all elements. + cli.categorize (); // Parse high-level elements. tdb2.set_location (data_dir); // Prepare the task database. From d32b6fff1244f4464daa0413b0812d90dbe57f55 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:03:15 -0400 Subject: [PATCH 18/97] CLI - Improved diagnostics, for now. --- src/CLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 114b781c0..6c32c983f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -251,7 +251,7 @@ void CLI::dump (const std::string& label) const for (i = _filter.begin (); i != _filter.end (); ++i) std::cout << "# _filter '" << *i << "'\n"; - std::cout << "# _command '" << _command << "'" << (_readOnly ? "(read)" : "(write)") << "\n"; + std::cout << "# _command '" << _command << "' " << (_readOnly ? "(read)" : "(write)") << "\n"; for (i = _modifications.begin (); i != _modifications.end (); ++i) std::cout << "# _modifications '" << *i << "'\n"; From acca1c66a3a3c8292e22aa6a77b62c772ed4f89a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:23:55 -0400 Subject: [PATCH 19/97] CLI - Implemented ::getFilter. --- src/CLI.cpp | 24 ++++++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 6c32c983f..579a15a33 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -232,6 +232,30 @@ bool CLI::canonicalize ( return false; } +//////////////////////////////////////////////////////////////////////////////// +const std::string CLI::getFilter () const +{ + std::string filter = ""; + + if (_filter.size ()) + { + filter = "("; + + std::vector ::const_iterator i; + for (i = _filter.begin (); i != _filter.end (); ++i) + { + if (i != _filter.begin ()) + filter += ' '; + + filter += *i; + } + + filter += ')'; + } + + return filter; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 9750dfd6f..29e2ab499 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -42,6 +42,7 @@ public: void categorize (); bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; + const std::string getFilter () const; private: void extractOverrides (); From c79a09d0b8800459e718e16ff1ad9ad261055fb5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:35:33 -0400 Subject: [PATCH 20/97] CLI - Implemented ::add. --- src/CLI.cpp | 11 +++++++++++ src/CLI.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 579a15a33..8541ecf54 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -78,6 +78,17 @@ void CLI::initialize (int argc, const char** argv) extractOverrides (); } +//////////////////////////////////////////////////////////////////////////////// +void CLI::add (const std::string& arg) +{ + _args.push_back (arg); + + dump ("CLI::add"); + extractOverrides (); + aliasExpansion (); + categorize (); +} + //////////////////////////////////////////////////////////////////////////////// void CLI::extractOverrides () { diff --git a/src/CLI.h b/src/CLI.h index 29e2ab499..a15da5458 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -38,6 +38,7 @@ public: void alias (const std::string&, const std::string&); void entity (const std::string&, const std::string&); void initialize (int, const char**); + void add (const std::string&); void aliasExpansion (); void categorize (); bool exactMatch (const std::string&, const std::string&) const; From 99ff5cd372023a7cdc182c5034920cc0c1d475cc Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:36:20 -0400 Subject: [PATCH 21/97] CmdCustom - Added parallel cli handling. --- src/commands/CmdCustom.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 964e49553..1db9bf765 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -90,6 +90,9 @@ int CmdCustom::execute (std::string& output) context.parser.captureLast (")"); */ + if (reportFilter != "") + context.cli.add ("("); + // Prepend the argument list with those from the report filter. std::string lexeme; Lexer::Type type; @@ -97,7 +100,13 @@ int CmdCustom::execute (std::string& output) lex.ambiguity (false); std::vector filterArgs; while (lex.token (lexeme, type)) + { filterArgs.push_back (lexeme); + context.cli.add (lexeme); + } + + if (reportFilter != "") + context.cli.add (")"); std::vector ::reverse_iterator arg; for (arg = filterArgs.rbegin (); arg != filterArgs.rend (); ++ arg) From 05fdfafd2afef1572615fec4a91563f6fef00b33 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:42:37 -0400 Subject: [PATCH 22/97] CLI - Preserves original args. --- src/CLI.cpp | 8 +++++++- src/CLI.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 8541ecf54..5cb2263bb 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -72,7 +72,9 @@ void CLI::initialize (int argc, const char** argv) { _program = argv[0]; for (int i = 1; i < argc; ++i) - _args.push_back (argv[i]); + _original_args.push_back (argv[i]); + + _args = _original_args; dump ("CLI::initialize"); extractOverrides (); @@ -81,6 +83,7 @@ void CLI::initialize (int argc, const char** argv) //////////////////////////////////////////////////////////////////////////////// void CLI::add (const std::string& arg) { + _original_args.push_back (arg); _args.push_back (arg); dump ("CLI::add"); @@ -274,6 +277,9 @@ void CLI::dump (const std::string& label) const << "# _program '" << _program << "'\n"; std::vector ::const_iterator i; + for (i = _original_args.begin (); i != _original_args.end (); ++i) + std::cout << "# _original_args '" << *i << "'\n"; + for (i = _args.begin (); i != _args.end (); ++i) std::cout << "# _args '" << *i << "'\n"; diff --git a/src/CLI.h b/src/CLI.h index a15da5458..44cb41fe7 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -53,6 +53,7 @@ public: std::multimap _entities; std::map _aliases; std::string _program; + std::vector _original_args; std::vector _args; std::string _rc; std::map _overrides; From 54d975dac309b96d796956ff8cb9a560a8baa23e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 01:52:39 -0400 Subject: [PATCH 23/97] CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Colㄡrized the ::dump output. --- src/CLI.cpp | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 5cb2263bb..f5f64ab33 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -274,29 +275,42 @@ const std::string CLI::getFilter () const void CLI::dump (const std::string& label) const { std::cout << "# " << label << "\n" - << "# _program '" << _program << "'\n"; + << "# _program " << _program << "\n"; + std::cout << "# _original_args "; + Color colorOrigArgs ("gray10 on gray4"); std::vector ::const_iterator i; for (i = _original_args.begin (); i != _original_args.end (); ++i) - std::cout << "# _original_args '" << *i << "'\n"; + { + if (i != _original_args.begin ()) + std::cout << ' '; + std::cout << colorOrigArgs.colorize (*i); + } + std::cout << "\n"; + std::cout << "# _args "; + Color colorArgs ("gray16 on gray4"); for (i = _args.begin (); i != _args.end (); ++i) - std::cout << "# _args '" << *i << "'\n"; + { + if (i != _args.begin ()) + std::cout << ' '; + std::cout << colorArgs.colorize (*i); + } + std::cout << "\n"; - std::cout << "# _rc '" << _rc << "'\n"; + std::cout << "# _rc " << _rc << "\n"; std::map ::const_iterator m; for (m = _overrides.begin (); m != _overrides.end (); ++m) - std::cout << "# _overrides '" << m->first << "' --> '" << m->second << "'\n"; + std::cout << "# _overrides " << m->first << " --> " << m->second << "\n"; for (i = _filter.begin (); i != _filter.end (); ++i) - std::cout << "# _filter '" << *i << "'\n"; + std::cout << "# _filter " << *i << "\n"; - std::cout << "# _command '" << _command << "' " << (_readOnly ? "(read)" : "(write)") << "\n"; + std::cout << "# _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; for (i = _modifications.begin (); i != _modifications.end (); ++i) - std::cout << "# _modifications '" << *i << "'\n"; - + std::cout << "# _modifications " << *i << "\n"; } //////////////////////////////////////////////////////////////////////////////// From 51a98609d9eef270fa03f9ae8fa9256c1911d336 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:22:25 -0400 Subject: [PATCH 24/97] CLI - Stubbed ::getWords and ::getModifications. --- src/CLI.cpp | 14 ++++++++++++++ src/CLI.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index f5f64ab33..522db0829 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -271,6 +271,20 @@ const std::string CLI::getFilter () const return filter; } +//////////////////////////////////////////////////////////////////////////////// +const std::vector CLI::getWords () const +{ + std::vector words; + return words; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::vector CLI::getModifications () const +{ + std::vector modifications; + return modifications; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 44cb41fe7..78bdb17e5 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -44,6 +44,8 @@ public: bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; const std::string getFilter () const; + const std::vector getWords () const; + const std::vector getModifications () const; private: void extractOverrides (); From 6d6447282623cf2aaa81d43a0f8a00add1c046ac Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:23:09 -0400 Subject: [PATCH 25/97] Context - Removed calls to now-private methods. --- src/Context.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Context.cpp b/src/Context.cpp index 97a4c3de3..ad21ccf82 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -109,10 +109,6 @@ int Context::initialize (int argc, const char** argv) // Scan command line for 'rc:' only. Parser::getOverrides (argc, argv, rc_file._data); cli.initialize (argc, argv); // task arg0 arg1 ... -/* - std::cout << "# cli._rc=" << cli._rc << "\n"; - rc_file = cli._rc; -*/ // TASKRC environment variable overrides the command line. char* override = getenv ("TASKRC"); @@ -243,8 +239,6 @@ int Context::initialize (int argc, const char** argv) } // Now the entities are loaded, parsing may resume. - cli.aliasExpansion (); - parser.findBinary (); // parser.resolveAliases (); parser.findCommand (); // @@ -254,7 +248,6 @@ int Context::initialize (int argc, const char** argv) staticInitialization (); // Decouple code from Context. parser.parse (); // Parse all elements. - cli.categorize (); // Parse high-level elements. tdb2.set_location (data_dir); // Prepare the task database. From 7812bce079a6792e802a635a10c56c98123082d4 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:25:26 -0400 Subject: [PATCH 26/97] CLI - Reorganized methods to match header sequence. --- src/CLI.cpp | 55 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 522db0829..54106d129 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -91,34 +91,8 @@ void CLI::add (const std::string& arg) extractOverrides (); aliasExpansion (); categorize (); -} -//////////////////////////////////////////////////////////////////////////////// -void CLI::extractOverrides () -{ - std::vector reconstructed; - - std::vector ::iterator i; - for (i = _args.begin (); i != _args.end (); ++i) - { - if (i->find ("rc:") == 0) - { - _rc = i->substr (3); - } - else if (i->find ("rc.") == 0) - { - std::string::size_type sep = i->find ('=', 3); - if (sep == std::string::npos) - sep = i->find (':', 3); - if (sep != std::string::npos) - _overrides[i->substr (3, sep - 3)] = i->substr (sep + 1); - } - else - reconstructed.push_back (*i); - } - - _args = reconstructed; - dump ("CLI::extractOverrides"); + dump ("CLI::add"); } //////////////////////////////////////////////////////////////////////////////// @@ -152,8 +126,33 @@ void CLI::aliasExpansion () _args = reconstructed; } while (action && counter++ < safetyValveDefault); +} - dump ("CLI::aliasExpansion"); +//////////////////////////////////////////////////////////////////////////////// +void CLI::extractOverrides () +{ + std::vector reconstructed; + + std::vector ::iterator i; + for (i = _args.begin (); i != _args.end (); ++i) + { + if (i->find ("rc:") == 0) + { + _rc = i->substr (3); + } + else if (i->find ("rc.") == 0) + { + std::string::size_type sep = i->find ('=', 3); + if (sep == std::string::npos) + sep = i->find (':', 3); + if (sep != std::string::npos) + _overrides[i->substr (3, sep - 3)] = i->substr (sep + 1); + } + else + reconstructed.push_back (*i); + } + + _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// From d6e11761a61c6582cd7b47397f669d2e67f63179 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:26:12 -0400 Subject: [PATCH 27/97] CLI - Added diagnostics only to ::initialize and ::add. - Now properly clears and regenerates all data on change. --- src/CLI.cpp | 40 ++++++++++++++++++++++++++++------------ src/CLI.h | 9 ++++----- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 54106d129..e76048db1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -71,25 +71,48 @@ void CLI::entity (const std::string& name, const std::string& value) // Capture the original, intact command line arguments. void CLI::initialize (int argc, const char** argv) { + // Clean what needs to be cleaned. Everything in this case. + _program = ""; + _original_args.clear (); + _args.clear (); + _rc = ""; + _overrides.clear (); + _command = ""; + _readOnly = false; + _filter.clear (); + _modifications.clear (); + _program = argv[0]; for (int i = 1; i < argc; ++i) _original_args.push_back (argv[i]); _args = _original_args; - dump ("CLI::initialize"); + aliasExpansion (); extractOverrides (); + categorize (); + + dump ("CLI::initialize"); } //////////////////////////////////////////////////////////////////////////////// void CLI::add (const std::string& arg) { - _original_args.push_back (arg); - _args.push_back (arg); + // Clean what needs to be cleaned. Most in this case. + _program = ""; + _args.clear (); + _rc = ""; + _overrides.clear (); + _command = ""; + _readOnly = false; + _filter.clear (); + _modifications.clear (); + + _original_args.push_back (arg); + _args = _original_args; - dump ("CLI::add"); - extractOverrides (); aliasExpansion (); + extractOverrides (); categorize (); dump ("CLI::add"); @@ -160,11 +183,6 @@ void CLI::categorize () { bool foundCommand = false; - _filter.clear (); - _modifications.clear (); - _command = ""; - _readOnly = false; - std::vector ::iterator i; for (i = _args.begin (); i != _args.end (); ++i) { @@ -182,8 +200,6 @@ void CLI::categorize () _filter.push_back (*i); } } - - dump ("CLI::categorize"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 78bdb17e5..c41d81fea 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -39,16 +39,16 @@ public: void entity (const std::string&, const std::string&); void initialize (int, const char**); void add (const std::string&); - void aliasExpansion (); - void categorize (); - bool exactMatch (const std::string&, const std::string&) const; - bool canonicalize (std::string&, const std::string&, const std::string&) const; const std::string getFilter () const; const std::vector getWords () const; const std::vector getModifications () const; private: + void aliasExpansion (); void extractOverrides (); + void categorize (); + bool exactMatch (const std::string&, const std::string&) const; + bool canonicalize (std::string&, const std::string&, const std::string&) const; void dump (const std::string&) const; public: @@ -59,7 +59,6 @@ public: std::vector _args; std::string _rc; std::map _overrides; - std::string _command; bool _readOnly; std::vector _filter; From f353e1f3d5c150f5ce282c85a4f4e6c154678e2d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:40:13 -0400 Subject: [PATCH 28/97] CLI - Removed reset of _program on ::add, which never gets restored. --- src/CLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index e76048db1..deebed165 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -96,10 +96,10 @@ void CLI::initialize (int argc, const char** argv) } //////////////////////////////////////////////////////////////////////////////// +// Capture a single argument, and recalc everything. void CLI::add (const std::string& arg) { // Clean what needs to be cleaned. Most in this case. - _program = ""; _args.clear (); _rc = ""; _overrides.clear (); From 34fd7b4b042cd85e68c8319bd19ef1e5ecd0fefc Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 14 Oct 2014 23:49:13 -0400 Subject: [PATCH 29/97] CLI - Relocated public methods to top. - Removed const for methods, which are no longer const. --- src/CLI.cpp | 83 +++++++++++++++++++++++++++++------------------------ src/CLI.h | 6 ++-- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index deebed165..0e08c339e 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -118,6 +118,51 @@ void CLI::add (const std::string& arg) dump ("CLI::add"); } +//////////////////////////////////////////////////////////////////////////////// +const std::string CLI::getFilter () +{ + // Remove all the syntactic sugar. + unsweetenTags (); + + std::string filter = ""; + + if (_filter.size ()) + { + filter = "("; + + std::vector ::const_iterator i; + for (i = _filter.begin (); i != _filter.end (); ++i) + { + if (i != _filter.begin ()) + filter += ' '; + + filter += *i; + } + + filter += ')'; + } + + return filter; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::vector CLI::getWords () +{ + std::vector words; + // TODO Processing here. + return words; +} + +//////////////////////////////////////////////////////////////////////////////// +const std::vector CLI::getModifications () +{ + // Remove all the syntactic sugar. + + std::vector modifications; + // TODO Processing here. + return modifications; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::aliasExpansion () { @@ -262,44 +307,6 @@ bool CLI::canonicalize ( return false; } -//////////////////////////////////////////////////////////////////////////////// -const std::string CLI::getFilter () const -{ - std::string filter = ""; - - if (_filter.size ()) - { - filter = "("; - - std::vector ::const_iterator i; - for (i = _filter.begin (); i != _filter.end (); ++i) - { - if (i != _filter.begin ()) - filter += ' '; - - filter += *i; - } - - filter += ')'; - } - - return filter; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector CLI::getWords () const -{ - std::vector words; - return words; -} - -//////////////////////////////////////////////////////////////////////////////// -const std::vector CLI::getModifications () const -{ - std::vector modifications; - return modifications; -} - //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index c41d81fea..a61aa4144 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -39,9 +39,9 @@ public: void entity (const std::string&, const std::string&); void initialize (int, const char**); void add (const std::string&); - const std::string getFilter () const; - const std::vector getWords () const; - const std::vector getModifications () const; + const std::string getFilter (); + const std::vector getWords (); + const std::vector getModifications (); private: void aliasExpansion (); From c2f8c81a887c508988aa6cb19a38db3106bd23e2 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 00:02:45 -0400 Subject: [PATCH 30/97] CLI - Implemented ::unsweetenTags, which resolves the syntactic sugar to an expression. --- src/CLI.cpp | 31 +++++++++++++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 32 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 0e08c339e..ba896584f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -307,6 +308,36 @@ bool CLI::canonicalize ( return false; } +//////////////////////////////////////////////////////////////////////////////// +// +tag --> tags _hastag_ tag +// -tag --> tags _notag_ tag +void CLI::unsweetenTags () +{ + std::vector reconstructed; + + std::vector ::iterator i; + for (i = _filter.begin (); i != _filter.end (); ++i) + { + Nibbler n (*i); + std::string tag; + std::string sign; + + if (n.getN (1, sign) && + (sign == "+" || sign == "-") && + n.getUntilEOS (tag) && + tag.find (' ') == std::string::npos) + { + reconstructed.push_back ("tags"); + reconstructed.push_back (sign == "+" ? "_hastag_" : "_notag_"); + reconstructed.push_back (tag); + } + else + reconstructed.push_back (*i); + } + + _filter = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index a61aa4144..35828c7ee 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -49,6 +49,7 @@ private: void categorize (); bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; + void unsweetenTags (); void dump (const std::string&) const; public: From 8b78251735a8549bdda80b0501300f3e82aaff4e Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 00:27:43 -0400 Subject: [PATCH 31/97] CLI - Filter elements are now rendered on one line in ::dump. --- src/CLI.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index ba896584f..73c2deaaf 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -371,8 +371,15 @@ void CLI::dump (const std::string& label) const for (m = _overrides.begin (); m != _overrides.end (); ++m) std::cout << "# _overrides " << m->first << " --> " << m->second << "\n"; + std::cout << "# _filter "; + Color colorFilter ("gray20 on gray8"); for (i = _filter.begin (); i != _filter.end (); ++i) - std::cout << "# _filter " << *i << "\n"; + { + if (i != _filter.begin ()) + std::cout << ' '; + std::cout << colorFilter.colorize (*i); + } + std::cout << "\n"; std::cout << "# _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; From b98da56a7c922e680433e5652a93f9c62e0c21af Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 00:28:16 -0400 Subject: [PATCH 32/97] CLI - Implemented A class, to represent a single argument. Much like a tree node. --- src/CLI.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/CLI.h | 25 ++++++++++++ 2 files changed, 133 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 73c2deaaf..93f551eea 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,113 @@ static int minimumMatchLength = 3; // Alias expansion limit. Any more indicates some kind of error. static int safetyValveDefault = 10; +//////////////////////////////////////////////////////////////////////////////// +A::A (const std::string& name) +: _name (name) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +A::~A () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +A::A (const A& other) +: _name (other._name) +, _tags (other._tags) +, _attributes (other._attributes) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +A& A::operator= (const A& other) +{ + if (this != &other) + { + _name = other._name; + _tags = other._tags; + _attributes = other._attributes; + } + + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +bool A::hasTag (const std::string& tag) const +{ + if (std::find (_tags.begin (), _tags.end (), tag) != _tags.end ()) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +void A::tag (const std::string& tag) +{ + if (! hasTag (tag)) + _tags.push_back (tag); +} + +//////////////////////////////////////////////////////////////////////////////// +void A::unTag (const std::string& tag) +{ + std::vector ::iterator i; + for (i = _tags.begin (); i != _tags.end (); ++i) + { + if (*i == tag) + { + _tags.erase (i); + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +void A::attribute (const std::string& name, const std::string& value) +{ + _attributes[name] = value; +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +void A::attribute (const std::string& name, const int value) +{ + _attributes[name] = format (value); +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +void A::attribute (const std::string& name, const double value) +{ + _attributes[name] = format (value, 1, 8); +} + +//////////////////////////////////////////////////////////////////////////////// +// Accessor for attributes. +std::string A::attribute (const std::string& name) +{ + // Prevent autovivification. + std::map::iterator i = _attributes.find (name); + if (i != _attributes.end ()) + return i->second; + + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +void A::removeAttribute (const std::string& name) +{ + _attributes.erase (name); +} + +//////////////////////////////////////////////////////////////////////////////// +std::string A::dump () +{ + return "A::dump"; +} + //////////////////////////////////////////////////////////////////////////////// CLI::CLI () : _program ("") diff --git a/src/CLI.h b/src/CLI.h index 35828c7ee..e900fc189 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -30,6 +30,31 @@ #include #include +// Represents a single argument. +class A +{ +public: + A (const std::string&); + ~A (); + A (const A&); + A& operator= (const A&); + bool hasTag (const std::string&) const; + void tag (const std::string&); + void unTag (const std::string&); + void attribute (const std::string&, const std::string&); + void attribute (const std::string&, const int); + void attribute (const std::string&, const double); + std::string attribute (const std::string&); + void removeAttribute (const std::string&); + std::string dump (); + +public: + std::string _name; + std::vector _tags; + std::map _attributes; +}; + +// Represents the command line. class CLI { public: From 87ece489db71f9819cf59ab8c04e2de569b444d0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 00:35:46 -0400 Subject: [PATCH 33/97] CLI - Implemented A::dump. --- src/CLI.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- src/CLI.h | 4 ++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 93f551eea..b7990f46a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -128,7 +128,7 @@ void A::attribute (const std::string& name, const double value) //////////////////////////////////////////////////////////////////////////////// // Accessor for attributes. -std::string A::attribute (const std::string& name) +const std::string A::attribute (const std::string& name) { // Prevent autovivification. std::map::iterator i = _attributes.find (name); @@ -145,9 +145,47 @@ void A::removeAttribute (const std::string& name) } //////////////////////////////////////////////////////////////////////////////// -std::string A::dump () +const std::string A::dump () { - return "A::dump"; + std::string output = ""; + + // Dump attributes. + std::string atts; + std::map ::iterator a; + for (a = _attributes.begin (); a != _attributes.end (); ++a) + { + if (a != _attributes.begin ()) + atts += " "; + + atts += a->first + "='\033[33m" + a->second + "\033[0m'"; + } + + if (atts.length ()) + output += " " + atts; + + // Dump tags. + std::string tags; + std::vector ::iterator tag; + for (tag = _tags.begin (); tag != _tags.end (); ++tag) + { + if (tags.length ()) + tags += ' '; + + if (*tag == "BINARY") tags += "\033[1;37;44m" + *tag + "\033[0m"; + else if (*tag == "CMD") tags += "\033[1;37;46m" + *tag + "\033[0m"; + else if (*tag == "FILTER") tags += "\033[1;37;42m" + *tag + "\033[0m"; + else if (*tag == "MODIFICATION") tags += "\033[1;37;43m" + *tag + "\033[0m"; + else if (*tag == "RC") tags += "\033[1;37;41m" + *tag + "\033[0m"; + else if (*tag == "CONFIG") tags += "\033[1;37;101m" + *tag + "\033[0m"; + else if (*tag == "?") tags += "\033[38;5;255;48;5;232m" + *tag + "\033[0m"; + else tags += "\033[32m" + *tag + "\033[0m"; + } + + if (tags.length ()) + output += ' ' + tags; + output += "\n"; + + return output; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index e900fc189..8b0b9bc48 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -44,9 +44,9 @@ public: void attribute (const std::string&, const std::string&); void attribute (const std::string&, const int); void attribute (const std::string&, const double); - std::string attribute (const std::string&); + const std::string attribute (const std::string&); void removeAttribute (const std::string&); - std::string dump (); + const std::string dump (); public: std::string _name; From 854dc08615f7a1266c835ac242648c7da1259761 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:08:44 -0400 Subject: [PATCH 34/97] CLI - Upgraded _args vector from std::string to A. --- src/CLI.cpp | 100 +++++++++++++++++++++++++++++----------------------- src/CLI.h | 6 ++-- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index b7990f46a..26daeec83 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -44,9 +44,10 @@ static int minimumMatchLength = 3; static int safetyValveDefault = 10; //////////////////////////////////////////////////////////////////////////////// -A::A (const std::string& name) -: _name (name) +A::A (const std::string& name, const std::string& raw) { + _name = name; + attribute ("raw", raw); } //////////////////////////////////////////////////////////////////////////////// @@ -145,13 +146,13 @@ void A::removeAttribute (const std::string& name) } //////////////////////////////////////////////////////////////////////////////// -const std::string A::dump () +const std::string A::dump () const { - std::string output = ""; + std::string output = _name; // Dump attributes. std::string atts; - std::map ::iterator a; + std::map ::const_iterator a; for (a = _attributes.begin (); a != _attributes.end (); ++a) { if (a != _attributes.begin ()) @@ -165,7 +166,7 @@ const std::string A::dump () // Dump tags. std::string tags; - std::vector ::iterator tag; + std::vector ::const_iterator tag; for (tag = _tags.begin (); tag != _tags.end (); ++tag) { if (tags.length ()) @@ -183,7 +184,6 @@ const std::string A::dump () if (tags.length ()) output += ' ' + tags; - output += "\n"; return output; } @@ -233,7 +233,13 @@ void CLI::initialize (int argc, const char** argv) for (int i = 1; i < argc; ++i) _original_args.push_back (argv[i]); - _args = _original_args; + std::vector ::iterator i; + for (i = _original_args.begin (); i != _original_args.end (); ++i) + { + A a ("arg", *i); + a.tag ("ORIGINAL"); + _args.push_back (a); + } aliasExpansion (); extractOverrides (); @@ -256,7 +262,13 @@ void CLI::add (const std::string& arg) _modifications.clear (); _original_args.push_back (arg); - _args = _original_args; + std::vector ::iterator i; + for (i = _original_args.begin (); i != _original_args.end (); ++i) + { + A a ("argAdd", *i); + a.tag ("ORIGINAL"); + _args.push_back (a); + } aliasExpansion (); extractOverrides (); @@ -318,19 +330,23 @@ void CLI::aliasExpansion () do { action = false; - std::vector reconstructed; + std::vector reconstructed; - std::vector ::iterator i; + std::vector ::iterator i; for (i = _args.begin (); i != _args.end (); ++i) { - if (_aliases.find (*i) != _aliases.end ()) + if (_aliases.find (i->_name) != _aliases.end ()) { std::vector lexed; - Lexer::token_split (lexed, _aliases[*i]); + Lexer::token_split (lexed, _aliases[i->_name]); std::vector ::iterator l; for (l = lexed.begin (); l != lexed.end (); ++l) - reconstructed.push_back (*l); + { + A a ("argLex", *l); + a.tag ("LEX"); + reconstructed.push_back (a); + } action = true; } @@ -346,22 +362,22 @@ void CLI::aliasExpansion () //////////////////////////////////////////////////////////////////////////////// void CLI::extractOverrides () { - std::vector reconstructed; - - std::vector ::iterator i; + std::vector reconstructed; + std::vector ::iterator i; for (i = _args.begin (); i != _args.end (); ++i) { - if (i->find ("rc:") == 0) + std::string raw = i->attribute ("raw"); + if (raw.find ("rc:") == 0) { - _rc = i->substr (3); + _rc = raw.substr (3); } - else if (i->find ("rc.") == 0) + else if (raw.find ("rc.") == 0) { - std::string::size_type sep = i->find ('=', 3); + std::string::size_type sep = raw.find ('=', 3); if (sep == std::string::npos) - sep = i->find (':', 3); + sep = raw.find (':', 3); if (sep != std::string::npos) - _overrides[i->substr (3, sep - 3)] = i->substr (sep + 1); + _overrides[raw.substr (3, sep - 3)] = raw.substr (sep + 1); } else reconstructed.push_back (*i); @@ -375,21 +391,22 @@ void CLI::categorize () { bool foundCommand = false; - std::vector ::iterator i; + std::vector ::iterator i; for (i = _args.begin (); i != _args.end (); ++i) { - if (canonicalize (_command, "cmd", *i)) + std::string raw = i->attribute ("raw"); + if (canonicalize (_command, "cmd", raw)) { foundCommand = true; _readOnly = ! exactMatch ("writecmd", _command); } else if (foundCommand && ! _readOnly) { - _modifications.push_back (*i); + _modifications.push_back (raw); } else { - _filter.push_back (*i); + _filter.push_back (raw); } } } @@ -487,10 +504,10 @@ void CLI::unsweetenTags () //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { - std::cout << "# " << label << "\n" - << "# _program " << _program << "\n"; + std::cout << label << "\n" + << " _program " << _program << "\n"; - std::cout << "# _original_args "; + std::cout << " _original_args "; Color colorOrigArgs ("gray10 on gray4"); std::vector ::const_iterator i; for (i = _original_args.begin (); i != _original_args.end (); ++i) @@ -501,23 +518,18 @@ void CLI::dump (const std::string& label) const } std::cout << "\n"; - std::cout << "# _args "; - Color colorArgs ("gray16 on gray4"); - for (i = _args.begin (); i != _args.end (); ++i) - { - if (i != _args.begin ()) - std::cout << ' '; - std::cout << colorArgs.colorize (*i); - } - std::cout << "\n"; + std::cout << " _args\n"; + std::vector ::const_iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + std::cout << " " << a->dump () << "\n"; - std::cout << "# _rc " << _rc << "\n"; + std::cout << " _rc " << _rc << "\n"; std::map ::const_iterator m; for (m = _overrides.begin (); m != _overrides.end (); ++m) - std::cout << "# _overrides " << m->first << " --> " << m->second << "\n"; + std::cout << " _overrides " << m->first << " --> " << m->second << "\n"; - std::cout << "# _filter "; + std::cout << " _filter "; Color colorFilter ("gray20 on gray8"); for (i = _filter.begin (); i != _filter.end (); ++i) { @@ -527,10 +539,10 @@ void CLI::dump (const std::string& label) const } std::cout << "\n"; - std::cout << "# _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; + std::cout << " _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; for (i = _modifications.begin (); i != _modifications.end (); ++i) - std::cout << "# _modifications " << *i << "\n"; + std::cout << " _modifications " << *i << "\n"; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 8b0b9bc48..b75763f89 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -34,7 +34,7 @@ class A { public: - A (const std::string&); + A (const std::string&, const std::string&); ~A (); A (const A&); A& operator= (const A&); @@ -46,7 +46,7 @@ public: void attribute (const std::string&, const double); const std::string attribute (const std::string&); void removeAttribute (const std::string&); - const std::string dump (); + const std::string dump () const; public: std::string _name; @@ -82,7 +82,7 @@ public: std::map _aliases; std::string _program; std::vector _original_args; - std::vector _args; + std::vector _args; std::string _rc; std::map _overrides; std::string _command; From 6388d3827b1fead5e749ed6db711a378169ecec3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:24:02 -0400 Subject: [PATCH 35/97] CLI - Converted from std::string to A. --- src/CLI.cpp | 56 ++++++++++++++++++++++++++++++++--------------------- src/CLI.h | 6 +++--- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 26daeec83..545f6a72e 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -129,10 +129,10 @@ void A::attribute (const std::string& name, const double value) //////////////////////////////////////////////////////////////////////////////// // Accessor for attributes. -const std::string A::attribute (const std::string& name) +const std::string A::attribute (const std::string& name) const { // Prevent autovivification. - std::map::iterator i = _attributes.find (name); + std::map::const_iterator i = _attributes.find (name); if (i != _attributes.end ()) return i->second; @@ -289,13 +289,13 @@ const std::string CLI::getFilter () { filter = "("; - std::vector ::const_iterator i; + std::vector ::const_iterator i; for (i = _filter.begin (); i != _filter.end (); ++i) { if (i != _filter.begin ()) filter += ' '; - filter += *i; + filter += i->attribute ("raw"); } filter += ')'; @@ -402,11 +402,15 @@ void CLI::categorize () } else if (foundCommand && ! _readOnly) { - _modifications.push_back (raw); + A a ("argMod", raw); + a.tag ("MODIFICATION"); + _modifications.push_back (a); } else { - _filter.push_back (raw); + A a ("argFilt", raw); + a.tag ("FILTER"); + _filter.push_back (a); } } } @@ -476,12 +480,11 @@ bool CLI::canonicalize ( // -tag --> tags _notag_ tag void CLI::unsweetenTags () { - std::vector reconstructed; - - std::vector ::iterator i; + std::vector reconstructed; + std::vector ::iterator i; for (i = _filter.begin (); i != _filter.end (); ++i) { - Nibbler n (*i); + Nibbler n (i->attribute ("raw")); std::string tag; std::string sign; @@ -490,9 +493,17 @@ void CLI::unsweetenTags () n.getUntilEOS (tag) && tag.find (' ') == std::string::npos) { - reconstructed.push_back ("tags"); - reconstructed.push_back (sign == "+" ? "_hastag_" : "_notag_"); - reconstructed.push_back (tag); + A left ("argTag", "tags"); + left.tag ("ATT"); + reconstructed.push_back (left); + + A op ("argTag", sign == "+" ? "_hastag_" : "_notag_"); + op.tag ("OP"); + reconstructed.push_back (op); + + A right ("argTag", tag); + right.tag ("LITERAL"); + reconstructed.push_back (right); } else reconstructed.push_back (*i); @@ -529,20 +540,21 @@ void CLI::dump (const std::string& label) const for (m = _overrides.begin (); m != _overrides.end (); ++m) std::cout << " _overrides " << m->first << " --> " << m->second << "\n"; - std::cout << " _filter "; - Color colorFilter ("gray20 on gray8"); - for (i = _filter.begin (); i != _filter.end (); ++i) + if (_filter.size ()) { - if (i != _filter.begin ()) - std::cout << ' '; - std::cout << colorFilter.colorize (*i); + std::cout << " _filter\n"; + for (a = _filter.begin (); a != _filter.end (); ++a) + std::cout << " " << a->dump () << "\n"; } - std::cout << "\n"; std::cout << " _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; - for (i = _modifications.begin (); i != _modifications.end (); ++i) - std::cout << " _modifications " << *i << "\n"; + if (_modifications.size ()) + { + std::cout << " _modifications\n"; + for (a = _modifications.begin (); a != _modifications.end (); ++a) + std::cout << " " << a->dump () << "\n"; + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index b75763f89..3b09b681f 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -44,7 +44,7 @@ public: void attribute (const std::string&, const std::string&); void attribute (const std::string&, const int); void attribute (const std::string&, const double); - const std::string attribute (const std::string&); + const std::string attribute (const std::string&) const; void removeAttribute (const std::string&); const std::string dump () const; @@ -87,8 +87,8 @@ public: std::map _overrides; std::string _command; bool _readOnly; - std::vector _filter; - std::vector _modifications; + std::vector _filter; + std::vector _modifications; }; #endif From b3b509eabec823a84e3452f72aa2e3424e063bbe Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:33:12 -0400 Subject: [PATCH 36/97] CLI - Added default constructor, so it plays nice with others. - Added ::clear method to reset all members. --- src/CLI.cpp | 14 ++++++++++++++ src/CLI.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 545f6a72e..bbda45c1d 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -43,6 +43,12 @@ static int minimumMatchLength = 3; // Alias expansion limit. Any more indicates some kind of error. static int safetyValveDefault = 10; +//////////////////////////////////////////////////////////////////////////////// +A::A () +: _name ("") +{ +} + //////////////////////////////////////////////////////////////////////////////// A::A (const std::string& name, const std::string& raw) { @@ -76,6 +82,14 @@ A& A::operator= (const A& other) return *this; } +//////////////////////////////////////////////////////////////////////////////// +void A::clear () +{ + _name = ""; + _tags.clear (); + _attributes.clear (); +} + //////////////////////////////////////////////////////////////////////////////// bool A::hasTag (const std::string& tag) const { diff --git a/src/CLI.h b/src/CLI.h index 3b09b681f..2899e00f4 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -34,10 +34,12 @@ class A { public: + A (); A (const std::string&, const std::string&); ~A (); A (const A&); A& operator= (const A&); + void clear (); bool hasTag (const std::string&) const; void tag (const std::string&); void unTag (const std::string&); From e5780474da0cd18de10c95605aee6729924f26fa Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:34:36 -0400 Subject: [PATCH 37/97] CLI - Converted _program from std::string to A. --- src/CLI.cpp | 13 ++++++++----- src/CLI.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index bbda45c1d..9e46f5cdc 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -204,8 +204,7 @@ const std::string A::dump () const //////////////////////////////////////////////////////////////////////////////// CLI::CLI () -: _program ("") -, _rc ("") +: _rc ("") , _command ("") , _readOnly (false) { @@ -233,7 +232,7 @@ void CLI::entity (const std::string& name, const std::string& value) void CLI::initialize (int argc, const char** argv) { // Clean what needs to be cleaned. Everything in this case. - _program = ""; + _program.clear (); _original_args.clear (); _args.clear (); _rc = ""; @@ -243,7 +242,10 @@ void CLI::initialize (int argc, const char** argv) _filter.clear (); _modifications.clear (); - _program = argv[0]; + _program._name = "arg"; + _program.attribute ("raw", argv[0]); + _program.tag ("BINARY"); + for (int i = 1; i < argc; ++i) _original_args.push_back (argv[i]); @@ -530,7 +532,8 @@ void CLI::unsweetenTags () void CLI::dump (const std::string& label) const { std::cout << label << "\n" - << " _program " << _program << "\n"; + << " _program\n" + << " " << _program.dump () << "\n"; std::cout << " _original_args "; Color colorOrigArgs ("gray10 on gray4"); diff --git a/src/CLI.h b/src/CLI.h index 2899e00f4..9aeb1d541 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -82,7 +82,7 @@ private: public: std::multimap _entities; std::map _aliases; - std::string _program; + A _program; std::vector _original_args; std::vector _args; std::string _rc; From 698c801dbc24eba096c4fb8777b7dd00292dd75f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:43:27 -0400 Subject: [PATCH 38/97] CLI - Converted _command from std::string to A. --- src/CLI.cpp | 17 +++++++++++------ src/CLI.h | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 9e46f5cdc..8f3dd0548 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -205,7 +205,6 @@ const std::string A::dump () const //////////////////////////////////////////////////////////////////////////////// CLI::CLI () : _rc ("") -, _command ("") , _readOnly (false) { } @@ -237,7 +236,7 @@ void CLI::initialize (int argc, const char** argv) _args.clear (); _rc = ""; _overrides.clear (); - _command = ""; + _command.clear (); _readOnly = false; _filter.clear (); _modifications.clear (); @@ -272,7 +271,7 @@ void CLI::add (const std::string& arg) _args.clear (); _rc = ""; _overrides.clear (); - _command = ""; + _command.clear (); _readOnly = false; _filter.clear (); _modifications.clear (); @@ -411,10 +410,15 @@ void CLI::categorize () for (i = _args.begin (); i != _args.end (); ++i) { std::string raw = i->attribute ("raw"); - if (canonicalize (_command, "cmd", raw)) + std::string command; + if (canonicalize (command, "cmd", raw)) { + _command._name = "argCmd"; + _command.attribute ("raw", raw); + _command.attribute ("canonical", command); + _readOnly = ! exactMatch ("writecmd", command); + _command.tag (_readOnly ? "READCMD" : "WRITECMD"); foundCommand = true; - _readOnly = ! exactMatch ("writecmd", _command); } else if (foundCommand && ! _readOnly) { @@ -564,7 +568,8 @@ void CLI::dump (const std::string& label) const std::cout << " " << a->dump () << "\n"; } - std::cout << " _command " << _command << " " << (_readOnly ? "(read)" : "(write)") << "\n"; + std::cout << " _command\n" + << " " << _command.dump () << "\n"; if (_modifications.size ()) { diff --git a/src/CLI.h b/src/CLI.h index 9aeb1d541..b1dc2da78 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -87,7 +87,7 @@ public: std::vector _args; std::string _rc; std::map _overrides; - std::string _command; + A _command; bool _readOnly; std::vector _filter; std::vector _modifications; From 295feda3b496baea96ca09c78e904f6f34614e4d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:44:21 -0400 Subject: [PATCH 39/97] Parser - Corrected findTags comment. --- src/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser.cpp b/src/Parser.cpp index bea915269..f359b1f3e 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -851,7 +851,7 @@ void Parser::findSubstitution () } //////////////////////////////////////////////////////////////////////////////// -// +tag +// +tag|-tag void Parser::findTag () { bool action = true; From c3f7524006173971ecd2feda226e9895fff38d5b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 01:47:36 -0400 Subject: [PATCH 40/97] CLI - Now only dumps the parse tree on ::getFilter. --- src/CLI.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 8f3dd0548..74f31bf53 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -259,8 +259,6 @@ void CLI::initialize (int argc, const char** argv) aliasExpansion (); extractOverrides (); categorize (); - - dump ("CLI::initialize"); } //////////////////////////////////////////////////////////////////////////////// @@ -288,8 +286,6 @@ void CLI::add (const std::string& arg) aliasExpansion (); extractOverrides (); categorize (); - - dump ("CLI::add"); } //////////////////////////////////////////////////////////////////////////////// @@ -316,6 +312,7 @@ const std::string CLI::getFilter () filter += ')'; } + dump ("CLI::getFilter"); return filter; } From dd8391351d386cb39fdbf164b1fa49ea76122f89 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 02:08:48 -0400 Subject: [PATCH 41/97] CLI - Merged _program into _args. - Merged _overrides into _args. - Rewrote :extractOverrides as ::findOverrides. --- src/CLI.cpp | 94 +++++++++++++++++++++++++++++------------------------ src/CLI.h | 4 +-- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 74f31bf53..8587aaedc 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -231,33 +231,35 @@ void CLI::entity (const std::string& name, const std::string& value) void CLI::initialize (int argc, const char** argv) { // Clean what needs to be cleaned. Everything in this case. - _program.clear (); _original_args.clear (); _args.clear (); _rc = ""; - _overrides.clear (); _command.clear (); _readOnly = false; _filter.clear (); _modifications.clear (); - _program._name = "arg"; - _program.attribute ("raw", argv[0]); - _program.tag ("BINARY"); - - for (int i = 1; i < argc; ++i) + for (int i = 0; i < argc; ++i) + { _original_args.push_back (argv[i]); - std::vector ::iterator i; - for (i = _original_args.begin (); i != _original_args.end (); ++i) - { - A a ("arg", *i); - a.tag ("ORIGINAL"); - _args.push_back (a); + if (i == 0) + { + A a ("arg", argv[i]); + a.tag ("ORIGINAL"); + a.tag ("BINARY"); + _args.push_back (a); + } + else + { + A a ("arg", argv[i]); + a.tag ("ORIGINAL"); + _args.push_back (a); + } } aliasExpansion (); - extractOverrides (); + findOverrides (); categorize (); } @@ -268,23 +270,32 @@ void CLI::add (const std::string& arg) // Clean what needs to be cleaned. Most in this case. _args.clear (); _rc = ""; - _overrides.clear (); _command.clear (); _readOnly = false; _filter.clear (); _modifications.clear (); _original_args.push_back (arg); - std::vector ::iterator i; - for (i = _original_args.begin (); i != _original_args.end (); ++i) + + for (int i = 0; i < _original_args.size (); ++i) { - A a ("argAdd", *i); - a.tag ("ORIGINAL"); - _args.push_back (a); + if (i == 0) + { + A a ("arg", _original_args[i]); + a.tag ("ORIGINAL"); + a.tag ("BINARY"); + _args.push_back (a); + } + else + { + A a ("arg", _original_args[i]); + a.tag ("ORIGINAL"); + _args.push_back (a); + } } aliasExpansion (); - extractOverrides (); + findOverrides (); categorize (); } @@ -293,6 +304,7 @@ const std::string CLI::getFilter () { // Remove all the syntactic sugar. unsweetenTags (); + // TODO all the other types: att, attmod, pattern, id, uuid ... std::string filter = ""; @@ -320,17 +332,21 @@ const std::string CLI::getFilter () const std::vector CLI::getWords () { std::vector words; + // TODO Processing here. + + dump ("CLI::getWords"); return words; } //////////////////////////////////////////////////////////////////////////////// const std::vector CLI::getModifications () { - // Remove all the syntactic sugar. - std::vector modifications; + // TODO Processing here. + + dump ("CLI::getModifications"); return modifications; } @@ -372,16 +388,17 @@ void CLI::aliasExpansion () } //////////////////////////////////////////////////////////////////////////////// -void CLI::extractOverrides () +void CLI::findOverrides () { - std::vector reconstructed; - std::vector ::iterator i; - for (i = _args.begin (); i != _args.end (); ++i) + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) { - std::string raw = i->attribute ("raw"); + std::string raw = a->attribute ("raw"); + if (raw.find ("rc:") == 0) { - _rc = raw.substr (3); + a->tag ("RC"); + a->attribute ("file", raw.substr (3)); } else if (raw.find ("rc.") == 0) { @@ -389,13 +406,13 @@ void CLI::extractOverrides () if (sep == std::string::npos) sep = raw.find (':', 3); if (sep != std::string::npos) - _overrides[raw.substr (3, sep - 3)] = raw.substr (sep + 1); + { + a->tag ("CONFIG"); + a->attribute ("name", raw.substr (3, sep - 3)); + a->attribute ("value", raw.substr (sep + 1)); + } } - else - reconstructed.push_back (*i); } - - _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// @@ -533,10 +550,7 @@ void CLI::unsweetenTags () void CLI::dump (const std::string& label) const { std::cout << label << "\n" - << " _program\n" - << " " << _program.dump () << "\n"; - - std::cout << " _original_args "; + << " _original_args "; Color colorOrigArgs ("gray10 on gray4"); std::vector ::const_iterator i; for (i = _original_args.begin (); i != _original_args.end (); ++i) @@ -554,10 +568,6 @@ void CLI::dump (const std::string& label) const std::cout << " _rc " << _rc << "\n"; - std::map ::const_iterator m; - for (m = _overrides.begin (); m != _overrides.end (); ++m) - std::cout << " _overrides " << m->first << " --> " << m->second << "\n"; - if (_filter.size ()) { std::cout << " _filter\n"; diff --git a/src/CLI.h b/src/CLI.h index b1dc2da78..895c16ac1 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -72,7 +72,7 @@ public: private: void aliasExpansion (); - void extractOverrides (); + void findOverrides (); void categorize (); bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; @@ -82,11 +82,9 @@ private: public: std::multimap _entities; std::map _aliases; - A _program; std::vector _original_args; std::vector _args; std::string _rc; - std::map _overrides; A _command; bool _readOnly; std::vector _filter; From 83898359e31f3a2eccbdbdc7c98232f0f43577d3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 02:24:35 -0400 Subject: [PATCH 42/97] CLI - Combined all elements into the single _args list. --- src/CLI.cpp | 77 +++++++++++++++++++---------------------------------- src/CLI.h | 5 ---- 2 files changed, 28 insertions(+), 54 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 8587aaedc..6eb083b28 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -204,8 +204,6 @@ const std::string A::dump () const //////////////////////////////////////////////////////////////////////////////// CLI::CLI () -: _rc ("") -, _readOnly (false) { } @@ -233,11 +231,6 @@ void CLI::initialize (int argc, const char** argv) // Clean what needs to be cleaned. Everything in this case. _original_args.clear (); _args.clear (); - _rc = ""; - _command.clear (); - _readOnly = false; - _filter.clear (); - _modifications.clear (); for (int i = 0; i < argc; ++i) { @@ -269,12 +262,6 @@ void CLI::add (const std::string& arg) { // Clean what needs to be cleaned. Most in this case. _args.clear (); - _rc = ""; - _command.clear (); - _readOnly = false; - _filter.clear (); - _modifications.clear (); - _original_args.push_back (arg); for (int i = 0; i < _original_args.size (); ++i) @@ -302,12 +289,16 @@ void CLI::add (const std::string& arg) //////////////////////////////////////////////////////////////////////////////// const std::string CLI::getFilter () { +// TODO Convert to _args. +/* // Remove all the syntactic sugar. unsweetenTags (); // TODO all the other types: att, attmod, pattern, id, uuid ... +*/ std::string filter = ""; +/* if (_filter.size ()) { filter = "("; @@ -323,6 +314,7 @@ const std::string CLI::getFilter () filter += ')'; } +*/ dump ("CLI::getFilter"); return filter; @@ -419,32 +411,35 @@ void CLI::findOverrides () void CLI::categorize () { bool foundCommand = false; + bool readOnly = false; - std::vector ::iterator i; - for (i = _args.begin (); i != _args.end (); ++i) + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) { - std::string raw = i->attribute ("raw"); - std::string command; - if (canonicalize (command, "cmd", raw)) + std::string raw = a->attribute ("raw"); + std::string canonical; + if (canonicalize (canonical, "cmd", raw)) { - _command._name = "argCmd"; - _command.attribute ("raw", raw); - _command.attribute ("canonical", command); - _readOnly = ! exactMatch ("writecmd", command); - _command.tag (_readOnly ? "READCMD" : "WRITECMD"); + readOnly = ! exactMatch ("writecmd", canonical); + + a->tag ("CMD"); + a->tag (readOnly ? "READCMD" : "WRITECMD"); + a->attribute ("canonical", canonical); foundCommand = true; } - else if (foundCommand && ! _readOnly) + else if (a->hasTag ("BINARY") || + a->hasTag ("CONFIG") || + a->hasTag ("RC")) { - A a ("argMod", raw); - a.tag ("MODIFICATION"); - _modifications.push_back (a); + // NOP + } + else if (foundCommand && ! readOnly) + { + a->tag ("MODIFICATION"); } else { - A a ("argFilt", raw); - a.tag ("FILTER"); - _filter.push_back (a); + a->tag ("FILTER"); } } } @@ -514,6 +509,8 @@ bool CLI::canonicalize ( // -tag --> tags _notag_ tag void CLI::unsweetenTags () { +// TODO Convert from _filter to _args. +/* std::vector reconstructed; std::vector ::iterator i; for (i = _filter.begin (); i != _filter.end (); ++i) @@ -544,6 +541,7 @@ void CLI::unsweetenTags () } _filter = reconstructed; +*/ } //////////////////////////////////////////////////////////////////////////////// @@ -565,25 +563,6 @@ void CLI::dump (const std::string& label) const std::vector ::const_iterator a; for (a = _args.begin (); a != _args.end (); ++a) std::cout << " " << a->dump () << "\n"; - - std::cout << " _rc " << _rc << "\n"; - - if (_filter.size ()) - { - std::cout << " _filter\n"; - for (a = _filter.begin (); a != _filter.end (); ++a) - std::cout << " " << a->dump () << "\n"; - } - - std::cout << " _command\n" - << " " << _command.dump () << "\n"; - - if (_modifications.size ()) - { - std::cout << " _modifications\n"; - for (a = _modifications.begin (); a != _modifications.end (); ++a) - std::cout << " " << a->dump () << "\n"; - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 895c16ac1..402390948 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -84,11 +84,6 @@ public: std::map _aliases; std::vector _original_args; std::vector _args; - std::string _rc; - A _command; - bool _readOnly; - std::vector _filter; - std::vector _modifications; }; #endif From 8dd9082697d9f110632e20084e14026b74e0aaef Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 02:32:32 -0400 Subject: [PATCH 43/97] CLI - Categorize has a better definition of FILTER. --- src/CLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 6eb083b28..0785b7c58 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -437,7 +437,7 @@ void CLI::categorize () { a->tag ("MODIFICATION"); } - else + else if (!foundCommand || (foundCommand && readOnly)) { a->tag ("FILTER"); } From ae4272f477e77520b9d0c7cc1b574243fcadaf55 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 02:33:50 -0400 Subject: [PATCH 44/97] CLI - When unsweetening tags, preserve the FILTER tag. --- src/CLI.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 0785b7c58..94afd845c 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -526,14 +526,17 @@ void CLI::unsweetenTags () { A left ("argTag", "tags"); left.tag ("ATT"); + left.tag ("FILTER"); reconstructed.push_back (left); A op ("argTag", sign == "+" ? "_hastag_" : "_notag_"); op.tag ("OP"); + op.tag ("FILTER"); reconstructed.push_back (op); A right ("argTag", tag); right.tag ("LITERAL"); + right.tag ("FILTER"); reconstructed.push_back (right); } else From f29b6a4be48eb2386cedcd2594288f754f266be1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 02:34:44 -0400 Subject: [PATCH 45/97] CLI - Convert ::unsweetenTags from _filter to _args. --- src/CLI.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 94afd845c..f7c40b877 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -289,15 +289,13 @@ void CLI::add (const std::string& arg) //////////////////////////////////////////////////////////////////////////////// const std::string CLI::getFilter () { -// TODO Convert to _args. -/* // Remove all the syntactic sugar. unsweetenTags (); // TODO all the other types: att, attmod, pattern, id, uuid ... -*/ std::string filter = ""; +// TODO Convert to _args. /* if (_filter.size ()) { @@ -509,13 +507,11 @@ bool CLI::canonicalize ( // -tag --> tags _notag_ tag void CLI::unsweetenTags () { -// TODO Convert from _filter to _args. -/* std::vector reconstructed; - std::vector ::iterator i; - for (i = _filter.begin (); i != _filter.end (); ++i) + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) { - Nibbler n (i->attribute ("raw")); + Nibbler n (a->attribute ("raw")); std::string tag; std::string sign; @@ -540,11 +536,10 @@ void CLI::unsweetenTags () reconstructed.push_back (right); } else - reconstructed.push_back (*i); + reconstructed.push_back (*a); } - _filter = reconstructed; -*/ + _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// From 8afb39dea680768dde9caa0bc79993b5c13767d6 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 07:34:29 -0400 Subject: [PATCH 46/97] CLI - Implemented ::unsweetenAtts to resolve syntactic sugar to an expression. --- src/CLI.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 88 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index f7c40b877..308f497da 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -291,6 +291,7 @@ const std::string CLI::getFilter () { // Remove all the syntactic sugar. unsweetenTags (); + unsweetenAtts (); // TODO all the other types: att, attmod, pattern, id, uuid ... std::string filter = ""; @@ -542,6 +543,92 @@ void CLI::unsweetenTags () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +// :['"][]['"] --> name = value +void CLI::unsweetenAtts () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getName (name) && + name.length ()) + { + if (n.skip (':')) + { + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) + { + if (value == "") + value = "''"; + + std::string canonical; + if (canonicalize (canonical, "uda", name)) + { + A left ("argUDA", name); + left.attribute ("canonical", canonical); + left.tag ("UDA"); + left.tag ("MODIFIABLE"); + left.tag ("FILTER"); + reconstructed.push_back (left); + found = true; + } + + else if (canonicalize (canonical, "pseudo", name)) + { + A left ("argUDA", name); + left.attribute ("canonical", canonical); + left.tag ("PSEUDO"); + left.tag ("FILTER"); + reconstructed.push_back (left); + found = true; + } + + else if (canonicalize (canonical, "attribute", name)) + { + A lhs ("argAtt", name); + lhs.attribute ("canonical", canonical); + lhs.tag ("ATTRIBUTE"); + lhs.tag ("FILTER"); + + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + lhs.tag ("MODIFIABLE"); + } + + A op ("argAtt", "="); + op.tag ("OP"); + op.tag ("FILTER"); + + A rhs ("argAtt", value); + rhs.tag ("FILTER"); + + reconstructed.push_back (lhs); + reconstructed.push_back (op); + reconstructed.push_back (rhs); + found = true; + } + } + } + } + + if (!found) + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 402390948..0d8bebcca 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -77,6 +77,7 @@ private: bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; void unsweetenTags (); + void unsweetenAtts (); void dump (const std::string&) const; public: From 9f8c4e02a7aac9cc276d95912c207f0fa012e1ac Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 15 Oct 2014 07:42:29 -0400 Subject: [PATCH 47/97] CLI - Implemented ::getFilter to extract all the non-PSEUDO, FILTER items. --- src/CLI.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 308f497da..59bbee1a1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -287,6 +287,7 @@ void CLI::add (const std::string& arg) } //////////////////////////////////////////////////////////////////////////////// +// Extract all the FILTER-tagged items. const std::string CLI::getFilter () { // Remove all the syntactic sugar. @@ -295,28 +296,28 @@ const std::string CLI::getFilter () // TODO all the other types: att, attmod, pattern, id, uuid ... std::string filter = ""; - -// TODO Convert to _args. -/* - if (_filter.size ()) + if (_args.size ()) { - filter = "("; - - std::vector ::const_iterator i; - for (i = _filter.begin (); i != _filter.end (); ++i) + std::vector ::const_iterator a; + for (a = _args.begin (); a != _args.end (); ++a) { - if (i != _filter.begin ()) - filter += ' '; + if (a->hasTag ("FILTER") && + ! a->hasTag ("PSEUDO")) + { + if (filter != "") + filter += ' '; - filter += i->attribute ("raw"); + std::string term = a->attribute ("canonical"); + if (term == "") + term = a->attribute ("raw"); + + filter += term; + } } - - filter += ')'; } -*/ dump ("CLI::getFilter"); - return filter; + return "(" + filter + ")"; } //////////////////////////////////////////////////////////////////////////////// From 80b385ee939680e38b5502ce0bacda6fc79bca6a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 16 Oct 2014 00:36:52 -0400 Subject: [PATCH 48/97] CLI - Renamed 'canonical' to 'name', for legacy reasons. --- src/CLI.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 59bbee1a1..1bce84ba2 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -307,7 +307,7 @@ const std::string CLI::getFilter () if (filter != "") filter += ' '; - std::string term = a->attribute ("canonical"); + std::string term = a->attribute ("name"); if (term == "") term = a->attribute ("raw"); @@ -424,7 +424,7 @@ void CLI::categorize () a->tag ("CMD"); a->tag (readOnly ? "READCMD" : "WRITECMD"); - a->attribute ("canonical", canonical); + a->attribute ("name", canonical); foundCommand = true; } else if (a->hasTag ("BINARY") || @@ -574,7 +574,7 @@ void CLI::unsweetenAtts () if (canonicalize (canonical, "uda", name)) { A left ("argUDA", name); - left.attribute ("canonical", canonical); + left.attribute ("name", canonical); left.tag ("UDA"); left.tag ("MODIFIABLE"); left.tag ("FILTER"); @@ -585,7 +585,7 @@ void CLI::unsweetenAtts () else if (canonicalize (canonical, "pseudo", name)) { A left ("argUDA", name); - left.attribute ("canonical", canonical); + left.attribute ("name", canonical); left.tag ("PSEUDO"); left.tag ("FILTER"); reconstructed.push_back (left); @@ -595,7 +595,7 @@ void CLI::unsweetenAtts () else if (canonicalize (canonical, "attribute", name)) { A lhs ("argAtt", name); - lhs.attribute ("canonical", canonical); + lhs.attribute ("name", canonical); lhs.tag ("ATTRIBUTE"); lhs.tag ("FILTER"); From 0603711aaccd443cc63fe767aa016f760d82be5d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 16 Oct 2014 00:37:48 -0400 Subject: [PATCH 49/97] CLI - Implemnted ::unsweetenAttMods. --- src/CLI.cpp | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/CLI.h | 1 + 2 files changed, 173 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 1bce84ba2..c7e2959ac 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -293,7 +293,8 @@ const std::string CLI::getFilter () // Remove all the syntactic sugar. unsweetenTags (); unsweetenAtts (); - // TODO all the other types: att, attmod, pattern, id, uuid ... + unsweetenAttMods (); + // TODO all the other types: pattern, id, uuid ... std::string filter = ""; if (_args.size ()) @@ -630,6 +631,176 @@ void CLI::unsweetenAtts () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +// .[:=]['"]['"] --> name value +void CLI::unsweetenAttMods () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getUntil (".", name) && + name.length ()) + { + std::string canonical; + if (canonicalize (canonical, "attribute", name) || + canonicalize (canonical, "uda", name)) + { + if (n.skip ('.')) + { + std::string sense = "+"; + if (n.skip ('~')) + sense = "-"; + + std::string modifier; + n.getUntilOneOf (":=", modifier); + + if (n.skip (':') || + n.skip ('=')) + { + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) + { + if (value == "") + value = "''"; + + A lhs ("argAttMod", name); + lhs.tag ("ATTMOD"); + lhs.tag ("FILTER"); + + lhs.attribute ("name", canonical); + lhs.attribute ("raw", value); + lhs.attribute ("modifier", modifier); + lhs.attribute ("sense", sense); + + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + lhs.tag ("MODIFIABLE"); + } + + A op ("argAttmod", ""); + op.tag ("FILTER"); + + A rhs ("argAttMod", ""); + rhs.tag ("FILTER"); + + if (modifier == "before" || modifier == "under" || modifier == "below") + { + op.attribute ("raw", "<"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "after" || modifier == "over" || modifier == "above") + { + op.attribute ("raw", ">"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "none") + { + op.attribute ("raw", "=="); + op.tag ("OP"); + rhs.attribute ("raw", "''"); + } + else if (modifier == "any") + { + op.attribute ("raw", "!="); + op.tag ("OP"); + rhs.attribute ("raw", "''"); + } + else if (modifier == "is" || modifier == "equals") + { + op.attribute ("raw", "=="); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "isnt" || modifier == "not") + { + op.attribute ("raw", "!="); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "has" || modifier == "contains") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "hasnt") + { + op.attribute ("raw", "!~"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "startswith" || modifier == "left") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", "'^" + value + "'"); + } + else if (modifier == "endswith" || modifier == "right") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", "'" + value + "$'"); + } + else if (modifier == "word") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + + +#if defined (DARWIN) + rhs.attribute ("raw", value); +#elif defined (SOLARIS) + rhs.attribute ("raw", "'\\<" + value + "\\>'"); +#else + rhs.attribute ("raw", "'\\b" + value + "\\b'"); +#endif + } + else if (modifier == "noword") + { + op.attribute ("raw", "!~"); + op.tag ("OP"); + +#if defined (DARWIN) + rhs.attribute ("raw", value); +#elif defined (SOLARIS) + rhs.attribute ("raw", "'\\<" + value + "\\>'"); +#else + rhs.attribute ("raw", "'\\b" + value + "\\b'"); +#endif + } + else + throw format (STRING_PARSER_UNKNOWN_ATTMOD, modifier); + + reconstructed.push_back (lhs); + reconstructed.push_back (op); + reconstructed.push_back (rhs); + found = true; + } + } + } + } + } + + if (!found) + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 0d8bebcca..d8f254641 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -78,6 +78,7 @@ private: bool canonicalize (std::string&, const std::string&, const std::string&) const; void unsweetenTags (); void unsweetenAtts (); + void unsweetenAttMods (); void dump (const std::string&) const; public: From 932865d3b5330a806c25425b8c9ae3d4354b804c Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 16 Oct 2014 00:39:56 -0400 Subject: [PATCH 50/97] CLI - Renamed unsweetenAtts to unsweetenAttributes, unsweetenAttMods to unsweetenAttributeModifiers. --- src/CLI.cpp | 8 ++++---- src/CLI.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index c7e2959ac..dcbe1051a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -292,8 +292,8 @@ const std::string CLI::getFilter () { // Remove all the syntactic sugar. unsweetenTags (); - unsweetenAtts (); - unsweetenAttMods (); + unsweetenAttributes (); + unsweetenAttributeModifiers (); // TODO all the other types: pattern, id, uuid ... std::string filter = ""; @@ -547,7 +547,7 @@ void CLI::unsweetenTags () //////////////////////////////////////////////////////////////////////////////// // :['"][]['"] --> name = value -void CLI::unsweetenAtts () +void CLI::unsweetenAttributes () { std::vector reconstructed; std::vector ::iterator a; @@ -633,7 +633,7 @@ void CLI::unsweetenAtts () //////////////////////////////////////////////////////////////////////////////// // .[:=]['"]['"] --> name value -void CLI::unsweetenAttMods () +void CLI::unsweetenAttributeModifiers () { std::vector reconstructed; std::vector ::iterator a; diff --git a/src/CLI.h b/src/CLI.h index d8f254641..cbf70dbfa 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -77,8 +77,8 @@ private: bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; void unsweetenTags (); - void unsweetenAtts (); - void unsweetenAttMods (); + void unsweetenAttributes (); + void unsweetenAttributeModifiers (); void dump (const std::string&) const; public: From 8d359ddd702c2ec231be3c45e26a297cf802ee09 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 16 Oct 2014 00:53:59 -0400 Subject: [PATCH 51/97] CLI - Implemented ::unsweetenPatterns. --- src/CLI.cpp | 40 +++++++++++++++++++++++++++++++++++++++- src/CLI.h | 1 + 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index dcbe1051a..bf13969b0 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -294,7 +294,8 @@ const std::string CLI::getFilter () unsweetenTags (); unsweetenAttributes (); unsweetenAttributeModifiers (); - // TODO all the other types: pattern, id, uuid ... + unsweetenPatterns (); + // TODO all the other types: id, uuid ... std::string filter = ""; if (_args.size ()) @@ -801,6 +802,43 @@ void CLI::unsweetenAttributeModifiers () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +// /pattern/ --> description ~ pattern +void CLI::unsweetenPatterns () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + Nibbler n (a->attribute ("raw")); + std::string pattern; + + if (n.getQuoted ('/', pattern) && + n.depleted () && + pattern.length () > 0) + { + A lhs ("argPattern", "description"); + lhs.tag ("ATT"); + lhs.tag ("FILTER"); + reconstructed.push_back (lhs); + + A op ("argPattern", "~"); + op.tag ("OP"); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A rhs ("argPattern", "'" + pattern + "'"); + rhs.tag ("LITERAL"); + rhs.tag ("FILTER"); + reconstructed.push_back (rhs); + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index cbf70dbfa..fafe74d29 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -79,6 +79,7 @@ private: void unsweetenTags (); void unsweetenAttributes (); void unsweetenAttributeModifiers (); + void unsweetenPatterns (); void dump (const std::string&) const; public: From 171fabbcda3839b7b36479961e8ca59eac6e2bb0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 17 Oct 2014 16:32:11 -0400 Subject: [PATCH 52/97] CLI - Corrected comment to include quotes that are necessary for patterns. --- src/CLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index bf13969b0..235503a56 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -803,7 +803,7 @@ void CLI::unsweetenAttributeModifiers () } //////////////////////////////////////////////////////////////////////////////// -// /pattern/ --> description ~ pattern +// /pattern/ --> description ~ 'pattern' void CLI::unsweetenPatterns () { std::vector reconstructed; From cd8f7ddac4c8888a03798316e3a8a85961683a10 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 17:59:51 -0400 Subject: [PATCH 53/97] CLI - Can now safely re-analyze command line if something changes. This required a ::analzye method to be called late in Context::initialize. --- src/CLI.cpp | 35 +++++++++++++---------------------- src/CLI.h | 1 + src/Context.cpp | 1 + 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 235503a56..55851c06a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -230,30 +230,10 @@ void CLI::initialize (int argc, const char** argv) { // Clean what needs to be cleaned. Everything in this case. _original_args.clear (); - _args.clear (); - for (int i = 0; i < argc; ++i) - { _original_args.push_back (argv[i]); - if (i == 0) - { - A a ("arg", argv[i]); - a.tag ("ORIGINAL"); - a.tag ("BINARY"); - _args.push_back (a); - } - else - { - A a ("arg", argv[i]); - a.tag ("ORIGINAL"); - _args.push_back (a); - } - } - - aliasExpansion (); - findOverrides (); - categorize (); + analyze (); } //////////////////////////////////////////////////////////////////////////////// @@ -261,9 +241,20 @@ void CLI::initialize (int argc, const char** argv) void CLI::add (const std::string& arg) { // Clean what needs to be cleaned. Most in this case. - _args.clear (); _original_args.push_back (arg); + analyze (); +} + +//////////////////////////////////////////////////////////////////////////////// +// Intended to be called after ::initialize() and ::add(), to perform the final +// analysis. Analysis is also performed directly after the above, because there +// is a need to extract overrides early, before entities are proviedd. +void CLI::analyze () +{ + // Clean what needs to be cleaned. Most in this case. + _args.clear (); + for (int i = 0; i < _original_args.size (); ++i) { if (i == 0) diff --git a/src/CLI.h b/src/CLI.h index fafe74d29..99546668e 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -66,6 +66,7 @@ public: void entity (const std::string&, const std::string&); void initialize (int, const char**); void add (const std::string&); + void analyze (); const std::string getFilter (); const std::vector getWords (); const std::vector getModifications (); diff --git a/src/Context.cpp b/src/Context.cpp index ad21ccf82..1cc1ebc88 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -248,6 +248,7 @@ int Context::initialize (int argc, const char** argv) staticInitialization (); // Decouple code from Context. parser.parse (); // Parse all elements. + cli.analyze (); // Parse all elements. tdb2.set_location (data_dir); // Prepare the task database. From f862ad15e655163d063f3b2de0776d7bc7bd92b9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 18:18:03 -0400 Subject: [PATCH 54/97] CLI - ::unsweetenTags no longer clobbers non-FILTER args. --- src/CLI.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 55851c06a..1ad6a23aa 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -506,29 +506,34 @@ void CLI::unsweetenTags () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - Nibbler n (a->attribute ("raw")); - std::string tag; - std::string sign; - - if (n.getN (1, sign) && - (sign == "+" || sign == "-") && - n.getUntilEOS (tag) && - tag.find (' ') == std::string::npos) + if (a->hasTag ("FILTER")) { - A left ("argTag", "tags"); - left.tag ("ATT"); - left.tag ("FILTER"); - reconstructed.push_back (left); + Nibbler n (a->attribute ("raw")); + std::string tag; + std::string sign; - A op ("argTag", sign == "+" ? "_hastag_" : "_notag_"); - op.tag ("OP"); - op.tag ("FILTER"); - reconstructed.push_back (op); + if (n.getN (1, sign) && + (sign == "+" || sign == "-") && + n.getUntilEOS (tag) && + tag.find (' ') == std::string::npos) + { + A left ("argTag", "tags"); + left.tag ("ATT"); + left.tag ("FILTER"); + reconstructed.push_back (left); - A right ("argTag", tag); - right.tag ("LITERAL"); - right.tag ("FILTER"); - reconstructed.push_back (right); + A op ("argTag", sign == "+" ? "_hastag_" : "_notag_"); + op.tag ("OP"); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A right ("argTag", tag); + right.tag ("LITERAL"); + right.tag ("FILTER"); + reconstructed.push_back (right); + } + else + reconstructed.push_back (*a); } else reconstructed.push_back (*a); From 720cc57192488658d0f40eb5e084a155c9e52838 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 18:18:48 -0400 Subject: [PATCH 55/97] CLI - ::unsweetenAttributes no longer clobbers non-FILTER args. --- src/CLI.cpp | 121 +++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 1ad6a23aa..36b3ec647 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -550,78 +550,83 @@ void CLI::unsweetenAttributes () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - // Look for a valid attribute name. - bool found = false; - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getName (name) && - name.length ()) + if (a->hasTag ("FILTER")) { - if (n.skip (':')) + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getName (name) && + name.length ()) { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) + if (n.skip (':')) { - if (value == "") - value = "''"; - - std::string canonical; - if (canonicalize (canonical, "uda", name)) + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) { - A left ("argUDA", name); - left.attribute ("name", canonical); - left.tag ("UDA"); - left.tag ("MODIFIABLE"); - left.tag ("FILTER"); - reconstructed.push_back (left); - found = true; - } + if (value == "") + value = "''"; - else if (canonicalize (canonical, "pseudo", name)) - { - A left ("argUDA", name); - left.attribute ("name", canonical); - left.tag ("PSEUDO"); - left.tag ("FILTER"); - reconstructed.push_back (left); - found = true; - } - - else if (canonicalize (canonical, "attribute", name)) - { - A lhs ("argAtt", name); - lhs.attribute ("name", canonical); - lhs.tag ("ATTRIBUTE"); - lhs.tag ("FILTER"); - - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) + std::string canonical; + if (canonicalize (canonical, "uda", name)) { - lhs.tag ("MODIFIABLE"); + A left ("argUDA", name); + left.attribute ("name", canonical); + left.tag ("UDA"); + left.tag ("MODIFIABLE"); + left.tag ("FILTER"); + reconstructed.push_back (left); + found = true; } - A op ("argAtt", "="); - op.tag ("OP"); - op.tag ("FILTER"); + else if (canonicalize (canonical, "pseudo", name)) + { + A left ("argUDA", name); + left.attribute ("name", canonical); + left.tag ("PSEUDO"); + left.tag ("FILTER"); + reconstructed.push_back (left); + found = true; + } - A rhs ("argAtt", value); - rhs.tag ("FILTER"); + else if (canonicalize (canonical, "attribute", name)) + { + A lhs ("argAtt", name); + lhs.attribute ("name", canonical); + lhs.tag ("ATTRIBUTE"); + lhs.tag ("FILTER"); - reconstructed.push_back (lhs); - reconstructed.push_back (op); - reconstructed.push_back (rhs); - found = true; + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + lhs.tag ("MODIFIABLE"); + } + + A op ("argAtt", "="); + op.tag ("OP"); + op.tag ("FILTER"); + + A rhs ("argAtt", value); + rhs.tag ("FILTER"); + + reconstructed.push_back (lhs); + reconstructed.push_back (op); + reconstructed.push_back (rhs); + found = true; + } } } } - } - if (!found) + if (!found) + reconstructed.push_back (*a); + } + else reconstructed.push_back (*a); } From f809f2d81963f7d8fff5137f4102364582579983 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 18:19:09 -0400 Subject: [PATCH 56/97] CLI - ::unsweetenAttributeModifiers no longer clobbers non-FILTER args. --- src/CLI.cpp | 264 ++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 131 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 36b3ec647..e06646ced 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -641,162 +641,164 @@ void CLI::unsweetenAttributeModifiers () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - // Look for a valid attribute name. - bool found = false; - Nibbler n (a->attribute ("raw")); - std::string name; - if (n.getUntil (".", name) && - name.length ()) + if (a->hasTag ("FILTER")) { - std::string canonical; - if (canonicalize (canonical, "attribute", name) || - canonicalize (canonical, "uda", name)) + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getUntil (".", name) && + name.length ()) { - if (n.skip ('.')) + std::string canonical; + if (canonicalize (canonical, "attribute", name) || + canonicalize (canonical, "uda", name)) { - std::string sense = "+"; - if (n.skip ('~')) - sense = "-"; - - std::string modifier; - n.getUntilOneOf (":=", modifier); - - if (n.skip (':') || - n.skip ('=')) + if (n.skip ('.')) { - std::string value; - if (n.getQuoted ('"', value) || - n.getQuoted ('\'', value) || - n.getUntilEOS (value) || - n.depleted ()) + std::string sense = "+"; + if (n.skip ('~')) + sense = "-"; + + std::string modifier; + n.getUntilOneOf (":=", modifier); + + if (n.skip (':') || + n.skip ('=')) { - if (value == "") - value = "''"; + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) + { + if (value == "") + value = "''"; - A lhs ("argAttMod", name); - lhs.tag ("ATTMOD"); - lhs.tag ("FILTER"); + A lhs ("argAttMod", name); + lhs.tag ("ATTMOD"); + lhs.tag ("FILTER"); - lhs.attribute ("name", canonical); - lhs.attribute ("raw", value); - lhs.attribute ("modifier", modifier); - lhs.attribute ("sense", sense); + lhs.attribute ("name", canonical); + lhs.attribute ("raw", value); + lhs.attribute ("modifier", modifier); + lhs.attribute ("sense", sense); - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) - { - lhs.tag ("MODIFIABLE"); - } + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + lhs.tag ("MODIFIABLE"); + } - A op ("argAttmod", ""); - op.tag ("FILTER"); - - A rhs ("argAttMod", ""); - rhs.tag ("FILTER"); - - if (modifier == "before" || modifier == "under" || modifier == "below") - { - op.attribute ("raw", "<"); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "after" || modifier == "over" || modifier == "above") - { - op.attribute ("raw", ">"); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "none") - { - op.attribute ("raw", "=="); - op.tag ("OP"); - rhs.attribute ("raw", "''"); - } - else if (modifier == "any") - { - op.attribute ("raw", "!="); - op.tag ("OP"); - rhs.attribute ("raw", "''"); - } - else if (modifier == "is" || modifier == "equals") - { - op.attribute ("raw", "=="); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "isnt" || modifier == "not") - { - op.attribute ("raw", "!="); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "has" || modifier == "contains") - { - op.attribute ("raw", "~"); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "hasnt") - { - op.attribute ("raw", "!~"); - op.tag ("OP"); - rhs.attribute ("raw", value); - } - else if (modifier == "startswith" || modifier == "left") - { - op.attribute ("raw", "~"); - op.tag ("OP"); - rhs.attribute ("raw", "'^" + value + "'"); - } - else if (modifier == "endswith" || modifier == "right") - { - op.attribute ("raw", "~"); - op.tag ("OP"); - rhs.attribute ("raw", "'" + value + "$'"); - } - else if (modifier == "word") - { - op.attribute ("raw", "~"); - op.tag ("OP"); + A op ("argAttmod", ""); + op.tag ("FILTER"); + A rhs ("argAttMod", ""); + rhs.tag ("FILTER"); + if (modifier == "before" || modifier == "under" || modifier == "below") + { + op.attribute ("raw", "<"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "after" || modifier == "over" || modifier == "above") + { + op.attribute ("raw", ">"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "none") + { + op.attribute ("raw", "=="); + op.tag ("OP"); + rhs.attribute ("raw", "''"); + } + else if (modifier == "any") + { + op.attribute ("raw", "!="); + op.tag ("OP"); + rhs.attribute ("raw", "''"); + } + else if (modifier == "is" || modifier == "equals") + { + op.attribute ("raw", "=="); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "isnt" || modifier == "not") + { + op.attribute ("raw", "!="); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "has" || modifier == "contains") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "hasnt") + { + op.attribute ("raw", "!~"); + op.tag ("OP"); + rhs.attribute ("raw", value); + } + else if (modifier == "startswith" || modifier == "left") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", "'^" + value + "'"); + } + else if (modifier == "endswith" || modifier == "right") + { + op.attribute ("raw", "~"); + op.tag ("OP"); + rhs.attribute ("raw", "'" + value + "$'"); + } + else if (modifier == "word") + { + op.attribute ("raw", "~"); + op.tag ("OP"); #if defined (DARWIN) - rhs.attribute ("raw", value); + rhs.attribute ("raw", value); #elif defined (SOLARIS) - rhs.attribute ("raw", "'\\<" + value + "\\>'"); + rhs.attribute ("raw", "'\\<" + value + "\\>'"); #else - rhs.attribute ("raw", "'\\b" + value + "\\b'"); + rhs.attribute ("raw", "'\\b" + value + "\\b'"); #endif - } - else if (modifier == "noword") - { - op.attribute ("raw", "!~"); - op.tag ("OP"); - + } + else if (modifier == "noword") + { + op.attribute ("raw", "!~"); + op.tag ("OP"); #if defined (DARWIN) - rhs.attribute ("raw", value); + rhs.attribute ("raw", value); #elif defined (SOLARIS) - rhs.attribute ("raw", "'\\<" + value + "\\>'"); + rhs.attribute ("raw", "'\\<" + value + "\\>'"); #else - rhs.attribute ("raw", "'\\b" + value + "\\b'"); + rhs.attribute ("raw", "'\\b" + value + "\\b'"); #endif - } - else - throw format (STRING_PARSER_UNKNOWN_ATTMOD, modifier); + } + else + throw format (STRING_PARSER_UNKNOWN_ATTMOD, modifier); - reconstructed.push_back (lhs); - reconstructed.push_back (op); - reconstructed.push_back (rhs); - found = true; + reconstructed.push_back (lhs); + reconstructed.push_back (op); + reconstructed.push_back (rhs); + found = true; + } } } } } - } - if (!found) + if (!found) + reconstructed.push_back (*a); + } + else reconstructed.push_back (*a); } From 83ab844ba4c4533dcea811b62692398dd8258cf3 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 18:19:27 -0400 Subject: [PATCH 57/97] CLI - ::unsweetenPatterns no longer clobbers non-FILTER args. --- src/CLI.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index e06646ced..f4a7854e1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -813,27 +813,32 @@ void CLI::unsweetenPatterns () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - Nibbler n (a->attribute ("raw")); - std::string pattern; - - if (n.getQuoted ('/', pattern) && - n.depleted () && - pattern.length () > 0) + if (a->hasTag ("FILTER")) { - A lhs ("argPattern", "description"); - lhs.tag ("ATT"); - lhs.tag ("FILTER"); - reconstructed.push_back (lhs); + Nibbler n (a->attribute ("raw")); + std::string pattern; - A op ("argPattern", "~"); - op.tag ("OP"); - op.tag ("FILTER"); - reconstructed.push_back (op); + if (n.getQuoted ('/', pattern) && + n.depleted () && + pattern.length () > 0) + { + A lhs ("argPattern", "description"); + lhs.tag ("ATT"); + lhs.tag ("FILTER"); + reconstructed.push_back (lhs); - A rhs ("argPattern", "'" + pattern + "'"); - rhs.tag ("LITERAL"); - rhs.tag ("FILTER"); - reconstructed.push_back (rhs); + A op ("argPattern", "~"); + op.tag ("OP"); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A rhs ("argPattern", "'" + pattern + "'"); + rhs.tag ("LITERAL"); + rhs.tag ("FILTER"); + reconstructed.push_back (rhs); + } + else + reconstructed.push_back (*a); } else reconstructed.push_back (*a); From c4bb9fbc96a262cb2eea7aeb77706d75238d0eee Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 23:17:49 -0400 Subject: [PATCH 58/97] CLI - Stubbed ::unsweetenIDs. --- src/CLI.cpp | 34 +++++++++++++++++++++++++++------- src/CLI.h | 1 + 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index f4a7854e1..74324fee1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -272,22 +272,23 @@ void CLI::analyze () } } + // Find argument types. aliasExpansion (); findOverrides (); categorize (); + + // Remove all the syntactic sugar. + unsweetenTags (); + unsweetenAttributes (); + unsweetenAttributeModifiers (); + unsweetenPatterns (); + unsweetenIDs (); } //////////////////////////////////////////////////////////////////////////////// // Extract all the FILTER-tagged items. const std::string CLI::getFilter () { - // Remove all the syntactic sugar. - unsweetenTags (); - unsweetenAttributes (); - unsweetenAttributeModifiers (); - unsweetenPatterns (); - // TODO all the other types: id, uuid ... - std::string filter = ""; if (_args.size ()) { @@ -847,6 +848,25 @@ void CLI::unsweetenPatterns () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +void CLI::unsweetenIDs () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER")) + { + + + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 99546668e..066809a5d 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -81,6 +81,7 @@ private: void unsweetenAttributes (); void unsweetenAttributeModifiers (); void unsweetenPatterns (); + void unsweetenIDs (); void dump (const std::string&) const; public: From 60d356f009cdbf9caeeac0b5064f1c125cc58efc Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 23:18:25 -0400 Subject: [PATCH 59/97] CLI - Stubbed ::unsweetenUUIDs. --- src/CLI.cpp | 20 ++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 74324fee1..d138fe7bd 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -283,6 +283,7 @@ void CLI::analyze () unsweetenAttributeModifiers (); unsweetenPatterns (); unsweetenIDs (); + unsweetenUUIDs (); } //////////////////////////////////////////////////////////////////////////////// @@ -867,6 +868,25 @@ void CLI::unsweetenIDs () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +void CLI::unsweetenUUIDs () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER")) + { + + + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::dump (const std::string& label) const { diff --git a/src/CLI.h b/src/CLI.h index 066809a5d..a601a311a 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -82,6 +82,7 @@ private: void unsweetenAttributeModifiers (); void unsweetenPatterns (); void unsweetenIDs (); + void unsweetenUUIDs (); void dump (const std::string&) const; public: From 7f61bcecca00f9969b2eec46c10dbf179b42bf91 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 19 Oct 2014 23:42:16 -0400 Subject: [PATCH 60/97] CLI - Implemented ::unsweetenUUIDs. --- src/CLI.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index d138fe7bd..5b0334e53 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -282,7 +282,7 @@ void CLI::analyze () unsweetenAttributes (); unsweetenAttributeModifiers (); unsweetenPatterns (); - unsweetenIDs (); +// unsweetenIDs (); unsweetenUUIDs (); } @@ -877,8 +877,75 @@ void CLI::unsweetenUUIDs () { if (a->hasTag ("FILTER")) { + bool found = false; + std::string raw = a->attribute ("raw"); + // UUIDs have a limited character set. + if (raw.find_first_not_of ("0123456789abcdefABCDEF-") == std::string::npos) + { + Nibbler n (raw); + std::vector uuidList; + std::string uuid; + if (n.getUUID (uuid) || + n.getPartialUUID (uuid)) + { + uuidList.push_back (uuid); + while (n.skip (',')) + { + if (! n.getUUID (uuid) && + ! n.getPartialUUID (uuid)) + throw std::string (STRING_PARSER_UUID_AFTER_COMMA); + + uuidList.push_back (uuid); + } + + if (n.depleted ()) + { + A openParen ("argSeq", "("); + openParen.tag ("FILTER"); + openParen.tag ("OP"); + reconstructed.push_back (openParen); + + std::vector ::iterator u; + for (u = uuidList.begin (); u != uuidList.end (); ++u) + { + if (u != uuidList.begin ()) + { + A openParen ("argSeq", "or"); + openParen.tag ("FILTER"); + openParen.tag ("OP"); + reconstructed.push_back (openParen); + } + + A uuid ("argSeq", "uuid"); + uuid.tag ("FILTER"); + uuid.tag ("UUID"); + reconstructed.push_back (uuid); + + A equal ("argSeq", "="); + equal.tag ("FILTER"); + equal.tag ("OP"); + reconstructed.push_back (equal); + + A value ("argSeq", "'" + *u + "'"); + value.tag ("FILTER"); + value.tag ("LITERAL"); + reconstructed.push_back (value); + } + + A closeParen ("argSeq", ")"); + closeParen.tag ("FILTER"); + closeParen.tag ("OP"); + reconstructed.push_back (closeParen); + + found = true; + } + } + } + + if (!found) + reconstructed.push_back (*a); } else reconstructed.push_back (*a); From c8f49bcafbf44c052d35c2376db2173da3714f05 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 00:22:02 -0400 Subject: [PATCH 61/97] CLI - Added comma (,) to the set of acceptable characters for a UUID list. --- src/CLI.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 5b0334e53..377db481a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -881,7 +881,7 @@ void CLI::unsweetenUUIDs () std::string raw = a->attribute ("raw"); // UUIDs have a limited character set. - if (raw.find_first_not_of ("0123456789abcdefABCDEF-") == std::string::npos) + if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos) { Nibbler n (raw); std::vector uuidList; @@ -920,7 +920,7 @@ void CLI::unsweetenUUIDs () A uuid ("argSeq", "uuid"); uuid.tag ("FILTER"); - uuid.tag ("UUID"); + uuid.tag ("ATTR"); reconstructed.push_back (uuid); A equal ("argSeq", "="); @@ -930,7 +930,7 @@ void CLI::unsweetenUUIDs () A value ("argSeq", "'" + *u + "'"); value.tag ("FILTER"); - value.tag ("LITERAL"); + value.tag ("STRING"); reconstructed.push_back (value); } From 97f302f276ac4ac5b1fce796cebd13893b034287 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 00:22:47 -0400 Subject: [PATCH 62/97] CLI - Added constructors to match the overloaded ::attribute methods. --- src/CLI.cpp | 14 ++++++++++++++ src/CLI.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 377db481a..d996cb5b0 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -56,6 +56,20 @@ A::A (const std::string& name, const std::string& raw) attribute ("raw", raw); } +//////////////////////////////////////////////////////////////////////////////// +A::A (const std::string& name, const int raw) +{ + _name = name; + attribute ("raw", raw); +} + +//////////////////////////////////////////////////////////////////////////////// +A::A (const std::string& name, const double raw) +{ + _name = name; + attribute ("raw", raw); +} + //////////////////////////////////////////////////////////////////////////////// A::~A () { diff --git a/src/CLI.h b/src/CLI.h index a601a311a..2a11dc6f5 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -36,6 +36,8 @@ class A public: A (); A (const std::string&, const std::string&); + A (const std::string&, const int); + A (const std::string&, const double); ~A (); A (const A&); A& operator= (const A&); From caaa07f88957bdd98b916eca2e417af229cad103 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 00:26:00 -0400 Subject: [PATCH 63/97] CLI - Implemented ::unsweetenIDs. --- src/CLI.cpp | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index d996cb5b0..28826e778 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -296,7 +296,7 @@ void CLI::analyze () unsweetenAttributes (); unsweetenAttributeModifiers (); unsweetenPatterns (); -// unsweetenIDs (); + unsweetenIDs (); unsweetenUUIDs (); } @@ -864,6 +864,14 @@ void CLI::unsweetenPatterns () } //////////////////////////////////////////////////////////////////////////////// +// An ID sequence can be: +// +// a single ID: 1 +// a list of IDs: 1,3,5 +// a list of IDs: 1 3 5 +// a range: 5-10 +// or a combination: 1,3,5-10 12 +// void CLI::unsweetenIDs () { std::vector reconstructed; @@ -872,8 +880,180 @@ void CLI::unsweetenIDs () { if (a->hasTag ("FILTER")) { + bool found = false; + std::string raw = a->attribute ("raw"); + // IDs have a limited character set. + if (raw.find_first_not_of ("0123456789,-") == std::string::npos) + { + // Container for min/max ID ranges. + std::vector > ranges; + // Split the ID list into elements. + std::vector elements; + split (elements, raw, ','); + + bool not_an_id = false; + std::vector ::iterator e; + for (e = elements.begin (); e != elements.end (); ++e) + { + // Split the ID range into min/max. + std::vector terms; + split (terms, *e, '-'); + + if (terms.size () == 1) + { + if (! digitsOnly (terms[0])) + { + not_an_id = true; + break; + } + + Nibbler n (terms[0]); + int id; + if (n.getUnsignedInt (id) && + n.depleted ()) + { + ranges.push_back (std::pair (id, id)); + } + else + { + not_an_id = true; + break; + } + } + else if (terms.size () == 2) + { + if (! digitsOnly (terms[0]) || + ! digitsOnly (terms[1])) + { + not_an_id = true; + break; + } + + Nibbler n_min (terms[0]); + Nibbler n_max (terms[1]); + int id_min; + int id_max; + if (n_min.getUnsignedInt (id_min) && + n_min.depleted () && + n_max.getUnsignedInt (id_max) && + n_max.depleted ()) + { + if (id_min > id_max) + throw std::string (STRING_PARSER_RANGE_INVERTED); + + ranges.push_back (std::pair (id_min, id_max)); + } + else + { + not_an_id = true; + break; + } + } + else + { + not_an_id = true; + break; + } + } + + if (! not_an_id) + { + // Now convert the ranges into an infix expression. + A openParen ("argSeq", "("); + openParen.tag ("FILTER"); + openParen.tag ("OP"); + reconstructed.push_back (openParen); + + std::vector >::iterator r; + for (r = ranges.begin (); r != ranges.end (); ++r) + { + if (r != ranges.begin ()) + { + A opOp ("argSeq", "or"); + opOp.tag ("FILTER"); + opOp.tag ("OP"); + reconstructed.push_back (opOp); + } + + if (r->first == r->second) + { + A id ("argSeq", "id"); + id.tag ("FILTER"); + id.tag ("ATTR"); + reconstructed.push_back (id); + + A equal ("argSeq", "=="); + equal.tag ("FILTER"); + equal.tag ("OP"); + reconstructed.push_back (equal); + + A value ("argSeq", r->first); + value.tag ("FILTER"); + value.tag ("NUMBER"); + reconstructed.push_back (value); + } + else + { + A rangeOpenParen ("argSeq", "("); + rangeOpenParen.tag ("FILTER"); + rangeOpenParen.tag ("OP"); + reconstructed.push_back (rangeOpenParen); + + A startId ("argSeq", "id"); + startId.tag ("FILTER"); + startId.tag ("ATTR"); + reconstructed.push_back (startId); + + A gte ("argSeq", ">="); + gte.tag ("FILTER"); + gte.tag ("OP"); + reconstructed.push_back (gte); + + A startValue ("argSeq", r->first); + startValue.tag ("FILTER"); + startValue.tag ("NUMBER"); + reconstructed.push_back (startValue); + + A andOp ("argSeq", "and"); + andOp.tag ("FILTER"); + andOp.tag ("OP"); + reconstructed.push_back (andOp); + + A endId ("argSeq", "id"); + endId.tag ("FILTER"); + endId.tag ("ATTR"); + reconstructed.push_back (endId); + + A lte ("argSeq", "<="); + lte.tag ("FILTER"); + lte.tag ("OP"); + reconstructed.push_back (lte); + + A endValue ("argSeq", r->second); + endValue.tag ("FILTER"); + endValue.tag ("NUMBER"); + reconstructed.push_back (endValue); + + A rangeCloseParen ("argSeq", ")"); + rangeCloseParen.tag ("FILTER"); + rangeCloseParen.tag ("OP"); + reconstructed.push_back (rangeCloseParen); + } + } + + A closeParen ("argSeq", ")"); + closeParen.tag ("FILTER"); + closeParen.tag ("OP"); + reconstructed.push_back (closeParen); + + found = true; + } + } + + if (!found) + reconstructed.push_back (*a); } else reconstructed.push_back (*a); From 24219e23a155df6c03b8312a523f198c8fb486bf Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 00:35:00 -0400 Subject: [PATCH 64/97] CLI - Renamed unsweeten methods to desugar, because they remove syntactic sugar. --- src/CLI.cpp | 26 +++++++++++++------------- src/CLI.h | 12 ++++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 28826e778..c05170acc 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -292,12 +292,12 @@ void CLI::analyze () categorize (); // Remove all the syntactic sugar. - unsweetenTags (); - unsweetenAttributes (); - unsweetenAttributeModifiers (); - unsweetenPatterns (); - unsweetenIDs (); - unsweetenUUIDs (); + desugarTags (); + desugarAttributes (); + desugarAttributeModifiers (); + desugarPatterns (); + desugarIDs (); + desugarUUIDs (); } //////////////////////////////////////////////////////////////////////////////// @@ -326,7 +326,7 @@ const std::string CLI::getFilter () } dump ("CLI::getFilter"); - return "(" + filter + ")"; + return "( " + filter + " )"; } //////////////////////////////////////////////////////////////////////////////// @@ -516,7 +516,7 @@ bool CLI::canonicalize ( //////////////////////////////////////////////////////////////////////////////// // +tag --> tags _hastag_ tag // -tag --> tags _notag_ tag -void CLI::unsweetenTags () +void CLI::desugarTags () { std::vector reconstructed; std::vector ::iterator a; @@ -560,7 +560,7 @@ void CLI::unsweetenTags () //////////////////////////////////////////////////////////////////////////////// // :['"][]['"] --> name = value -void CLI::unsweetenAttributes () +void CLI::desugarAttributes () { std::vector reconstructed; std::vector ::iterator a; @@ -651,7 +651,7 @@ void CLI::unsweetenAttributes () //////////////////////////////////////////////////////////////////////////////// // .[:=]['"]['"] --> name value -void CLI::unsweetenAttributeModifiers () +void CLI::desugarAttributeModifiers () { std::vector reconstructed; std::vector ::iterator a; @@ -823,7 +823,7 @@ void CLI::unsweetenAttributeModifiers () //////////////////////////////////////////////////////////////////////////////// // /pattern/ --> description ~ 'pattern' -void CLI::unsweetenPatterns () +void CLI::desugarPatterns () { std::vector reconstructed; std::vector ::iterator a; @@ -872,7 +872,7 @@ void CLI::unsweetenPatterns () // a range: 5-10 // or a combination: 1,3,5-10 12 // -void CLI::unsweetenIDs () +void CLI::desugarIDs () { std::vector reconstructed; std::vector ::iterator a; @@ -1063,7 +1063,7 @@ void CLI::unsweetenIDs () } //////////////////////////////////////////////////////////////////////////////// -void CLI::unsweetenUUIDs () +void CLI::desugarUUIDs () { std::vector reconstructed; std::vector ::iterator a; diff --git a/src/CLI.h b/src/CLI.h index 2a11dc6f5..4fd5c4af2 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -79,12 +79,12 @@ private: void categorize (); bool exactMatch (const std::string&, const std::string&) const; bool canonicalize (std::string&, const std::string&, const std::string&) const; - void unsweetenTags (); - void unsweetenAttributes (); - void unsweetenAttributeModifiers (); - void unsweetenPatterns (); - void unsweetenIDs (); - void unsweetenUUIDs (); + void desugarTags (); + void desugarAttributes (); + void desugarAttributeModifiers (); + void desugarPatterns (); + void desugarIDs (); + void desugarUUIDs (); void dump (const std::string&) const; public: From b484abea4a164a735c18449ccef12ca78bd81808 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 01:01:27 -0400 Subject: [PATCH 65/97] CLI, Filter - Moved parse tree dump into Context::debug output. --- src/CLI.cpp | 52 ++++++++++++++++++++++++++------------------------ src/CLI.h | 2 +- src/Filter.cpp | 4 ++++ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index c05170acc..994a4afbe 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -25,7 +25,8 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include +#include +#include // TODO Remove. #include #include #include @@ -325,7 +326,6 @@ const std::string CLI::getFilter () } } - dump ("CLI::getFilter"); return "( " + filter + " )"; } @@ -336,7 +336,6 @@ const std::vector CLI::getWords () // TODO Processing here. - dump ("CLI::getWords"); return words; } @@ -347,10 +346,34 @@ const std::vector CLI::getModifications () // TODO Processing here. - dump ("CLI::getModifications"); return modifications; } +//////////////////////////////////////////////////////////////////////////////// +const std::string CLI::dump () const +{ + std::stringstream out; + + out << "\033[1mCLI Parser\033[0m\n" + << " _original_args\n "; + Color colorOrigArgs ("gray10 on gray4"); + std::vector ::const_iterator i; + for (i = _original_args.begin (); i != _original_args.end (); ++i) + { + if (i != _original_args.begin ()) + out << ' '; + out << colorOrigArgs.colorize (*i); + } + out << "\n"; + + out << " _args\n"; + std::vector ::const_iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + out << " " << a->dump () << "\n"; + + return out.str (); +} + //////////////////////////////////////////////////////////////////////////////// void CLI::aliasExpansion () { @@ -1149,24 +1172,3 @@ void CLI::desugarUUIDs () } //////////////////////////////////////////////////////////////////////////////// -void CLI::dump (const std::string& label) const -{ - std::cout << label << "\n" - << " _original_args "; - Color colorOrigArgs ("gray10 on gray4"); - std::vector ::const_iterator i; - for (i = _original_args.begin (); i != _original_args.end (); ++i) - { - if (i != _original_args.begin ()) - std::cout << ' '; - std::cout << colorOrigArgs.colorize (*i); - } - std::cout << "\n"; - - std::cout << " _args\n"; - std::vector ::const_iterator a; - for (a = _args.begin (); a != _args.end (); ++a) - std::cout << " " << a->dump () << "\n"; -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 4fd5c4af2..6f8f4d2d2 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -72,6 +72,7 @@ public: const std::string getFilter (); const std::vector getWords (); const std::vector getModifications (); + const std::string dump () const; private: void aliasExpansion (); @@ -85,7 +86,6 @@ private: void desugarPatterns (); void desugarIDs (); void desugarUUIDs (); - void dump (const std::string&) const; public: std::multimap _entities; diff --git a/src/Filter.cpp b/src/Filter.cpp index 7636ee68f..046cada37 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -74,6 +74,8 @@ void Filter::subset (const std::vector & input, std::vector & output if (context.config.getInteger ("debug.parser") >= 1) { + context.debug (context.cli.dump ()); + Tree* t = context.parser.tree (); if (t) context.debug (t->dump ()); @@ -121,6 +123,8 @@ void Filter::subset (std::vector & output) if (context.config.getInteger ("debug.parser") >= 1) { + context.debug (context.cli.dump ()); + Tree* t = context.parser.tree (); if (t) context.debug (t->dump ()); From 626354999c4093333037cc4a38c6023511298673 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 01:22:49 -0400 Subject: [PATCH 66/97] CLI - Implemented ::decomposeModAttribute. --- src/CLI.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/CLI.h | 1 + 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 994a4afbe..05d7e4106 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -292,13 +292,16 @@ void CLI::analyze () findOverrides (); categorize (); - // Remove all the syntactic sugar. + // Remove all the syntactic sugar for FILTERs.. desugarTags (); desugarAttributes (); desugarAttributeModifiers (); desugarPatterns (); desugarIDs (); desugarUUIDs (); + + // Decompose the elements for MODIFICATIONs. + decomposeModAttributes (); } //////////////////////////////////////////////////////////////////////////////// @@ -1172,3 +1175,87 @@ void CLI::desugarUUIDs () } //////////////////////////////////////////////////////////////////////////////// +void CLI::decomposeModAttributes () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("MODIFICATION")) + { + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getName (name) && + name.length ()) + { + if (n.skip (':')) + { + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) + { + if (value == "") + value = "''"; + + std::string canonical; + if (canonicalize (canonical, "uda", name)) + { + A attr ("argUDA", name); + attr.attribute ("name", canonical); + attr.attribute ("value", value); + attr.tag ("UDA"); + attr.tag ("MODIFIABLE"); + attr.tag ("MODIFICATION"); + reconstructed.push_back (attr); + found = true; + } + + else if (canonicalize (canonical, "pseudo", name)) + { + A attr ("argUDA", name); + attr.attribute ("name", canonical); + attr.attribute ("value", value); + attr.tag ("PSEUDO"); + attr.tag ("MODIFICATION"); + reconstructed.push_back (attr); + found = true; + } + + else if (canonicalize (canonical, "attribute", name)) + { + A attr ("argAtt", name); + attr.attribute ("name", canonical); + attr.attribute ("value", value); + attr.tag ("ATTRIBUTE"); + attr.tag ("MODIFICATION"); + + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + attr.tag ("MODIFIABLE"); + } + + reconstructed.push_back (attr); + found = true; + } + } + } + } + + if (!found) + reconstructed.push_back (*a); + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 6f8f4d2d2..0e1424432 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -86,6 +86,7 @@ private: void desugarPatterns (); void desugarIDs (); void desugarUUIDs (); + void decomposeModAttributes (); public: std::multimap _entities; From f2e533d013ce7106987f30050afdf26f412a891f Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 01:33:42 -0400 Subject: [PATCH 67/97] CLI - Implemented ::decomposeModAttributeModifiers. --- src/CLI.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++++++------ src/CLI.h | 1 + 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 05d7e4106..9f24cc091 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -302,6 +302,7 @@ void CLI::analyze () // Decompose the elements for MODIFICATIONs. decomposeModAttributes (); + decomposeModAttributeModifiers (); } //////////////////////////////////////////////////////////////////////////////// @@ -1214,17 +1215,6 @@ void CLI::decomposeModAttributes () found = true; } - else if (canonicalize (canonical, "pseudo", name)) - { - A attr ("argUDA", name); - attr.attribute ("name", canonical); - attr.attribute ("value", value); - attr.tag ("PSEUDO"); - attr.tag ("MODIFICATION"); - reconstructed.push_back (attr); - found = true; - } - else if (canonicalize (canonical, "attribute", name)) { A attr ("argAtt", name); @@ -1259,3 +1249,96 @@ void CLI::decomposeModAttributes () } //////////////////////////////////////////////////////////////////////////////// +void CLI::decomposeModAttributeModifiers () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("MODIFICATION")) + { + // Look for a valid attribute name. + bool found = false; + Nibbler n (a->attribute ("raw")); + std::string name; + if (n.getUntil (".", name) && + name.length ()) + { + std::string canonical; + if (canonicalize (canonical, "attribute", name) || + canonicalize (canonical, "uda", name)) + { + if (n.skip ('.')) + { + std::string sense = "+"; + if (n.skip ('~')) + sense = "-"; + + std::string modifier; + n.getUntilOneOf (":=", modifier); + + if (n.skip (':') || + n.skip ('=')) + { + std::string value; + if (n.getQuoted ('"', value) || + n.getQuoted ('\'', value) || + n.getUntilEOS (value) || + n.depleted ()) + { + if (value == "") + value = "''"; + + std::string canonical; + if (canonicalize (canonical, "uda", name)) + { + A attmod ("argUDA", name); + attmod.attribute ("name", canonical); + attmod.attribute ("modifier", modifier); + attmod.attribute ("sense", sense); + attmod.attribute ("value", value); + attmod.tag ("UDA"); + attmod.tag ("MODIFIABLE"); + attmod.tag ("MODIFICATION"); + reconstructed.push_back (attmod); + found = true; + } + + else if (canonicalize (canonical, "attribute", name)) + { + A attmod ("argAtt", name); + attmod.attribute ("name", canonical); + attmod.attribute ("modifier", modifier); + attmod.attribute ("sense", sense); + attmod.attribute ("value", value); + attmod.tag ("ATTMOD"); + attmod.tag ("MODIFICATION"); + + std::map ::const_iterator col; + col = context.columns.find (canonical); + if (col != context.columns.end () && + col->second->modifiable ()) + { + attmod.tag ("MODIFIABLE"); + } + + reconstructed.push_back (attmod); + found = true; + } + } + } + } + } + } + + if (!found) + reconstructed.push_back (*a); + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 0e1424432..5b0cc2b15 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -87,6 +87,7 @@ private: void desugarIDs (); void desugarUUIDs (); void decomposeModAttributes (); + void decomposeModAttributeModifiers (); public: std::multimap _entities; From 5dcc4150570df9bebb69539ea7c10d653ba98065 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 01:48:33 -0400 Subject: [PATCH 68/97] CLI - Implemented ::decomposeModTags. --- src/CLI.cpp | 105 +++++++++++++++++++++++++++------------------------- src/CLI.h | 1 + 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 9f24cc091..37864502f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -303,6 +303,7 @@ void CLI::analyze () // Decompose the elements for MODIFICATIONs. decomposeModAttributes (); decomposeModAttributeModifiers (); + decomposeModTags (); } //////////////////////////////////////////////////////////////////////////////// @@ -1185,7 +1186,6 @@ void CLI::decomposeModAttributes () if (a->hasTag ("MODIFICATION")) { // Look for a valid attribute name. - bool found = false; Nibbler n (a->attribute ("raw")); std::string name; if (n.getName (name) && @@ -1205,44 +1205,32 @@ void CLI::decomposeModAttributes () std::string canonical; if (canonicalize (canonical, "uda", name)) { - A attr ("argUDA", name); - attr.attribute ("name", canonical); - attr.attribute ("value", value); - attr.tag ("UDA"); - attr.tag ("MODIFIABLE"); - attr.tag ("MODIFICATION"); - reconstructed.push_back (attr); - found = true; + a->attribute ("name", canonical); + a->attribute ("value", value); + a->tag ("UDA"); + a->tag ("MODIFIABLE"); } else if (canonicalize (canonical, "attribute", name)) { - A attr ("argAtt", name); - attr.attribute ("name", canonical); - attr.attribute ("value", value); - attr.tag ("ATTRIBUTE"); - attr.tag ("MODIFICATION"); + a->attribute ("name", canonical); + a->attribute ("value", value); + a->tag ("ATTRIBUTE"); std::map ::const_iterator col; col = context.columns.find (canonical); if (col != context.columns.end () && col->second->modifiable ()) { - attr.tag ("MODIFIABLE"); + a->tag ("MODIFIABLE"); } - - reconstructed.push_back (attr); - found = true; } } } } - - if (!found) - reconstructed.push_back (*a); } - else - reconstructed.push_back (*a); + + reconstructed.push_back (*a); } _args = reconstructed; @@ -1258,7 +1246,6 @@ void CLI::decomposeModAttributeModifiers () if (a->hasTag ("MODIFICATION")) { // Look for a valid attribute name. - bool found = false; Nibbler n (a->attribute ("raw")); std::string name; if (n.getUntil (".", name) && @@ -1292,50 +1279,68 @@ void CLI::decomposeModAttributeModifiers () std::string canonical; if (canonicalize (canonical, "uda", name)) { - A attmod ("argUDA", name); - attmod.attribute ("name", canonical); - attmod.attribute ("modifier", modifier); - attmod.attribute ("sense", sense); - attmod.attribute ("value", value); - attmod.tag ("UDA"); - attmod.tag ("MODIFIABLE"); - attmod.tag ("MODIFICATION"); - reconstructed.push_back (attmod); - found = true; + a->attribute ("name", canonical); + a->attribute ("modifier", modifier); + a->attribute ("sense", sense); + a->attribute ("value", value); + a->tag ("UDA"); + a->tag ("MODIFIABLE"); } else if (canonicalize (canonical, "attribute", name)) { - A attmod ("argAtt", name); - attmod.attribute ("name", canonical); - attmod.attribute ("modifier", modifier); - attmod.attribute ("sense", sense); - attmod.attribute ("value", value); - attmod.tag ("ATTMOD"); - attmod.tag ("MODIFICATION"); + a->attribute ("name", canonical); + a->attribute ("modifier", modifier); + a->attribute ("sense", sense); + a->attribute ("value", value); + a->tag ("ATTMOD"); std::map ::const_iterator col; col = context.columns.find (canonical); if (col != context.columns.end () && col->second->modifiable ()) { - attmod.tag ("MODIFIABLE"); + a->tag ("MODIFIABLE"); } - - reconstructed.push_back (attmod); - found = true; } } } } } } - - if (!found) - reconstructed.push_back (*a); } - else - reconstructed.push_back (*a); + + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::decomposeModTags () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("MODIFICATION")) + { + Nibbler n (a->attribute ("raw")); + std::string tag; + std::string sign; + + if (n.getN (1, sign) && + (sign == "+" || sign == "-") && + n.getUntilEOS (tag) && + tag.find (' ') == std::string::npos) + { + a->attribute ("name", tag); + a->attribute ("sign", sign); + a->tag ("TAG"); + } + } + + reconstructed.push_back (*a); } _args = reconstructed; diff --git a/src/CLI.h b/src/CLI.h index 5b0cc2b15..940d9c7a8 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -88,6 +88,7 @@ private: void desugarUUIDs (); void decomposeModAttributes (); void decomposeModAttributeModifiers (); + void decomposeModTags (); public: std::multimap _entities; From 6dea38806b96ee3ff70070616209fc6dff26b2ef Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 20 Oct 2014 02:03:03 -0400 Subject: [PATCH 69/97] CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implemented ::decomposeModЅubstitutions. --- src/CLI.cpp | 49 ++++++++++++++++++++++++++++++++++--------------- src/CLI.h | 1 + 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 37864502f..1245a3237 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -304,6 +304,7 @@ void CLI::analyze () decomposeModAttributes (); decomposeModAttributeModifiers (); decomposeModTags (); + decomposeModSubstitutions (); } //////////////////////////////////////////////////////////////////////////////// @@ -1179,7 +1180,6 @@ void CLI::desugarUUIDs () //////////////////////////////////////////////////////////////////////////////// void CLI::decomposeModAttributes () { - std::vector reconstructed; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { @@ -1229,17 +1229,12 @@ void CLI::decomposeModAttributes () } } } - - reconstructed.push_back (*a); } - - _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// void CLI::decomposeModAttributeModifiers () { - std::vector reconstructed; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { @@ -1309,17 +1304,12 @@ void CLI::decomposeModAttributeModifiers () } } } - - reconstructed.push_back (*a); } - - _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// void CLI::decomposeModTags () { - std::vector reconstructed; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { @@ -1339,11 +1329,40 @@ void CLI::decomposeModTags () a->tag ("TAG"); } } - - reconstructed.push_back (*a); } - - _args = reconstructed; +} + +//////////////////////////////////////////////////////////////////////////////// +void CLI::decomposeModSubstitutions () +{ + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("MODIFICATION")) + { + std::string raw = a->attribute ("raw"); + Nibbler n (raw); + std::string from; + std::string to; + bool global = false; + if (n.getQuoted ('/', from) && + n.backN () && + n.getQuoted ('/', to)) + { + if (n.skip ('g')) + global = true; + + if (n.depleted () && + ! Directory (raw).exists ()) + { + a->tag ("SUBSTITUTION"); + a->attribute ("from", from); + a->attribute ("to", to); + a->attribute ("global", global ? 1 : 0); + } + } + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CLI.h b/src/CLI.h index 940d9c7a8..57b55bbb8 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -89,6 +89,7 @@ private: void decomposeModAttributes (); void decomposeModAttributeModifiers (); void decomposeModTags (); + void decomposeModSubstitutions (); public: std::multimap _entities; From 8cb287ec6956701457d988a862580662347d67c9 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 22 Oct 2014 23:44:31 -0400 Subject: [PATCH 70/97] CLI - Tags the binary basename as either TW or CALENDAR. --- src/CLI.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 1245a3237..f0f53d34a 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -277,6 +277,19 @@ void CLI::analyze () A a ("arg", _original_args[i]); a.tag ("ORIGINAL"); a.tag ("BINARY"); + + std::string basename = "task"; + std::string raw = _original_args[i]; + std::string::size_type slash = raw.rfind ('/'); + if (slash != std::string::npos) + basename = raw.substr (slash + 1); + + a.attribute ("basename", basename); + if (basename == "cal" || basename == "calendar") + a.tag ("CALENDAR"); + else if (basename == "task" || basename == "tw" || basename == "t") + a.tag ("TW"); + _args.push_back (a); } else From e4a237fcd3cc1df782b7d0b95148f46017cea6ec Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 00:34:52 -0400 Subject: [PATCH 71/97] CLI - Implemented ::insertJunctions. --- src/CLI.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/CLI.h | 1 + 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index f0f53d34a..235930e66 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -305,13 +305,14 @@ void CLI::analyze () findOverrides (); categorize (); - // Remove all the syntactic sugar for FILTERs.. + // Remove all the syntactic sugar for FILTERs. desugarTags (); desugarAttributes (); desugarAttributeModifiers (); desugarPatterns (); desugarIDs (); desugarUUIDs (); + insertJunctions (); // Decompose the elements for MODIFICATIONs. decomposeModAttributes (); @@ -1190,6 +1191,71 @@ void CLI::desugarUUIDs () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +// Two consecutive FILTER, ID or UUID arguments: +// +// ID ID --> ID or ID +// ID UUID --> ID or UUID +// UUID ID --> UUID or ID +// UUID UUID --> UUID or UUID +// +// Two consecutive FILTER, non-OP arguments that are not "(" or ")" need an +// "and" operator inserted between them. +// +// ) --> ) and +// ( --> ( +// ) ( --> ) and ( +// --> and +// +void CLI::insertJunctions () +{ + std::vector reconstructed; + std::vector ::iterator prev = _args.begin (); + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER")) + { + // The prev iterator should be the first FILTER arg. + if (prev == _args.begin ()) + prev = a; + + // Insert OR between consecutive FILTER ID/UUID args. + if (a != prev && + (prev->hasTag ("ID") || prev->hasTag ("UUID")) && + (a->hasTag ("ID") || a->hasTag ("UUID"))) + { + A opOr ("argOp", "or"); + opOr.tag ("FILTER"); + opOr.tag ("OP"); + reconstructed.push_back (opOr); + } + + // Insert AND between terms. + else if (a != prev) + { + if ((! prev->hasTag ("OP") && a->attribute ("raw") == "(") || + (! prev->hasTag ("OP") && ! a->hasTag ("OP")) || + (prev->attribute ("raw") == ")" && ! a->hasTag ("OP")) || + (prev->attribute ("raw") == ")" && a->attribute ("raw") == "(")) + { + A opOr ("argOp", "and"); + opOr.tag ("FILTER"); + opOr.tag ("OP"); + reconstructed.push_back (opOr); + } + } + + // Previous FILTER arg. + prev = a; + } + + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::decomposeModAttributes () { diff --git a/src/CLI.h b/src/CLI.h index 57b55bbb8..ffcae07eb 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -86,6 +86,7 @@ private: void desugarPatterns (); void desugarIDs (); void desugarUUIDs (); + void insertJunctions (); void decomposeModAttributes (); void decomposeModAttributeModifiers (); void decomposeModTags (); From fab9fe2a7da3192c6329b83c01dd2aee3b234973 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 00:36:04 -0400 Subject: [PATCH 72/97] Filter - Modified algorithm for ::pendingOnly. --- src/Filter.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Filter.cpp b/src/Filter.cpp index 046cada37..1f2d03fb3 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -214,9 +214,11 @@ bool Filter::pendingOnly () Tree* tree = context.parser.tree (); // To skip loading completed.data, there should be: - // - 'status:pending' - // - no 'or' operators - // - no 'xor' operators + // - 'status' in filter + // - no 'completed' + // - no 'deleted' + // - no 'xor' + // - no 'or' int countStatus = 0; int countPending = 0; int countId = 0; @@ -244,7 +246,7 @@ bool Filter::pendingOnly () return false; // Only one 'status == pending' is allowed. - if (countStatus == 1 && countPending != 1) + if (countStatus != 1 || countPending != 1) return false; return true; From 7f3cc3897e9b9529359cf0d13d4c6ff9954380a5 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 00:45:20 -0400 Subject: [PATCH 73/97] CLI - Implemented ::findOperators. --- src/CLI.cpp | 22 ++++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 235930e66..1e87a56c5 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -312,6 +312,7 @@ void CLI::analyze () desugarPatterns (); desugarIDs (); desugarUUIDs (); + findOperators (); insertJunctions (); // Decompose the elements for MODIFICATIONs. @@ -1191,6 +1192,27 @@ void CLI::desugarUUIDs () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +void CLI::findOperators () +{ + // Find the category. + std::pair ::const_iterator, std::multimap ::const_iterator> c; + c = _entities.equal_range ("operator"); + + // Extract a list of entities for category. + std::vector options; + std::multimap ::const_iterator e; + for (e = c.first; e != c.second; ++e) + options.push_back (e->second); + + // Walk the arguments and tag as OP. + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + if (a->hasTag ("FILTER")) + if (std::find (options.begin (), options.end (), a->attribute ("raw")) != options.end ()) + a->tag ("OP"); +} + //////////////////////////////////////////////////////////////////////////////// // Two consecutive FILTER, ID or UUID arguments: // diff --git a/src/CLI.h b/src/CLI.h index ffcae07eb..676d65a9e 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -86,6 +86,7 @@ private: void desugarPatterns (); void desugarIDs (); void desugarUUIDs (); + void findOperators (); void insertJunctions (); void decomposeModAttributes (); void decomposeModAttributeModifiers (); From 5d790a07de0f2613f92261068df6ea5def5d3d52 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 00:45:39 -0400 Subject: [PATCH 74/97] CLI - PSEUDO args are no longer considered FILTER. --- src/CLI.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 1e87a56c5..063d25085 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -332,8 +332,7 @@ const std::string CLI::getFilter () std::vector ::const_iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - if (a->hasTag ("FILTER") && - ! a->hasTag ("PSEUDO")) + if (a->hasTag ("FILTER")) { if (filter != "") filter += ' '; @@ -647,7 +646,6 @@ void CLI::desugarAttributes () A left ("argUDA", name); left.attribute ("name", canonical); left.tag ("PSEUDO"); - left.tag ("FILTER"); reconstructed.push_back (left); found = true; } From 371bb0a5b148556c996d852e1c39ccd9c7b38ff6 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 01:17:54 -0400 Subject: [PATCH 75/97] CLI - Implemented A::unTagAll, to clear all tags. --- src/CLI.cpp | 6 ++++++ src/CLI.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 063d25085..c20bdc7d3 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -135,6 +135,12 @@ void A::unTag (const std::string& tag) } } +//////////////////////////////////////////////////////////////////////////////// +void A::unTagAll () +{ + _tags.clear (); +} + //////////////////////////////////////////////////////////////////////////////// // Accessor for attributes. void A::attribute (const std::string& name, const std::string& value) diff --git a/src/CLI.h b/src/CLI.h index 676d65a9e..7e8e5918f 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -45,6 +45,7 @@ public: bool hasTag (const std::string&) const; void tag (const std::string&); void unTag (const std::string&); + void unTagAll (); void attribute (const std::string&, const std::string&); void attribute (const std::string&, const int); void attribute (const std::string&, const double); From 014a09cd55ec7a12f3eae7f3b91d3a5fd4c2621b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 23 Oct 2014 01:18:42 -0400 Subject: [PATCH 76/97] CLI - Implemented TERMINATOR/TERMINATED detection. --- src/CLI.cpp | 66 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index c20bdc7d3..3ce0e7db5 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -410,23 +410,35 @@ void CLI::aliasExpansion () action = false; std::vector reconstructed; + bool terminated = false; + std::string raw; std::vector ::iterator i; for (i = _args.begin (); i != _args.end (); ++i) { - if (_aliases.find (i->_name) != _aliases.end ()) + raw = i->attribute ("raw"); + + if (raw == "--") + terminated = true; + + if (! terminated) { - std::vector lexed; - Lexer::token_split (lexed, _aliases[i->_name]); - - std::vector ::iterator l; - for (l = lexed.begin (); l != lexed.end (); ++l) + if (_aliases.find (raw) != _aliases.end ()) { - A a ("argLex", *l); - a.tag ("LEX"); - reconstructed.push_back (a); - } + std::vector lexed; + Lexer::token_split (lexed, _aliases[raw]); - action = true; + std::vector ::iterator l; + for (l = lexed.begin (); l != lexed.end (); ++l) + { + A a ("argLex", *l); + a.tag ("LEX"); + reconstructed.push_back (a); + } + + action = true; + } + else + reconstructed.push_back (*i); } else reconstructed.push_back (*i); @@ -440,10 +452,18 @@ void CLI::aliasExpansion () //////////////////////////////////////////////////////////////////////////////// void CLI::findOverrides () { + std::string raw; + bool terminated = false; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { - std::string raw = a->attribute ("raw"); + raw = a->attribute ("raw"); + + if (raw == "--") + terminated = true; + + if (terminated) + continue; if (raw.find ("rc:") == 0) { @@ -470,11 +490,29 @@ void CLI::categorize () { bool foundCommand = false; bool readOnly = false; + bool terminated = false; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { std::string raw = a->attribute ("raw"); + + if (raw == "--") + { + a->tag ("TERMINATOR"); + terminated = true; + } + + if (terminated) + { + a->unTagAll (); + a->tag ("TERMINATED"); + a->tag ("WORD"); + + // TODO This prevents MODIFICATION tagging below. + continue; + } + std::string canonical; if (canonicalize (canonical, "cmd", raw)) { @@ -929,9 +967,9 @@ void CLI::desugarIDs () if (a->hasTag ("FILTER")) { bool found = false; - std::string raw = a->attribute ("raw"); // IDs have a limited character set. + std::string raw = a->attribute ("raw"); if (raw.find_first_not_of ("0123456789,-") == std::string::npos) { // Container for min/max ID ranges. @@ -1120,9 +1158,9 @@ void CLI::desugarUUIDs () if (a->hasTag ("FILTER")) { bool found = false; - std::string raw = a->attribute ("raw"); // UUIDs have a limited character set. + std::string raw = a->attribute ("raw"); if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos) { Nibbler n (raw); From ce2679c3fa4753926b49dbceacf4152f04e58c01 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Oct 2014 16:24:35 -0400 Subject: [PATCH 77/97] CLI - Properly tags TERMINATOR, TERMINATED. --- src/CLI.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 3ce0e7db5..7109a9022 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -499,11 +499,12 @@ void CLI::categorize () if (raw == "--") { + a->unTagAll (); a->tag ("TERMINATOR"); terminated = true; } - if (terminated) + else if (terminated) { a->unTagAll (); a->tag ("TERMINATED"); From 5add257d8b2319d58d91098202f183345b1c7257 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Oct 2014 16:33:35 -0400 Subject: [PATCH 78/97] CLI - Preserve ORIGINAL tag after ::unTagAll. --- src/CLI.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 7109a9022..44c41f436 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -500,6 +500,7 @@ void CLI::categorize () if (raw == "--") { a->unTagAll (); + a->tag ("ORIGINAL"); a->tag ("TERMINATOR"); terminated = true; } @@ -507,6 +508,7 @@ void CLI::categorize () else if (terminated) { a->unTagAll (); + a->tag ("ORIGINAL"); a->tag ("TERMINATED"); a->tag ("WORD"); From dbefd7d6fe2dc816ec63bbb89bdd4eef003e1857 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Oct 2014 22:00:36 -0400 Subject: [PATCH 79/97] CLI - Tightened restriction in ::categorize. --- src/CLI.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 44c41f436..8f280c3d1 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -503,21 +503,21 @@ void CLI::categorize () a->tag ("ORIGINAL"); a->tag ("TERMINATOR"); terminated = true; + continue; } - else if (terminated) + if (terminated) { a->unTagAll (); a->tag ("ORIGINAL"); a->tag ("TERMINATED"); a->tag ("WORD"); - - // TODO This prevents MODIFICATION tagging below. - continue; } std::string canonical; - if (canonicalize (canonical, "cmd", raw)) + if (! terminated && + ! foundCommand && + canonicalize (canonical, "cmd", raw)) { readOnly = ! exactMatch ("writecmd", canonical); @@ -526,8 +526,9 @@ void CLI::categorize () a->attribute ("name", canonical); foundCommand = true; } - else if (a->hasTag ("BINARY") || - a->hasTag ("CONFIG") || + else if (a->hasTag ("TERMINATOR") || + a->hasTag ("BINARY") || + a->hasTag ("CONFIG") || a->hasTag ("RC")) { // NOP From e0fac11eedbcdbc08199aa3fecd533aca87ff93b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Oct 2014 22:01:53 -0400 Subject: [PATCH 80/97] CLI - Argument decomposition now skips terminated args. --- src/CLI.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 8f280c3d1..94ed3cce9 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -1330,6 +1330,9 @@ void CLI::decomposeModAttributes () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { + if (a->hasTag ("TERMINATOR")) + break; + if (a->hasTag ("MODIFICATION")) { // Look for a valid attribute name. @@ -1385,6 +1388,9 @@ void CLI::decomposeModAttributeModifiers () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { + if (a->hasTag ("TERMINATOR")) + break; + if (a->hasTag ("MODIFICATION")) { // Look for a valid attribute name. @@ -1460,6 +1466,9 @@ void CLI::decomposeModTags () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { + if (a->hasTag ("TERMINATOR")) + break; + if (a->hasTag ("MODIFICATION")) { Nibbler n (a->attribute ("raw")); @@ -1485,6 +1494,9 @@ void CLI::decomposeModSubstitutions () std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { + if (a->hasTag ("TERMINATOR")) + break; + if (a->hasTag ("MODIFICATION")) { std::string raw = a->attribute ("raw"); From b7efb753b5fc849289d4bbf9ed3719281698d234 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Fri, 24 Oct 2014 23:00:06 -0400 Subject: [PATCH 81/97] Filter - Rewrote ::pendingOnly to work with CLI instead of Parser. --- src/Filter.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Filter.cpp b/src/Filter.cpp index 1f2d03fb3..c1b52c1e0 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -224,16 +224,17 @@ bool Filter::pendingOnly () int countId = 0; int countOr = 0; int countXor = 0; - std::vector ::iterator i; - for (i = tree->_branches.begin (); i != tree->_branches.end (); ++i) + + std::vector ::iterator a; + for (a = context.cli._args.begin (); a != context.cli._args.end (); ++a) { - if ((*i)->hasTag ("FILTER")) + if (a->hasTag ("FILTER")) { - if ((*i)->hasTag ("ID")) ++countId; - if ((*i)->hasTag ("OP") && (*i)->attribute ("raw") == "or") ++countOr; - if ((*i)->hasTag ("OP") && (*i)->attribute ("raw") == "xor") ++countXor; - if ((*i)->hasTag ("ATTRIBUTE") && (*i)->attribute ("name") == "status") ++countStatus; - if ((*i)->hasTag ("ATTRIBUTE") && (*i)->attribute ("raw") == "pending") ++countPending; + if (a->hasTag ("ID")) ++countId; + if (a->hasTag ("OP") && a->attribute ("raw") == "or") ++countOr; + if (a->hasTag ("OP") && a->attribute ("raw") == "xor") ++countXor; + if (a->hasTag ("ATTRIBUTE") && a->attribute ("name") == "status") ++countStatus; + if ( a->attribute ("raw") == "pending") ++countPending; } } From 5daf67338712e61ba2eb75652075c39b8f98f0dd Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 13:15:24 -0400 Subject: [PATCH 82/97] CLI - Standardized use of 'ATT' and 'ATTR' tags to 'ATTRIBUTE'. --- src/CLI.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 94ed3cce9..ab0a3fa8f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -625,7 +625,7 @@ void CLI::desugarTags () tag.find (' ') == std::string::npos) { A left ("argTag", "tags"); - left.tag ("ATT"); + left.tag ("ATTRIBUTE"); left.tag ("FILTER"); reconstructed.push_back (left); @@ -929,7 +929,7 @@ void CLI::desugarPatterns () pattern.length () > 0) { A lhs ("argPattern", "description"); - lhs.tag ("ATT"); + lhs.tag ("ATTRIBUTE"); lhs.tag ("FILTER"); reconstructed.push_back (lhs); @@ -1071,7 +1071,7 @@ void CLI::desugarIDs () { A id ("argSeq", "id"); id.tag ("FILTER"); - id.tag ("ATTR"); + id.tag ("ATTRIBUTE"); reconstructed.push_back (id); A equal ("argSeq", "=="); @@ -1093,7 +1093,7 @@ void CLI::desugarIDs () A startId ("argSeq", "id"); startId.tag ("FILTER"); - startId.tag ("ATTR"); + startId.tag ("ATTRIBUTE"); reconstructed.push_back (startId); A gte ("argSeq", ">="); @@ -1113,7 +1113,7 @@ void CLI::desugarIDs () A endId ("argSeq", "id"); endId.tag ("FILTER"); - endId.tag ("ATTR"); + endId.tag ("ATTRIBUTE"); reconstructed.push_back (endId); A lte ("argSeq", "<="); @@ -1204,7 +1204,7 @@ void CLI::desugarUUIDs () A uuid ("argSeq", "uuid"); uuid.tag ("FILTER"); - uuid.tag ("ATTR"); + uuid.tag ("ATTRIBUTE"); reconstructed.push_back (uuid); A equal ("argSeq", "="); From 7ff55037a63bd8ed15515b4c185b2925cdb677b8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 13:16:31 -0400 Subject: [PATCH 83/97] CLI - Tagged expanded aliases with ALIAS. --- src/CLI.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index ab0a3fa8f..4606c68b7 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -431,6 +431,7 @@ void CLI::aliasExpansion () for (l = lexed.begin (); l != lexed.end (); ++l) { A a ("argLex", *l); + a.tag ("ALIAS"); a.tag ("LEX"); reconstructed.push_back (a); } From 22d3852bfd474a6d112a5b0efe1fec1e6f0c0e46 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 13:42:05 -0400 Subject: [PATCH 84/97] CLI - Updated ::desugarAttributes to properly handle UDA and PSEUDO args. - Cleaned up handling or ATTRIBUTE. --- src/CLI.cpp | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 4606c68b7..62d01b902 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -681,21 +681,32 @@ void CLI::desugarAttributes () std::string canonical; if (canonicalize (canonical, "uda", name)) { - A left ("argUDA", name); - left.attribute ("name", canonical); - left.tag ("UDA"); - left.tag ("MODIFIABLE"); - left.tag ("FILTER"); - reconstructed.push_back (left); + A lhs ("argUDA", name); + lhs.attribute ("name", canonical); + lhs.tag ("UDA"); + lhs.tag ("ATTRIBUTE"); + lhs.tag ("FILTER"); + + A op ("argUDA", "="); + op.tag ("OP"); + op.tag ("FILTER"); + + A rhs ("argUDA", value); + rhs.tag ("LITERAL"); + rhs.tag ("FILTER"); + + reconstructed.push_back (lhs); + reconstructed.push_back (op); + reconstructed.push_back (rhs); found = true; } else if (canonicalize (canonical, "pseudo", name)) { - A left ("argUDA", name); - left.attribute ("name", canonical); - left.tag ("PSEUDO"); - reconstructed.push_back (left); + A lhs ("argPseudo", name); + lhs.attribute ("name", canonical); + lhs.tag ("PSEUDO"); + reconstructed.push_back (lhs); found = true; } @@ -706,19 +717,16 @@ void CLI::desugarAttributes () lhs.tag ("ATTRIBUTE"); lhs.tag ("FILTER"); - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) - { - lhs.tag ("MODIFIABLE"); - } + std::string operatorLiteral = "="; + if (canonical == "status") + operatorLiteral = "=="; - A op ("argAtt", "="); + A op ("argAtt", operatorLiteral); op.tag ("OP"); op.tag ("FILTER"); A rhs ("argAtt", value); + rhs.tag ("LITERAL"); rhs.tag ("FILTER"); reconstructed.push_back (lhs); From d0ae05ba1c02b4a3b87087a81c832b200cd8a757 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 13:43:39 -0400 Subject: [PATCH 85/97] CLI - Removed MODIFIABLE tags for FILTER args - pointless. - Added LITERAL and REGEX tags for ATTMOD values. --- src/CLI.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 62d01b902..016e772f6 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -795,18 +795,9 @@ void CLI::desugarAttributeModifiers () lhs.tag ("FILTER"); lhs.attribute ("name", canonical); - lhs.attribute ("raw", value); lhs.attribute ("modifier", modifier); lhs.attribute ("sense", sense); - std::map ::const_iterator col; - col = context.columns.find (canonical); - if (col != context.columns.end () && - col->second->modifiable ()) - { - lhs.tag ("MODIFIABLE"); - } - A op ("argAttmod", ""); op.tag ("FILTER"); @@ -818,60 +809,70 @@ void CLI::desugarAttributeModifiers () op.attribute ("raw", "<"); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "after" || modifier == "over" || modifier == "above") { op.attribute ("raw", ">"); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "none") { op.attribute ("raw", "=="); op.tag ("OP"); rhs.attribute ("raw", "''"); + rhs.tag ("LITERAL"); } else if (modifier == "any") { op.attribute ("raw", "!="); op.tag ("OP"); rhs.attribute ("raw", "''"); + rhs.tag ("LITERAL"); } else if (modifier == "is" || modifier == "equals") { op.attribute ("raw", "=="); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "isnt" || modifier == "not") { op.attribute ("raw", "!="); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "has" || modifier == "contains") { op.attribute ("raw", "~"); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "hasnt") { op.attribute ("raw", "!~"); op.tag ("OP"); rhs.attribute ("raw", value); + rhs.tag ("LITERAL"); } else if (modifier == "startswith" || modifier == "left") { op.attribute ("raw", "~"); op.tag ("OP"); rhs.attribute ("raw", "'^" + value + "'"); + rhs.tag ("REGEX"); } else if (modifier == "endswith" || modifier == "right") { op.attribute ("raw", "~"); op.tag ("OP"); rhs.attribute ("raw", "'" + value + "$'"); + rhs.tag ("REGEX"); } else if (modifier == "word") { @@ -884,6 +885,7 @@ void CLI::desugarAttributeModifiers () #else rhs.attribute ("raw", "'\\b" + value + "\\b'"); #endif + rhs.tag ("REGEX"); } else if (modifier == "noword") { @@ -896,6 +898,7 @@ void CLI::desugarAttributeModifiers () #else rhs.attribute ("raw", "'\\b" + value + "\\b'"); #endif + rhs.tag ("REGEX"); } else throw format (STRING_PARSER_UNKNOWN_ATTMOD, modifier); From 12941488ce7fdbced9839116dc320bbcee6ad2e0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 13:44:56 -0400 Subject: [PATCH 86/97] CmdCustom - Removed redundant pair of parentheses from custom report filters. Only one pair is needed. --- src/commands/CmdCustom.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 1db9bf765..b6894de44 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -81,18 +81,6 @@ int CmdCustom::execute (std::string& output) split (sortOrder, reportSort, ','); validateSortColumns (sortOrder); -/* - TODO Wow, this addition causes memory errors. - - // Surround the command-line filter with parentheses, to protect it from - // the 'and' placed between the report filter and the command line filter. - context.parser.captureFirst ("("); - context.parser.captureLast (")"); -*/ - - if (reportFilter != "") - context.cli.add ("("); - // Prepend the argument list with those from the report filter. std::string lexeme; Lexer::Type type; @@ -105,9 +93,6 @@ int CmdCustom::execute (std::string& output) context.cli.add (lexeme); } - if (reportFilter != "") - context.cli.add (")"); - std::vector ::reverse_iterator arg; for (arg = filterArgs.rbegin (); arg != filterArgs.rend (); ++ arg) context.parser.captureFirst (*arg); From 0c4b447c772a44f6ff5ec406404a417b074ec04d Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 14:35:00 -0400 Subject: [PATCH 87/97] Task - Added CLI::dump. --- src/Task.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Task.cpp b/src/Task.cpp index 2d4ac1966..7a7b4c14d 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1907,9 +1907,13 @@ float Task::urgency_blocking () const void Task::modify (modType type, bool text_required /* = false */) { std::string text = ""; + Tree* tree = context.parser.tree (); - if (tree) + if (context.config.getInteger ("debug.parser") >= 1) + { + context.debug (context.cli.dump ()); context.debug (tree->dump ()); + } context.debug ("Task::modify"); std::string label = " MODIFICATION "; From a780bd01936abce1f0228e737ba5317211e22dad Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:15:31 -0400 Subject: [PATCH 88/97] CLI - Implemented ::desugarPlainArgs to upgrade WORD to PATTERN when found in a FILTER context. --- src/CLI.cpp | 35 +++++++++++++++++++++++++++++++++++ src/CLI.h | 1 + 2 files changed, 36 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 016e772f6..74998b398 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -318,6 +318,7 @@ void CLI::analyze () desugarPatterns (); desugarIDs (); desugarUUIDs (); + //desugarPlainArgs (); findOperators (); insertJunctions (); @@ -1250,6 +1251,40 @@ void CLI::desugarUUIDs () _args = reconstructed; } +//////////////////////////////////////////////////////////////////////////////// +void CLI::desugarPlainArgs () +{ + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER") && + ! a->hasTag ("ATTRIBUTE") && + ! a->hasTag ("OP") && + ! a->hasTag ("LITERAL")) + { + A lhs ("argPattern", "description"); + lhs.tag ("ATTRIBUTE"); + lhs.tag ("FILTER"); + reconstructed.push_back (lhs); + + A op ("argPattern", "~"); + op.tag ("OP"); + op.tag ("FILTER"); + reconstructed.push_back (op); + + A rhs ("argPattern", "'" + a->attribute ("raw") + "'"); + rhs.tag ("LITERAL"); + rhs.tag ("FILTER"); + reconstructed.push_back (rhs); + } + else + reconstructed.push_back (*a); + } + + _args = reconstructed; +} + //////////////////////////////////////////////////////////////////////////////// void CLI::findOperators () { diff --git a/src/CLI.h b/src/CLI.h index 7e8e5918f..76070721a 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -87,6 +87,7 @@ private: void desugarPatterns (); void desugarIDs (); void desugarUUIDs (); + void desugarPlainArgs (); void findOperators (); void insertJunctions (); void decomposeModAttributes (); From 725682a058c78b26ad5e72aabc77f5a4160cf6e6 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:16:56 -0400 Subject: [PATCH 89/97] CLI - Placed filter parentheses around only non-trivial filters. --- src/CLI.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 74998b398..6391c9d9f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -351,9 +351,11 @@ const std::string CLI::getFilter () filter += term; } } + + filter = "( " + filter + " )"; } - return "( " + filter + " )"; + return filter; } //////////////////////////////////////////////////////////////////////////////// From 9d5299e84332ab6ab0e456a847058bdefa7e47df Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:17:35 -0400 Subject: [PATCH 90/97] CLI - Now uses the attribute 'canonical' instead of 'name' for CMD args. --- src/CLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 6391c9d9f..ab9776295 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -527,7 +527,7 @@ void CLI::categorize () a->tag ("CMD"); a->tag (readOnly ? "READCMD" : "WRITECMD"); - a->attribute ("name", canonical); + a->attribute ("canonical", canonical); foundCommand = true; } else if (a->hasTag ("TERMINATOR") || From 4861c1ef1b7d4a9b1b9f15a4cc78b85721a5a3c8 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:18:29 -0400 Subject: [PATCH 91/97] CLI - Implemented ::getWords. --- src/CLI.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index ab9776295..477441281 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -363,8 +363,23 @@ const std::vector CLI::getWords () { std::vector words; - // TODO Processing here. + std::vector ::const_iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (! a->hasTag ("BINARY") && + ! a->hasTag ("RC") && + ! a->hasTag ("CONFIG") && + ! a->hasTag ("CMD") && + ! a->hasTag ("TERMINATOR") && + a->hasTag ("ORIGINAL")) + { + words.push_back (a->attribute ("raw")); + } + } + std::string all; + join (all, " ", words); + std::cout << "# CLI::getWords " << all << "\n"; return words; } From 0ca4b34f75a283cd23cf48624f83291926aecafe Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:36:52 -0400 Subject: [PATCH 92/97] CLI - Properly labels ID and UUID values as literals. --- src/CLI.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CLI.cpp b/src/CLI.cpp index 477441281..49b17ea3d 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -1111,6 +1111,7 @@ void CLI::desugarIDs () A value ("argSeq", r->first); value.tag ("FILTER"); + value.tag ("LITERAL"); value.tag ("NUMBER"); reconstructed.push_back (value); } @@ -1133,6 +1134,7 @@ void CLI::desugarIDs () A startValue ("argSeq", r->first); startValue.tag ("FILTER"); + startValue.tag ("LITERAL"); startValue.tag ("NUMBER"); reconstructed.push_back (startValue); @@ -1153,6 +1155,7 @@ void CLI::desugarIDs () A endValue ("argSeq", r->second); endValue.tag ("FILTER"); + endValue.tag ("LITERAL"); endValue.tag ("NUMBER"); reconstructed.push_back (endValue); @@ -1244,6 +1247,7 @@ void CLI::desugarUUIDs () A value ("argSeq", "'" + *u + "'"); value.tag ("FILTER"); + value.tag ("LITERAL"); value.tag ("STRING"); reconstructed.push_back (value); } @@ -1277,6 +1281,7 @@ void CLI::desugarPlainArgs () { if (a->hasTag ("FILTER") && ! a->hasTag ("ATTRIBUTE") && + ! a->hasTag ("ATTMOD") && ! a->hasTag ("OP") && ! a->hasTag ("LITERAL")) { From 0138c13833bde87a0c218eb629fe101e4c3fbf9c Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:51:35 -0400 Subject: [PATCH 93/97] CLI - Allow ::getWords to run ::analyze but skip the desugar and decomposition steps. --- src/CLI.cpp | 40 +++++++++++++++++++++++----------------- src/CLI.h | 2 +- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 49b17ea3d..28014544e 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -271,7 +271,7 @@ void CLI::add (const std::string& arg) // Intended to be called after ::initialize() and ::add(), to perform the final // analysis. Analysis is also performed directly after the above, because there // is a need to extract overrides early, before entities are proviedd. -void CLI::analyze () +void CLI::analyze (bool parse /* = true */) { // Clean what needs to be cleaned. Most in this case. _args.clear (); @@ -311,22 +311,25 @@ void CLI::analyze () findOverrides (); categorize (); - // Remove all the syntactic sugar for FILTERs. - desugarTags (); - desugarAttributes (); - desugarAttributeModifiers (); - desugarPatterns (); - desugarIDs (); - desugarUUIDs (); - //desugarPlainArgs (); - findOperators (); - insertJunctions (); + if (parse) + { + // Remove all the syntactic sugar for FILTERs. + desugarTags (); + desugarAttributes (); + desugarAttributeModifiers (); + desugarPatterns (); + desugarIDs (); + desugarUUIDs (); + findOperators (); + insertJunctions (); + desugarPlainArgs (); - // Decompose the elements for MODIFICATIONs. - decomposeModAttributes (); - decomposeModAttributeModifiers (); - decomposeModTags (); - decomposeModSubstitutions (); + // Decompose the elements for MODIFICATIONs. + decomposeModAttributes (); + decomposeModAttributeModifiers (); + decomposeModTags (); + decomposeModSubstitutions (); + } } //////////////////////////////////////////////////////////////////////////////// @@ -361,8 +364,11 @@ const std::string CLI::getFilter () //////////////////////////////////////////////////////////////////////////////// const std::vector CLI::getWords () { - std::vector words; + // Re-analyze the arguments, but do not de-sugar or decompose any. Analysis + // only. + analyze (false); + std::vector words; std::vector ::const_iterator a; for (a = _args.begin (); a != _args.end (); ++a) { diff --git a/src/CLI.h b/src/CLI.h index 76070721a..2854b4def 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -69,7 +69,7 @@ public: void entity (const std::string&, const std::string&); void initialize (int, const char**); void add (const std::string&); - void analyze (); + void analyze (bool parse = true); const std::string getFilter (); const std::vector getWords (); const std::vector getModifications (); From 160c4d90d9ec6cb45a137a31cc4c99e288491deb Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 16:57:42 -0400 Subject: [PATCH 94/97] CLI - Removed ::getWords debug output. --- src/CLI.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 28014544e..895aedfc8 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -383,9 +383,6 @@ const std::vector CLI::getWords () } } - std::string all; - join (all, " ", words); - std::cout << "# CLI::getWords " << all << "\n"; return words; } From b4f72286ff204415904c65ea806f817f51c94e1b Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 18:23:53 -0400 Subject: [PATCH 95/97] CLI - Renamed ::desugarIDs to ::findIDs, as it is now a passive method. - Renamed ::desugarUUIDs to ::findUUIDs, as it is now a passive method. - Added ::insertIDExpr which creates one ID/UUID clause from the harvested ID and UUID values. --- src/CLI.cpp | 302 ++++++++++++++++++++++++++-------------------------- src/CLI.h | 8 +- 2 files changed, 156 insertions(+), 154 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 895aedfc8..59cf6702f 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -251,6 +251,9 @@ void CLI::initialize (int argc, const char** argv) { // Clean what needs to be cleaned. Everything in this case. _original_args.clear (); + _id_ranges.clear (); + _uuid_list.clear (); + for (int i = 0; i < argc; ++i) _original_args.push_back (argv[i]); @@ -275,6 +278,8 @@ void CLI::analyze (bool parse /* = true */) { // Clean what needs to be cleaned. Most in this case. _args.clear (); + _id_ranges.clear (); + _uuid_list.clear (); for (int i = 0; i < _original_args.size (); ++i) { @@ -318,8 +323,9 @@ void CLI::analyze (bool parse /* = true */) desugarAttributes (); desugarAttributeModifiers (); desugarPatterns (); - desugarIDs (); - desugarUUIDs (); + findIDs (); + findUUIDs (); + insertIDExpr (); findOperators (); insertJunctions (); desugarPlainArgs (); @@ -995,9 +1001,8 @@ void CLI::desugarPatterns () // a range: 5-10 // or a combination: 1,3,5-10 12 // -void CLI::desugarIDs () +void CLI::findIDs () { - std::vector reconstructed; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { @@ -1016,7 +1021,7 @@ void CLI::desugarIDs () std::vector elements; split (elements, raw, ','); - bool not_an_id = false; + bool is_an_id = true; std::vector ::iterator e; for (e = elements.begin (); e != elements.end (); ++e) { @@ -1028,7 +1033,7 @@ void CLI::desugarIDs () { if (! digitsOnly (terms[0])) { - not_an_id = true; + is_an_id = false; break; } @@ -1041,7 +1046,7 @@ void CLI::desugarIDs () } else { - not_an_id = true; + is_an_id = false; break; } } @@ -1050,7 +1055,7 @@ void CLI::desugarIDs () if (! digitsOnly (terms[0]) || ! digitsOnly (terms[1])) { - not_an_id = true; + is_an_id = false; break; } @@ -1070,135 +1075,39 @@ void CLI::desugarIDs () } else { - not_an_id = true; + is_an_id = false; break; } } else { - not_an_id = true; + is_an_id = false; break; } } - if (! not_an_id) + if (is_an_id) { - // Now convert the ranges into an infix expression. - A openParen ("argSeq", "("); - openParen.tag ("FILTER"); - openParen.tag ("OP"); - reconstructed.push_back (openParen); + a->tag ("ID"); + // Save the ranges. std::vector >::iterator r; for (r = ranges.begin (); r != ranges.end (); ++r) - { - if (r != ranges.begin ()) - { - A opOp ("argSeq", "or"); - opOp.tag ("FILTER"); - opOp.tag ("OP"); - reconstructed.push_back (opOp); - } - - if (r->first == r->second) - { - A id ("argSeq", "id"); - id.tag ("FILTER"); - id.tag ("ATTRIBUTE"); - reconstructed.push_back (id); - - A equal ("argSeq", "=="); - equal.tag ("FILTER"); - equal.tag ("OP"); - reconstructed.push_back (equal); - - A value ("argSeq", r->first); - value.tag ("FILTER"); - value.tag ("LITERAL"); - value.tag ("NUMBER"); - reconstructed.push_back (value); - } - else - { - A rangeOpenParen ("argSeq", "("); - rangeOpenParen.tag ("FILTER"); - rangeOpenParen.tag ("OP"); - reconstructed.push_back (rangeOpenParen); - - A startId ("argSeq", "id"); - startId.tag ("FILTER"); - startId.tag ("ATTRIBUTE"); - reconstructed.push_back (startId); - - A gte ("argSeq", ">="); - gte.tag ("FILTER"); - gte.tag ("OP"); - reconstructed.push_back (gte); - - A startValue ("argSeq", r->first); - startValue.tag ("FILTER"); - startValue.tag ("LITERAL"); - startValue.tag ("NUMBER"); - reconstructed.push_back (startValue); - - A andOp ("argSeq", "and"); - andOp.tag ("FILTER"); - andOp.tag ("OP"); - reconstructed.push_back (andOp); - - A endId ("argSeq", "id"); - endId.tag ("FILTER"); - endId.tag ("ATTRIBUTE"); - reconstructed.push_back (endId); - - A lte ("argSeq", "<="); - lte.tag ("FILTER"); - lte.tag ("OP"); - reconstructed.push_back (lte); - - A endValue ("argSeq", r->second); - endValue.tag ("FILTER"); - endValue.tag ("LITERAL"); - endValue.tag ("NUMBER"); - reconstructed.push_back (endValue); - - A rangeCloseParen ("argSeq", ")"); - rangeCloseParen.tag ("FILTER"); - rangeCloseParen.tag ("OP"); - reconstructed.push_back (rangeCloseParen); - } - } - - A closeParen ("argSeq", ")"); - closeParen.tag ("FILTER"); - closeParen.tag ("OP"); - reconstructed.push_back (closeParen); - - found = true; + _id_ranges.push_back (*r); } } - - if (!found) - reconstructed.push_back (*a); } - else - reconstructed.push_back (*a); } - - _args = reconstructed; } //////////////////////////////////////////////////////////////////////////////// -void CLI::desugarUUIDs () +void CLI::findUUIDs () { - std::vector reconstructed; std::vector ::iterator a; for (a = _args.begin (); a != _args.end (); ++a) { if (a->hasTag ("FILTER")) { - bool found = false; - // UUIDs have a limited character set. std::string raw = a->attribute ("raw"); if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos) @@ -1222,51 +1131,140 @@ void CLI::desugarUUIDs () if (n.depleted ()) { - A openParen ("argSeq", "("); - openParen.tag ("FILTER"); - openParen.tag ("OP"); - reconstructed.push_back (openParen); - - std::vector ::iterator u; - for (u = uuidList.begin (); u != uuidList.end (); ++u) - { - if (u != uuidList.begin ()) - { - A openParen ("argSeq", "or"); - openParen.tag ("FILTER"); - openParen.tag ("OP"); - reconstructed.push_back (openParen); - } - - A uuid ("argSeq", "uuid"); - uuid.tag ("FILTER"); - uuid.tag ("ATTRIBUTE"); - reconstructed.push_back (uuid); - - A equal ("argSeq", "="); - equal.tag ("FILTER"); - equal.tag ("OP"); - reconstructed.push_back (equal); - - A value ("argSeq", "'" + *u + "'"); - value.tag ("FILTER"); - value.tag ("LITERAL"); - value.tag ("STRING"); - reconstructed.push_back (value); - } - - A closeParen ("argSeq", ")"); - closeParen.tag ("FILTER"); - closeParen.tag ("OP"); - reconstructed.push_back (closeParen); - - found = true; + _uuid_list = uuidList; + a->tag ("UUID"); } } } + } + } +} - if (!found) - reconstructed.push_back (*a); +//////////////////////////////////////////////////////////////////////////////// +void CLI::insertIDExpr () +{ + // Iterate over all args. The first ID/UUID arg found will be replaced by + // the combined ID clause. All other ID/UUID args are removed. + bool foundID = false; + std::vector reconstructed; + std::vector ::iterator a; + for (a = _args.begin (); a != _args.end (); ++a) + { + if (a->hasTag ("FILTER") && + (a->hasTag ("ID") || + a->hasTag ("UUID"))) + { + if (! foundID) + { + foundID = true; + + // Construct a single sequence that represents all _id_ranges and + // _uuid_list in one clause. This is essentially converting this: + // + // 1,2-3 uuid,uuid uuid 4 + // + // into: + // + // ( + // ( id == 1 ) + // or ( ( id >= 2 ) and ( id <= 3 ) ) + // or ( id == 4 ) + // or ( uuid = $UUID ) + // or ( uuid = $UUID ) + // ) + + A openParen ("argSeq", "("); openParen.tag ("FILTER"); openParen.tag ("OP"); + A closeParen ("argSeq", ")"); closeParen.tag ("FILTER"); closeParen.tag ("OP"); + A opOr ("argSeq", "or"); opOr.tag ("FILTER"); opOr.tag ("OP"); + A opAnd ("argSeq", "and"); opAnd.tag ("FILTER"); opAnd.tag ("OP"); + A opSimilar ("argSeq", "="); opSimilar.tag ("FILTER"); opSimilar.tag ("OP"); + A opEqual ("argSeq", "=="); opEqual.tag ("FILTER"); opEqual.tag ("OP"); + A opGTE ("argSeq", ">="); opGTE.tag ("FILTER"); opGTE.tag ("OP"); + A opLTE ("argSeq", "<="); opLTE.tag ("FILTER"); opLTE.tag ("OP"); + + A argID ("argSeq", "id"); + argID.tag ("FILTER"); + argID.tag ("ATTRIBUTE"); + argID.tag ("OP"); + + A argUUID ("argSeq", "uuid"); + argUUID.tag ("FILTER"); + argUUID.tag ("ATTRIBUTE"); + argUUID.tag ("OP"); + + reconstructed.push_back (openParen); + + // Add all ID ranges. + std::vector >::iterator r; + for (r = _id_ranges.begin (); r != _id_ranges.end (); ++r) + { + if (r != _id_ranges.begin ()) + reconstructed.push_back (opOr); + + if (r->first == r->second) + { + reconstructed.push_back (openParen); + reconstructed.push_back (argID); + reconstructed.push_back (opEqual); + + A value ("argSeq", r->first); + value.tag ("FILTER"); + value.tag ("LITERAL"); + value.tag ("NUMBER"); + reconstructed.push_back (value); + + reconstructed.push_back (closeParen); + } + else + { + reconstructed.push_back (openParen); + reconstructed.push_back (argID); + reconstructed.push_back (opGTE); + + A startValue ("argSeq", r->first); + startValue.tag ("FILTER"); + startValue.tag ("LITERAL"); + startValue.tag ("NUMBER"); + reconstructed.push_back (startValue); + + reconstructed.push_back (opAnd); + reconstructed.push_back (argID); + reconstructed.push_back (opLTE); + + A endValue ("argSeq", r->second); + endValue.tag ("FILTER"); + endValue.tag ("LITERAL"); + endValue.tag ("NUMBER"); + reconstructed.push_back (endValue); + + reconstructed.push_back (closeParen); + } + } + + // Add all UUID list items. + std::vector ::iterator u; + for (u = _uuid_list.begin (); u != _uuid_list.end (); ++u) + { + if (u != _uuid_list.begin ()) + reconstructed.push_back (opOr); + + reconstructed.push_back (openParen); + reconstructed.push_back (argUUID); + reconstructed.push_back (opSimilar); + + A value ("argSeq", "'" + *u + "'"); + value.tag ("FILTER"); + value.tag ("LITERAL"); + value.tag ("STRING"); + reconstructed.push_back (value); + + reconstructed.push_back (closeParen); + } + + reconstructed.push_back (closeParen); + } + + // No 'else' which cause all other ID/UUID args to be eaten. } else reconstructed.push_back (*a); diff --git a/src/CLI.h b/src/CLI.h index 2854b4def..2ebadc31f 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -85,8 +85,9 @@ private: void desugarAttributes (); void desugarAttributeModifiers (); void desugarPatterns (); - void desugarIDs (); - void desugarUUIDs (); + void findIDs (); + void findUUIDs (); + void insertIDExpr (); void desugarPlainArgs (); void findOperators (); void insertJunctions (); @@ -100,6 +101,9 @@ public: std::map _aliases; std::vector _original_args; std::vector _args; + + std::vector > _id_ranges; + std::vector _uuid_list; }; #endif From 08634a8bb5d4e341956abc1ea4e9e2746199d6b4 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 18:25:24 -0400 Subject: [PATCH 96/97] CLI - Removed the 'ID/UUID or ID/UUID' processing from ::insertJunctions, as they are no longer needed, given ::insertIDExpr. --- src/CLI.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 59cf6702f..9f1106946 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -1330,13 +1330,6 @@ void CLI::findOperators () } //////////////////////////////////////////////////////////////////////////////// -// Two consecutive FILTER, ID or UUID arguments: -// -// ID ID --> ID or ID -// ID UUID --> ID or UUID -// UUID ID --> UUID or ID -// UUID UUID --> UUID or UUID -// // Two consecutive FILTER, non-OP arguments that are not "(" or ")" need an // "and" operator inserted between them. // @@ -1358,17 +1351,6 @@ void CLI::insertJunctions () if (prev == _args.begin ()) prev = a; - // Insert OR between consecutive FILTER ID/UUID args. - if (a != prev && - (prev->hasTag ("ID") || prev->hasTag ("UUID")) && - (a->hasTag ("ID") || a->hasTag ("UUID"))) - { - A opOr ("argOp", "or"); - opOr.tag ("FILTER"); - opOr.tag ("OP"); - reconstructed.push_back (opOr); - } - // Insert AND between terms. else if (a != prev) { From 861743c37d6dcce85382e1d5039f20575d027655 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 25 Oct 2014 18:45:03 -0400 Subject: [PATCH 97/97] CLI - Properly combines _id_ranges and _uuid_list from multiple arguments. - Properly inserts an 'or' OP between the id and uuid sections. - Removed mistaken OP tag from 'id' and 'uuid' attributes. --- src/CLI.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/CLI.cpp b/src/CLI.cpp index 9f1106946..b1a68bcea 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -1131,8 +1131,12 @@ void CLI::findUUIDs () if (n.depleted ()) { - _uuid_list = uuidList; a->tag ("UUID"); + + // Save the list. + std::vector ::iterator u; + for (u = uuidList.begin (); u != uuidList.end (); ++u) + _uuid_list.push_back (*u); } } } @@ -1173,6 +1177,7 @@ void CLI::insertIDExpr () // or ( uuid = $UUID ) // ) + // Building block operators. A openParen ("argSeq", "("); openParen.tag ("FILTER"); openParen.tag ("OP"); A closeParen ("argSeq", ")"); closeParen.tag ("FILTER"); closeParen.tag ("OP"); A opOr ("argSeq", "or"); opOr.tag ("FILTER"); opOr.tag ("OP"); @@ -1182,15 +1187,14 @@ void CLI::insertIDExpr () A opGTE ("argSeq", ">="); opGTE.tag ("FILTER"); opGTE.tag ("OP"); A opLTE ("argSeq", "<="); opLTE.tag ("FILTER"); opLTE.tag ("OP"); + // Building block attributes. A argID ("argSeq", "id"); argID.tag ("FILTER"); argID.tag ("ATTRIBUTE"); - argID.tag ("OP"); A argUUID ("argSeq", "uuid"); argUUID.tag ("FILTER"); argUUID.tag ("ATTRIBUTE"); - argUUID.tag ("OP"); reconstructed.push_back (openParen); @@ -1241,6 +1245,11 @@ void CLI::insertIDExpr () } } + // Combine the ID and UUID sections wiþh 'or'. + if (_id_ranges.size () && + _uuid_list.size ()) + reconstructed.push_back (opOr); + // Add all UUID list items. std::vector ::iterator u; for (u = _uuid_list.begin (); u != _uuid_list.end (); ++u)