Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon Jun 26 13:25:57 CEST 2006 ScriptingService.cxx 00003 00004 ScriptingService.cxx - description 00005 ------------------- 00006 begin : Mon June 26 2006 00007 copyright : (C) 2006 Peter Soetens 00008 email : peter.soetens@fmtc.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 00040 #include "ScriptingService.hpp" 00041 #include "../Logger.hpp" 00042 #include "../TaskContext.hpp" 00043 #include <algorithm> 00044 #include <functional> 00045 #include <fstream> 00046 #include <iterator> 00047 #include "scripting/rtt-scripting-config.h" 00048 #include "ProgramExceptions.hpp" 00049 #include "StatementProcessor.hpp" 00050 #include "../Service.hpp" 00051 #include "Parser.hpp" 00052 #include "parse_exception.hpp" 00053 #include "../OperationCaller.hpp" 00054 #include "../internal/mystd.hpp" 00055 #include "../plugin/ServicePlugin.hpp" 00056 00057 ORO_SERVICE_NAMED_PLUGIN( RTT::scripting::ScriptingService, "scripting" ) 00058 00059 00060 namespace RTT { 00061 using namespace detail; 00062 using namespace std; 00063 00064 ScriptingService::shared_ptr ScriptingService::Create(TaskContext* parent){ 00065 shared_ptr sp(new ScriptingService(parent)); 00066 parent->provides()->addService( sp ); 00067 return sp; 00068 } 00069 00070 ScriptingService::ScriptingService( TaskContext* parent ) 00071 : Service("scripting", parent), 00072 sproc(0) 00073 { 00074 this->doc("Orocos Scripting service. Use this service in order to load or query programs or state machines."); 00075 this->createInterface(); 00076 ZeroPeriodWarning = true; 00077 this->addProperty("ZeroPeriodWarning",ZeroPeriodWarning) 00078 .doc("If this is set to false, the warning log when loading a program or a state machine into a Component" 00079 " with a null period will not be printed. Be sure you have something else triggering periodically" 00080 " your Component activity unless your script may not work."); 00081 } 00082 00083 ScriptingService::~ScriptingService() 00084 { 00085 // since we are refcounted, we don't need to inform the owner 00086 // that we're being deleted. 00087 this->clear(); 00088 delete sproc; 00089 } 00090 00091 void ScriptingService::clear() { 00092 while ( !states.empty() ) { 00093 // try to unload all 00094 Logger::log() << Logger::Info << "ScriptingService unloads StateMachine "<< states.begin()->first << "..."<<Logger::endl; 00095 #ifndef ORO_EMBEDDED 00096 try { 00097 this->unloadStateMachine( states.begin()->first ); 00098 } 00099 catch ( program_load_exception& ple) { 00100 Logger::log() << Logger::Error << ple.what() <<Logger::endl; 00101 states.erase( states.begin() ); // plainly remove it to avoid endless loop. 00102 } 00103 #else 00104 if (this->unloadStateMachine( states.begin()->first ) == false) { 00105 Logger::log() << Logger::Error << "Error during unload !" <<Logger::endl; 00106 states.erase( states.begin() ); // plainly remove it to avoid endless loop. 00107 } 00108 #endif 00109 } 00110 while ( !programs.empty() ) { 00111 // try to unload all 00112 Logger::log() << Logger::Info << "ScriptingService unloads Program "<< programs.begin()->first << "..."<<Logger::endl; 00113 #ifndef ORO_EMBEDDED 00114 try { 00115 this->unloadProgram( programs.begin()->first ); 00116 } 00117 catch ( program_load_exception& ple) { 00118 Logger::log() << Logger::Error << ple.what() <<Logger::endl; 00119 programs.erase( programs.begin() ); // plainly remove it to avoid endless loop. 00120 } 00121 #else 00122 if (this->unloadProgram( programs.begin()->first ) == false) { 00123 Logger::log(Error) << "Error during unload !" <<Logger::endl; 00124 programs.erase( programs.begin() ); // plainly remove it to avoid endless loop. 00125 } 00126 #endif 00127 } 00128 Service::clear(); 00129 } 00130 00131 StateMachine::Status::StateMachineStatus ScriptingService::getStateMachineStatus(const string& name) const 00132 { 00133 StateMapIt it = states.find(name); 00134 if ( it != states.end() ) { 00135 return it->second->getStatus(); 00136 } 00137 return StateMachineStatus::unloaded; 00138 } 00139 00140 string ScriptingService::getStateMachineStatusStr(const string& name) const 00141 { 00142 switch ( getStateMachineStatus( name )) 00143 { 00144 case StateMachineStatus::inactive: 00145 return "inactive"; 00146 break; 00147 case StateMachineStatus::stopping: 00148 return "stopping"; 00149 break; 00150 case StateMachineStatus::stopped: 00151 return "stopped"; 00152 break; 00153 case StateMachineStatus::requesting: 00154 return "requesting"; 00155 break; 00156 case StateMachineStatus::running: 00157 return "running"; 00158 break; 00159 case StateMachineStatus::paused: 00160 return "paused"; 00161 break; 00162 case StateMachineStatus::active: 00163 return "active"; 00164 break; 00165 case StateMachineStatus::activating: 00166 return "activating"; 00167 break; 00168 case StateMachineStatus::deactivating: 00169 return "deactivating"; 00170 break; 00171 case StateMachineStatus::resetting: 00172 return "resetting"; 00173 break; 00174 case StateMachineStatus::error: 00175 return "error"; 00176 break; 00177 case StateMachineStatus::unloaded: 00178 return "unloaded"; 00179 break; 00180 } 00181 return "na"; 00182 } 00183 00184 bool ScriptingService::loadStateMachine( StateMachinePtr sc ) 00185 { 00186 // test if parent ... 00187 if ( sc->getParent() ) { 00188 string error( 00189 "Could not register StateMachine \"" + sc->getName() + 00190 "\" in the ScriptingService. It is not a root StateMachine." ); 00191 ORO_THROW_OR_RETURN( program_load_exception( error ) , false); 00192 } 00193 00194 if (this->recursiveCheckLoadStateMachine( sc ) == false) 00195 return false; // throws load_exception 00196 00197 if ( getOwner()->getPeriod() == 0 && ZeroPeriodWarning) { 00198 log(Warning) << "Loading StateMachine "<< sc->getName() 00199 << " in a TaskContext with getPeriod() == 0." 00200 << " Use setPeriod(period) in order to setup execution of scripts." 00201 << " If you know what you are doing, you may disable this warning using scripting.ZeroPeriodWarning=false" 00202 <<endlog(); 00203 } 00204 00205 this->recursiveLoadStateMachine( sc ); 00206 return true; 00207 } 00208 00209 bool ScriptingService::recursiveCheckLoadStateMachine( StateMachinePtr sc ) 00210 { 00211 // test if already present..., this cannot detect corrupt 00212 // trees with double names... 00213 if ( states.find(sc->getName()) != states.end() ) { 00214 string error( 00215 "Could not register StateMachine \"" + sc->getName() + 00216 "\" in the ScriptingService. A StateMachine with that name is already present." ); 00217 ORO_THROW_OR_RETURN( program_load_exception( error ), false ); 00218 00219 vector<StateMachinePtr>::const_iterator it2; 00220 for (it2 = sc->getChildren().begin(); it2 != sc->getChildren().end(); ++it2) 00221 { 00222 if ( this->recursiveCheckLoadStateMachine( *it2 ) == false) 00223 return false; 00224 } 00225 } 00226 return true; 00227 } 00228 00229 void ScriptingService::recursiveLoadStateMachine( StateMachinePtr sc ) 00230 { 00231 vector<StateMachinePtr>::const_iterator it; 00232 00233 // first load parent. 00234 states[sc->getName()] = sc; 00235 mowner->engine()->runFunction( sc.get() ); 00236 00237 // then load children. 00238 for (it = sc->getChildren().begin(); it != sc->getChildren().end(); ++it) 00239 { 00240 this->recursiveLoadStateMachine( *it ); 00241 } 00242 00243 } 00244 00245 bool ScriptingService::unloadStateMachine( const string& name ) 00246 { 00247 StateMapIt it = states.find(name); 00248 00249 if ( it != states.end() ) { 00250 // test if parent ... 00251 if ( it->second->getParent() ) { 00252 string error( 00253 "Could not unload StateMachine \"" + it->first + 00254 "\" in the ScriptingService. It is not a root StateMachine." ); 00255 ORO_THROW_OR_RETURN( program_unload_exception( error ), false); 00256 } 00257 if (recursiveCheckUnloadStateMachine( it->second ) == false) 00258 return false; 00259 recursiveUnloadStateMachine( it->second ); 00260 return true; 00261 } 00262 return false; 00263 } 00264 00265 bool ScriptingService::recursiveCheckUnloadStateMachine(StateMachinePtr si) 00266 { 00267 // check children 00268 vector<StateMachinePtr>::const_iterator it2; 00269 for (it2 = si->getChildren().begin(); 00270 it2 != si->getChildren().end(); 00271 ++it2) 00272 { 00273 StateMapIt it = states.find( (*it2)->getName() ); 00274 if ( it == states.end() ) { 00275 string error( 00276 "Could not unload StateMachine \"" + si->getName() + 00277 "\" in the ScriptingService. It contains not loaded child "+ (*it2)->getName() ); 00278 ORO_THROW_OR_RETURN( program_unload_exception( error ), false); 00279 } 00280 // all is ok, check child : 00281 if ( this->recursiveCheckUnloadStateMachine( it->second ) == false) 00282 return false; 00283 } 00284 return true; 00285 } 00286 00287 void ScriptingService::recursiveUnloadStateMachine(StateMachinePtr sc) { 00288 // first erase children 00289 for (vector<StateMachinePtr>::const_iterator it = sc->getChildren().begin(); 00290 it != sc->getChildren().end(); ++it) 00291 { 00292 this->recursiveUnloadStateMachine( *it ); 00293 } 00294 00295 // erase this sc : 00296 StateMap::iterator it = states.find( sc->getName() ); 00297 00298 assert( it != states.end() ); // we checked that this is possible 00299 00300 // lastly, unload the parent. 00301 states.erase(it); 00302 mowner->engine()->removeFunction( sc.get() ); 00303 } 00304 00305 bool ScriptingService::deleteStateMachine(const string& name) 00306 { 00307 return this->unloadStateMachine(name); 00308 } 00309 00310 const StateMachinePtr ScriptingService::getStateMachine(const string& name) const 00311 { 00312 StateMapIt it = states.find(name); 00313 return it == states.end() ? StateMachinePtr() : it->second; 00314 } 00315 00316 StateMachinePtr ScriptingService::getStateMachine(const string& name) 00317 { 00318 StateMapIt it = states.find(name); 00319 return it == states.end() ? StateMachinePtr() : it->second; 00320 } 00321 00322 vector<string> ScriptingService::getStateMachineList() const 00323 { 00324 return keys(states); 00325 } 00326 00327 ProgramInterface::Status::ProgramStatus ScriptingService::getProgramStatus(const string& name) const 00328 { 00329 ProgMapIt it = programs.find(name); 00330 00331 if ( it != programs.end() ) 00332 return it->second->getStatus(); 00333 return ProgramStatus::unknown; 00334 } 00335 00336 string ScriptingService::getProgramStatusStr(const string& name) const 00337 { 00338 switch ( getProgramStatus( name )) 00339 { 00340 case ProgramStatus::unknown: 00341 return "unknown"; 00342 break; 00343 case ProgramStatus::stopped: 00344 return "stopped"; 00345 break; 00346 case ProgramStatus::running: 00347 return "running"; 00348 break; 00349 case ProgramStatus::paused: 00350 return "paused"; 00351 break; 00352 case ProgramStatus::error: 00353 return "error"; 00354 break; 00355 } 00356 return "na"; 00357 } 00358 00359 bool ScriptingService::loadProgram(ProgramInterfacePtr pi) 00360 { 00361 if ( programs.find(pi->getName()) != programs.end() ) { 00362 log(Error) << "Could not load Program "<< pi->getName() << " in ScriptingService: name already in use."<<endlog(); 00363 return false; 00364 } 00365 if ( getOwner()->getPeriod() == 0 && ZeroPeriodWarning ) { 00366 log(Warning) << "Loading program " << pi->getName() 00367 << " in a TaskContext with getPeriod() == 0." 00368 << " Use setPeriod(period) in order to setup execution of scripts." 00369 << " If you know what you are doing, you may disable this warning using scripting.ZeroPeriodWarning=false" 00370 << endlog(); 00371 } 00372 programs[pi->getName()] = pi; 00373 pi->reset(); 00374 if ( mowner->engine()->runFunction( pi.get() ) == false) { 00375 programs.erase(pi->getName()); 00376 log(Error) << "Could not load Program "<< pi->getName() << " in ExecutionEngine."<<endlog(); 00377 return false; 00378 } 00379 return true; 00380 } 00381 00382 bool ScriptingService::unloadProgram(const string& name) 00383 { 00384 ProgMap::iterator it = programs.find(name); 00385 00386 if ( it != programs.end() ) 00387 { 00388 mowner->engine()->removeFunction( it->second.get() ); 00389 programs.erase( it ); 00390 return true; 00391 } 00392 string error("Could not unload Program \"" + name + 00393 "\" in the ScriptingService. It does not exist." ); 00394 ORO_THROW_OR_RETURN( program_unload_exception( error ), false); 00395 } 00396 00397 vector<string> ScriptingService::getProgramList() const 00398 { 00399 return keys(programs); 00400 } 00401 00402 const ProgramInterfacePtr ScriptingService::getProgram(const string& name) const 00403 { 00404 ProgMapIt it = programs.find(name); 00405 return it == programs.end() ? ProgramInterfacePtr() : it->second; 00406 } 00407 00408 ProgramInterfacePtr ScriptingService::getProgram(const string& name) 00409 { 00410 ProgMapIt it = programs.find(name); 00411 return it == programs.end() ? ProgramInterfacePtr() : it->second; 00412 } 00413 00414 00415 bool ScriptingService::doExecute(const string& code) 00416 { 00417 return this->execute(code) >= 0; 00418 } 00419 00420 bool ScriptingService::doLoadPrograms( const string& filename ) 00421 { 00422 return this->loadPrograms(filename, false); 00423 } 00424 00425 bool ScriptingService::doLoadProgramText( const string& code ) 00426 { 00427 return this->loadPrograms(code, "string", false); 00428 } 00429 bool ScriptingService::doUnloadProgram( const string& name ) 00430 { 00431 return this->unloadProgram(name, false); 00432 } 00433 00434 bool ScriptingService::doLoadStateMachines( const string& filename ) 00435 { 00436 return this->loadStateMachines(filename, false); 00437 } 00438 bool ScriptingService::doLoadStateMachineText( const string& code ) 00439 { 00440 return this->loadStateMachines(code, "string", false); 00441 } 00442 bool ScriptingService::doUnloadStateMachine( const string& name ) 00443 { 00444 return this->unloadStateMachine(name, false); 00445 } 00446 00447 void ScriptingService::createInterface() 00448 { 00449 // OperationCallers for loading and executing scripts 00450 addOperation("eval", &ScriptingService::eval, this).doc("Evaluate then script in the argument").arg("Code", "Statements, functions, program definitions etc."); 00451 addOperation("runScript", &ScriptingService::runScript, this).doc("Run a script from a given file.").arg("Filename", "The filename of the script."); 00452 00453 addOperation("execute", &ScriptingService::execute, this).doc("Execute a line of code (DEPRECATED).").arg("Code", "A single statement."); 00454 // OperationCallers for loading programs 00455 addOperation("loadPrograms", &ScriptingService::doLoadPrograms, this).doc("Load a program from a given file (DEPRECATED).").arg("Filename", "The filename of the script."); 00456 addOperation("loadProgramText", &ScriptingService::doLoadProgramText, this).doc("Load a program from a string (DEPRECATED).").arg("Code", "A string containing one or more program scripts."); 00457 addOperation("unloadProgram", &ScriptingService::doUnloadProgram, this).doc("Remove a loaded program.").arg("Name", "The name of the loaded Program"); 00458 00459 // Query OperationCallers for programs 00460 addOperation("getProgramList", &ScriptingService::getProgramList, this).doc("Get a list of all loaded program scripts."); 00461 addOperation("getProgramStatus", &ScriptingService::getProgramStatus, this).doc("Get the status of a program?").arg("Name", "The Name of the loaded Program"); 00462 addOperation("getProgramStatusStr", &ScriptingService::getProgramStatusStr, this).doc("Get the status of a program as a human readable string.").arg("Name", "The Name of the loaded Program"); 00463 addOperation("getProgramLine", &ScriptingService::getProgramLine, this).doc("Get the current line of execution of a program?").arg("Name", "The Name of the loaded Program"); 00464 addOperation("getProgramText", &ScriptingService::getProgramText, this).doc("Get the script of a program.").arg("Name", "The Name of the loaded Program"); 00465 00466 // OperationCallers for loading state machines 00467 addOperation("loadStateMachines", &ScriptingService::doLoadStateMachines, this).doc("Load a state machine from a given file (DEPRECATED).").arg("Filename", "The filename of the script."); 00468 addOperation("loadStateMachineText", &ScriptingService::doLoadStateMachineText, this).doc("Load a state machine from a string (DEPRECATED).").arg("Code", "A string containing one or more state machine scripts."); 00469 addOperation("unloadStateMachine", &ScriptingService::doUnloadStateMachine, this).doc("Remove a loaded state machine.").arg("Name", "The name of the loaded State Machine"); 00470 00471 // Query OperationCallers for state machines 00472 addOperation("getStateMachineList", &ScriptingService::getStateMachineList, this).doc("Get a list of all loaded state machines"); 00473 addOperation("getStateMachineStatus", &ScriptingService::getStateMachineStatus, this).doc("Get the status of a state machine?").arg("Name", "The Name of the loaded State Machine"); 00474 addOperation("getStateMachineStatusStr", &ScriptingService::getStateMachineStatusStr, this).doc("Get the status of a state machine as a human readable string."); 00475 addOperation("getStateMachineLine", &ScriptingService::getStateMachineLine, this).doc("Get the current line of execution of a state machine?").arg("Name", "The Name of the loaded State Machine"); 00476 addOperation("getStateMachineText", &ScriptingService::getStateMachineText, this).doc("Get the script of a StateMachine.").arg("Name", "The Name of the loaded StateMachine"); 00477 00478 // Query OperationCallers for programs 00479 addOperation("hasProgram", &ScriptingService::hasProgram, this).doc("Is a program loaded?").arg("Name", "The Name of the loaded Program"); 00480 addOperation("isProgramRunning", &ScriptingService::isProgramRunning, this).doc("Is a program running ?").arg("Name", "The Name of the Loaded Program"); 00481 addOperation("isProgramPaused", &ScriptingService::isProgramPaused, this).doc("Is a program paused ?").arg("Name", "The Name of the Loaded Program"); 00482 addOperation("inProgramError", &ScriptingService::inProgramError, this).doc("Is a program in error ?").arg("Name", "The Name of the Loaded Program"); 00483 00484 // Query OperationCallers for state machines 00485 addOperation("hasStateMachine", &ScriptingService::hasStateMachine, this).doc("Is a state machine loaded?").arg("Name", "The Name of the loaded State Machine"); 00486 addOperation("isStateMachineActive", &ScriptingService::isStateMachineActive, this).doc("Is a state machine active ?").arg("Name", "The Name of the Loaded StateMachine"); 00487 addOperation("isStateMachineRunning", &ScriptingService::isStateMachineRunning, this).doc("Is a state machine running ?").arg("Name", "The Name of the Loaded StateMachine"); 00488 addOperation("isStateMachinePaused", &ScriptingService::isStateMachinePaused, this).doc("Is a state machine paused ?").arg("Name", "The Name of the Loaded StateMachine"); 00489 addOperation("inStateMachineError", &ScriptingService::inStateMachineError, this).doc("Is a state machine in error ?").arg("Name", "The Name of the Loaded StateMachine"); 00490 addOperation("inStateMachineState", &ScriptingService::inStateMachineState, this).doc("Is a state machine in a given state ?").arg("Name", "The Name of the Loaded StateMachine").arg("State", "The name of the state in which it could be."); 00491 addOperation("getStateMachineState", &ScriptingService::getStateMachineState, this).doc("Get the current state name of a state machine.").arg("Name", "The Name of the Loaded StateMachine"); 00492 00493 // OperationCallers for programs 00494 addOperation("startProgram", &ScriptingService::startProgram, this).doc("Start a program").arg("Name", "The Name of the Loaded Program"); 00495 addOperation("stopProgram", &ScriptingService::stopProgram , this).doc("Stop a program").arg("Name", "The Name of the Started Program"); 00496 00497 addOperation("stepProgram", &ScriptingService::stepProgram , this).doc("Step a single program instruction").arg("Name", "The Name of the Paused Program"); 00498 addOperation("pauseProgram", &ScriptingService::pauseProgram , this).doc("Pause a program").arg("Name", "The Name of the Started Program"); 00499 00500 // OperationCallers for state machines 00501 // Activate/deactivate: 00502 addOperation("activateStateMachine", &ScriptingService::activateStateMachine , this).doc("Activate a StateMachine").arg("Name", "The Name of the Loaded StateMachine"); 00503 addOperation("deactivateStateMachine", &ScriptingService::deactivateStateMachine , this).doc("Deactivate a StateMachine").arg("Name", "The Name of the Stopped StateMachine"); 00504 00505 // start/stop/pause: 00506 addOperation("startStateMachine", &ScriptingService::startStateMachine , this).doc("Start a StateMachine").arg("Name", "The Name of the Activated/Paused StateMachine"); 00507 addOperation("pauseStateMachine", &ScriptingService::pauseStateMachine , this).doc("Pause a StateMachine").arg("Name", "The Name of a Started StateMachine"); 00508 addOperation("stopStateMachine", &ScriptingService::stopStateMachine , this).doc("Stop a StateMachine").arg("Name", "The Name of the Started/Paused StateMachine"); 00509 addOperation("resetStateMachine", &ScriptingService::resetStateMachine , this).doc("Reset a StateMachine").arg("Name", "The Name of the Stopped StateMachine"); 00510 00511 // request states 00512 addOperation("requestStateMachineState", &ScriptingService::requestStateMachineState , this).doc("Request a State change").arg("Name", "The Name of the StateMachine").arg("StateName", "The Name of the State to change to"); 00513 } 00514 00515 int ScriptingService::execute(const string& code ){ 00516 if (sproc == 0) 00517 sproc = new StatementProcessor(mowner); 00518 return sproc->execute( code ); 00519 } 00520 00521 ScriptingService::Functions ScriptingService::loadFunctions( const string& file, bool do_throw/* = false*/ ) 00522 { 00523 ifstream inputfile(file.c_str()); 00524 if ( !inputfile ) { 00525 Logger::In in("ScriptingService::loadFunctions"); 00526 Logger::log() << Logger::Error << "Script "+file+" does not exist." << Logger::endl; 00527 return Functions(); 00528 } 00529 string text; 00530 inputfile.unsetf( ios_base::skipws ); 00531 istream_iterator<char> streambegin( inputfile ); 00532 istream_iterator<char> streamend; 00533 std::copy( streambegin, streamend, back_inserter( text ) ); 00534 return this->loadFunctions( text, file, do_throw ); 00535 } 00536 00537 ScriptingService::Functions ScriptingService::loadFunctions( const string& code, const string& filename, bool mrethrow ) 00538 { 00539 00540 Logger::In in("ScriptingService::loadFunctions"); 00541 Parser p; 00542 Functions exec; 00543 Functions ret; 00544 try { 00545 Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl; 00546 ret = p.parseFunction(code, mowner, filename); 00547 } 00548 catch( const file_parse_exception& exc ) 00549 { 00550 #ifndef ORO_EMBEDDED 00551 Logger::log() << Logger::Error << filename<<" :"<< exc.what() << Logger::endl; 00552 if ( mrethrow ) 00553 throw; 00554 #endif 00555 return Functions(); 00556 } 00557 if ( ret.empty() ) 00558 { 00559 Logger::log() << Logger::Debug << "No Functions executed from "<< filename << Logger::endl; 00560 Logger::log() << Logger::Info << filename <<" : Successfully parsed." << Logger::endl; 00561 return Functions(); 00562 } else { 00563 // Load all listed functions in the TaskContext's Processor: 00564 for( Parser::ParsedFunctions::iterator it = ret.begin(); it != ret.end(); ++it) { 00565 Logger::log() << "Queueing Function "<< (*it)->getName() << Logger::endl; 00566 if ( mowner->engine()->runFunction( it->get() ) == false) { 00567 Logger::log() << Logger::Error << "Could not run Function '"<< (*it)->getName() <<"' :" << Logger::nl; 00568 Logger::log() << "Processor not accepting or function queue is full." << Logger::endl; 00569 } else 00570 exec.push_back( *it ); // is being executed. 00571 } 00572 } 00573 return exec; 00574 00575 } 00576 00577 bool ScriptingService::runScript( const string& file ) 00578 { 00579 ifstream inputfile(file.c_str()); 00580 if ( !inputfile ) { 00581 Logger::In in("ScriptingService::runScript"); 00582 Logger::log() << Logger::Error << "Script "+file+" does not exist." << Logger::endl; 00583 return false; 00584 } 00585 string text; 00586 inputfile.unsetf( ios_base::skipws ); 00587 istream_iterator<char> streambegin( inputfile ); 00588 istream_iterator<char> streamend; 00589 std::copy( streambegin, streamend, back_inserter( text ) ); 00590 00591 log(Info) << "Running Script "<< file <<" ..." << Logger::endl; 00592 return evalInternal( file, text ); 00593 } 00594 00595 bool ScriptingService::eval(const string& code) { 00596 return evalInternal("eval()", code); 00597 } 00598 00599 bool ScriptingService::evalInternal(const string& filename, const string& code ) 00600 { 00601 Logger::In in("ScriptingService"); 00602 Parser parser; 00603 try { 00604 parser.runScript(code, mowner, this, filename ); 00605 } 00606 catch( const file_parse_exception& exc ) 00607 { 00608 log(Error) <<filename<<" :"<< exc.what() << endlog(); 00609 return false; 00610 } 00611 return true; 00612 } 00613 00614 bool ScriptingService::loadPrograms( const string& file, bool do_throw /*= false*/ ) 00615 { 00616 ifstream inputfile(file.c_str()); 00617 if ( !inputfile ) { 00618 Logger::In in("ScriptingService::loadProgram"); 00619 Logger::log() << Logger::Error << "Script "+file+" does not exist." << Logger::endl; 00620 return false; 00621 } 00622 string text; 00623 inputfile.unsetf( ios_base::skipws ); 00624 istream_iterator<char> streambegin( inputfile ); 00625 istream_iterator<char> streamend; 00626 std::copy( streambegin, streamend, back_inserter( text ) ); 00627 return this->loadPrograms( text, file, do_throw ); 00628 } 00629 00630 bool ScriptingService::loadPrograms( const string& code, const string& filename, bool mrethrow ){ 00631 00632 Logger::In in("ProgramLoader::loadProgram"); 00633 Parser parser; 00634 Parser::ParsedPrograms pg_list; 00635 try { 00636 Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl; 00637 pg_list = parser.parseProgram(code, mowner, filename ); 00638 } 00639 catch( const file_parse_exception& exc ) 00640 { 00641 #ifndef ORO_EMBEDDED 00642 Logger::log() << Logger::Error <<filename<<" :"<< exc.what() << Logger::endl; 00643 if ( mrethrow ) 00644 throw; 00645 #endif 00646 return false; 00647 } 00648 if ( pg_list.empty() ) 00649 { 00650 Logger::log() << Logger::Info << filename <<" : Successfully parsed." << Logger::endl; 00651 return true; 00652 } else { 00653 // Load all listed programs in the TaskContext's Processor: 00654 bool error = false; 00655 string errors; 00656 for( Parser::ParsedPrograms::iterator it = pg_list.begin(); it != pg_list.end(); ++it) { 00657 try { 00658 Logger::log() << Logger::Info << "Loading Program '"<< (*it)->getName() <<"'" <<Logger::endl; 00659 if (this->loadProgram( *it ) == false) 00660 error = true; 00661 } catch (program_load_exception& e ) { 00662 Logger::log() << Logger::Error << "Could not load Program '"<< (*it)->getName() <<"' :" << Logger::nl; 00663 #ifndef ORO_EMBEDDED 00664 Logger::log() << e.what() << Logger::endl; 00665 if ( mrethrow ) 00666 errors += "Could not load Program '"+ (*it)->getName() +"' :\n"+e.what()+'\n'; 00667 #endif 00668 error = true; 00669 } 00670 } 00671 #ifndef ORO_EMBEDDED 00672 if (error && mrethrow ) 00673 throw program_load_exception( errors ); 00674 #endif 00675 return !error; 00676 } 00677 // never reached 00678 } 00679 00680 bool ScriptingService::unloadProgram( const string& name, bool do_throw ){ 00681 Logger::In in("ScriptingService::unloadProgram"); 00682 try { 00683 Logger::log() << Logger::Info << "Unloading Program '"<< name <<"'"<< Logger::endl; 00684 if (this->unloadProgram(name) == false) 00685 return false; 00686 } catch (program_unload_exception& e ) { 00687 Logger::log() << Logger::Error << "Could not unload Program '"<< name <<"' :" << Logger::nl; 00688 #ifndef ORO_EMBEDDED 00689 Logger::log() << e.what() << Logger::endl; 00690 if ( do_throw ) 00691 throw; 00692 #endif 00693 return false; 00694 } 00695 return true; 00696 } 00697 00698 00699 bool ScriptingService::loadStateMachines( const string& file, bool do_throw /*= false*/ ) 00700 { 00701 ifstream inputfile(file.c_str()); 00702 if ( !inputfile ) { 00703 Logger::In in("ScriptingService::loadStateMachine"); 00704 Logger::log() << Logger::Error << "Script "+file+" does not exist." << Logger::endl; 00705 return false; 00706 } 00707 string text; 00708 inputfile.unsetf( ios_base::skipws ); 00709 istream_iterator<char> streambegin( inputfile ); 00710 istream_iterator<char> streamend; 00711 std::copy( streambegin, streamend, back_inserter( text ) ); 00712 return this->loadStateMachines( text, file, do_throw ); 00713 } 00714 00715 bool ScriptingService::loadStateMachines( const string& code, const string& filename, bool mrethrow ) 00716 { 00717 Logger::In in("ScriptingService::loadStateMachine"); 00718 Parser parser; 00719 Parser::ParsedStateMachines pg_list; 00720 try { 00721 Logger::log() << Logger::Info << "Parsing file "<<filename << Logger::endl; 00722 pg_list = parser.parseStateMachine( code, mowner, filename ); 00723 } 00724 catch( const file_parse_exception& exc ) 00725 { 00726 #ifndef ORO_EMBEDDED 00727 Logger::log() << Logger::Error <<filename<<" :"<< exc.what() << Logger::endl; 00728 if ( mrethrow ) 00729 throw; 00730 #endif 00731 return false; 00732 } 00733 if ( pg_list.empty() ) 00734 { 00735 Logger::log() << Logger::Error << "No StateMachines instantiated in "<< filename << Logger::endl; 00736 return false; 00737 } else { 00738 bool error = false; 00739 string errors; 00740 // Load all listed stateMachines in the TaskContext's Processor: 00741 for( Parser::ParsedStateMachines::iterator it = pg_list.begin(); it != pg_list.end(); ++it) { 00742 try { 00743 Logger::log() << Logger::Info << "Loading StateMachine '"<< (*it)->getName()<<"'" << Logger::endl; 00744 if (this->loadStateMachine( *it ) == false) 00745 return false; 00746 } catch (program_load_exception& e ) { 00747 Logger::log() << Logger::Error << "Could not load StateMachine '"<< (*it)->getName()<<"' :" << Logger::nl; 00748 #ifndef ORO_EMBEDDED 00749 Logger::log() << e.what() << Logger::endl; 00750 if ( mrethrow ) 00751 errors += "Could not load Program '"+ (*it)->getName() +"' :\n"+e.what()+'\n'; 00752 #endif 00753 error = true; 00754 } 00755 } 00756 #ifndef ORO_EMBEDDED 00757 if ( error && mrethrow ) 00758 throw program_load_exception( errors ); 00759 #endif 00760 return !error; 00761 } 00762 // never reached 00763 return false; 00764 } 00765 00766 bool ScriptingService::unloadStateMachine( const string& name, bool do_throw ) { 00767 Logger::In in("ScriptingService::unloadStateMachine"); 00768 try { 00769 Logger::log() << Logger::Info << "Unloading StateMachine '"<< name <<"'"<< Logger::endl; 00770 if (this->unloadStateMachine(name) == false) 00771 return false; 00772 } catch (program_unload_exception& e ) { 00773 Logger::log() << Logger::Error << "Could not unload StateMachine '"<< name <<"' :" << Logger::nl; 00774 #ifndef ORO_EMBEDDED 00775 Logger::log() << e.what() << Logger::endl; 00776 if ( do_throw ) 00777 throw; 00778 #endif 00779 return false; 00780 } 00781 return true; 00782 } 00783 00784 bool ScriptingService::hasProgram(const string& name) const { 00785 return programs.find(name) != programs.end(); 00786 } 00787 00788 int ScriptingService::getProgramLine(const string& name) const { 00789 const ProgramInterfacePtr pi = getProgram(name); 00790 return pi ? pi->getLineNumber() : -1; 00791 } 00792 00793 string ScriptingService::getProgramText(const string& name ) const { 00794 const ProgramInterfacePtr pi = getProgram(name); 00795 return pi ? pi->getText() : ""; 00796 } 00797 00798 bool ScriptingService::hasStateMachine(const string& name) const { 00799 return states.find(name) != states.end(); 00800 } 00801 00802 string ScriptingService::getStateMachineText(const string& name ) const { 00803 const StateMachinePtr sm = getStateMachine(name); 00804 return sm ? sm->getText() : ""; 00805 } 00806 00807 int ScriptingService::getStateMachineLine(const string& name ) const { 00808 const StateMachinePtr sm = getStateMachine(name); 00809 return sm ? sm->getLineNumber() : -1; 00810 } 00811 00812 bool ScriptingService::startProgram(const string& name) 00813 { 00814 ProgramInterfacePtr pi = getProgram(name); 00815 if (pi) 00816 return pi->start(); 00817 return false; 00818 } 00819 00820 bool ScriptingService::isProgramRunning(const string& name) const 00821 { 00822 ProgramInterfacePtr pi = getProgram(name); 00823 if (pi) 00824 return pi->isRunning(); 00825 return false; 00826 } 00827 00828 bool ScriptingService::isProgramPaused(const string& name) const 00829 { 00830 ProgramInterfacePtr pi = getProgram(name); 00831 if (pi) 00832 return pi->isPaused(); 00833 return false; 00834 } 00835 00836 bool ScriptingService::inProgramError(const string& name) const 00837 { 00838 ProgramInterfacePtr pi = getProgram(name); 00839 if (pi) 00840 return pi->inError(); 00841 return false; 00842 } 00843 00844 bool ScriptingService::stopProgram(const string& name) 00845 { 00846 ProgramInterfacePtr pi = getProgram(name); 00847 if (pi) 00848 return pi->stop(); 00849 return false; 00850 } 00851 00852 bool ScriptingService::pauseProgram(const string& name) 00853 { 00854 ProgramInterfacePtr pi = getProgram(name); 00855 if (pi) 00856 return pi->pause(); 00857 return false; 00858 } 00859 00860 bool ScriptingService::stepProgram(const string& name) 00861 { 00862 ProgramInterfacePtr pi = getProgram(name); 00863 if (pi) 00864 return pi->step(); 00865 return false; 00866 } 00867 00868 bool ScriptingService::activateStateMachine(const string& name) 00869 { 00870 StateMachinePtr sm = getStateMachine(name); 00871 if (sm) 00872 return sm->activate(); 00873 return false; 00874 } 00875 00876 bool ScriptingService::deactivateStateMachine(const string& name) 00877 { 00878 StateMachinePtr sm = getStateMachine(name); 00879 if (sm) 00880 return sm->deactivate(); 00881 return false; 00882 } 00883 00884 bool ScriptingService::startStateMachine(const string& name) 00885 { 00886 StateMachinePtr sm = getStateMachine(name); 00887 if (sm) 00888 return sm->start(); 00889 return false; 00890 } 00891 00892 bool ScriptingService::pauseStateMachine(const string& name) 00893 { 00894 StateMachinePtr sm = getStateMachine(name); 00895 if (sm) 00896 return sm->pause(); 00897 return false; 00898 } 00899 00900 bool ScriptingService::stopStateMachine(const string& name) 00901 { 00902 StateMachinePtr sm = getStateMachine(name); 00903 if (sm) 00904 return sm->stop(); 00905 return false; 00906 } 00907 00908 bool ScriptingService::isStateMachinePaused(const string& name) const 00909 { 00910 StateMachinePtr sm = getStateMachine(name); 00911 if (sm) 00912 return sm->isPaused(); 00913 return false; 00914 } 00915 00916 bool ScriptingService::isStateMachineActive(const string& name) const 00917 { 00918 StateMachinePtr sm = getStateMachine(name); 00919 if (sm) 00920 return sm->isActive(); 00921 return false; 00922 } 00923 00924 bool ScriptingService::isStateMachineRunning(const string& name) const 00925 { 00926 StateMachinePtr sm = getStateMachine(name); 00927 if (sm) 00928 return sm->isAutomatic(); 00929 return false; 00930 } 00931 00932 bool ScriptingService::inStateMachineError(const string& name) const 00933 { 00934 StateMachinePtr sm = getStateMachine(name); 00935 if (sm) 00936 return sm->inError(); 00937 return false; 00938 } 00939 00940 string ScriptingService::getStateMachineState(const string& name) const 00941 { 00942 StateMachinePtr sm = getStateMachine(name); 00943 if (sm) 00944 return sm->getCurrentStateName(); 00945 return ""; 00946 } 00947 00948 bool ScriptingService::requestStateMachineState(const string& name, const string& state) 00949 { 00950 StateMachinePtr sm = getStateMachine(name); 00951 if (sm) 00952 return sm->requestState(state); 00953 return false; 00954 } 00955 00956 bool ScriptingService::inStateMachineState(const string& name, const string& state) const 00957 { 00958 StateMachinePtr sm = getStateMachine(name); 00959 if (sm) 00960 return sm->inState(state); 00961 return false; 00962 } 00963 00964 bool ScriptingService::resetStateMachine(const string& name) 00965 { 00966 StateMachinePtr sm = getStateMachine(name); 00967 if (sm) 00968 return sm->reset(); 00969 return false; 00970 } 00971 00972 }