Files
SingularityViewer/indra/lscript/lscript_compile/lscript_scope.h
2010-04-02 02:48:44 -03:00

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