forked from teamnwah/openmw-tes3coop
		
	Merge branch 'script'
Conflicts: readme.txt
This commit is contained in:
		
						commit
						6ac64bbe15
					
				
					 54 changed files with 1129 additions and 286 deletions
				
			
		| 
						 | 
				
			
			@ -38,7 +38,7 @@ opencs_units (model/tools
 | 
			
		|||
 | 
			
		||||
opencs_units_noqt (model/tools
 | 
			
		||||
    mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
 | 
			
		||||
    birthsigncheck spellcheck referenceablecheck
 | 
			
		||||
    birthsigncheck spellcheck referenceablecheck scriptcheck
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										103
									
								
								apps/opencs/model/tools/scriptcheck.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								apps/opencs/model/tools/scriptcheck.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
 | 
			
		||||
#include "scriptcheck.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/tokenloc.hpp>
 | 
			
		||||
#include <components/compiler/scanner.hpp>
 | 
			
		||||
#include <components/compiler/fileparser.hpp>
 | 
			
		||||
#include <components/compiler/exception.hpp>
 | 
			
		||||
#include <components/compiler/extensions0.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../world/data.hpp"
 | 
			
		||||
 | 
			
		||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
 | 
			
		||||
    Type type)
 | 
			
		||||
{
 | 
			
		||||
    std::ostringstream stream;
 | 
			
		||||
 | 
			
		||||
    CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
 | 
			
		||||
 | 
			
		||||
    stream << id.toString() << "|";
 | 
			
		||||
 | 
			
		||||
    if (type==ErrorMessage)
 | 
			
		||||
        stream << "error ";
 | 
			
		||||
    else
 | 
			
		||||
        stream << "warning ";
 | 
			
		||||
 | 
			
		||||
    stream
 | 
			
		||||
        << "script " << mFile
 | 
			
		||||
        << ", line " << loc.mLine << ", column " << loc.mColumn
 | 
			
		||||
        << " (" << loc.mLiteral << "): " << message;
 | 
			
		||||
 | 
			
		||||
    mMessages->push_back (stream.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
 | 
			
		||||
{
 | 
			
		||||
    std::ostringstream stream;
 | 
			
		||||
 | 
			
		||||
    CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
 | 
			
		||||
 | 
			
		||||
    stream << id.toString() << "|";
 | 
			
		||||
 | 
			
		||||
    if (type==ErrorMessage)
 | 
			
		||||
        stream << "error: ";
 | 
			
		||||
    else
 | 
			
		||||
        stream << "warning: ";
 | 
			
		||||
 | 
			
		||||
    stream << message;
 | 
			
		||||
 | 
			
		||||
    mMessages->push_back (stream.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
 | 
			
		||||
: mData (data), mContext (data), mMessages (0)
 | 
			
		||||
{
 | 
			
		||||
    /// \todo add an option to configure warning mode
 | 
			
		||||
    setWarningsMode (0);
 | 
			
		||||
 | 
			
		||||
    Compiler::registerExtensions (mExtensions);
 | 
			
		||||
    mContext.setExtensions (&mExtensions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CSMTools::ScriptCheckStage::setup()
 | 
			
		||||
{
 | 
			
		||||
    mContext.clear();
 | 
			
		||||
    mMessages = 0;
 | 
			
		||||
    mId.clear();
 | 
			
		||||
 | 
			
		||||
    return mData.getScripts().getSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMTools::ScriptCheckStage::perform (int stage, std::vector<std::string>& messages)
 | 
			
		||||
{
 | 
			
		||||
    mMessages = &messages;
 | 
			
		||||
    mId = mData.getScripts().getId (stage);
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        mFile = mData.getScripts().getRecord (stage).get().mId;
 | 
			
		||||
        std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText);
 | 
			
		||||
 | 
			
		||||
        Compiler::Scanner scanner (*this, input, mContext.getExtensions());
 | 
			
		||||
 | 
			
		||||
        Compiler::FileParser parser (*this, mContext);
 | 
			
		||||
 | 
			
		||||
        scanner.scan (parser);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const Compiler::SourceException&)
 | 
			
		||||
    {
 | 
			
		||||
        // error has already been reported via error handler
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& error)
 | 
			
		||||
    {
 | 
			
		||||
        std::ostringstream stream;
 | 
			
		||||
 | 
			
		||||
        CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
 | 
			
		||||
 | 
			
		||||
        stream << id.toString() << "|Critical compile error: " << error.what();
 | 
			
		||||
 | 
			
		||||
        messages.push_back (stream.str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mMessages = 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								apps/opencs/model/tools/scriptcheck.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								apps/opencs/model/tools/scriptcheck.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
#ifndef CSM_TOOLS_SCRIPTCHECK_H
 | 
			
		||||
#define CSM_TOOLS_SCRIPTCHECK_H
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/errorhandler.hpp>
 | 
			
		||||
#include <components/compiler/extensions.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../doc/stage.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../world/scriptcontext.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMTools
 | 
			
		||||
{
 | 
			
		||||
    /// \brief VerifyStage: make sure that scripts compile
 | 
			
		||||
    class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
 | 
			
		||||
    {
 | 
			
		||||
            const CSMWorld::Data& mData;
 | 
			
		||||
            Compiler::Extensions mExtensions;
 | 
			
		||||
            CSMWorld::ScriptContext mContext;
 | 
			
		||||
            std::string mId;
 | 
			
		||||
            std::string mFile;
 | 
			
		||||
            std::vector<std::string> *mMessages;
 | 
			
		||||
 | 
			
		||||
            virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
 | 
			
		||||
            ///< Report error to the user.
 | 
			
		||||
 | 
			
		||||
            virtual void report (const std::string& message, Type type);
 | 
			
		||||
            ///< Report a file related error
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            ScriptCheckStage (const CSMWorld::Data& data);
 | 
			
		||||
 | 
			
		||||
            virtual int setup();
 | 
			
		||||
            ///< \return number of steps
 | 
			
		||||
 | 
			
		||||
            virtual void perform (int stage, std::vector<std::string>& messages);
 | 
			
		||||
            ///< Messages resulting from this tage will be appended to \a messages.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#include "birthsigncheck.hpp"
 | 
			
		||||
#include "spellcheck.hpp"
 | 
			
		||||
#include "referenceablecheck.hpp"
 | 
			
		||||
#include "scriptcheck.hpp"
 | 
			
		||||
 | 
			
		||||
CSMDoc::Operation *CSMTools::Tools::get (int type)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +78,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
 | 
			
		|||
        mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
 | 
			
		||||
 | 
			
		||||
	mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
 | 
			
		||||
 | 
			
		||||
        mVerifier->appendStage (new ScriptCheckStage (mData));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return mVerifier;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,23 +5,92 @@
 | 
			
		|||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/quickfileparser.hpp>
 | 
			
		||||
#include <components/compiler/nullerrorhandler.hpp>
 | 
			
		||||
#include <components/compiler/scanner.hpp>
 | 
			
		||||
 | 
			
		||||
#include "data.hpp"
 | 
			
		||||
 | 
			
		||||
CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUpdated (false) {}
 | 
			
		||||
 | 
			
		||||
bool CSMWorld::ScriptContext::canDeclareLocals() const
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const
 | 
			
		||||
{
 | 
			
		||||
    int index = mData.getGlobals().searchId (name);
 | 
			
		||||
 | 
			
		||||
    if (index!=-1)
 | 
			
		||||
    {
 | 
			
		||||
        switch (mData.getGlobals().getRecord (index).get().mValue.getType())
 | 
			
		||||
        {
 | 
			
		||||
            case ESM::VT_Short: return 's';
 | 
			
		||||
            case ESM::VT_Long: return 'l';
 | 
			
		||||
            case ESM::VT_Float: return 'f';
 | 
			
		||||
 | 
			
		||||
            default: return ' ';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ' ';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std::string& id) const
 | 
			
		||||
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType (const std::string& name,
 | 
			
		||||
    const std::string& id) const
 | 
			
		||||
{
 | 
			
		||||
    return ' ';
 | 
			
		||||
    /// \todo invalidate locals cache on change to scripts
 | 
			
		||||
 | 
			
		||||
    std::string id2 = Misc::StringUtils::lowerCase (id);
 | 
			
		||||
 | 
			
		||||
    int index = mData.getScripts().searchId (id2);
 | 
			
		||||
    bool reference = false;
 | 
			
		||||
 | 
			
		||||
    if (index!=-1)
 | 
			
		||||
    {
 | 
			
		||||
        // ID is not a script ID. Search for a matching referenceable instead.
 | 
			
		||||
        index = mData.getReferenceables().searchId (id2);
 | 
			
		||||
 | 
			
		||||
        if (index!=-1)
 | 
			
		||||
        {
 | 
			
		||||
            // Referenceable found.
 | 
			
		||||
            int columnIndex = mData.getReferenceables().searchColumnIndex (Columns::ColumnId_Script);
 | 
			
		||||
 | 
			
		||||
            if (columnIndex!=-1)
 | 
			
		||||
            {
 | 
			
		||||
                id2 = Misc::StringUtils::lowerCase (mData.getReferenceables().
 | 
			
		||||
                    getData (index, columnIndex).toString().toUtf8().constData());
 | 
			
		||||
 | 
			
		||||
                if (!id2.empty())
 | 
			
		||||
                {
 | 
			
		||||
                    // Referenceable has a script -> use it.
 | 
			
		||||
                    index = mData.getScripts().searchId (id2);
 | 
			
		||||
                    reference = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (index==-1)
 | 
			
		||||
        return std::make_pair (' ', false);
 | 
			
		||||
 | 
			
		||||
    std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find (id2);
 | 
			
		||||
 | 
			
		||||
    if (iter==mLocals.end())
 | 
			
		||||
    {
 | 
			
		||||
        Compiler::Locals locals;
 | 
			
		||||
 | 
			
		||||
        Compiler::NullErrorHandler errorHandler;
 | 
			
		||||
        std::istringstream stream (mData.getScripts().getRecord (index).get().mScriptText);
 | 
			
		||||
        Compiler::QuickFileParser parser (errorHandler, *this, locals);
 | 
			
		||||
        Compiler::Scanner scanner (errorHandler, stream, getExtensions());
 | 
			
		||||
        scanner.scan (parser);
 | 
			
		||||
 | 
			
		||||
        iter = mLocals.insert (std::make_pair (id2, locals)).first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return std::make_pair (iter->second.getType (Misc::StringUtils::lowerCase (name)), reference);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CSMWorld::ScriptContext::isId (const std::string& name) const
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +100,7 @@ bool CSMWorld::ScriptContext::isId (const std::string& name) const
 | 
			
		|||
        mIds = mData.getIds();
 | 
			
		||||
 | 
			
		||||
        std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCase);
 | 
			
		||||
        std::sort (mIds.begin(), mIds.end());
 | 
			
		||||
 | 
			
		||||
        mIdsUpdated = true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +108,19 @@ bool CSMWorld::ScriptContext::isId (const std::string& name) const
 | 
			
		|||
    return std::binary_search (mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase (name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CSMWorld::ScriptContext::isJournalId (const std::string& name) const
 | 
			
		||||
{
 | 
			
		||||
    return mData.getJournals().searchId (name)!=-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMWorld::ScriptContext::invalidateIds()
 | 
			
		||||
{
 | 
			
		||||
    mIdsUpdated = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMWorld::ScriptContext::clear()
 | 
			
		||||
{
 | 
			
		||||
    mIds.clear();
 | 
			
		||||
    mIdsUpdated = false;
 | 
			
		||||
    mLocals.clear();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,8 +3,10 @@
 | 
			
		|||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/context.hpp>
 | 
			
		||||
#include <components/compiler/locals.hpp>
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +17,7 @@ namespace CSMWorld
 | 
			
		|||
            const Data& mData;
 | 
			
		||||
            mutable std::vector<std::string> mIds;
 | 
			
		||||
            mutable bool mIdsUpdated;
 | 
			
		||||
            mutable std::map<std::string, Compiler::Locals> mLocals;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,13 +29,23 @@ namespace CSMWorld
 | 
			
		|||
            virtual char getGlobalType (const std::string& name) const;
 | 
			
		||||
            ///< 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
 | 
			
		||||
            virtual char getMemberType (const std::string& name, const std::string& id) const;
 | 
			
		||||
            ///< 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            virtual std::pair<char, bool> getMemberType (const std::string& name,
 | 
			
		||||
                const std::string& id) const;
 | 
			
		||||
            ///< Return type of member variable \a name in script \a id or in script of reference of
 | 
			
		||||
            /// \a id
 | 
			
		||||
            /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            /// second: true: script of reference
 | 
			
		||||
 | 
			
		||||
            virtual bool isId (const std::string& name) const;
 | 
			
		||||
            ///< Does \a name match an ID, that can be referenced?
 | 
			
		||||
 | 
			
		||||
            virtual bool isJournalId (const std::string& name) const;
 | 
			
		||||
            ///< Does \a name match a journal ID?
 | 
			
		||||
 | 
			
		||||
            void invalidateIds();
 | 
			
		||||
 | 
			
		||||
            void clear();
 | 
			
		||||
            ///< Remove all cached data.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,6 +155,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
 | 
			
		|||
  , mSkipMenu (false)
 | 
			
		||||
  , mUseSound (true)
 | 
			
		||||
  , mCompileAll (false)
 | 
			
		||||
  , mWarningsMode (1)
 | 
			
		||||
  , mScriptContext (0)
 | 
			
		||||
  , mFSStrict (false)
 | 
			
		||||
  , mScriptConsoleMode (false)
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +425,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
 | 
			
		|||
    mScriptContext->setExtensions (&mExtensions);
 | 
			
		||||
 | 
			
		||||
    mEnvironment.setScriptManager (new MWScript::ScriptManager (MWBase::Environment::get().getWorld()->getStore(),
 | 
			
		||||
        mVerboseScripts, *mScriptContext));
 | 
			
		||||
        mVerboseScripts, *mScriptContext, mWarningsMode));
 | 
			
		||||
 | 
			
		||||
    // Create game mechanics system
 | 
			
		||||
    MWMechanics::MechanicsManager* mechanics = new MWMechanics::MechanicsManager;
 | 
			
		||||
| 
						 | 
				
			
			@ -612,8 +613,12 @@ void OMW::Engine::setStartupScript (const std::string& path)
 | 
			
		|||
    mStartupScript = path;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void OMW::Engine::setActivationDistanceOverride (int distance)
 | 
			
		||||
{
 | 
			
		||||
    mActivationDistanceOverride = distance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OMW::Engine::setWarningsMode (int mode)
 | 
			
		||||
{
 | 
			
		||||
    mWarningsMode = mode;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +74,7 @@ namespace OMW
 | 
			
		|||
            bool mSkipMenu;
 | 
			
		||||
            bool mUseSound;
 | 
			
		||||
            bool mCompileAll;
 | 
			
		||||
            int mWarningsMode;
 | 
			
		||||
            std::string mFocusName;
 | 
			
		||||
            std::map<std::string,std::string> mFallbackMap;
 | 
			
		||||
            bool mScriptConsoleMode;
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +182,8 @@ namespace OMW
 | 
			
		|||
            /// Override the game setting specified activation distance.
 | 
			
		||||
            void setActivationDistanceOverride (int distance);
 | 
			
		||||
 | 
			
		||||
            void setWarningsMode (int mode);
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            Files::ConfigurationManager& mCfgMgr;
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -136,6 +136,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
 | 
			
		|||
        ("script-run", bpo::value<std::string>()->default_value(""),
 | 
			
		||||
            "select a file containing a list of console commands that is executed on startup")
 | 
			
		||||
 | 
			
		||||
        ("script-warn", bpo::value<int>()->implicit_value (1)
 | 
			
		||||
            ->default_value (1),
 | 
			
		||||
            "handling of warnings when compiling scripts\n"
 | 
			
		||||
            "\t0 - ignore warning\n"
 | 
			
		||||
            "\t1 - show warning but consider script as correctly compiled anyway\n"
 | 
			
		||||
            "\t2 - treat warnings as errors")
 | 
			
		||||
 | 
			
		||||
        ("skip-menu", bpo::value<bool>()->implicit_value(true)
 | 
			
		||||
            ->default_value(false), "skip main menu on game startup")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -241,6 +248,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
 | 
			
		|||
    engine.setScriptConsoleMode (variables["script-console"].as<bool>());
 | 
			
		||||
    engine.setStartupScript (variables["script-run"].as<std::string>());
 | 
			
		||||
    engine.setActivationDistanceOverride (variables["activate-dist"].as<int>());
 | 
			
		||||
    engine.setWarningsMode (variables["script-warn"].as<int>());
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@
 | 
			
		|||
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/esm/loaddial.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/locals.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwbase/environment.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -28,16 +30,32 @@ namespace MWScript
 | 
			
		|||
        return MWBase::Environment::get().getWorld()->getGlobalVariableType (name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char CompilerContext::getMemberType (const std::string& name, const std::string& id) const
 | 
			
		||||
    std::pair<char, bool> CompilerContext::getMemberType (const std::string& name,
 | 
			
		||||
        const std::string& id) const
 | 
			
		||||
    {
 | 
			
		||||
        MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false);
 | 
			
		||||
        std::string script;
 | 
			
		||||
        bool reference = false;
 | 
			
		||||
 | 
			
		||||
        std::string script = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        if (const ESM::Script *scriptRecord =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().search (id))
 | 
			
		||||
        {
 | 
			
		||||
            script = scriptRecord->mId;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false);
 | 
			
		||||
 | 
			
		||||
        if (script.empty())
 | 
			
		||||
            return ' ';
 | 
			
		||||
            script = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
            reference = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name);
 | 
			
		||||
        char type = ' ';
 | 
			
		||||
 | 
			
		||||
        if (!script.empty())
 | 
			
		||||
            type = MWBase::Environment::get().getScriptManager()->getLocals (script).getType (
 | 
			
		||||
                Misc::StringUtils::lowerCase (name));
 | 
			
		||||
 | 
			
		||||
        return std::make_pair (type, reference);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool CompilerContext::isId (const std::string& name) const
 | 
			
		||||
| 
						 | 
				
			
			@ -67,4 +85,14 @@ namespace MWScript
 | 
			
		|||
            store.get<ESM::Static>().search (name) ||
 | 
			
		||||
            store.get<ESM::Weapon>().search (name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool CompilerContext::isJournalId (const std::string& name) const
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::ESMStore &store =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore();
 | 
			
		||||
 | 
			
		||||
        const ESM::Dialogue *topic = store.get<ESM::Dialogue>().search (name);
 | 
			
		||||
 | 
			
		||||
        return topic && topic->mType==ESM::Dialogue::Journal;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,11 +30,18 @@ namespace MWScript
 | 
			
		|||
            /// 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            virtual char getGlobalType (const std::string& name) const;
 | 
			
		||||
 | 
			
		||||
            virtual char getMemberType (const std::string& name, const std::string& id) const;
 | 
			
		||||
            ///< 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            virtual std::pair<char, bool> getMemberType (const std::string& name,
 | 
			
		||||
                const std::string& id) const;
 | 
			
		||||
            ///< Return type of member variable \a name in script \a id or in script of reference of
 | 
			
		||||
            /// \a id
 | 
			
		||||
            /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            /// second: true: script of reference
 | 
			
		||||
 | 
			
		||||
            virtual bool isId (const std::string& name) const;
 | 
			
		||||
            ///< Does \a name match an ID, that can be referenced?
 | 
			
		||||
 | 
			
		||||
            virtual bool isJournalId (const std::string& name) const;
 | 
			
		||||
            ///< Does \a name match a journal ID?
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,9 @@ op 0x20023: AiFollow, explicit reference
 | 
			
		|||
op 0x20024: AiFollowCell
 | 
			
		||||
op 0x20025: AiFollowCell, explicit reference
 | 
			
		||||
op 0x20026: ModRegion
 | 
			
		||||
opcodes 0x20027-0x3ffff unused
 | 
			
		||||
op 0x20027: RemoveSoulGem
 | 
			
		||||
op 0x20028: RemoveSoulGem, explicit reference
 | 
			
		||||
opcodes 0x20029-0x3ffff unused
 | 
			
		||||
 | 
			
		||||
Segment 4:
 | 
			
		||||
(not implemented yet)
 | 
			
		||||
| 
						 | 
				
			
			@ -308,8 +310,8 @@ op 0x20001f1: GetDetected
 | 
			
		|||
op 0x20001f2: GetDetected, explicit reference
 | 
			
		||||
op 0x20001f3: AddSoulGem
 | 
			
		||||
op 0x20001f4: AddSoulGem, explicit reference
 | 
			
		||||
op 0x20001f5: RemoveSoulGem
 | 
			
		||||
op 0x20001f6: RemoveSoulGem, explicit reference
 | 
			
		||||
op 0x20001f5: unused
 | 
			
		||||
op 0x20001f6: unused
 | 
			
		||||
op 0x20001f7: PlayBink
 | 
			
		||||
op 0x20001f8: Drop
 | 
			
		||||
op 0x20001f9: Drop, explicit reference
 | 
			
		||||
| 
						 | 
				
			
			@ -381,5 +383,7 @@ op 0x200023a: StartCombat
 | 
			
		|||
op 0x200023b: StartCombatExplicit
 | 
			
		||||
op 0x200023c: StopCombat
 | 
			
		||||
op 0x200023d: StopCombatExplicit
 | 
			
		||||
op 0x200023e: GetPcInJail
 | 
			
		||||
op 0x200023f: GetPcTraveling
 | 
			
		||||
 | 
			
		||||
opcodes 0x200023e-0x3ffffff unused
 | 
			
		||||
opcodes 0x2000240-0x3ffffff unused
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,4 +148,25 @@ namespace MWScript
 | 
			
		|||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Locals& GlobalScripts::getLocals (const std::string& name)
 | 
			
		||||
    {
 | 
			
		||||
        std::string name2 = Misc::StringUtils::lowerCase (name);
 | 
			
		||||
        std::map<std::string, std::pair<bool, Locals> >::iterator iter =
 | 
			
		||||
            mScripts.find (name2);
 | 
			
		||||
 | 
			
		||||
        if (iter==mScripts.end())
 | 
			
		||||
        {
 | 
			
		||||
            if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
 | 
			
		||||
            {
 | 
			
		||||
                Locals locals;
 | 
			
		||||
 | 
			
		||||
                locals.configure (*script);
 | 
			
		||||
 | 
			
		||||
                iter = mScripts.insert (std::make_pair (name, std::make_pair (false, locals))).first;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return iter->second.second;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,6 +52,10 @@ namespace MWScript
 | 
			
		|||
            ///< Records for variables that do not exist are dropped silently.
 | 
			
		||||
            ///
 | 
			
		||||
            /// \return Known type?
 | 
			
		||||
 | 
			
		||||
            Locals& getLocals (const std::string& name);
 | 
			
		||||
            ///< If the script \a name has not been added as a global script yet, it is added
 | 
			
		||||
            /// automatically, but is not set to running state.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,47 @@ namespace MWScript
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Locals& InterpreterContext::getMemberLocals (std::string& id, bool global)
 | 
			
		||||
        const
 | 
			
		||||
    {
 | 
			
		||||
        if (global)
 | 
			
		||||
        {
 | 
			
		||||
            return MWBase::Environment::get().getScriptManager()->getGlobalScripts().
 | 
			
		||||
                getLocals (id);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
 | 
			
		||||
             id = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
 | 
			
		||||
            ptr.getRefData().setLocals (
 | 
			
		||||
                *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
 | 
			
		||||
 | 
			
		||||
            return ptr.getRefData().getLocals();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Locals& InterpreterContext::getMemberLocals (std::string& id, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        if (global)
 | 
			
		||||
        {
 | 
			
		||||
            return MWBase::Environment::get().getScriptManager()->getGlobalScripts().
 | 
			
		||||
                getLocals (id);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
 | 
			
		||||
            id = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
 | 
			
		||||
            ptr.getRefData().setLocals (
 | 
			
		||||
                *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (id));
 | 
			
		||||
 | 
			
		||||
            return ptr.getRefData().getLocals();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    InterpreterContext::InterpreterContext (
 | 
			
		||||
        MWScript::Locals *locals, MWWorld::Ptr reference)
 | 
			
		||||
    : mLocals (locals), mReference (reference),
 | 
			
		||||
| 
						 | 
				
			
			@ -407,82 +448,80 @@ namespace MWScript
 | 
			
		|||
        MWBase::Environment::get().getWorld()->disable (ref);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const
 | 
			
		||||
    int InterpreterContext::getMemberShort (const std::string& id, const std::string& name,
 | 
			
		||||
        bool global) const
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        const Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
 | 
			
		||||
            scriptId, name, 's');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        return ptr.getRefData().getLocals().mShorts[index];
 | 
			
		||||
        return locals.mShorts[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const
 | 
			
		||||
    int InterpreterContext::getMemberLong (const std::string& id, const std::string& name,
 | 
			
		||||
        bool global) const
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        const Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
 | 
			
		||||
            scriptId, name, 'l');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        return ptr.getRefData().getLocals().mLongs[index];
 | 
			
		||||
        return locals.mLongs[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const
 | 
			
		||||
    float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name,
 | 
			
		||||
        bool global) const
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        const Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (
 | 
			
		||||
            scriptId, name, 'f');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        return ptr.getRefData().getLocals().mFloats[index];
 | 
			
		||||
        return locals.mFloats[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value)
 | 
			
		||||
    void InterpreterContext::setMemberShort (const std::string& id, const std::string& name,
 | 
			
		||||
        int value, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
 | 
			
		||||
        int index =
 | 
			
		||||
            MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        ptr.getRefData().getLocals().mShorts[index] = value;
 | 
			
		||||
        locals.mShorts[index] = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value)
 | 
			
		||||
    void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
 | 
			
		||||
        int index =
 | 
			
		||||
            MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        ptr.getRefData().getLocals().mLongs[index] = value;
 | 
			
		||||
        locals.mLongs[index] = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value)
 | 
			
		||||
    void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        const MWWorld::Ptr ptr = getReference (id, false);
 | 
			
		||||
        std::string scriptId (id);
 | 
			
		||||
 | 
			
		||||
        std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
 | 
			
		||||
        Locals& locals = getMemberLocals (scriptId, global);
 | 
			
		||||
 | 
			
		||||
        int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
 | 
			
		||||
        int index =
 | 
			
		||||
            MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
 | 
			
		||||
 | 
			
		||||
        ptr.getRefData().setLocals (
 | 
			
		||||
            *MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptId));
 | 
			
		||||
        ptr.getRefData().getLocals().mFloats[index] = value;
 | 
			
		||||
        locals.mFloats[index] = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MWWorld::Ptr InterpreterContext::getReference(bool required)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,12 @@ namespace MWScript
 | 
			
		|||
 | 
			
		||||
            const MWWorld::Ptr getReference (const std::string& id, bool activeOnly, bool doThrow=true) const;
 | 
			
		||||
 | 
			
		||||
            const Locals& getMemberLocals (std::string& id, bool global) const;
 | 
			
		||||
            ///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
 | 
			
		||||
 | 
			
		||||
            Locals& getMemberLocals (std::string& id, bool global);
 | 
			
		||||
            ///< \a id is changed to the respective script ID, if \a id wasn't a script ID before
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            InterpreterContext (MWScript::Locals *locals, MWWorld::Ptr reference);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,35 +81,35 @@ namespace MWScript
 | 
			
		|||
            virtual void setGlobalLong (const std::string& name, int value);
 | 
			
		||||
 | 
			
		||||
            virtual void setGlobalFloat (const std::string& name, float value);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::vector<std::string> getGlobals () const;
 | 
			
		||||
 | 
			
		||||
            virtual char getGlobalType (const std::string& name) const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getActionBinding(const std::string& action) const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCName() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCRace() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCClass() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCFaction() const;
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCRank() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCName() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCRace() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCClass() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCRank() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCNextRank() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual int getPCBounty() const;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getCurrentCellName() const;
 | 
			
		||||
 | 
			
		||||
            virtual bool isScriptRunning (const std::string& name) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -138,17 +144,17 @@ namespace MWScript
 | 
			
		|||
 | 
			
		||||
            virtual void disable (const std::string& id = "");
 | 
			
		||||
 | 
			
		||||
            virtual int getMemberShort (const std::string& id, const std::string& name) const;
 | 
			
		||||
            virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const;
 | 
			
		||||
 | 
			
		||||
            virtual int getMemberLong (const std::string& id, const std::string& name) const;
 | 
			
		||||
            virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const;
 | 
			
		||||
 | 
			
		||||
            virtual float getMemberFloat (const std::string& id, const std::string& name) const;
 | 
			
		||||
            virtual float getMemberFloat (const std::string& id, const std::string& name, bool global) const;
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberShort (const std::string& id, const std::string& name, int value);
 | 
			
		||||
            virtual void setMemberShort (const std::string& id, const std::string& name, int value, bool global);
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberLong (const std::string& id, const std::string& name, int value);
 | 
			
		||||
            virtual void setMemberLong (const std::string& id, const std::string& name, int value, bool global);
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberFloat (const std::string& id, const std::string& name, float value);
 | 
			
		||||
            virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global);
 | 
			
		||||
 | 
			
		||||
            MWWorld::Ptr getReference(bool required=true);
 | 
			
		||||
            ///< Reference, that the script is running from (can be empty)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -365,17 +365,21 @@ namespace MWScript
 | 
			
		|||
        };
 | 
			
		||||
 | 
			
		||||
        template<class R>
 | 
			
		||||
        class OpRemoveSoulGem : public Interpreter::Opcode0
 | 
			
		||||
        class OpRemoveSoulGem : public Interpreter::Opcode1
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
 | 
			
		||||
                {
 | 
			
		||||
                    MWWorld::Ptr ptr = R()(runtime);
 | 
			
		||||
 | 
			
		||||
                    std::string soul = runtime.getStringLiteral (runtime[0].mInteger);
 | 
			
		||||
                    runtime.pop();
 | 
			
		||||
 | 
			
		||||
                    // throw away additional arguments
 | 
			
		||||
                    for (unsigned int i=0; i<arg0; ++i)
 | 
			
		||||
                        runtime.pop();
 | 
			
		||||
 | 
			
		||||
                    MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
 | 
			
		||||
                    for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
 | 
			
		||||
                    {
 | 
			
		||||
| 
						 | 
				
			
			@ -818,6 +822,28 @@ namespace MWScript
 | 
			
		|||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpGetPcInJail : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime &runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    /// \todo implement jail check
 | 
			
		||||
                    runtime.push (0);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpGetPcTraveling : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime &runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    /// \todo implement traveling check
 | 
			
		||||
                    runtime.push (0);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        void installOpcodes (Interpreter::Interpreter& interpreter)
 | 
			
		||||
        {
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
 | 
			
		||||
| 
						 | 
				
			
			@ -850,8 +876,8 @@ namespace MWScript
 | 
			
		|||
            interpreter.installSegment5 (Compiler::Misc::opcodeGetEffectExplicit, new OpGetEffect<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeAddSoulGem, new OpAddSoulGem<ImplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeAddSoulGemExplicit, new OpAddSoulGem<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment3 (Compiler::Misc::opcodeRemoveSoulGem, new OpRemoveSoulGem<ImplicitRef>);
 | 
			
		||||
            interpreter.installSegment3 (Compiler::Misc::opcodeRemoveSoulGemExplicit, new OpRemoveSoulGem<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeDrop, new OpDrop<ImplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeDropExplicit, new OpDrop<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeDropSoulGem, new OpDropSoulGem<ImplicitRef>);
 | 
			
		||||
| 
						 | 
				
			
			@ -888,6 +914,8 @@ namespace MWScript
 | 
			
		|||
            interpreter.installSegment5 (Compiler::Misc::opcodeCastExplicit, new OpCast<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpell, new OpExplodeSpell<ImplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpellExplicit, new OpExplodeSpell<ExplicitRef>);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeGetPcInJail, new OpGetPcInJail);
 | 
			
		||||
            interpreter.installSegment5 (Compiler::Misc::opcodeGetPcTraveling, new OpGetPcTraveling);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,22 +7,28 @@
 | 
			
		|||
#include <exception>
 | 
			
		||||
 | 
			
		||||
#include <components/esm/loadscpt.hpp>
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/compiler/scanner.hpp>
 | 
			
		||||
#include <components/compiler/context.hpp>
 | 
			
		||||
#include <components/compiler/exception.hpp>
 | 
			
		||||
#include <components/compiler/quickfileparser.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
 | 
			
		||||
#include "extensions.hpp"
 | 
			
		||||
 | 
			
		||||
namespace MWScript
 | 
			
		||||
{
 | 
			
		||||
    ScriptManager::ScriptManager (const MWWorld::ESMStore& store, bool verbose,
 | 
			
		||||
        Compiler::Context& compilerContext)
 | 
			
		||||
        Compiler::Context& compilerContext, int warningsMode)
 | 
			
		||||
    : mErrorHandler (std::cerr), mStore (store), mVerbose (verbose),
 | 
			
		||||
      mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext),
 | 
			
		||||
      mOpcodesInstalled (false), mGlobalScripts (store)
 | 
			
		||||
    {}
 | 
			
		||||
    {
 | 
			
		||||
        mErrorHandler.setWarningsMode (warningsMode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool ScriptManager::compile (const std::string& name)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,37 +144,33 @@ namespace MWScript
 | 
			
		|||
 | 
			
		||||
    Compiler::Locals& ScriptManager::getLocals (const std::string& name)
 | 
			
		||||
    {
 | 
			
		||||
        std::string name2 = Misc::StringUtils::lowerCase (name);
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            ScriptCollection::iterator iter = mScripts.find (name);
 | 
			
		||||
            ScriptCollection::iterator iter = mScripts.find (name2);
 | 
			
		||||
 | 
			
		||||
            if (iter!=mScripts.end())
 | 
			
		||||
                return iter->second.second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            std::map<std::string, Compiler::Locals>::iterator iter = mOtherLocals.find (name);
 | 
			
		||||
            std::map<std::string, Compiler::Locals>::iterator iter = mOtherLocals.find (name2);
 | 
			
		||||
 | 
			
		||||
            if (iter!=mOtherLocals.end())
 | 
			
		||||
                return iter->second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Compiler::Locals locals;
 | 
			
		||||
 | 
			
		||||
        if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
 | 
			
		||||
        if (const ESM::Script *script = mStore.get<ESM::Script>().find (name2))
 | 
			
		||||
        {
 | 
			
		||||
            int index = 0;
 | 
			
		||||
            Compiler::Locals locals;
 | 
			
		||||
 | 
			
		||||
            for (int i=0; i<script->mData.mNumShorts; ++i)
 | 
			
		||||
                locals.declare ('s', script->mVarNames[index++]);
 | 
			
		||||
 | 
			
		||||
            for (int i=0; i<script->mData.mNumLongs; ++i)
 | 
			
		||||
                locals.declare ('l', script->mVarNames[index++]);
 | 
			
		||||
 | 
			
		||||
            for (int i=0; i<script->mData.mNumFloats; ++i)
 | 
			
		||||
                locals.declare ('f', script->mVarNames[index++]);
 | 
			
		||||
            std::istringstream stream (script->mScriptText);
 | 
			
		||||
            Compiler::QuickFileParser parser (mErrorHandler, mCompilerContext, locals);
 | 
			
		||||
            Compiler::Scanner scanner (mErrorHandler, stream, mCompilerContext.getExtensions());
 | 
			
		||||
            scanner.scan (parser);
 | 
			
		||||
 | 
			
		||||
            std::map<std::string, Compiler::Locals>::iterator iter =
 | 
			
		||||
                mOtherLocals.insert (std::make_pair (name, locals)).first;
 | 
			
		||||
                mOtherLocals.insert (std::make_pair (name2, locals)).first;
 | 
			
		||||
 | 
			
		||||
            return iter->second;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -214,8 +216,10 @@ namespace MWScript
 | 
			
		|||
                throw std::runtime_error ("invalid variable type");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string variable2 = Misc::StringUtils::lowerCase (variable);
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i<size; ++i)
 | 
			
		||||
            if (script->mVarNames.at (i+offset)==variable)
 | 
			
		||||
            if (Misc::StringUtils::lowerCase (script->mVarNames.at (i+offset))==variable2)
 | 
			
		||||
                return i;
 | 
			
		||||
 | 
			
		||||
        throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ namespace MWScript
 | 
			
		|||
        public:
 | 
			
		||||
 | 
			
		||||
            ScriptManager (const MWWorld::ESMStore& store, bool verbose,
 | 
			
		||||
                Compiler::Context& compilerContext);
 | 
			
		||||
                Compiler::Context& compilerContext, int warningsMode);
 | 
			
		||||
 | 
			
		||||
            virtual void run (const std::string& name, Interpreter::Context& interpreterContext);
 | 
			
		||||
            ///< Run the script with the given name (compile first, if not compiled yet)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,8 @@ add_component_dir (files
 | 
			
		|||
add_component_dir (compiler
 | 
			
		||||
    context controlparser errorhandler exception exprparser extensions fileparser generator
 | 
			
		||||
    lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler
 | 
			
		||||
    stringparser tokenloc nullerrorhandler opcodes extensions0
 | 
			
		||||
    stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser
 | 
			
		||||
    quickfileparser
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
add_component_dir (interpreter
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,11 +33,18 @@ namespace Compiler
 | 
			
		|||
            virtual char getGlobalType (const std::string& name) const = 0;
 | 
			
		||||
            ///< 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
 | 
			
		||||
            virtual char getMemberType (const std::string& name, const std::string& id) const = 0;
 | 
			
		||||
            ///< 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            virtual std::pair<char, bool> getMemberType (const std::string& name,
 | 
			
		||||
                const std::string& id) const = 0;
 | 
			
		||||
            ///< Return type of member variable \a name in script \a id or in script of reference of
 | 
			
		||||
            /// \a id
 | 
			
		||||
            /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
 | 
			
		||||
            /// second: true: script of reference
 | 
			
		||||
 | 
			
		||||
            virtual bool isId (const std::string& name) const = 0;
 | 
			
		||||
            ///< Does \a name match an ID, that can be referenced?
 | 
			
		||||
 | 
			
		||||
            virtual bool isJournalId (const std::string& name) const = 0;
 | 
			
		||||
            ///< Does \a name match a journal ID?
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@
 | 
			
		|||
 | 
			
		||||
#include "scanner.hpp"
 | 
			
		||||
#include "generator.hpp"
 | 
			
		||||
#include "errorhandler.hpp"
 | 
			
		||||
#include "skipparser.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +72,7 @@ namespace Compiler
 | 
			
		|||
            }
 | 
			
		||||
            else if (keyword==Scanner::K_else)
 | 
			
		||||
            {
 | 
			
		||||
                mState = IfElseEndState;
 | 
			
		||||
                mState = IfElseJunkState; /// \todo should be IfElseEndState; add an option for that
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +108,7 @@ namespace Compiler
 | 
			
		|||
            Codes expr;
 | 
			
		||||
            mExprParser.append (expr);
 | 
			
		||||
 | 
			
		||||
            Generator::jump (loop, -static_cast<int> (mCodeBlock.size()-expr.size()));
 | 
			
		||||
            Generator::jump (loop, -static_cast<int> (mCodeBlock.size()+expr.size()));
 | 
			
		||||
 | 
			
		||||
            std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +122,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
            Codes loop2;
 | 
			
		||||
 | 
			
		||||
            Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()-expr.size()-skip.size()));
 | 
			
		||||
            Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()+expr.size()+skip.size()));
 | 
			
		||||
 | 
			
		||||
            if (loop.size()!=loop2.size())
 | 
			
		||||
                throw std::logic_error (
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +155,7 @@ namespace Compiler
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
    ControlParser::ControlParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
        Literals& literals)
 | 
			
		||||
    : Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
 | 
			
		||||
      mLineParser (errorHandler, context, locals, literals, mCodeBlock),
 | 
			
		||||
| 
						 | 
				
			
			@ -186,8 +188,11 @@ namespace Compiler
 | 
			
		|||
    {
 | 
			
		||||
        if (mState==StartState)
 | 
			
		||||
        {
 | 
			
		||||
            if (keyword==Scanner::K_if)
 | 
			
		||||
            if (keyword==Scanner::K_if || keyword==Scanner::K_elseif)
 | 
			
		||||
            {
 | 
			
		||||
                if (keyword==Scanner::K_elseif)
 | 
			
		||||
                    getErrorHandler().warning ("elseif without matching if", loc);
 | 
			
		||||
 | 
			
		||||
                mExprParser.reset();
 | 
			
		||||
                scanner.scan (mExprParser);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +208,8 @@ namespace Compiler
 | 
			
		|||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState)
 | 
			
		||||
        else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState ||
 | 
			
		||||
            mState==IfElseJunkState)
 | 
			
		||||
        {
 | 
			
		||||
            if (parseIfBody (keyword, loc, scanner))
 | 
			
		||||
                return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -226,6 +232,7 @@ namespace Compiler
 | 
			
		|||
                case IfEndState: mState = IfBodyState; return true;
 | 
			
		||||
                case IfElseifEndState: mState = IfElseifBodyState; return true;
 | 
			
		||||
                case IfElseEndState: mState = IfElseBodyState; return true;
 | 
			
		||||
                case IfElseJunkState: mState = IfElseBodyState; return true;
 | 
			
		||||
 | 
			
		||||
                case WhileEndState: mState = WhileBodyState; return true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +250,13 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
                default: ;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        else if (code==Scanner::S_open && mState==IfElseJunkState)
 | 
			
		||||
        {
 | 
			
		||||
            SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
            scanner.scan (skip);
 | 
			
		||||
            mState = IfElseBodyState;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Parser::parseSpecial (code, loc, scanner);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,8 @@ namespace Compiler
 | 
			
		|||
                IfElseEndState, IfElseBodyState,
 | 
			
		||||
                IfEndifState,
 | 
			
		||||
                WhileEndState, WhileBodyState,
 | 
			
		||||
                WhileEndwhileState
 | 
			
		||||
                WhileEndwhileState,
 | 
			
		||||
                IfElseJunkState
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            typedef std::vector<Interpreter::Type_Code> Codes;
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +48,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
            ControlParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
                Literals& literals);
 | 
			
		||||
 | 
			
		||||
            void appendCode (std::vector<Interpreter::Type_Code>& code) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										83
									
								
								components/compiler/declarationparser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								components/compiler/declarationparser.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
 | 
			
		||||
#include "declarationparser.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "scanner.hpp"
 | 
			
		||||
#include "errorhandler.hpp"
 | 
			
		||||
#include "skipparser.hpp"
 | 
			
		||||
#include "locals.hpp"
 | 
			
		||||
 | 
			
		||||
Compiler::DeclarationParser::DeclarationParser (ErrorHandler& errorHandler, const Context& context,
 | 
			
		||||
    Locals& locals)
 | 
			
		||||
: Parser (errorHandler, context), mLocals (locals), mState (State_Begin), mType (0)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
bool Compiler::DeclarationParser::parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
    Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    if (mState==State_Name)
 | 
			
		||||
    {
 | 
			
		||||
        std::string name2 = Misc::StringUtils::lowerCase (name);
 | 
			
		||||
 | 
			
		||||
        char type = mLocals.getType (name2);
 | 
			
		||||
 | 
			
		||||
        if (type!=' ')
 | 
			
		||||
        {
 | 
			
		||||
            /// \todo add option to make re-declared local variables an error
 | 
			
		||||
            getErrorHandler().warning ("can't re-declare local variable (ignoring declaration)",
 | 
			
		||||
                loc);
 | 
			
		||||
 | 
			
		||||
            mState = State_End;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mLocals.declare (mType, name2);
 | 
			
		||||
 | 
			
		||||
        mState = State_End;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Parser::parseName (name, loc, scanner);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Compiler::DeclarationParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    if (mState==State_Begin)
 | 
			
		||||
    {
 | 
			
		||||
        switch (keyword)
 | 
			
		||||
        {
 | 
			
		||||
            case Scanner::K_short: mType = 's'; break;
 | 
			
		||||
            case Scanner::K_long: mType = 'l'; break;
 | 
			
		||||
            case Scanner::K_float: mType = 'f'; break;
 | 
			
		||||
            default: mType = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mType)
 | 
			
		||||
        {
 | 
			
		||||
            mState = State_Name;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (mState==State_Name)
 | 
			
		||||
    {
 | 
			
		||||
        // allow keywords to be used as local variable names. MW script compiler, you suck!
 | 
			
		||||
        /// \todo option to disable this atrocity.
 | 
			
		||||
        return parseName (loc.mLiteral, loc, scanner);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Parser::parseKeyword (keyword, loc, scanner);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Compiler::DeclarationParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    if (code==Scanner::S_newline && mState==State_End)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return Parser::parseSpecial (code, loc, scanner);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Compiler::DeclarationParser::reset()
 | 
			
		||||
{
 | 
			
		||||
    mState = State_Begin;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								components/compiler/declarationparser.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								components/compiler/declarationparser.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
#ifndef COMPILER_DECLARATIONPARSER_H_INCLUDED
 | 
			
		||||
#define COMPILER_DECLARATIONPARSER_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "parser.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    class Locals;
 | 
			
		||||
 | 
			
		||||
    class DeclarationParser : public Parser
 | 
			
		||||
    {
 | 
			
		||||
            enum State
 | 
			
		||||
            {
 | 
			
		||||
                State_Begin, State_Name, State_End
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            Locals& mLocals;
 | 
			
		||||
            State mState;
 | 
			
		||||
            char mType;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            DeclarationParser (ErrorHandler& errorHandler, const Context& context, Locals& locals);
 | 
			
		||||
 | 
			
		||||
            virtual bool parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
                Scanner& scanner);
 | 
			
		||||
            ///< Handle a name token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle a keyword token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle a special character token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            void reset();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ namespace Compiler
 | 
			
		|||
{
 | 
			
		||||
    // constructor
 | 
			
		||||
 | 
			
		||||
    ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0) {}
 | 
			
		||||
    ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0), mWarningsMode (1) {}
 | 
			
		||||
 | 
			
		||||
    // destructor
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +36,13 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    void ErrorHandler::warning (const std::string& message, const TokenLoc& loc)
 | 
			
		||||
    {
 | 
			
		||||
        ++mWarnings;
 | 
			
		||||
        report (message, loc, WarningMessage);
 | 
			
		||||
        if (mWarningsMode==1)
 | 
			
		||||
        {
 | 
			
		||||
            ++mWarnings;
 | 
			
		||||
            report (message, loc, WarningMessage);
 | 
			
		||||
        }
 | 
			
		||||
        else if (mWarningsMode==2)
 | 
			
		||||
            error (message, loc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Generate an error message.
 | 
			
		||||
| 
						 | 
				
			
			@ -62,4 +67,9 @@ namespace Compiler
 | 
			
		|||
    {
 | 
			
		||||
        mErrors = mWarnings = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ErrorHandler::setWarningsMode (int mode)
 | 
			
		||||
    {
 | 
			
		||||
        mWarningsMode = mode;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ namespace Compiler
 | 
			
		|||
    {
 | 
			
		||||
            int mWarnings;
 | 
			
		||||
            int mErrors;
 | 
			
		||||
            int mWarningsMode;
 | 
			
		||||
 | 
			
		||||
        protected:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,8 +61,11 @@ namespace Compiler
 | 
			
		|||
            void endOfFile();
 | 
			
		||||
            ///< Generate an error message for an unexpected EOF.
 | 
			
		||||
 | 
			
		||||
           virtual void reset();
 | 
			
		||||
            virtual void reset();
 | 
			
		||||
            ///< Remove all previous error/warning events
 | 
			
		||||
 | 
			
		||||
            void setWarningsMode (int mode);
 | 
			
		||||
            ///< // 0 ignore, 1 rate as warning, 2 rate as error
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@
 | 
			
		|||
#include <stack>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "generator.hpp"
 | 
			
		||||
#include "scanner.hpp"
 | 
			
		||||
#include "errorhandler.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +16,6 @@
 | 
			
		|||
#include "stringparser.hpp"
 | 
			
		||||
#include "extensions.hpp"
 | 
			
		||||
#include "context.hpp"
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -203,21 +204,22 @@ namespace Compiler
 | 
			
		|||
        std::string name2 = Misc::StringUtils::lowerCase (name);
 | 
			
		||||
        std::string id = Misc::StringUtils::lowerCase (mExplicit);
 | 
			
		||||
 | 
			
		||||
        char type = getContext().getMemberType (name2, id);
 | 
			
		||||
        std::pair<char, bool> type = getContext().getMemberType (name2, id);
 | 
			
		||||
 | 
			
		||||
        if (type!=' ')
 | 
			
		||||
        if (type.first!=' ')
 | 
			
		||||
        {
 | 
			
		||||
            Generator::fetchMember (mCode, mLiterals, type, name2, id);
 | 
			
		||||
            Generator::fetchMember (mCode, mLiterals, type.first, name2, id, !type.second);
 | 
			
		||||
 | 
			
		||||
            mNextOperand = false;
 | 
			
		||||
            mExplicit.clear();
 | 
			
		||||
            mOperands.push_back (type=='f' ? 'f' : 'l');
 | 
			
		||||
            mOperands.push_back (type.first=='f' ? 'f' : 'l');
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
    ExprParser::ExprParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
        Literals& literals, bool argument)
 | 
			
		||||
    : Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
 | 
			
		||||
      mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false)
 | 
			
		||||
| 
						 | 
				
			
			@ -308,6 +310,22 @@ namespace Compiler
 | 
			
		|||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // die in a fire, Morrowind script compiler!
 | 
			
		||||
            if (const Extensions *extensions = getContext().getExtensions())
 | 
			
		||||
            {
 | 
			
		||||
                if (getContext().isJournalId (name2))
 | 
			
		||||
                {
 | 
			
		||||
                    // JournalID used as an argument. Use the index of that JournalID
 | 
			
		||||
                    Generator::pushString (mCode, mLiterals, name2);
 | 
			
		||||
                    int keyword = extensions->searchKeyword ("getjournalindex");
 | 
			
		||||
                    extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit, 0);
 | 
			
		||||
                    mNextOperand = false;
 | 
			
		||||
                    mOperands.push_back ('l');
 | 
			
		||||
 | 
			
		||||
                    return 2;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (mExplicit.empty() && getContext().isId (name2))
 | 
			
		||||
            {
 | 
			
		||||
                mExplicit = name2;
 | 
			
		||||
| 
						 | 
				
			
			@ -326,6 +344,31 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
    {
 | 
			
		||||
        if (const Extensions *extensions = getContext().getExtensions())
 | 
			
		||||
        {
 | 
			
		||||
            std::string argumentType; // ignored
 | 
			
		||||
            bool hasExplicit = false; // ignored
 | 
			
		||||
            if (extensions->isInstruction (keyword, argumentType, hasExplicit))
 | 
			
		||||
            {
 | 
			
		||||
                // pretend this is not a keyword
 | 
			
		||||
                return parseName (loc.mLiteral, loc, scanner);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (keyword==Scanner::K_end || keyword==Scanner::K_begin ||
 | 
			
		||||
            keyword==Scanner::K_short || keyword==Scanner::K_long ||
 | 
			
		||||
            keyword==Scanner::K_float || keyword==Scanner::K_if ||
 | 
			
		||||
            keyword==Scanner::K_endif || keyword==Scanner::K_else ||
 | 
			
		||||
            keyword==Scanner::K_elseif || keyword==Scanner::K_while ||
 | 
			
		||||
            keyword==Scanner::K_endwhile || keyword==Scanner::K_return ||
 | 
			
		||||
            keyword==Scanner::K_messagebox || keyword==Scanner::K_set ||
 | 
			
		||||
            keyword==Scanner::K_to || keyword==Scanner::K_startscript ||
 | 
			
		||||
            keyword==Scanner::K_stopscript || keyword==Scanner::K_enable ||
 | 
			
		||||
            keyword==Scanner::K_disable)
 | 
			
		||||
        {
 | 
			
		||||
            return parseName (loc.mLiteral, loc, scanner);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mFirst = false;
 | 
			
		||||
 | 
			
		||||
        if (!mExplicit.empty())
 | 
			
		||||
| 
						 | 
				
			
			@ -368,8 +411,15 @@ namespace Compiler
 | 
			
		|||
                    char returnType;
 | 
			
		||||
                    std::string argumentType;
 | 
			
		||||
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType, true))
 | 
			
		||||
                    bool hasExplicit = true;
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!hasExplicit)
 | 
			
		||||
                        {
 | 
			
		||||
                            getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
 | 
			
		||||
                            mExplicit.clear();
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        start();
 | 
			
		||||
 | 
			
		||||
                        mTokenLoc = loc;
 | 
			
		||||
| 
						 | 
				
			
			@ -490,7 +540,9 @@ namespace Compiler
 | 
			
		|||
                    char returnType;
 | 
			
		||||
                    std::string argumentType;
 | 
			
		||||
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType, false))
 | 
			
		||||
                    bool hasExplicit = false;
 | 
			
		||||
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
 | 
			
		||||
                    {
 | 
			
		||||
                        mTokenLoc = loc;
 | 
			
		||||
                        int optionals = parseArguments (argumentType, scanner);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,6 +570,14 @@ namespace Compiler
 | 
			
		|||
    {
 | 
			
		||||
        if (!mExplicit.empty())
 | 
			
		||||
        {
 | 
			
		||||
            if (mRefOp && code==Scanner::S_open)
 | 
			
		||||
            {
 | 
			
		||||
                /// \todo add option to disable this workaround
 | 
			
		||||
                mOperators.push_back ('(');
 | 
			
		||||
                mTokenLoc = loc;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!mRefOp && code==Scanner::S_ref)
 | 
			
		||||
            {
 | 
			
		||||
                mRefOp = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -687,11 +747,11 @@ namespace Compiler
 | 
			
		|||
            {
 | 
			
		||||
                optional = true;
 | 
			
		||||
            }
 | 
			
		||||
            else if (*iter=='S' || *iter=='c')
 | 
			
		||||
            else if (*iter=='S' || *iter=='c' || *iter=='x')
 | 
			
		||||
            {
 | 
			
		||||
                stringParser.reset();
 | 
			
		||||
 | 
			
		||||
                if (optional)
 | 
			
		||||
                if (optional || *iter=='x')
 | 
			
		||||
                    stringParser.setOptional (true);
 | 
			
		||||
 | 
			
		||||
                if (*iter=='c') stringParser.smashCase();
 | 
			
		||||
| 
						 | 
				
			
			@ -700,18 +760,21 @@ namespace Compiler
 | 
			
		|||
                if (optional && stringParser.isEmpty())
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                if (invert)
 | 
			
		||||
                if (*iter!='x')
 | 
			
		||||
                {
 | 
			
		||||
                    std::vector<Interpreter::Type_Code> tmp;
 | 
			
		||||
                    stringParser.append (tmp);
 | 
			
		||||
                    if (invert)
 | 
			
		||||
                    {
 | 
			
		||||
                        std::vector<Interpreter::Type_Code> tmp;
 | 
			
		||||
                        stringParser.append (tmp);
 | 
			
		||||
 | 
			
		||||
                    stack.push (tmp);
 | 
			
		||||
                        stack.push (tmp);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        stringParser.append (code);
 | 
			
		||||
 | 
			
		||||
                    if (optional)
 | 
			
		||||
                        ++optionalCount;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    stringParser.append (code);
 | 
			
		||||
 | 
			
		||||
                if (optional)
 | 
			
		||||
                    ++optionalCount;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
            ExprParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
                Literals& literals, bool argument = false);
 | 
			
		||||
            ///< constructor
 | 
			
		||||
            /// \param argument Parser is used to parse function- or instruction-
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +101,7 @@ namespace Compiler
 | 
			
		|||
            /// \param arguments Each character represents one arguments ('l': integer,
 | 
			
		||||
            /// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
 | 
			
		||||
            /// optional)
 | 
			
		||||
            /// 'x': optional string that will be ignored (die in a fire, MW script compiler!)
 | 
			
		||||
            /// \param invert Store arguments in reverted order.
 | 
			
		||||
            /// \return number of optional arguments
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ namespace Compiler
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType,
 | 
			
		||||
        bool explicitReference) const
 | 
			
		||||
        bool& explicitReference) const
 | 
			
		||||
    {
 | 
			
		||||
        std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ namespace Compiler
 | 
			
		|||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (explicitReference && iter->second.mCodeExplicit==-1)
 | 
			
		||||
            return false;
 | 
			
		||||
            explicitReference = false;
 | 
			
		||||
 | 
			
		||||
        returnType = iter->second.mReturn;
 | 
			
		||||
        argumentType = iter->second.mArguments;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ namespace Compiler
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool Extensions::isInstruction (int keyword, std::string& argumentType,
 | 
			
		||||
        bool explicitReference) const
 | 
			
		||||
        bool& explicitReference) const
 | 
			
		||||
    {
 | 
			
		||||
        std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ namespace Compiler
 | 
			
		|||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (explicitReference && iter->second.mCodeExplicit==-1)
 | 
			
		||||
            return false;
 | 
			
		||||
            explicitReference = false;
 | 
			
		||||
 | 
			
		||||
        argumentType = iter->second.mArguments;
 | 
			
		||||
        return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,13 +47,17 @@ namespace Compiler
 | 
			
		|||
            /// - keyword must be all lower case.
 | 
			
		||||
 | 
			
		||||
            bool isFunction (int keyword, char& returnType, std::string& argumentType,
 | 
			
		||||
                bool explicitReference) const;
 | 
			
		||||
                bool& explicitReference) const;
 | 
			
		||||
            ///< Is this keyword registered with a function? If yes, return return and argument
 | 
			
		||||
            /// types.
 | 
			
		||||
            /// \param explicitReference In: has explicit reference; Out: set to false, if
 | 
			
		||||
            /// explicit reference is not available for this instruction.
 | 
			
		||||
 | 
			
		||||
            bool isInstruction (int keyword, std::string& argumentType,
 | 
			
		||||
                bool explicitReference) const;
 | 
			
		||||
                bool& explicitReference) const;
 | 
			
		||||
            ///< Is this keyword registered with a function? If yes, return argument types.
 | 
			
		||||
            /// \param explicitReference In: has explicit reference; Out: set to false, if
 | 
			
		||||
            /// explicit reference is not available for this instruction.
 | 
			
		||||
 | 
			
		||||
            void registerFunction (const std::string& keyword, char returnType,
 | 
			
		||||
                const std::string& argumentType, int code, int codeExplicit = -1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ namespace Compiler
 | 
			
		|||
                opcodeAiEscortCellExplicit);
 | 
			
		||||
            extensions.registerInstruction ("aiwander", "fff/llllllllll", opcodeAiWander,
 | 
			
		||||
                opcodeAiWanderExplicit);
 | 
			
		||||
            extensions.registerInstruction ("aifollow", "cffff/l", opcodeAiFollow,
 | 
			
		||||
            extensions.registerInstruction ("aifollow", "cffff/llllllll", opcodeAiFollow,
 | 
			
		||||
                opcodeAiFollowExplicit);
 | 
			
		||||
            extensions.registerInstruction ("aifollowcell", "ccffff/l", opcodeAiFollowCell,
 | 
			
		||||
                opcodeAiFollowCellExplicit);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ namespace Compiler
 | 
			
		|||
            extensions.registerInstruction ("toggleai", "", opcodeToggleAI, opcodeToggleAI);
 | 
			
		||||
            extensions.registerInstruction ("tai", "", opcodeToggleAI, opcodeToggleAI);
 | 
			
		||||
            extensions.registerInstruction("startcombat", "c", opcodeStartCombat, opcodeStartCombatExplicit);
 | 
			
		||||
            extensions.registerInstruction("stopcombat", "", opcodeStopCombat, opcodeStopCombatExplicit);
 | 
			
		||||
            extensions.registerInstruction("stopcombat", "x", opcodeStopCombat, opcodeStopCombatExplicit);
 | 
			
		||||
            extensions.registerFunction ("gethello", 'l', "", opcodeGetHello, opcodeGetHelloExplicit);
 | 
			
		||||
            extensions.registerFunction ("getfight", 'l', "", opcodeGetFight, opcodeGetFightExplicit);
 | 
			
		||||
            extensions.registerFunction ("getflee", 'l', "", opcodeGetFlee, opcodeGetFleeExplicit);
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +190,7 @@ namespace Compiler
 | 
			
		|||
            extensions.registerInstruction ("enableclassmenu", "", opcodeEnableClassMenu);
 | 
			
		||||
            extensions.registerInstruction ("enablenamemenu", "", opcodeEnableNameMenu);
 | 
			
		||||
            extensions.registerInstruction ("enableracemenu", "", opcodeEnableRaceMenu);
 | 
			
		||||
            extensions.registerInstruction ("enablestatreviewmenu", "", 
 | 
			
		||||
            extensions.registerInstruction ("enablestatreviewmenu", "",
 | 
			
		||||
                opcodeEnableStatsReviewMenu);
 | 
			
		||||
 | 
			
		||||
            extensions.registerInstruction ("enableinventorymenu", "", opcodeEnableInventoryMenu);
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +253,7 @@ namespace Compiler
 | 
			
		|||
            extensions.registerFunction ("getlocked", 'l', "", opcodeGetLocked, opcodeGetLockedExplicit);
 | 
			
		||||
            extensions.registerFunction ("geteffect", 'l', "S", opcodeGetEffect, opcodeGetEffectExplicit);
 | 
			
		||||
            extensions.registerInstruction ("addsoulgem", "cc", opcodeAddSoulGem, opcodeAddSoulGemExplicit);
 | 
			
		||||
            extensions.registerInstruction ("removesoulgem", "c", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
 | 
			
		||||
            extensions.registerInstruction ("removesoulgem", "c/l", opcodeRemoveSoulGem, opcodeRemoveSoulGemExplicit);
 | 
			
		||||
            extensions.registerInstruction ("drop", "cl", opcodeDrop, opcodeDropExplicit);
 | 
			
		||||
            extensions.registerInstruction ("dropsoulgem", "c", opcodeDropSoulGem, opcodeDropSoulGemExplicit);
 | 
			
		||||
            extensions.registerFunction ("getattacked", 'l', "", opcodeGetAttacked, opcodeGetAttackedExplicit);
 | 
			
		||||
| 
						 | 
				
			
			@ -276,6 +276,8 @@ namespace Compiler
 | 
			
		|||
            extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode);
 | 
			
		||||
            extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation);
 | 
			
		||||
            extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation);
 | 
			
		||||
            extensions.registerFunction ("getpcinjail", 'l', "", opcodeGetPcInJail);
 | 
			
		||||
            extensions.registerFunction ("getpctraveling", 'l', "", opcodeGetPcTraveling);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -396,7 +398,7 @@ namespace Compiler
 | 
			
		|||
            extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel);
 | 
			
		||||
            extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel);
 | 
			
		||||
 | 
			
		||||
            extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
 | 
			
		||||
            extensions.registerInstruction ("addspell", "cx", opcodeAddSpell, opcodeAddSpellExplicit);
 | 
			
		||||
            extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
 | 
			
		||||
                opcodeRemoveSpellExplicit);
 | 
			
		||||
            extensions.registerInstruction ("removespelleffects", "c", opcodeRemoveSpellEffects,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -260,34 +260,34 @@ namespace
 | 
			
		|||
        code.push_back (Compiler::Generator::segment5 (44));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opStoreMemberShort (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opStoreMemberShort (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (59));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 65 : 59));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opStoreMemberLong (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opStoreMemberLong (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (60));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 66 : 60));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opStoreMemberFloat (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opStoreMemberFloat (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (61));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 67 : 61));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opFetchMemberShort (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opFetchMemberShort (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (62));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 68 : 62));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opFetchMemberLong (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opFetchMemberLong (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (63));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 69 : 63));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opFetchMemberFloat (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
    void opFetchMemberFloat (Compiler::Generator::CodeContainer& code, bool global)
 | 
			
		||||
    {
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (64));
 | 
			
		||||
        code.push_back (Compiler::Generator::segment5 (global ? 70 : 64));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opRandom (Compiler::Generator::CodeContainer& code)
 | 
			
		||||
| 
						 | 
				
			
			@ -593,7 +593,7 @@ namespace Compiler
 | 
			
		|||
            else if (offset<0)
 | 
			
		||||
                opJumpBackward (code, -offset);
 | 
			
		||||
            else
 | 
			
		||||
                throw std::logic_error ("inifite loop");
 | 
			
		||||
                throw std::logic_error ("infinite loop");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void jumpOnZero (CodeContainer& code, int offset)
 | 
			
		||||
| 
						 | 
				
			
			@ -738,7 +738,8 @@ namespace Compiler
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        void assignToMember (CodeContainer& code, Literals& literals, char localType,
 | 
			
		||||
            const std::string& name, const std::string& id, const CodeContainer& value, char valueType)
 | 
			
		||||
            const std::string& name, const std::string& id, const CodeContainer& value,
 | 
			
		||||
            char valueType, bool global)
 | 
			
		||||
        {
 | 
			
		||||
            int index = literals.addString (name);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -766,17 +767,17 @@ namespace Compiler
 | 
			
		|||
            {
 | 
			
		||||
                case 'f':
 | 
			
		||||
 | 
			
		||||
                    opStoreMemberFloat (code);
 | 
			
		||||
                    opStoreMemberFloat (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case 's':
 | 
			
		||||
 | 
			
		||||
                    opStoreMemberShort (code);
 | 
			
		||||
                    opStoreMemberShort (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case 'l':
 | 
			
		||||
 | 
			
		||||
                    opStoreMemberLong (code);
 | 
			
		||||
                    opStoreMemberLong (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
| 
						 | 
				
			
			@ -786,7 +787,7 @@ namespace Compiler
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        void fetchMember (CodeContainer& code, Literals& literals, char localType,
 | 
			
		||||
            const std::string& name, const std::string& id)
 | 
			
		||||
            const std::string& name, const std::string& id, bool global)
 | 
			
		||||
        {
 | 
			
		||||
            int index = literals.addString (name);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -800,17 +801,17 @@ namespace Compiler
 | 
			
		|||
            {
 | 
			
		||||
                case 'f':
 | 
			
		||||
 | 
			
		||||
                    opFetchMemberFloat (code);
 | 
			
		||||
                    opFetchMemberFloat (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case 's':
 | 
			
		||||
 | 
			
		||||
                    opFetchMemberShort (code);
 | 
			
		||||
                    opFetchMemberShort (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case 'l':
 | 
			
		||||
 | 
			
		||||
                    opFetchMemberLong (code);
 | 
			
		||||
                    opFetchMemberLong (code, global);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -102,10 +102,12 @@ namespace Compiler
 | 
			
		|||
            const std::string& name);
 | 
			
		||||
 | 
			
		||||
        void assignToMember (CodeContainer& code, Literals& literals, char memberType,
 | 
			
		||||
            const std::string& name, const std::string& id, const CodeContainer& value, char valueType);
 | 
			
		||||
            const std::string& name, const std::string& id, const CodeContainer& value, char valueType, bool global);
 | 
			
		||||
        ///< \param global Member of a global script instead of a script of a reference.
 | 
			
		||||
 | 
			
		||||
        void fetchMember (CodeContainer& code, Literals& literals, char memberType,
 | 
			
		||||
            const std::string& name, const std::string& id);
 | 
			
		||||
            const std::string& name, const std::string& id, bool global);
 | 
			
		||||
        ///< \param global Member of a global script instead of a script of a reference.
 | 
			
		||||
 | 
			
		||||
        void random (CodeContainer& code);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
 | 
			
		||||
#include "lineparser.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "scanner.hpp"
 | 
			
		||||
#include "context.hpp"
 | 
			
		||||
#include "errorhandler.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +10,7 @@
 | 
			
		|||
#include "locals.hpp"
 | 
			
		||||
#include "generator.hpp"
 | 
			
		||||
#include "extensions.hpp"
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
#include "declarationparser.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +50,7 @@ namespace Compiler
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LineParser::LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
    LineParser::LineParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
        Literals& literals, std::vector<Interpreter::Type_Code>& code, bool allowExpression)
 | 
			
		||||
    : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code),
 | 
			
		||||
       mState (BeginState), mExprParser (errorHandler, context, locals, literals),
 | 
			
		||||
| 
						 | 
				
			
			@ -82,33 +84,9 @@ namespace Compiler
 | 
			
		|||
    bool LineParser::parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
        Scanner& scanner)
 | 
			
		||||
    {
 | 
			
		||||
        if (mState==ShortState || mState==LongState || mState==FloatState)
 | 
			
		||||
        if (mState==PotentialEndState)
 | 
			
		||||
        {
 | 
			
		||||
            if (!getContext().canDeclareLocals())
 | 
			
		||||
            {
 | 
			
		||||
                getErrorHandler().error ("local variables can't be declared in this context", loc);
 | 
			
		||||
                SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
                scanner.scan (skip);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            std::string name2 = Misc::StringUtils::lowerCase (name);
 | 
			
		||||
 | 
			
		||||
            char type = mLocals.getType (name2);
 | 
			
		||||
 | 
			
		||||
            if (type!=' ')
 | 
			
		||||
            {
 | 
			
		||||
                /// \todo add option to make re-declared local variables an error
 | 
			
		||||
                getErrorHandler().warning ("can't re-declare local variable", loc);
 | 
			
		||||
                SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
                scanner.scan (skip);
 | 
			
		||||
                mState = EndState;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mLocals.declare (mState==ShortState ? 's' : (mState==LongState ? 'l' : 'f'),
 | 
			
		||||
                name2);
 | 
			
		||||
 | 
			
		||||
            getErrorHandler().warning ("stay string argument (ignoring it)", loc);
 | 
			
		||||
            mState = EndState;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -142,12 +120,13 @@ namespace Compiler
 | 
			
		|||
        if (mState==SetMemberVarState)
 | 
			
		||||
        {
 | 
			
		||||
            mMemberName = name;
 | 
			
		||||
            char type = getContext().getMemberType (mMemberName, mName);
 | 
			
		||||
            std::pair<char, bool> type = getContext().getMemberType (mMemberName, mName);
 | 
			
		||||
 | 
			
		||||
            if (type!=' ')
 | 
			
		||||
            if (type.first!=' ')
 | 
			
		||||
            {
 | 
			
		||||
                mState = SetMemberVarState2;
 | 
			
		||||
                mType = type;
 | 
			
		||||
                mType = type.first;
 | 
			
		||||
                mReferenceMember = type.second;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +219,34 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    bool LineParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
    {
 | 
			
		||||
        if (mState==SetMemberVarState)
 | 
			
		||||
        {
 | 
			
		||||
            mMemberName = loc.mLiteral;
 | 
			
		||||
            std::pair<char, bool> type = getContext().getMemberType (mMemberName, mName);
 | 
			
		||||
 | 
			
		||||
            if (type.first!=' ')
 | 
			
		||||
            {
 | 
			
		||||
                mState = SetMemberVarState2;
 | 
			
		||||
                mType = type.first;
 | 
			
		||||
                mReferenceMember = type.second;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mState==SetPotentialMemberVarState && keyword==Scanner::K_to)
 | 
			
		||||
        {
 | 
			
		||||
            getErrorHandler().warning ("unknown variable (ignoring set instruction)", loc);
 | 
			
		||||
            SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
            scanner.scan (skip);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mState==SetState)
 | 
			
		||||
        {
 | 
			
		||||
            // allow keywords to be used as variable names when assigning a value to a variable.
 | 
			
		||||
            return parseName (loc.mLiteral, loc, scanner);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mState==BeginState || mState==ExplicitState)
 | 
			
		||||
        {
 | 
			
		||||
            switch (keyword)
 | 
			
		||||
| 
						 | 
				
			
			@ -247,13 +254,13 @@ namespace Compiler
 | 
			
		|||
                case Scanner::K_enable:
 | 
			
		||||
 | 
			
		||||
                    Generator::enable (mCode, mLiterals, mExplicit);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    mState = PotentialEndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
                case Scanner::K_disable:
 | 
			
		||||
 | 
			
		||||
                    Generator::disable (mCode, mLiterals, mExplicit);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    mState = PotentialEndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -262,8 +269,15 @@ namespace Compiler
 | 
			
		|||
            {
 | 
			
		||||
                std::string argumentType;
 | 
			
		||||
 | 
			
		||||
                if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState))
 | 
			
		||||
                bool hasExplicit = mState==ExplicitState;
 | 
			
		||||
                if (extensions->isInstruction (keyword, argumentType, hasExplicit))
 | 
			
		||||
                {
 | 
			
		||||
                    if (!hasExplicit && mState==ExplicitState)
 | 
			
		||||
                    {
 | 
			
		||||
                        getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
 | 
			
		||||
                        mExplicit.clear();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true);
 | 
			
		||||
 | 
			
		||||
                    extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
 | 
			
		||||
| 
						 | 
				
			
			@ -287,9 +301,16 @@ namespace Compiler
 | 
			
		|||
                    char returnType;
 | 
			
		||||
                    std::string argumentType;
 | 
			
		||||
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType,
 | 
			
		||||
                        !mExplicit.empty()))
 | 
			
		||||
                    bool hasExplicit = !mExplicit.empty();
 | 
			
		||||
 | 
			
		||||
                    if (extensions->isFunction (keyword, returnType, argumentType, hasExplicit))
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!hasExplicit && !mExplicit.empty())
 | 
			
		||||
                        {
 | 
			
		||||
                            getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
 | 
			
		||||
                            mExplicit.clear();
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        scanner.putbackKeyword (keyword, loc);
 | 
			
		||||
                        parseExpression (scanner, loc);
 | 
			
		||||
                        mState = EndState;
 | 
			
		||||
| 
						 | 
				
			
			@ -299,13 +320,38 @@ namespace Compiler
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mState==ExplicitState)
 | 
			
		||||
        {
 | 
			
		||||
            // drop stray explicit reference
 | 
			
		||||
            getErrorHandler().warning ("stray explicit reference (ignoring it)", loc);
 | 
			
		||||
            mState = BeginState;
 | 
			
		||||
            mExplicit.clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mState==BeginState)
 | 
			
		||||
        {
 | 
			
		||||
            switch (keyword)
 | 
			
		||||
            {
 | 
			
		||||
                case Scanner::K_short: mState = ShortState; return true;
 | 
			
		||||
                case Scanner::K_long: mState = LongState; return true;
 | 
			
		||||
                case Scanner::K_float: mState = FloatState; return true;
 | 
			
		||||
                case Scanner::K_short:
 | 
			
		||||
                case Scanner::K_long:
 | 
			
		||||
                case Scanner::K_float:
 | 
			
		||||
                {
 | 
			
		||||
                    if (!getContext().canDeclareLocals())
 | 
			
		||||
                    {
 | 
			
		||||
                        getErrorHandler().error (
 | 
			
		||||
                            "local variables can't be declared in this context", loc);
 | 
			
		||||
                        SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
                        scanner.scan (skip);
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    DeclarationParser declaration (getErrorHandler(), getContext(), mLocals);
 | 
			
		||||
                    if (declaration.parseKeyword (keyword, loc, scanner))
 | 
			
		||||
                        scanner.scan (declaration);
 | 
			
		||||
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                case Scanner::K_set: mState = SetState; return true;
 | 
			
		||||
                case Scanner::K_messagebox: mState = MessageState; return true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -328,6 +374,24 @@ namespace Compiler
 | 
			
		|||
                    Generator::stopScript (mCode);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
                case Scanner::K_else:
 | 
			
		||||
 | 
			
		||||
                    getErrorHandler().warning ("stay else (ignoring it)", loc);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
                case Scanner::K_endif:
 | 
			
		||||
 | 
			
		||||
                    getErrorHandler().warning ("stay endif (ignoring it)", loc);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
                case Scanner::K_begin:
 | 
			
		||||
 | 
			
		||||
                    getErrorHandler().warning ("stay begin (ignoring it)", loc);
 | 
			
		||||
                    mState = EndState;
 | 
			
		||||
                    return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (mState==SetLocalVarState && keyword==Scanner::K_to)
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +429,8 @@ namespace Compiler
 | 
			
		|||
            std::vector<Interpreter::Type_Code> code;
 | 
			
		||||
            char type = mExprParser.append (code);
 | 
			
		||||
 | 
			
		||||
            Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type);
 | 
			
		||||
            Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type,
 | 
			
		||||
                !mReferenceMember);
 | 
			
		||||
 | 
			
		||||
            mState = EndState;
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -389,7 +454,8 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    bool LineParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
    {
 | 
			
		||||
        if (code==Scanner::S_newline && (mState==EndState || mState==BeginState))
 | 
			
		||||
        if (code==Scanner::S_newline &&
 | 
			
		||||
            (mState==EndState || mState==BeginState || mState==PotentialEndState))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (code==Scanner::S_comma && mState==MessageState)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,11 +20,10 @@ namespace Compiler
 | 
			
		|||
            enum State
 | 
			
		||||
            {
 | 
			
		||||
                BeginState,
 | 
			
		||||
                ShortState, LongState, FloatState,
 | 
			
		||||
                SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState,
 | 
			
		||||
                SetMemberVarState, SetMemberVarState2,
 | 
			
		||||
                MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState,
 | 
			
		||||
                EndState,
 | 
			
		||||
                EndState, PotentialEndState /* may have a stray string argument */,
 | 
			
		||||
                PotentialExplicitState, ExplicitState, MemberState
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +33,7 @@ namespace Compiler
 | 
			
		|||
            State mState;
 | 
			
		||||
            std::string mName;
 | 
			
		||||
            std::string mMemberName;
 | 
			
		||||
            bool mReferenceMember;
 | 
			
		||||
            int mButtons;
 | 
			
		||||
            std::string mExplicit;
 | 
			
		||||
            char mType;
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            LineParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
            LineParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
                Literals& literals, std::vector<Interpreter::Type_Code>& code,
 | 
			
		||||
                bool allowExpression = false);
 | 
			
		||||
            ///< \param allowExpression Allow lines consisting of a naked expression
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@
 | 
			
		|||
#include <ostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    const std::vector<std::string>& Locals::get (char type) const
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +99,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    void Locals::declare (char type, const std::string& name)
 | 
			
		||||
    {
 | 
			
		||||
        get (type).push_back (name);
 | 
			
		||||
        get (type).push_back (Misc::StringUtils::lowerCase (name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Locals::clear()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,8 +203,8 @@ namespace Compiler
 | 
			
		|||
        const int opcodeGetEffectExplicit = 0x20001d0;
 | 
			
		||||
        const int opcodeAddSoulGem = 0x20001f3;
 | 
			
		||||
        const int opcodeAddSoulGemExplicit = 0x20001f4;
 | 
			
		||||
        const int opcodeRemoveSoulGem = 0x20001f5;
 | 
			
		||||
        const int opcodeRemoveSoulGemExplicit = 0x20001f6;
 | 
			
		||||
        const int opcodeRemoveSoulGem = 0x20027;
 | 
			
		||||
        const int opcodeRemoveSoulGemExplicit = 0x20028;
 | 
			
		||||
        const int opcodeDrop = 0x20001f8;
 | 
			
		||||
        const int opcodeDropExplicit = 0x20001f9;
 | 
			
		||||
        const int opcodeDropSoulGem = 0x20001fa;
 | 
			
		||||
| 
						 | 
				
			
			@ -245,6 +245,8 @@ namespace Compiler
 | 
			
		|||
        const int opcodeCastExplicit = 0x2000228;
 | 
			
		||||
        const int opcodeExplodeSpell = 0x2000229;
 | 
			
		||||
        const int opcodeExplodeSpellExplicit = 0x200022a;
 | 
			
		||||
        const int opcodeGetPcInJail = 0x200023e;
 | 
			
		||||
        const int opcodeGetPcTraveling = 0x200023f;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    namespace Sky
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    // Return context
 | 
			
		||||
 | 
			
		||||
    Context& Parser::getContext()
 | 
			
		||||
    const Context& Parser::getContext() const
 | 
			
		||||
    {
 | 
			
		||||
        return mContext;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ namespace Compiler
 | 
			
		|||
        return lowerCase;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Parser::Parser (ErrorHandler& errorHandler, Context& context)
 | 
			
		||||
    Parser::Parser (ErrorHandler& errorHandler, const Context& context)
 | 
			
		||||
    : mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ namespace Compiler
 | 
			
		|||
    class Parser
 | 
			
		||||
    {
 | 
			
		||||
            ErrorHandler& mErrorHandler;
 | 
			
		||||
            Context& mContext;
 | 
			
		||||
            const Context& mContext;
 | 
			
		||||
            bool mOptional;
 | 
			
		||||
            bool mEmpty;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,14 +38,14 @@ namespace Compiler
 | 
			
		|||
            ErrorHandler& getErrorHandler();
 | 
			
		||||
            ///< Return error handler
 | 
			
		||||
 | 
			
		||||
            Context& getContext();
 | 
			
		||||
            const Context& getContext() const;
 | 
			
		||||
            ///< Return context
 | 
			
		||||
 | 
			
		||||
            static std::string toLower (const std::string& name);
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            Parser (ErrorHandler& errorHandler, Context& context);
 | 
			
		||||
            Parser (ErrorHandler& errorHandler, const Context& context);
 | 
			
		||||
            ///< constructor
 | 
			
		||||
 | 
			
		||||
            virtual ~Parser();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										52
									
								
								components/compiler/quickfileparser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								components/compiler/quickfileparser.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
 | 
			
		||||
#include "quickfileparser.hpp"
 | 
			
		||||
 | 
			
		||||
#include "skipparser.hpp"
 | 
			
		||||
#include "scanner.hpp"
 | 
			
		||||
 | 
			
		||||
Compiler::QuickFileParser::QuickFileParser (ErrorHandler& errorHandler, const Context& context,
 | 
			
		||||
    Locals& locals)
 | 
			
		||||
: Parser (errorHandler, context), mDeclarationParser (errorHandler, context, locals)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
bool Compiler::QuickFileParser::parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
    Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
    scanner.scan (skip);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Compiler::QuickFileParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    if (keyword==Scanner::K_end)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (keyword==Scanner::K_short || keyword==Scanner::K_long || keyword==Scanner::K_float)
 | 
			
		||||
    {
 | 
			
		||||
        mDeclarationParser.reset();
 | 
			
		||||
        scanner.putbackKeyword (keyword, loc);
 | 
			
		||||
        scanner.scan (mDeclarationParser);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
    scanner.scan (skip);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Compiler::QuickFileParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
    if (code!=Scanner::S_newline)
 | 
			
		||||
    {
 | 
			
		||||
        SkipParser skip (getErrorHandler(), getContext());
 | 
			
		||||
        scanner.scan (skip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Compiler::QuickFileParser::parseEOF (Scanner& scanner)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								components/compiler/quickfileparser.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								components/compiler/quickfileparser.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
#ifndef COMPILER_QUICKFILEPARSER_H_INCLUDED
 | 
			
		||||
#define COMPILER_QUICKFILEPARSER_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "parser.hpp"
 | 
			
		||||
#include "declarationparser.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    class Locals;
 | 
			
		||||
 | 
			
		||||
    /// \brief File parser variant that ignores everything but variable declarations
 | 
			
		||||
    class QuickFileParser : public Parser
 | 
			
		||||
    {
 | 
			
		||||
            DeclarationParser mDeclarationParser;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            QuickFileParser (ErrorHandler& errorHandler, const Context& context, Locals& locals);
 | 
			
		||||
 | 
			
		||||
            virtual bool parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
                Scanner& scanner);
 | 
			
		||||
            ///< Handle a name token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle a keyword token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle a special character token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual void parseEOF (Scanner& scanner);
 | 
			
		||||
            ///< Handle EOF token.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -370,9 +370,9 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
        if (c=='\n')
 | 
			
		||||
            special = S_newline;
 | 
			
		||||
        else if (c=='(')
 | 
			
		||||
        else if (c=='(' || c=='[') /// \todo option to disable the use of [ as alias for (
 | 
			
		||||
            special = S_open;
 | 
			
		||||
        else if (c==')')
 | 
			
		||||
        else if (c==')' || c==']')  /// \todo option to disable the use of ] as alias for )
 | 
			
		||||
            special = S_close;
 | 
			
		||||
        else if (c=='.')
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    ScriptParser::ScriptParser (ErrorHandler& errorHandler, Context& context,
 | 
			
		||||
    ScriptParser::ScriptParser (ErrorHandler& errorHandler, const Context& context,
 | 
			
		||||
        Locals& locals, bool end)
 | 
			
		||||
    : Parser (errorHandler, context), mOutput (locals),
 | 
			
		||||
      mLineParser (errorHandler, context, locals, mOutput.getLiterals(), mOutput.getCode()),
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ namespace Compiler
 | 
			
		|||
 | 
			
		||||
    bool ScriptParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
 | 
			
		||||
    {
 | 
			
		||||
        if (keyword==Scanner::K_while || keyword==Scanner::K_if)
 | 
			
		||||
        if (keyword==Scanner::K_while || keyword==Scanner::K_if || keyword==Scanner::K_elseif)
 | 
			
		||||
        {
 | 
			
		||||
            mControlParser.reset();
 | 
			
		||||
            if (mControlParser.parseKeyword (keyword, loc, scanner))
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +71,12 @@ namespace Compiler
 | 
			
		|||
        if (code==Scanner::S_newline) // empty line
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if (code==Scanner::S_open) /// \todo Option to switch this off
 | 
			
		||||
        {
 | 
			
		||||
            scanner.putbackSpecial (code, loc);
 | 
			
		||||
            return parseKeyword (Scanner::K_if, loc, scanner);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mLineParser.reset();
 | 
			
		||||
        if (mLineParser.parseSpecial (code, loc, scanner))
 | 
			
		||||
            scanner.scan (mLineParser);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ namespace Compiler
 | 
			
		|||
    class Locals;
 | 
			
		||||
 | 
			
		||||
    // Script parser, to be used in dialogue scripts and as part of FileParser
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    class ScriptParser : public Parser
 | 
			
		||||
    {
 | 
			
		||||
            Output mOutput;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,14 +21,14 @@ namespace Compiler
 | 
			
		|||
            bool mEnd;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
            /// \param end of script is marked by end keyword.
 | 
			
		||||
            ScriptParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
 | 
			
		||||
            ScriptParser (ErrorHandler& errorHandler, const Context& context, Locals& locals,
 | 
			
		||||
                bool end = false);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            void getCode (std::vector<Interpreter::Type_Code>& code) const;
 | 
			
		||||
            ///< store generated code in \æ code.
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            virtual bool parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
                Scanner& scanner);
 | 
			
		||||
            ///< Handle a name token.
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +43,8 @@ namespace Compiler
 | 
			
		|||
            /// \return fetch another token?
 | 
			
		||||
 | 
			
		||||
            virtual void parseEOF (Scanner& scanner);
 | 
			
		||||
            ///< Handle EOF token.  
 | 
			
		||||
            
 | 
			
		||||
            ///< Handle EOF token.
 | 
			
		||||
 | 
			
		||||
            void reset();
 | 
			
		||||
            ///< Reset parser to clean state.
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    SkipParser::SkipParser (ErrorHandler& errorHandler, Context& context)
 | 
			
		||||
    SkipParser::SkipParser (ErrorHandler& errorHandler, const Context& context)
 | 
			
		||||
    : Parser (errorHandler, context)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ namespace Compiler
 | 
			
		|||
    {
 | 
			
		||||
        if (code==Scanner::S_newline)
 | 
			
		||||
            return false;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,13 +8,13 @@ namespace Compiler
 | 
			
		|||
    // \brief Skip parser for skipping a line
 | 
			
		||||
    //
 | 
			
		||||
    // This parser is mainly intended for skipping the rest of a faulty line.
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    class SkipParser : public Parser
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
           
 | 
			
		||||
            SkipParser (ErrorHandler& errorHandler, Context& context);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            SkipParser (ErrorHandler& errorHandler, const Context& context);
 | 
			
		||||
 | 
			
		||||
            virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle an int token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
 | 
			
		||||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals)
 | 
			
		||||
    StringParser::StringParser (ErrorHandler& errorHandler, const Context& context, Literals& literals)
 | 
			
		||||
    : Parser (errorHandler, context), mLiterals (literals), mState (StartState), mSmashCase (false)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,22 +10,22 @@
 | 
			
		|||
namespace Compiler
 | 
			
		||||
{
 | 
			
		||||
    class Literals;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    class StringParser : public Parser
 | 
			
		||||
    {
 | 
			
		||||
            enum State
 | 
			
		||||
            {
 | 
			
		||||
                StartState, CommaState
 | 
			
		||||
            };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            Literals& mLiterals;
 | 
			
		||||
            State mState;
 | 
			
		||||
            std::vector<Interpreter::Type_Code> mCode;
 | 
			
		||||
            bool mSmashCase;
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
        
 | 
			
		||||
            StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals);
 | 
			
		||||
 | 
			
		||||
            StringParser (ErrorHandler& errorHandler, const Context& context, Literals& literals);
 | 
			
		||||
 | 
			
		||||
            virtual bool parseName (const std::string& name, const TokenLoc& loc,
 | 
			
		||||
                Scanner& scanner);
 | 
			
		||||
| 
						 | 
				
			
			@ -35,15 +35,15 @@ namespace Compiler
 | 
			
		|||
            virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
 | 
			
		||||
            ///< Handle a special character token.
 | 
			
		||||
            /// \return fetch another token?
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            void append (std::vector<Interpreter::Type_Code>& code);
 | 
			
		||||
            ///< Append code for parsed string.
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            void smashCase();
 | 
			
		||||
            ///< Transform all scanned strings to lower case
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            void reset();
 | 
			
		||||
            ///< Reset parser to clean state (this includes the smashCase function).    
 | 
			
		||||
            ///< Reset parser to clean state (this includes the smashCase function).
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,33 +50,33 @@ namespace Interpreter
 | 
			
		|||
            virtual void setGlobalFloat (const std::string& name, float value) = 0;
 | 
			
		||||
 | 
			
		||||
            virtual std::vector<std::string> getGlobals () const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual char getGlobalType (const std::string& name) const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual std::string getActionBinding(const std::string& action) const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCName() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCRace() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCClass() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCFaction() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getNPCRank() const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCName() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCRace() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCClass() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCRank() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getPCNextRank() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual int getPCBounty() const = 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            virtual std::string getCurrentCellName() const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual bool isScriptRunning (const std::string& name) const = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -96,17 +96,17 @@ namespace Interpreter
 | 
			
		|||
 | 
			
		||||
            virtual void disable (const std::string& id = "") = 0;
 | 
			
		||||
 | 
			
		||||
            virtual int getMemberShort (const std::string& id, const std::string& name) const = 0;
 | 
			
		||||
            virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual int getMemberLong (const std::string& id, const std::string& name) const = 0;
 | 
			
		||||
            virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual float getMemberFloat (const std::string& id, const std::string& name) const = 0;
 | 
			
		||||
            virtual float getMemberFloat (const std::string& id, const std::string& name, bool global) const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberShort (const std::string& id, const std::string& name, int value) = 0;
 | 
			
		||||
            virtual void setMemberShort (const std::string& id, const std::string& name, int value, bool global) = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberLong (const std::string& id, const std::string& name, int value) = 0;
 | 
			
		||||
            virtual void setMemberLong (const std::string& id, const std::string& name, int value, bool global) = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void setMemberFloat (const std::string& id, const std::string& name, float value)
 | 
			
		||||
            virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global)
 | 
			
		||||
                = 0;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,5 +127,11 @@ op 61: store stack[0] in member float stack[2] of object with ID stack[1]
 | 
			
		|||
op 62: replace stack[0] with member short stack[1] of object with ID stack[0]
 | 
			
		||||
op 63: replace stack[0] with member short stack[1] of object with ID stack[0]
 | 
			
		||||
op 64: replace stack[0] with member short stack[1] of object with ID stack[0]
 | 
			
		||||
opcodes 65-33554431 unused
 | 
			
		||||
op 65: store stack[0] in member short stack[2] of global script with ID stack[1]
 | 
			
		||||
op 66: store stack[0] in member long stack[2] of global script with ID stack[1]
 | 
			
		||||
op 67: store stack[0] in member float stack[2] of global script with ID stack[1]
 | 
			
		||||
op 68: replace stack[0] with member short stack[1] of global script with ID stack[0]
 | 
			
		||||
op 69: replace stack[0] with member short stack[1] of global script with ID stack[0]
 | 
			
		||||
op 70: replace stack[0] with member short stack[1] of global script with ID stack[0]
 | 
			
		||||
opcodes 71-33554431 unused
 | 
			
		||||
opcodes 33554432-67108863 reserved for extensions
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,12 +40,18 @@ namespace Interpreter
 | 
			
		|||
        interpreter.installSegment5 (42, new OpFetchGlobalShort);
 | 
			
		||||
        interpreter.installSegment5 (43, new OpFetchGlobalLong);
 | 
			
		||||
        interpreter.installSegment5 (44, new OpFetchGlobalFloat);
 | 
			
		||||
        interpreter.installSegment5 (59, new OpStoreMemberShort);
 | 
			
		||||
        interpreter.installSegment5 (60, new OpStoreMemberLong);
 | 
			
		||||
        interpreter.installSegment5 (61, new OpStoreMemberFloat);
 | 
			
		||||
        interpreter.installSegment5 (62, new OpFetchMemberShort);
 | 
			
		||||
        interpreter.installSegment5 (63, new OpFetchMemberLong);
 | 
			
		||||
        interpreter.installSegment5 (64, new OpFetchMemberFloat);
 | 
			
		||||
        interpreter.installSegment5 (59, new OpStoreMemberShort (false));
 | 
			
		||||
        interpreter.installSegment5 (60, new OpStoreMemberLong (false));
 | 
			
		||||
        interpreter.installSegment5 (61, new OpStoreMemberFloat (false));
 | 
			
		||||
        interpreter.installSegment5 (62, new OpFetchMemberShort (false));
 | 
			
		||||
        interpreter.installSegment5 (63, new OpFetchMemberLong (false));
 | 
			
		||||
        interpreter.installSegment5 (64, new OpFetchMemberFloat (false));
 | 
			
		||||
        interpreter.installSegment5 (65, new OpStoreMemberShort (true));
 | 
			
		||||
        interpreter.installSegment5 (66, new OpStoreMemberLong (true));
 | 
			
		||||
        interpreter.installSegment5 (67, new OpStoreMemberFloat (true));
 | 
			
		||||
        interpreter.installSegment5 (68, new OpFetchMemberShort (true));
 | 
			
		||||
        interpreter.installSegment5 (69, new OpFetchMemberLong (true));
 | 
			
		||||
        interpreter.installSegment5 (70, new OpFetchMemberFloat (true));
 | 
			
		||||
 | 
			
		||||
        // math
 | 
			
		||||
        interpreter.installSegment5 (9, new OpAddInt<Type_Integer>);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -208,8 +208,12 @@ namespace Interpreter
 | 
			
		|||
 | 
			
		||||
    class OpStoreMemberShort : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpStoreMemberShort (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Integer data = runtime[0].mInteger;
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +222,7 @@ namespace Interpreter
 | 
			
		|||
                index = runtime[2].mInteger;
 | 
			
		||||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
 | 
			
		||||
                runtime.getContext().setMemberShort (id, variable, data);
 | 
			
		||||
                runtime.getContext().setMemberShort (id, variable, data, mGlobal);
 | 
			
		||||
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			@ -228,8 +232,12 @@ namespace Interpreter
 | 
			
		|||
 | 
			
		||||
    class OpStoreMemberLong : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpStoreMemberLong (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Integer data = runtime[0].mInteger;
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +246,7 @@ namespace Interpreter
 | 
			
		|||
                index = runtime[2].mInteger;
 | 
			
		||||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
 | 
			
		||||
                runtime.getContext().setMemberLong (id, variable, data);
 | 
			
		||||
                runtime.getContext().setMemberLong (id, variable, data, mGlobal);
 | 
			
		||||
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			@ -248,8 +256,12 @@ namespace Interpreter
 | 
			
		|||
 | 
			
		||||
    class OpStoreMemberFloat : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpStoreMemberFloat (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Float data = runtime[0].mFloat;
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +270,7 @@ namespace Interpreter
 | 
			
		|||
                index = runtime[2].mInteger;
 | 
			
		||||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
 | 
			
		||||
                runtime.getContext().setMemberFloat (id, variable, data);
 | 
			
		||||
                runtime.getContext().setMemberFloat (id, variable, data, mGlobal);
 | 
			
		||||
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
| 
						 | 
				
			
			@ -268,8 +280,12 @@ namespace Interpreter
 | 
			
		|||
 | 
			
		||||
    class OpFetchMemberShort : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpFetchMemberShort (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Integer index = runtime[0].mInteger;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,15 +294,19 @@ namespace Interpreter
 | 
			
		|||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
 | 
			
		||||
                int value = runtime.getContext().getMemberShort (id, variable);
 | 
			
		||||
                int value = runtime.getContext().getMemberShort (id, variable, mGlobal);
 | 
			
		||||
                runtime[0].mInteger = value;
 | 
			
		||||
            }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class OpFetchMemberLong : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpFetchMemberLong (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Integer index = runtime[0].mInteger;
 | 
			
		||||
| 
						 | 
				
			
			@ -295,15 +315,19 @@ namespace Interpreter
 | 
			
		|||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
 | 
			
		||||
                int value = runtime.getContext().getMemberLong (id, variable);
 | 
			
		||||
                int value = runtime.getContext().getMemberLong (id, variable, mGlobal);
 | 
			
		||||
                runtime[0].mInteger = value;
 | 
			
		||||
            }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class OpFetchMemberFloat : public Opcode0
 | 
			
		||||
    {
 | 
			
		||||
            bool mGlobal;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            OpFetchMemberFloat (bool global) : mGlobal (global) {}
 | 
			
		||||
 | 
			
		||||
            virtual void execute (Runtime& runtime)
 | 
			
		||||
            {
 | 
			
		||||
                Type_Integer index = runtime[0].mInteger;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,7 +336,7 @@ namespace Interpreter
 | 
			
		|||
                std::string variable = runtime.getStringLiteral (index);
 | 
			
		||||
                runtime.pop();
 | 
			
		||||
 | 
			
		||||
                float value = runtime.getContext().getMemberFloat (id, variable);
 | 
			
		||||
                float value = runtime.getContext().getMemberFloat (id, variable, mGlobal);
 | 
			
		||||
                runtime[0].mFloat = value;
 | 
			
		||||
            }
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,13 @@ Allowed options:
 | 
			
		|||
  --script-run arg                      select a file containing a list of
 | 
			
		||||
                                        console commands that is executed on
 | 
			
		||||
                                        startup
 | 
			
		||||
  --new-game [=arg(=1)] (=0)            activate char gen/new game mechanics
 | 
			
		||||
   --script-warn [=arg(=1)] (=1)        handling of warnings when compiling
 | 
			
		||||
                                        scripts
 | 
			
		||||
                                        0 - ignore warning
 | 
			
		||||
                                        1 - show warning but consider script as
 | 
			
		||||
                                        correctly compiled anyway
 | 
			
		||||
                                        2 - treat warnings as errors
 | 
			
		||||
  --skip-menu [=arg(=1)] (=0)           skip main menu on game startup
 | 
			
		||||
  --fs-strict [=arg(=1)] (=0)           strict file system handling (no case
 | 
			
		||||
                                        folding)
 | 
			
		||||
  --encoding arg (=win1252)             Character encoding used in OpenMW game
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue