413 lines
8.1 KiB
C++
413 lines
8.1 KiB
C++
/**
|
|
* @file lscript_scope.h
|
|
* @brief builds nametable and checks scope
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2002-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#ifndef LL_LSCRIPT_SCOPE_H
|
|
#define LL_LSCRIPT_SCOPE_H
|
|
|
|
#include "string_table.h"
|
|
#include "llmap.h"
|
|
#include "lscript_byteformat.h"
|
|
|
|
typedef enum e_lscript_identifier_type
|
|
{
|
|
LIT_INVALID,
|
|
LIT_GLOBAL,
|
|
LIT_VARIABLE,
|
|
LIT_FUNCTION,
|
|
LIT_LABEL,
|
|
LIT_STATE,
|
|
LIT_HANDLER,
|
|
LIT_LIBRARY_FUNCTION,
|
|
LIT_EOF
|
|
} LSCRIPTIdentifierType;
|
|
|
|
const char LSCRIPTFunctionTypeStrings[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
'0',
|
|
'i',
|
|
'f',
|
|
's',
|
|
'k',
|
|
'v',
|
|
'q',
|
|
'l',
|
|
'0'
|
|
};
|
|
|
|
const char * const LSCRIPTListDescription[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"PUSHARGB 0",
|
|
"PUSHARGB 1",
|
|
"PUSHARGB 2",
|
|
"PUSHARGB 3",
|
|
"PUSHARGB 4",
|
|
"PUSHARGB 5",
|
|
"PUSHARGB 6",
|
|
"PUSHARGB 7",
|
|
"PUSHARGB 0"
|
|
};
|
|
|
|
const char * const LSCRIPTTypePush[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"PUSHE",
|
|
"PUSHE",
|
|
"PUSHE",
|
|
"PUSHE",
|
|
"PUSHEV",
|
|
"PUSHEQ",
|
|
"PUSHE",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeReturn[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"LOADP -12",
|
|
"LOADP -12",
|
|
"STORES -12\nPOP",
|
|
"STORES -12\nPOP",
|
|
"LOADVP -20",
|
|
"LOADQP -24",
|
|
"LOADLP -12",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypePop[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"POP",
|
|
"POP",
|
|
"POPS",
|
|
"POPS",
|
|
"POPV",
|
|
"POPQ",
|
|
"POPL",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeDuplicate[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"DUP",
|
|
"DUP",
|
|
"DUPS",
|
|
"DUPS",
|
|
"DUPV",
|
|
"DUPQ",
|
|
"DUPL",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeLocalStore[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"STORE ",
|
|
"STORE ",
|
|
"STORES ",
|
|
"STORES ",
|
|
"STOREV ",
|
|
"STOREQ ",
|
|
"STOREL ",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeLocalDeclaration[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"STOREP ",
|
|
"STOREP ",
|
|
"STORESP ",
|
|
"STORESP ",
|
|
"STOREVP ",
|
|
"STOREQP ",
|
|
"STORELP ",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeGlobalStore[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"STOREG ",
|
|
"STOREG ",
|
|
"STORESG ",
|
|
"STORESG ",
|
|
"STOREGV ",
|
|
"STOREGQ ",
|
|
"STORELG ",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeLocalPush[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"PUSH ",
|
|
"PUSH ",
|
|
"PUSHS ",
|
|
"PUSHS ",
|
|
"PUSHV ",
|
|
"PUSHQ ",
|
|
"PUSHL ",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeLocalPush1[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"PUSHARGI 1",
|
|
"PUSHARGF 1",
|
|
"undefined",
|
|
"undefined",
|
|
"undefined",
|
|
"undefined",
|
|
"undefined",
|
|
"undefined"
|
|
};
|
|
|
|
const char * const LSCRIPTTypeGlobalPush[LST_EOF] = /*Flawfinder: ignore*/
|
|
{
|
|
"INVALID",
|
|
"PUSHG ",
|
|
"PUSHG ",
|
|
"PUSHGS ",
|
|
"PUSHGS ",
|
|
"PUSHGV ",
|
|
"PUSHGQ ",
|
|
"PUSHGL ",
|
|
"undefined"
|
|
};
|
|
|
|
class LLScriptSimpleAssignable;
|
|
|
|
class LLScriptArgString
|
|
{
|
|
public:
|
|
LLScriptArgString() : mString(NULL) {}
|
|
~LLScriptArgString() { delete [] mString; }
|
|
|
|
LSCRIPTType getType(S32 count)
|
|
{
|
|
if (!mString)
|
|
return LST_NULL;
|
|
S32 length = (S32)strlen(mString); /*Flawfinder: ignore*/
|
|
if (count >= length)
|
|
{
|
|
return LST_NULL;
|
|
}
|
|
switch(mString[count])
|
|
{
|
|
case 'i':
|
|
return LST_INTEGER;
|
|
case 'f':
|
|
return LST_FLOATINGPOINT;
|
|
case 's':
|
|
return LST_STRING;
|
|
case 'k':
|
|
return LST_KEY;
|
|
case 'v':
|
|
return LST_VECTOR;
|
|
case 'q':
|
|
return LST_QUATERNION;
|
|
case 'l':
|
|
return LST_LIST;
|
|
default:
|
|
return LST_NULL;
|
|
}
|
|
}
|
|
|
|
void addType(LSCRIPTType type)
|
|
{
|
|
S32 count = 0;
|
|
if (mString)
|
|
{
|
|
count = (S32)strlen(mString); /*Flawfinder: ignore*/
|
|
char *temp = new char[count + 2];
|
|
memcpy(temp, mString, count); /*Flawfinder: ignore*/
|
|
delete [] mString;
|
|
mString = temp;
|
|
mString[count + 1] = 0;
|
|
}
|
|
else
|
|
{
|
|
mString = new char[count + 2];
|
|
mString[count + 1] = 0;
|
|
}
|
|
mString[count++] = LSCRIPTFunctionTypeStrings[type];
|
|
}
|
|
|
|
S32 getNumber()
|
|
{
|
|
if (mString)
|
|
return (S32)strlen(mString); /*Flawfinder: ignore*/
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
char *mString;
|
|
};
|
|
|
|
class LLScriptScopeEntry
|
|
{
|
|
public:
|
|
LLScriptScopeEntry(const char *identifier, LSCRIPTIdentifierType idtype, LSCRIPTType type, S32 count = 0)
|
|
: mIdentifier(identifier), mIDType(idtype), mType(type), mOffset(0), mSize(0), mAssignable(NULL), mCount(count), mLibraryNumber(0)
|
|
{
|
|
}
|
|
|
|
~LLScriptScopeEntry() {}
|
|
|
|
const char *mIdentifier;
|
|
LSCRIPTIdentifierType mIDType;
|
|
LSCRIPTType mType;
|
|
S32 mOffset;
|
|
S32 mSize;
|
|
LLScriptSimpleAssignable *mAssignable;
|
|
S32 mCount; // NOTE: Index for locals in CIL.
|
|
U16 mLibraryNumber;
|
|
LLScriptArgString mFunctionArgs;
|
|
LLScriptArgString mLocals;
|
|
};
|
|
|
|
class LLScriptScope
|
|
{
|
|
public:
|
|
LLScriptScope(LLStringTable *stable)
|
|
: mParentScope(NULL), mSTable(stable), mFunctionCount(0), mStateCount(0)
|
|
{
|
|
}
|
|
|
|
~LLScriptScope()
|
|
{
|
|
mEntryMap.deleteAllData();
|
|
}
|
|
|
|
LLScriptScopeEntry *addEntry(const char *identifier, LSCRIPTIdentifierType idtype, LSCRIPTType type)
|
|
{
|
|
const char *name = mSTable->addString(identifier);
|
|
if (!mEntryMap.checkData(name))
|
|
{
|
|
if (idtype == LIT_FUNCTION)
|
|
mEntryMap[name] = new LLScriptScopeEntry(name, idtype, type, mFunctionCount++);
|
|
else if (idtype == LIT_STATE)
|
|
mEntryMap[name] = new LLScriptScopeEntry(name, idtype, type, mStateCount++);
|
|
else
|
|
mEntryMap[name] = new LLScriptScopeEntry(name, idtype, type);
|
|
return mEntryMap[name];
|
|
}
|
|
else
|
|
{
|
|
// identifier already exists at this scope
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
BOOL checkEntry(const char *identifier)
|
|
{
|
|
const char *name = mSTable->addString(identifier);
|
|
if (mEntryMap.checkData(name))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// identifier already exists at this scope
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
LLScriptScopeEntry *findEntry(const char *identifier)
|
|
{
|
|
const char *name = mSTable->addString(identifier);
|
|
LLScriptScope *scope = this;
|
|
|
|
while (scope)
|
|
{
|
|
if (scope->mEntryMap.checkData(name))
|
|
{
|
|
// cool, we found it at this scope
|
|
return scope->mEntryMap[name];
|
|
}
|
|
scope = scope->mParentScope;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LLScriptScopeEntry *findEntryTyped(const char *identifier, LSCRIPTIdentifierType idtype)
|
|
{
|
|
const char *name = mSTable->addString(identifier);
|
|
LLScriptScope *scope = this;
|
|
|
|
while (scope)
|
|
{
|
|
if (scope->mEntryMap.checkData(name))
|
|
{
|
|
// need to check type, and if type is function we need to check both types
|
|
if (idtype == LIT_FUNCTION)
|
|
{
|
|
if (scope->mEntryMap[name]->mIDType == LIT_FUNCTION)
|
|
{
|
|
return scope->mEntryMap[name];
|
|
}
|
|
else if (scope->mEntryMap[name]->mIDType == LIT_LIBRARY_FUNCTION)
|
|
{
|
|
return scope->mEntryMap[name];
|
|
}
|
|
}
|
|
else if (scope->mEntryMap[name]->mIDType == idtype)
|
|
{
|
|
// cool, we found it at this scope
|
|
return scope->mEntryMap[name];
|
|
}
|
|
}
|
|
scope = scope->mParentScope;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void addParentScope(LLScriptScope *scope)
|
|
{
|
|
mParentScope = scope;
|
|
}
|
|
|
|
LLMap<const char *, LLScriptScopeEntry *> mEntryMap;
|
|
LLScriptScope *mParentScope;
|
|
LLStringTable *mSTable;
|
|
S32 mFunctionCount;
|
|
S32 mStateCount;
|
|
};
|
|
|
|
extern LLStringTable *gScopeStringTable;
|
|
|
|
|
|
|
|
#endif
|