From 823c03ba3b113daa95f4dd37fa1936e158f29359 Mon Sep 17 00:00:00 2001 From: "Walter F.J. Mueller" Date: Sun, 2 Apr 2017 13:54:51 +0200 Subject: [PATCH] tcl command handling update - support now sub-command handling - support dynamically created commands (like 'virt') - support command info (via '?' option) --- doc/CHANGELOG.md | 4 + tools/src/librtcltools/RtclCmdBase.cpp | 100 +++++++++++++++++------ tools/src/librtcltools/RtclCmdBase.hpp | 15 ++-- tools/src/librtcltools/RtclProxyBase.cpp | 9 +- 4 files changed, 96 insertions(+), 32 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index df52ee44..295200ec 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -17,6 +17,10 @@ software or firmware builds or that the documentation is consistent. The full set of tests is only run for tagged releases._ ### Summary +- move to Ubuntu 16.04 as development platform + - document urjtag build (jtag in Ubuntu 16.04 is broken) + - add environment sanity wrappers for acroread,awk,firefox to ensure + proper operation of vivado under Ubuntu 16.04 - use Rtime; drop Rtools::TimeOfDayAsDouble() - probe/setup auxilliary devices: kw11l,kw11p,iist - librw11/Rw11Cpu: add ModLalh() diff --git a/tools/src/librtcltools/RtclCmdBase.cpp b/tools/src/librtcltools/RtclCmdBase.cpp index d3d957c6..5c14ca88 100644 --- a/tools/src/librtcltools/RtclCmdBase.cpp +++ b/tools/src/librtcltools/RtclCmdBase.cpp @@ -1,6 +1,6 @@ -// $Id: RtclCmdBase.cpp 584 2014-08-22 19:38:12Z mueller $ +// $Id: RtclCmdBase.cpp 863 2017-04-02 11:43:15Z mueller $ // -// Copyright 2011-2014 by Walter F.J. Mueller +// Copyright 2011-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,6 +13,9 @@ // // Revision History: // Date Rev Version Comment +// 2017-04-02 863 1.1 add DelMeth(),TstMeth(); add M_info() and '?' +// rename fMapMeth -> fMethMap +// 2017-03-11 859 1.1 support now sub-command handling // 2014-08-22 584 1.0.3 use nullptr // 2013-02-10 485 1.0.2 add static const defs // 2013-02-05 483 1.0.1 remove 'unknown specified, full match only' logic @@ -21,7 +24,7 @@ /*! \file - \version $Id: RtclCmdBase.cpp 584 2014-08-22 19:38:12Z mueller $ + \version $Id: RtclCmdBase.cpp 863 2017-04-02 11:43:15Z mueller $ \brief Implemenation of RtclCmdBase. */ @@ -29,6 +32,7 @@ #include "librtools/Rexception.hpp" #include "Rtcl.hpp" +#include "RtclOPtr.hpp" using namespace std; @@ -40,8 +44,6 @@ using namespace std; // all method definitions in namespace Retro namespace Retro { -typedef std::pair mmap_ins_t; - //------------------------------------------+----------------------------------- // constants definitions @@ -52,7 +54,7 @@ const int RtclCmdBase::kERR; //! FIXME_docs RtclCmdBase::RtclCmdBase() - : fMapMeth() + : fMethMap() {} //------------------------------------------+----------------------------------- @@ -70,36 +72,38 @@ int RtclCmdBase::DispatchCmd(RtclArgs& args) Tcl_Interp* interp = args.Interp(); - // no method name given - if (args.Objc() <= 1) { // no args - it_match = fMapMeth.find("$default"); // default method registered ? - if (it_match != fMapMeth.end()) { + if (size_t(args.Objc()) == args.NDone()) {// no args left -> no method name + it_match = fMethMap.find("$default"); // default method registered ? + if (it_match != fMethMap.end()) { return (it_match->second)(args); } - Tcl_WrongNumArgs(interp, 1, args.Objv(), "option ?args?"); // or fail + // or fail + Tcl_WrongNumArgs(interp, args.NDone(), args.Objv(), "option ?args?"); return kERR; } - // here if at least method name given - string name(Tcl_GetString(args[1])); + string name; + args.GetArg("cmd", name); // will always succeed + it_match = fMethMap.lower_bound(name); - it_match = fMapMeth.lower_bound(name); + // handle '?' + if (name == "?") return M_info(args); // no leading substring match - if (it_match==fMapMeth.end() || + if (it_match==fMethMap.end() || name!=it_match->first.substr(0,name.length())) { - mmap_cit_t it_un = fMapMeth.find("$unknown"); // unknown method registered ? - if (it_un!=fMapMeth.end()) { + mmap_cit_t it_un = fMethMap.find("$unknown"); // unknown method registered ? + if (it_un!=fMethMap.end()) { return (it_un->second)(args); } Tcl_AppendResult(interp, "-E: bad option '", name.c_str(), "': must be ", nullptr); const char* delim = ""; - for (mmap_cit_t it1=fMapMeth.begin(); it1!=fMapMeth.end(); it1++) { - if (it1->first.c_str()[0] != '$') { - Tcl_AppendResult(interp, delim, it1->first.c_str(), nullptr); + for (const auto& kv : fMethMap) { + if (kv.first.c_str()[0] != '$') { + Tcl_AppendResult(interp, delim, kv.first.c_str(), nullptr); delim = ","; } } @@ -110,11 +114,11 @@ int RtclCmdBase::DispatchCmd(RtclArgs& args) if (name != it_match->first) { mmap_cit_t it1 = it_match; it1++; - if (it1!=fMapMeth.end() && name==it1->first.substr(0,name.length())) { + if (it1!=fMethMap.end() && name==it1->first.substr(0,name.length())) { Tcl_AppendResult(interp, "-E: ambiguous option '", name.c_str(), "': must be ", nullptr); const char* delim = ""; - for (it1=it_match; it1!=fMapMeth.end() && + for (it1=it_match; it1!=fMethMap.end() && name==it1->first.substr(0,name.length()); it1++) { Tcl_AppendResult(interp, delim, it1->first.c_str(), nullptr); delim = ","; @@ -131,11 +135,61 @@ int RtclCmdBase::DispatchCmd(RtclArgs& args) void RtclCmdBase::AddMeth(const std::string& name, const methfo_t& methfo) { - mmap_ins_t ret = fMapMeth.insert(mmap_val_t(name, methfo)); + auto ret = fMethMap.emplace(name, methfo); if (ret.second == false) // or use !(ret.second) throw Rexception("RtclCmdBase::AddMeth:", string("Bad args: duplicate name: '") + name + "'"); return; } +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void RtclCmdBase::DelMeth(const std::string& name) +{ + if (fMethMap.erase(name) == 0) // balk if not existing + throw Rexception("RtclCmdBase::DelMeth:", + string("Bad args: non-existing name: '") + name + "'"); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +bool RtclCmdBase::TstMeth(const std::string& name) +{ + return fMethMap.find(name) != fMethMap.end(); +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +int RtclCmdBase::M_info(RtclArgs& args) +{ + Tcl_Interp* interp = args.Interp(); + string cname(""); + if (!args.GetArg("??cname", cname)) return TCL_ERROR; + if (!args.AllDone()) return TCL_ERROR; + + RtclOPtr rlist(Tcl_NewListObj(0,nullptr)); + if (cname == "") { // no name --> return all + for (const auto& kv : fMethMap) { + if (kv.first[0] == '$') continue; // skip $nnn internals + RtclOPtr pele(Tcl_NewStringObj(kv.first.c_str(), -1)); + Tcl_ListObjAppendElement(nullptr, rlist, pele); + } + + } else { // name seen --> return matches + auto it_match = fMethMap.lower_bound(cname); + for (auto it=it_match; it!=fMethMap.end() && + cname==it->first.substr(0,cname.length()); it++) { + RtclOPtr pele(Tcl_NewStringObj(it->first.c_str(), -1)); + Tcl_ListObjAppendElement(nullptr, rlist, pele); + } + } + + Tcl_SetObjResult(interp, rlist); + return TCL_OK; +} + } // end namespace Retro diff --git a/tools/src/librtcltools/RtclCmdBase.hpp b/tools/src/librtcltools/RtclCmdBase.hpp index ea35d89b..6d37d96a 100644 --- a/tools/src/librtcltools/RtclCmdBase.hpp +++ b/tools/src/librtcltools/RtclCmdBase.hpp @@ -1,6 +1,6 @@ -// $Id: RtclCmdBase.hpp 511 2013-04-27 13:51:46Z mueller $ +// $Id: RtclCmdBase.hpp 863 2017-04-02 11:43:15Z mueller $ // -// Copyright 2013- by Walter F.J. Mueller +// Copyright 2013-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,13 +13,15 @@ // // Revision History: // Date Rev Version Comment +// 2017-04-02 863 1.1 add DelMeth(),TstMeth(); add M_info() and '?' +// rename fMapMeth -> fMethMap // 2013-04-26 511 1.0.1 AddMeth() now public // 2013-02-02 480 1.0 Initial version (refactored out from ProxyBase) // --------------------------------------------------------------------------- /*! \file - \version $Id: RtclCmdBase.hpp 511 2013-04-27 13:51:46Z mueller $ + \version $Id: RtclCmdBase.hpp 863 2017-04-02 11:43:15Z mueller $ \brief Declaration of class RtclCmdBase. */ @@ -52,15 +54,18 @@ namespace Retro { int DispatchCmd(RtclArgs& args); void AddMeth(const std::string& name, const methfo_t& methfo); + void DelMeth(const std::string& name); + bool TstMeth(const std::string& name); // some constants (also defined in cpp) static const int kOK = TCL_OK; // +// Copyright 2011-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2017-03-11 859 1.5 adopt new DispatchCmd() logic // 2014-08-22 584 1.4.3 use nullptr // 2013-02-09 485 1.4.2 add CommandName() // 2013-02-05 483 1.4.1 ClassCmdConfig: use RtclArgs @@ -27,7 +28,7 @@ /*! \file - \version $Id: RtclProxyBase.cpp 584 2014-08-22 19:38:12Z mueller $ + \version $Id: RtclProxyBase.cpp 859 2017-03-11 22:36:45Z mueller $ \brief Implemenation of RtclProxyBase. */ @@ -114,7 +115,7 @@ void RtclProxyBase::CreateObjectCmd(Tcl_Interp* interp, const char* name) int RtclProxyBase::TclObjectCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]) { - RtclArgs args(interp, objc, objv, 2); + RtclArgs args(interp, objc, objv, 1); return DispatchCmd(args); }