OpenASIP 2.2
Loading...
Searching...
No Matches
TclInterpreter.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file TclInterpreter.cc
26 *
27 * The definition of TclInterpreter class.
28 *
29 * @author Jussi Nykänen 2004 (nykanen-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2005 (pjaaskel-no.spam-cs.tut.fi)
31 * @note reviewed 27 May 2004 by pj, jn, vpj, ll
32 * @note rating: yellow
33 */
34
35#include <vector>
36#include <string>
37
38#include "TclInterpreter.hh"
39#include "Conversion.hh"
40#include "StringTools.hh"
41#include "Application.hh"
42
43using std::vector;
44using std::string;
45
46/**
47 * Constructor.
48 */
50 ScriptInterpreter(), context_(NULL), interpreter_(NULL) {
51}
52
53/**
54 * Destructor.
55 */
57 Tcl_DeleteInterp(interpreter_);
58}
59
60/**
61 * Initializes the interpreter.
62 *
63 * Interpreter instance is created, as well as argc and argv variables are
64 * set in interpreter.
65 *
66 * @param argc The number of command line arguments.
67 * @param argv The command line arguments.
68 * @param context The context for interpreter.
69 * @param reader LineReader for the interpreter.
70 */
71void
73 int argc,
74 char* argv[],
75 InterpreterContext* context,
76 LineReader* reader) {
77
78 setLineReader(reader);
80 interpreter_ = Tcl_CreateInterp();
81
82 if (argc == 0 || argv == NULL) {
83 return;
84 }
85
86 // argv is set to interpreter
87 char* args = Tcl_Merge(argc-1, (char **)argv+1);
88 char* argvStr = const_cast<char*>("argv");
89 Tcl_SetVar(interpreter_, argvStr, args, TCL_GLOBAL_ONLY);
90 ckfree(args);
91
92 // argc is set to interpreter
93 string buffer = Conversion::toString(argc-1);
94 setVariable("argc", buffer);
95 setVariable("argv0", argv[0]);
96}
97
98/**
99 * Sets a variable for interpreter.
100 *
101 * @param name The name of the variable.
102 * @param value The value for a variable.
103 * @exception NumberFormatException If converting value to string fails.
104 */
105void
107 const std::string& name, const DataObject& value) {
108 char* cName = StringTools::stringToCharPtr(name);
109 char* cValue = StringTools::stringToCharPtr(value.stringValue());
110 Tcl_SetVar(interpreter_, cName, cValue, TCL_GLOBAL_ONLY);
111 delete[] cName;
112 delete[] cValue;
113}
114
115/**
116 * Returns the DataObject corresponding a certain variable.
117 *
118 * @param name The name of the variable.
119 * @return The DataObject which holds the value of variable.
120 */
122TclInterpreter::variable(const std::string& name) {
123 DataObject object;
124 char* cName = StringTools::stringToCharPtr(name);
125 string value = Tcl_GetVar(interpreter_, cName, TCL_GLOBAL_ONLY);
126 delete[] cName;
127 object.setString(value);
128 return object;
129}
130
131/**
132 * Interprets one command line.
133 *
134 * @param commandLine The line to be interpreted.
135 * @return True if interpreting is successful, false otherwise.
136 */
137bool
138TclInterpreter::interpret(const std::string& commandLine) {
139
140 LineReader* reader = lineReader();
141 StringTools::trim(commandLine);
142 string command = StringTools::trim(commandLine);
143 if (!command.empty() && command.substr(command.length() - 1, 1) == "{" &&
144 reader != NULL) {
145 // command line ended with '{' so let's wait for more input
146 /// @todo This does not work with nested loops correctly!
147 /// It stops after it encouters the first line with only "}",
148 /// thus it stops after the nested loop definition stops.
149 string line = "";
150 do {
151 line = StringTools::trim(reader->readLine(" "));
152 StringTools::trim(line);
153 command += "\n" + line;
154 } while (!line.empty() && line.substr(line.length() - 1, 1) != "}");
155 }
156
157 char* cCommandLine = StringTools::stringToCharPtr(command);
158 int code = Tcl_Eval(interpreter_, cCommandLine);
159 delete[] cCommandLine;
160
161 Tcl_Obj* object = Tcl_GetObjResult(interpreter_);
162 DataObject* dObject = new DataObject(tclObjToDataObject(object));
163 setResult(dObject);
164
165 if (code == TCL_OK) {
166 setError(false);
167 return true;
168 } else {
169 setError(true);
170 return false;
171 }
172}
173
174/**
175 * Sets result to concrete interpreter.
176 *
177 * @param value The value to be set.
178 * @exception NumberFormatException If conversion to Tcl_Obj fails.
179 */
180void
182 Tcl_Obj* object = dataObjectToTclObj(value);
183 Tcl_SetObjResult(interpreter_, object);
184}
185
186/**
187 * Adds CustomCommand to interpreter.
188 *
189 * @param command The command to be added.
190 */
191void
193 char* cName = StringTools::stringToCharPtr(command.name());
194 Tcl_CreateObjCommand(
195 interpreter_, cName, customCommandRedirector, (ClientData)(&command),
196 NULL);
197 delete[] cName;
198}
199
200/**
201 * Removes custom command from interpreter.
202 *
203 * @param command The command to be removed.
204 */
205void
207 const CustomCommand& command) {
208
209 char* cName = StringTools::stringToCharPtr(command.name());
210 Tcl_DeleteCommand(interpreter_, cName);
211 delete[] cName;
212}
213
214/**
215 * Converts Tcl_Obj to DataObject.
216 *
217 * @param object The object to be converted.
218 * @return DataObject which was converted from Tcl_Obj.
219 */
222 DataObject dObj;
223 dObj.setString(Tcl_GetStringFromObj(object, NULL));
224 return dObj;
225}
226
227/**
228 * Converts DataObject to Tcl_Obj.
229 *
230 * @param object The object to be converted.
231 * @return Tcl_Obj converted from DataObject.
232 * @exception NumberFormatException If conversion fails.
233 */
234Tcl_Obj*
236 char* cName = StringTools::stringToCharPtr(object.stringValue());
237 Tcl_Obj* obj = Tcl_NewStringObj(cName, -1);
238 delete[] cName;
239 return obj;
240}
241
242/**
243 * Processes script file.
244 *
245 * @param scriptFileName The name of the script file.
246 * @return True, if process is successful, false otherwise.
247 * @exception UnreachableStream Don't throw it.
248 */
249bool
250TclInterpreter::processScriptFile(const std::string& scriptFileName) {
251 string command = "source " + scriptFileName;
252 if (!interpret(command)) {
253 return false;
254 }
255 return true;
256}
257
258/**
259 * This handler function is used to handle all CustomCommands.
260 *
261 * ClientData field contains CustomCommand to be executed. Tcl_Objs are
262 * converted to DataObjects which are then passed to CustomCommand.
263 *
264 * @param cd ClientData field.
265 * @param interp Not used.
266 * @param objc The number of Tcl_Objs.
267 * @param objv The Tcl_Objs.
268 */
269int
271 ClientData cd,
272 Tcl_Interp*,
273 int objc,
274 Tcl_Obj *CONST objv[]) {
275
276 vector<DataObject> args;
277
278 for (int i = 0; i < objc; i++) {
280 args.push_back(dObj);
281 }
282
283 CustomCommand* targetCommand = static_cast<CustomCommand*>(cd);
284 assert(cd != NULL);
285
286 if (targetCommand->execute(args)) {
287 return TCL_OK;
288 }
289 return TCL_ERROR;
290}
291
292/**
293 * Returns the context of the interpreter.
294 *
295 * @return The context of the interpreter.
296 */
299 return *context_;
300}
#define assert(condition)
static std::string toString(const T &source)
virtual bool execute(const std::vector< DataObject > &arguments)=0
std::string name() const
virtual std::string stringValue() const
virtual void setString(std::string value)
virtual std::string readLine(std::string prompt="")=0
virtual LineReader * lineReader() const
virtual void setVariable(const std::string &interpreterVariableName, const std::string &value)
virtual void setLineReader(LineReader *reader)
virtual void setError(bool state)
virtual void setResult(DataObject *result)
static std::string trim(const std::string &source)
static char * stringToCharPtr(const std::string &source)
virtual InterpreterContext & context() const
static Tcl_Obj * dataObjectToTclObj(const DataObject &object)
static DataObject tclObjToDataObject(Tcl_Obj *object)
virtual void initialize(int argc, char *argv[], InterpreterContext *context, LineReader *reader)
virtual ~TclInterpreter()
virtual void addCustomCommandToInterpreter(const CustomCommand &command)
Tcl_Interp * interpreter_
Interpreter instance.
static int customCommandRedirector(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
InterpreterContext * context_
Context for interpreter.
virtual void setResultToInterpreter(const DataObject &value)
virtual bool processScriptFile(const std::string &scriptFileName)
virtual void setVariableToInterpreter(const std::string &name, const DataObject &value)
virtual bool interpret(const std::string &commandLine)
virtual void removeCustomCommandFromInterpreter(const CustomCommand &command)
virtual DataObject variable(const std::string &name)