w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
RtclClassBase.cpp
Go to the documentation of this file.
1// $Id: RtclClassBase.cpp 1186 2019-07-12 17:49:59Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2011-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2018-12-18 1089 1.0.6 use c++ style casts
8// 2018-09-16 1047 1.0.5 coverity fixup (uninitialized pointer)
9// 2014-08-22 584 1.0.4 use nullptr
10// 2013-02-10 485 1.0.3 add static const defs
11// 2013-01-13 474 1.0.2 TclClassCmd(): check for existing Rtclproxy names
12// 2011-03-05 366 1.0.1 use AppendResultNewLines() in exception catcher
13// 2011-02-20 363 1.0 Initial version
14// 2011-02-11 360 0.1 First draft
15// ---------------------------------------------------------------------------
16
21#include <string.h>
22
23#include <stdexcept>
24
25#include "RtclClassBase.hpp"
26#include "RtclContext.hpp"
27#include "RtclOPtr.hpp"
28#include "Rtcl.hpp"
29
30using namespace std;
31
37// all method definitions in namespace Retro
38namespace Retro {
39
40//------------------------------------------+-----------------------------------
41// constants definitions
42
43const int RtclClassBase::kOK;
44const int RtclClassBase::kERR;
45
46//------------------------------------------+-----------------------------------
48
49RtclClassBase::RtclClassBase(const std::string& type)
50 : fType(type),
51 fInterp(0),
52 fCmdToken(0)
53{}
54
55//------------------------------------------+-----------------------------------
57
59{
61}
62
63//------------------------------------------+-----------------------------------
65
66void RtclClassBase::CreateClassCmd(Tcl_Interp* interp, const char* name)
67{
68 fInterp = interp;
69 fCmdToken =
70 Tcl_CreateObjCommand(interp, name, ThunkTclClassCmd,
71 reinterpret_cast<ClientData>(this),
72 reinterpret_cast<Tcl_CmdDeleteProc*>(ThunkTclCmdDeleteProc));
73 RtclContext::Find(interp).RegisterClass(this);
74 Tcl_CreateExitHandler(reinterpret_cast<Tcl_ExitProc*>(ThunkTclExitProc),
75 reinterpret_cast<ClientData>(this));
76 return;
77}
78
79//------------------------------------------+-----------------------------------
81
82int RtclClassBase::TclClassCmd(Tcl_Interp* interp, int objc,
83 Tcl_Obj* const objv[])
84{
85 // no args -> lists existing proxies
86 if (objc == 1) {
87 return ClassCmdList(interp);
88 }
89
90 // 2nd arg -delete -> delete proxy
91 const char* name = Tcl_GetString(objv[1]);
92 if (objc == 3 && strcmp(Tcl_GetString(objv[2]), "-delete")==0) {
93 return ClassCmdDelete(interp, name);
94 }
95
96 // check if proxy of given name already existing
97 RtclProxyBase* pprox = RtclContext::Find(interp).FindProxy("",name);
98 if (pprox) {
99 Tcl_AppendResult(interp, "-E: command name '", name,
100 "' exists already as RtclProxy of type '",
101 pprox->Type().c_str(), "'", nullptr);
102 return kERR;
103
104 }
105
106 // finally create new proxy
107 return ClassCmdCreate(interp, objc, objv);
108}
109
110//------------------------------------------+-----------------------------------
112
113int RtclClassBase::ClassCmdList(Tcl_Interp* interp)
114{
115 std::vector<RtclProxyBase*> list;
116 RtclContext::Find(interp).ListProxy(list, Type());
117 RtclOPtr rlist(Tcl_NewListObj(0, nullptr));
118
119 for (size_t i=0; i<list.size(); i++) {
120 const char* cmdname = Tcl_GetCommandName(interp, list[i]->Token());
121 RtclOPtr rval(Tcl_NewStringObj(cmdname, -1));
122 if (Tcl_ListObjAppendElement(interp, rlist, rval) != kOK) return kERR;
123 }
124
125 Tcl_SetObjResult(interp, rlist);
126
127 return kOK;
128}
129
130//------------------------------------------+-----------------------------------
132
133int RtclClassBase::ClassCmdDelete(Tcl_Interp* interp, const char* name)
134{
135 Tcl_CmdInfo cinfo;
136 if (Tcl_GetCommandInfo(interp, name, &cinfo) == 0) {
137 Tcl_AppendResult(interp, "-E: unknown command name '", name, "'", nullptr);
138 return kERR;
139 }
140
141 RtclContext& cntx = RtclContext::Find(interp);
142 if (!cntx.CheckProxy(reinterpret_cast<RtclProxyBase*>(cinfo.objClientData))) {
143 Tcl_AppendResult(interp, "-E: command '", name, "' is not a RtclProxy",
144 nullptr);
145 return kERR;
146 }
147 if (!cntx.CheckProxy(reinterpret_cast<RtclProxyBase*>(cinfo.objClientData),
148 Type())) {
149 Tcl_AppendResult(interp, "-E: command '", name,
150 "' is not a RtclProxy of type '",
151 Type().c_str(), "'", nullptr);
152 return kERR;
153 }
154
155 int irc = Tcl_DeleteCommand(interp, name);
156 if (irc != kOK) Tcl_AppendResult(interp, "-E: failed to delete '", name,
157 "'", nullptr);
158 return irc;
159}
160
161//------------------------------------------+-----------------------------------
163
164int RtclClassBase::ThunkTclClassCmd(ClientData cdata, Tcl_Interp* interp,
165 int objc, Tcl_Obj* const objv[])
166{
167 if (!cdata) {
168 Tcl_AppendResult(interp, "-E: BUG! ThunkTclClassCmd called with cdata == 0",
169 nullptr);
170 return kERR;
171 }
172
173 try {
174 return reinterpret_cast<RtclClassBase*>(cdata)->TclClassCmd(interp,
175 objc, objv);
176 } catch (exception& e) {
178 Tcl_AppendResult(interp, "-E: exception caught in ThunkTclClassCmd: '",
179 e.what(), "'", nullptr);
180 }
181 return kERR;
182}
183
184//------------------------------------------+-----------------------------------
186
188{
189 Tcl_DeleteExitHandler(reinterpret_cast<Tcl_ExitProc*>(ThunkTclExitProc),
190 cdata);
191 delete (reinterpret_cast<RtclClassBase*>(cdata));
192 return;
193}
194
195//------------------------------------------+-----------------------------------
197
199{
200 delete (reinterpret_cast<RtclClassBase*>(cdata));
201 return;
202}
203
204} // end namespace Retro
void CreateClassCmd(Tcl_Interp *interp, const char *name)
FIXME_docs.
RtclClassBase(const std::string &type=std::string())
Default constructor.
Tcl_Command fCmdToken
cmd token for class command
Tcl_Command Token() const
FIXME_docs.
static const int kOK
static void ThunkTclCmdDeleteProc(ClientData cdata)
FIXME_docs.
virtual int ClassCmdCreate(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])=0
virtual int TclClassCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
FIXME_docs.
virtual int ClassCmdDelete(Tcl_Interp *interp, const char *name)
FIXME_docs.
static void ThunkTclExitProc(ClientData cdata)
FIXME_docs.
static const int kERR
virtual int ClassCmdList(Tcl_Interp *interp)
FIXME_docs.
const std::string & Type() const
FIXME_docs.
Tcl_Interp * fInterp
tcl interpreter
static int ThunkTclClassCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
FIXME_docs.
virtual ~RtclClassBase()
Destructor.
void UnRegisterClass(RtclClassBase *pobj)
FIXME_docs.
Definition: RtclContext.cpp:70
void ListProxy(std::vector< RtclProxyBase * > &list, const std::string &type)
FIXME_docs.
RtclProxyBase * FindProxy(const std::string &type, const std::string &name)
FIXME_docs.
bool CheckProxy(RtclProxyBase *pobj)
FIXME_docs.
static RtclContext & Find(Tcl_Interp *interp)
FIXME_docs.
void RegisterClass(RtclClassBase *pobj)
FIXME_docs.
Definition: RtclContext.cpp:58
Implemenation (inline) of RtclOPtr.
Definition: RtclOPtr.hpp:23
const std::string & Type() const
FIXME_docs.
void AppendResultNewLines(Tcl_Interp *interp)
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47