1
0
mirror of https://github.com/wfjm/w11.git synced 2026-01-22 11:00:49 +00:00

tcl command handling update

- support now sub-command handling
- support dynamically created commands (like 'virt')
- support command info (via '?' option)
This commit is contained in:
Walter F.J. Mueller 2017-04-02 13:54:51 +02:00
parent 81b6d6854d
commit 823c03ba3b
4 changed files with 96 additions and 32 deletions

View File

@ -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()

View File

@ -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 <W.F.J.Mueller@gsi.de>
// Copyright 2011-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// 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<RtclCmdBase::mmap_it_t, bool> 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

View File

@ -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 <W.F.J.Mueller@gsi.de>
// Copyright 2013-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// 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; //<!
static const int kERR = TCL_ERROR; //<!
protected:
int M_info(RtclArgs& args);
protected:
mmap_t fMapMeth; //!< map for named methods
mmap_t fMethMap; //!< map for named methods
};
} // end namespace Retro

View File

@ -1,6 +1,6 @@
// $Id: RtclProxyBase.cpp 584 2014-08-22 19:38:12Z mueller $
// $Id: RtclProxyBase.cpp 859 2017-03-11 22:36:45Z mueller $
//
// Copyright 2011-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
// Copyright 2011-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// 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);
}