Orocos Real-Time Toolkit  2.6.0
ScriptingService.cpp
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 }