Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource2/src/core/TclBind.cc @ 5641

Last change on this file since 5641 was 5641, checked in by rgrieder, 15 years ago

Prepared build system for an external media directory.
This revision only runs in console mode! (tcl files working again)

  • Property svn:eol-style set to native
File size: 7.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "TclBind.h"
30
31#include <exception>
32#include <string>
33#include <cpptcl/cpptcl.h>
34
35#include "SpecialConfig.h"
36#include "util/Debug.h"
37#include "util/StringUtils.h"
38#include "CommandExecutor.h"
39#include "ConsoleCommand.h"
40#include "Core.h"
41#include "TclThreadManager.h"
42
43namespace orxonox
44{
45    SetConsoleCommandShortcut(TclBind, tcl);
46    SetConsoleCommandShortcut(TclBind, bgerror);
47
48    TclBind* TclBind::singletonPtr_s = 0;
49
50    TclBind::TclBind(const std::string& datapath)
51    {
52        this->interpreter_ = 0;
53        this->bSetTclDataPath_ = false;
54        this->setDataPath(datapath);
55    }
56
57    TclBind::~TclBind()
58    {
59        if (this->interpreter_)
60            delete this->interpreter_;
61    }
62
63    void TclBind::setDataPath(const std::string& datapath)
64    {
65        // String has POSIX slashes
66        this->tclDataPath_ = datapath + "tcl" + '/';
67        this->bSetTclDataPath_ = true;
68
69        this->initializeTclInterpreter();
70    }
71
72    void TclBind::initializeTclInterpreter()
73    {
74        if (this->bSetTclDataPath_ && !this->interpreter_)
75        {
76            this->interpreter_ = this->createTclInterpreter();
77
78            this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
79            this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
80            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
81            this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
82
83            try
84            {
85                this->interpreter_->eval("proc query        {args}    { ::orxonox::query $args }");
86                this->interpreter_->eval("proc crossquery   {id args} { ::orxonox::crossquery 0 $id $args }");
87                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossquery 0 $id $args }");
88                this->interpreter_->eval("proc running      {}        { return 1 }");
89                this->interpreter_->eval("set id 0");
90                this->interpreter_->eval("rename exit ::tcl::exit; proc exit {} { execute exit }");
91            }
92            catch (Tcl::tcl_error const &e)
93            {   COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl;   }
94            catch (std::exception const &e)
95            {   COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl;   }
96            catch (...)
97            {   COUT(1) << "Error while creating Tcl-interpreter." << std::endl;   }
98        }
99    }
100
101    Tcl::interpreter* TclBind::createTclInterpreter()
102    {
103        Tcl::interpreter* interpreter = new Tcl::interpreter();
104        std::string libpath = TclBind::getTclLibraryPath();
105
106        try
107        {
108            if (libpath != "")
109                interpreter->eval("set tcl_library \"" + libpath + "\"");
110
111            Tcl_Init(interpreter->get());
112
113            interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\"");
114        }
115        catch (Tcl::tcl_error const &e)
116        {   COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl;   }
117        catch (std::exception const &e)
118        {   COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl;   }
119        catch (...)
120        {   COUT(1) << "Error while creating Tcl-interpreter." << std::endl; COUT(1) << "Error: Tcl isn't properly initialized. Orxonox might possibly not work like that." << std::endl;   }
121
122        return interpreter;
123    }
124
125    std::string TclBind::getTclLibraryPath()
126    {
127#ifdef DEPENDENCY_PACKAGE_ENABLE
128        if (Core::isDevelopmentRun())
129            return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
130        else
131            return (Core::getRootPathString() + "lib/tcl");
132#else
133        return "";
134#endif
135    }
136
137    std::string TclBind::tcl_query(Tcl::object const &args)
138    {
139        COUT(4) << "Tcl_query: " << args.get() << std::endl;
140
141        std::string command = stripEnclosingBraces(args.get());
142
143        if (!CommandExecutor::execute(command, false))
144        {
145            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
146        }
147
148        if (CommandExecutor::getLastEvaluation().hasReturnvalue())
149            return CommandExecutor::getLastEvaluation().getReturnvalue().getString();
150
151        return "";
152    }
153
154    void TclBind::tcl_execute(Tcl::object const &args)
155    {
156        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
157        std::string command = stripEnclosingBraces(args.get());
158
159        if (!CommandExecutor::execute(command, false))
160        {
161            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
162        }
163    }
164
165    std::string TclBind::tcl(const std::string& tclcode)
166    {
167        if (TclBind::getInstance().interpreter_)
168        {
169            try
170            {
171                std::string output = TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
172                if (output != "")
173                {
174                    COUT(0) << "tcl> " << output << std::endl;
175                }
176                return output;
177            }
178            catch (Tcl::tcl_error const &e)
179            {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
180            catch (std::exception const &e)
181            {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
182        }
183
184        return "";
185    }
186
187    void TclBind::bgerror(std::string error)
188    {
189        COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
190    }
191
192    bool TclBind::eval(const std::string& tclcode)
193    {
194        try
195        {
196            TclBind::getInstance().interpreter_->eval(tclcode);
197            return true;
198        }
199        catch (Tcl::tcl_error const &e)
200        {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
201        catch (std::exception const &e)
202        {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
203
204        return false;
205    }
206}
Note: See TracBrowser for help on using the repository browser.