OpenASIP  2.0
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 
43 using std::vector;
44 using 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  */
71 void
73  int argc,
74  char* argv[],
75  InterpreterContext* context,
76  LineReader* reader) {
77 
78  setLineReader(reader);
79  context_ = context;
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  */
105 void
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  */
122 TclInterpreter::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  */
137 bool
138 TclInterpreter::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  */
180 void
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  */
191 void
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  */
205 void
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  */
234 Tcl_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  */
249 bool
250 TclInterpreter::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  */
269 int
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 }
TclInterpreter::addCustomCommandToInterpreter
virtual void addCustomCommandToInterpreter(const CustomCommand &command)
Definition: TclInterpreter.cc:192
CustomCommand::name
std::string name() const
TclInterpreter::removeCustomCommandFromInterpreter
virtual void removeCustomCommandFromInterpreter(const CustomCommand &command)
Definition: TclInterpreter.cc:206
TclInterpreter::variable
virtual DataObject variable(const std::string &name)
Definition: TclInterpreter.cc:122
DataObject
Definition: DataObject.hh:50
DataObject::stringValue
virtual std::string stringValue() const
Definition: DataObject.cc:344
StringTools::stringToCharPtr
static char * stringToCharPtr(const std::string &source)
Definition: StringTools.cc:83
TclInterpreter::interpreter_
Tcl_Interp * interpreter_
Interpreter instance.
Definition: TclInterpreter.hh:96
Conversion::toString
static std::string toString(const T &source)
LineReader::readLine
virtual std::string readLine(std::string prompt="")=0
TclInterpreter::context_
InterpreterContext * context_
Context for interpreter.
Definition: TclInterpreter.hh:94
CustomCommand::execute
virtual bool execute(const std::vector< DataObject > &arguments)=0
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
ScriptInterpreter::setLineReader
virtual void setLineReader(LineReader *reader)
Definition: ScriptInterpreter.cc:377
Conversion.hh
Application.hh
CustomCommand
Definition: CustomCommand.hh:54
TclInterpreter::interpret
virtual bool interpret(const std::string &commandLine)
Definition: TclInterpreter.cc:138
InterpreterContext
Definition: InterpreterContext.hh:40
TclInterpreter::setResultToInterpreter
virtual void setResultToInterpreter(const DataObject &value)
Definition: TclInterpreter.cc:181
ScriptInterpreter::setResult
virtual void setResult(DataObject *result)
Definition: ScriptInterpreter.cc:128
StringTools::trim
static std::string trim(const std::string &source)
Definition: StringTools.cc:55
TclInterpreter.hh
TclInterpreter::TclInterpreter
TclInterpreter()
Definition: TclInterpreter.cc:49
TclInterpreter::context
virtual InterpreterContext & context() const
Definition: TclInterpreter.cc:298
TclInterpreter::~TclInterpreter
virtual ~TclInterpreter()
Definition: TclInterpreter.cc:56
LineReader
Definition: LineReader.hh:52
TclInterpreter::setVariableToInterpreter
virtual void setVariableToInterpreter(const std::string &name, const DataObject &value)
Definition: TclInterpreter.cc:106
TclInterpreter::dataObjectToTclObj
static Tcl_Obj * dataObjectToTclObj(const DataObject &object)
Definition: TclInterpreter.cc:235
TclInterpreter::initialize
virtual void initialize(int argc, char *argv[], InterpreterContext *context, LineReader *reader)
Definition: TclInterpreter.cc:72
ScriptInterpreter::setVariable
virtual void setVariable(const std::string &interpreterVariableName, const std::string &value)
Definition: ScriptInterpreter.cc:240
ScriptInterpreter::setError
virtual void setError(bool state)
Definition: ScriptInterpreter.cc:205
DataObject::setString
virtual void setString(std::string value)
Definition: DataObject.cc:130
ScriptInterpreter
Definition: ScriptInterpreter.hh:55
TclInterpreter::customCommandRedirector
static int customCommandRedirector(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Definition: TclInterpreter.cc:270
ScriptInterpreter::lineReader
virtual LineReader * lineReader() const
Definition: ScriptInterpreter.cc:367
TclInterpreter::tclObjToDataObject
static DataObject tclObjToDataObject(Tcl_Obj *object)
Definition: TclInterpreter.cc:221
TclInterpreter::processScriptFile
virtual bool processScriptFile(const std::string &scriptFileName)
Definition: TclInterpreter.cc:250