diff options
| author | Dave Hiller <daveh@lindenlab.com> | 2008-07-31 12:15:15 +0000 | 
|---|---|---|
| committer | Dave Hiller <daveh@lindenlab.com> | 2008-07-31 12:15:15 +0000 | 
| commit | 9a7d68cfce5f71cf9d89536431d72941dc369749 (patch) | |
| tree | f7e0ce093abef0fcc7737cac63bc2a8dbf11b729 | |
| parent | f0f2a416911ba8de9ac1e08cd90720c0d789bb2e (diff) | |
svn merge -r93014:93396 svn+ssh://svn.lindenlab.com/svn/linden/branches/mono-r93014-qar633 dataserver-is-deprecated
52 files changed, 3576 insertions, 1109 deletions
| diff --git a/etc/message.xml b/etc/message.xml index f6f43bd0ff..80dc5607c0 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -449,6 +449,14 @@  					<key>trusted-sender</key>  					<boolean>false</boolean>  				</map> +				 +				<key>LandStatReply</key> +				<map> +					<key>flavor</key> +					<string>llsd</string> +					<key>trusted-sender</key> +					<boolean>false</boolean> +				</map>  				<key>StartGroupProposal</key>  				<map> @@ -493,7 +501,7 @@  			<boolean>false</boolean>  			<key>UpdateScriptAgentInventory</key> -			<boolean>true</boolean> +			<boolean>false</boolean>  			<key>UpdateGestureTaskInventory</key>  			<boolean>false</boolean> @@ -502,7 +510,7 @@  			<boolean>true</boolean>  			<key>UpdateScriptTaskInventory</key> -			<boolean>true</boolean> +			<boolean>false</boolean>  			<key>ViewerStartAuction</key>  			<boolean>true</boolean> diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 22f6c5bd42..27ba04558e 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -17,6 +17,7 @@ set(cmake_SOURCE_FILES      CURL.cmake      CMakeCopyIfDifferent.cmake      CopyWinLibs.cmake +    CSharpMacros.cmake      DirectX.cmake      ELFIO.cmake      EXPAT.cmake @@ -25,6 +26,7 @@ set(cmake_SOURCE_FILES      FindCARes.cmake      FindELFIO.cmake      FindGooglePerfTools.cmake +    FindMono.cmake      FindMySQL.cmake      FindOpenJPEG.cmake      FindXmlRpcEpi.cmake @@ -55,6 +57,7 @@ set(cmake_SOURCE_FILES      LLXML.cmake      LScript.cmake      Linking.cmake +    MonoEmbed.cmake      Mozlib.cmake      MySQL.cmake      NDOF.cmake diff --git a/indra/cmake/CSharpMacros.cmake b/indra/cmake/CSharpMacros.cmake new file mode 100644 index 0000000000..a4dd815043 --- /dev/null +++ b/indra/cmake/CSharpMacros.cmake @@ -0,0 +1,142 @@ +# - This is a support module for easy Mono/C# handling with CMake +# It defines the following macros: +# +# ADD_CS_LIBRARY (<target> <source>) +# ADD_CS_EXECUTABLE (<target> <source>) +# INSTALL_GAC (<target>) +# +# Note that the order of the arguments is important. +# +# You can optionally set the variable CS_FLAGS to tell the macros whether +# to pass additional flags to the compiler. This is particularly useful to +# set assembly references, unsafe code, etc... These flags are always reset +# after the target was added so you don't have to care about that. +# +# copyright (c) 2007 Arno Rehn arno@arnorehn.de +# +# Redistribution and use is allowed according to the terms of the GPL license. + + +# ----- support macros ----- +MACRO(GET_CS_LIBRARY_TARGET_DIR) +        IF (NOT LIBRARY_OUTPUT_PATH) +                SET(CS_LIBRARY_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) +        ELSE (NOT LIBRARY_OUTPUT_PATH) +                SET(CS_LIBRARY_TARGET_DIR ${LIBRARY_OUTPUT_PATH}) +        ENDIF (NOT LIBRARY_OUTPUT_PATH) +ENDMACRO(GET_CS_LIBRARY_TARGET_DIR) + +MACRO(GET_CS_EXECUTABLE_TARGET_DIR) +        IF (NOT EXECUTABLE_OUTPUT_PATH) +                SET(CS_EXECUTABLE_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) +        ELSE (NOT EXECUTABLE_OUTPUT_PATH) +                SET(CS_EXECUTABLE_TARGET_DIR ${EXECUTABLE_OUTPUT_PATH}) +        ENDIF (NOT EXECUTABLE_OUTPUT_PATH) +ENDMACRO(GET_CS_EXECUTABLE_TARGET_DIR) + +MACRO(MAKE_PROPER_FILE_LIST) +        FOREACH(file ${ARGN}) +                # first assume it's a relative path +                FILE(GLOB globbed ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +                IF(globbed) +                        FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file} native) +                ELSE(globbed) +                        FILE(TO_NATIVE_PATH ${file} native) +                ENDIF(globbed) +                SET(proper_file_list ${proper_file_list} ${native}) +                SET(native "") +        ENDFOREACH(file) +ENDMACRO(MAKE_PROPER_FILE_LIST) +# ----- end support macros ----- + +MACRO(ADD_CS_LIBRARY target) +        GET_CS_LIBRARY_TARGET_DIR() +         +        SET(target_DLL "${CS_LIBRARY_TARGET_DIR}/${target}.dll") +        MAKE_PROPER_FILE_LIST(${ARGN}) +        FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_DLL}) +         +        SET(target_KEY "${CMAKE_CURRENT_SOURCE_DIR}/${target}.key") +        SET(target_CS_FLAGS "${CS_FLAGS}") +        IF(${target}_CS_FLAGS) +                LIST(APPEND target_CS_FLAGS ${${target}_CS_FLAGS}) +        ENDIF(${target}_CS_FLAGS) +        IF(EXISTS ${target_KEY}) +                LIST(APPEND target_CS_FLAGS -keyfile:${target_KEY}) +        ENDIF(EXISTS ${target_KEY}) + +        FOREACH(ref ${${target}_REFS}) +                SET(ref_DLL ${CMAKE_CURRENT_BINARY_DIR}/${ref}.dll) +                IF(EXISTS ${ref_DLL}) +                        LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) +                ELSE(EXISTS ${ref_DLL}) +                        LIST(APPEND target_CS_FLAGS -r:${ref}) +                ENDIF(EXISTS ${ref_DLL}) +        ENDFOREACH(ref ${${target}_REFS}) + +        ADD_CUSTOM_COMMAND (OUTPUT ${target_DLL} +                COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_DLL} -target:library ${proper_file_list} +                MAIN_DEPENDENCY ${proper_file_list} +                DEPENDS ${ARGN} +                COMMENT "Building ${relative_path}") +        ADD_CUSTOM_TARGET (${target} ALL DEPENDS ${target_DLL}) + +        FOREACH(ref ${${target}_REFS}) +                GET_TARGET_PROPERTY(is_target ${ref} TYPE) +                IF(is_target) +                        ADD_DEPENDENCIES(${target} ${ref}) +                ENDIF(is_target) +        ENDFOREACH(ref ${${target}_REFS}) + +        SET(relative_path "") +        SET(proper_file_list "") +ENDMACRO(ADD_CS_LIBRARY) + +MACRO(ADD_CS_EXECUTABLE target) +        GET_CS_EXECUTABLE_TARGET_DIR() +         +        # Seems like cmake doesn't like the ".exe" ending for custom commands. +        # If we call it ${target}.exe, 'make' will later complain about a missing rule. +        # Create a fake target instead. +        SET(target_EXE "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe") +        SET(target_TOUCH "${CS_EXECUTABLE_TARGET_DIR}/${target}.exe-built") +        GET_DIRECTORY_PROPERTY(clean ADDITIONAL_MAKE_CLEAN_FILES) +        LIST(APPEND clean ${target}.exe) +        SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${clean}") +        MAKE_PROPER_FILE_LIST(${ARGN}) +        FILE(RELATIVE_PATH relative_path ${CMAKE_BINARY_DIR} ${target_EXE}) +        SET(target_CS_FLAGS "${CS_FLAGS}") +         +        FOREACH(ref ${${target}_REFS}) +                SET(ref_DLL ${CMAKE_CURRENT_SOURCE_DIR}/${ref}.dll) +                IF(EXISTS ${ref_DLL}) +                        LIST(APPEND target_CS_FLAGS -r:${ref_DLL}) +                ELSE(EXISTS ${ref_DLL}) +                        LIST(APPEND target_CS_FLAGS -r:${ref}) +                ENDIF(EXISTS ${ref_DLL}) +        ENDFOREACH(ref ${${target}_REFS}) + +        ADD_CUSTOM_COMMAND (OUTPUT "${target_TOUCH}" +                COMMAND ${MCS_EXECUTABLE} ${target_CS_FLAGS} -out:${target_EXE} ${proper_file_list} +                COMMAND ${CMAKE_COMMAND} -E touch ${target_TOUCH} +                MAIN_DEPENDENCY ${ARGN} +                DEPENDS ${ARGN} +                COMMENT "Building ${relative_path}") +        ADD_CUSTOM_TARGET ("${target}" ALL DEPENDS "${target_TOUCH}") + +        FOREACH(ref ${${target}_REFS}) +                GET_TARGET_PROPERTY(is_target ${ref} TYPE) +                IF(is_target) +                        ADD_DEPENDENCIES(${target} ${ref}) +                ENDIF(is_target) +        ENDFOREACH(ref ${${target}_REFS}) + +        SET(relative_path "") +        SET(proper_file_list "") +ENDMACRO(ADD_CS_EXECUTABLE) + +MACRO(INSTALL_GAC target) +        GET_CS_LIBRARY_TARGET_DIR() +         +        INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${GACUTIL_EXECUTABLE} -i ${CS_LIBRARY_TARGET_DIR}/${target}.dll -package 2.0)") +ENDMACRO(INSTALL_GAC target) diff --git a/indra/cmake/CopyBackToSource.cmake b/indra/cmake/CopyBackToSource.cmake new file mode 100644 index 0000000000..d217df9aec --- /dev/null +++ b/indra/cmake/CopyBackToSource.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +# Copies a binary back to the source directory + +MACRO(COPY_BACK_TO_SOURCE target) +   GET_TARGET_PROPERTY(FROM ${target} LOCATION) +   SET(TO ${CMAKE_CURRENT_SOURCE_DIR}) +   #MESSAGE("TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO}") +   ADD_CUSTOM_COMMAND( +        TARGET ${target} POST_BUILD +        COMMAND ${CMAKE_COMMAND} -E copy ${FROM} ${TO} +        DEPENDS ${FROM} +        COMMENT "Copying ${target} to ${CMAKE_CURRENT_BINARY_DIR}" +        ) +ENDMACRO(COPY_BACK_TO_SOURCE) + + diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake new file mode 100644 index 0000000000..f0a0705481 --- /dev/null +++ b/indra/cmake/FindMono.cmake @@ -0,0 +1,68 @@ +# - Try to find the mono, mcs, gmcs and gacutil +# +# defines +# +# MONO_FOUND - system has mono, mcs, gmcs and gacutil +# MONO_PATH - where to find 'mono' +# MCS_PATH - where to find 'mcs' +# GMCS_PATH - where to find 'gmcs' +# GACUTIL_PATH - where to find 'gacutil' +# +# copyright (c) 2007 Arno Rehn arno@arnorehn.de +# +# Redistribution and use is allowed according to the terms of the GPL license. +# Removed the check for gmcs + +FIND_PROGRAM (MONO_EXECUTABLE mono +             "C:/Program Files/Mono-1.9.1/bin" +             "C:/Program Files/Mono-1.2.6/bin" +             /bin +             /usr/bin +             /usr/local/bin +) +FIND_PROGRAM (MCS_EXECUTABLE mcs +             "C:/Program Files/Mono-1.9.1/bin" +             "C:/Program Files/Mono-1.2.6/bin" +             /bin +             /usr/bin +             /usr/local/bin +) +FIND_PROGRAM (GMCS_EXECUTABLE gmcs +             "C:/Program Files/Mono-1.9.1/bin" +             "C:/Program Files/Mono-1.2.6/bin" +             /bin +             /usr/bin +             /usr/local/bin +) +FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil +             "C:/Program Files/Mono-1.9.1/bin" +             "C:/Program Files/Mono-1.2.6/bin" +             /bin +             /usr/bin +             /usr/local/bin +) +FIND_PROGRAM (ILASM_EXECUTABLE +             ilasm +             NO_DEFAULT_PATH +             PATHS "C:/Program Files/Mono-1.9.1/bin" "C:/Apps/Mono-1.2.6/bin" "C:/Program Files/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin +) + +SET (MONO_FOUND FALSE) + +IF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) +        SET (MONO_FOUND TRUE) +ENDIF (MONO_EXECUTABLE AND MCS_EXECUTABLE AND GACUTIL_EXECUTABLE) + +IF (MONO_FOUND) +        IF (NOT Mono_FIND_QUIETLY) +                MESSAGE(STATUS "Found mono: ${MONO_EXECUTABLE}") +                MESSAGE(STATUS "Found mcs: ${MCS_EXECUTABLE}") +                MESSAGE(STATUS "Found gacutil: ${GACUTIL_EXECUTABLE}") +        ENDIF (NOT Mono_FIND_QUIETLY) +ELSE (MONO_FOUND) +        IF (Mono_FIND_REQUIRED) +                MESSAGE(FATAL_ERROR "Could not find one or more of the following programs: mono, mcs, gacutil") +        ENDIF (Mono_FIND_REQUIRED) +ENDIF (MONO_FOUND) + +MARK_AS_ADVANCED(MONO_EXECUTABLE MCS_EXECUTABLE GACUTIL_EXECUTABLE) diff --git a/indra/cmake/LScript.cmake b/indra/cmake/LScript.cmake index 227e4aaeda..86bfcb7440 100644 --- a/indra/cmake/LScript.cmake +++ b/indra/cmake/LScript.cmake @@ -3,11 +3,14 @@  set(LSCRIPT_INCLUDE_DIRS      ${LIBS_OPEN_DIR}/lscript      ${LIBS_OPEN_DIR}/lscript/lscript_compile -    ${LIBS_OPEN_DIR}/lscript/lscript_execute +    ${LIBS_OPEN_DIR}/lscript/lscript_execute     +    ${LIBS_OPEN_DIR}/lscript/lscript_execute_mono      )  set(LSCRIPT_LIBRARIES      lscript_compile -    lscript_execute +    lscript_execute          lscript_library      ) + +set(LSCRIPT_EXECUTE_MONO_LIBRARIES lscript_execute_mono)
\ No newline at end of file diff --git a/indra/cmake/MonoDeps.cmake b/indra/cmake/MonoDeps.cmake new file mode 100644 index 0000000000..52d5491563 --- /dev/null +++ b/indra/cmake/MonoDeps.cmake @@ -0,0 +1,48 @@ +# -*- cmake -*- + +set(MONO_PREBUILT_LIBRARIES_DIR ${LIBS_PREBUILT_DIR}/mono/1.0) + +set(MONO_PREBUILT_LIBRARIES +     Iesi.Collections.dll +     Iesi.Collections.pdb +     Mono.CompilerServices.SymbolWriter.dll +     Mono.PEToolkit.dll +     Mono.PEToolkit.pdb +     Mono.Security.dll +     PEAPI.dll +     RAIL.dll +     RAIL.pdb +  ) +   +  set(MONO_CORE_LIBRARIES +    System.dll +    System.Xml.dll +    mscorlib.dll) +     +if(WINDOWS) +    set(MONO_DEPENDENCIES +        DomainCreator +        DomainRegister +        LslLibrary +        LslUserScript +        Script +        ScriptTypes +        TestFormat +        UserScript +        UThread +        UThreadInjector +        ) +else(WINDOWS) +    set(MONO_DEPENDENCIES +        DomainCreator_POST_BUILD +        DomainRegister_POST_BUILD +        LslLibrary_POST_BUILD +        LslUserScript_POST_BUILD +        Script_POST_BUILD +        ScriptTypes_POST_BUILD +        TestFormat_POST_BUILD +        UserScript_POST_BUILD +        UThread_POST_BUILD +        UThreadInjector_POST_BUILD +        ) +endif(WINDOWS) diff --git a/indra/cmake/MonoEmbed.cmake b/indra/cmake/MonoEmbed.cmake new file mode 100644 index 0000000000..a310cd9bac --- /dev/null +++ b/indra/cmake/MonoEmbed.cmake @@ -0,0 +1,57 @@ +# -*- cmake -*- + +include(Prebuilt) +use_prebuilt_binary(libmono) + +SET(GLIB_2_0 glib-2.0) + +if (WINDOWS) +    SET(MONO_LIB mono)  +else (WINDOWS) +    SET(MONO_LIB mono) +    SET(M_LIBRARIES m) +    SET(GTHREAD_2_0 gthread-2.0) +endif(WINDOWS) + + +IF (DARWIN) + +  FIND_LIBRARY(MONO_LIBRARY NAMES Mono) +  # Find_file doesnt work as expected. Hardcode relative to Mono.framework.  +  #FIND_FILE(GLIB_CONFIG glibconfig.h ${MONO_LIBRARY}) +  #FIND_FILE(MONO_GLIB_LIBRARY glib.h ${MONO_LIBRARY}) +  SET(MONO_GLIB_LIBRARY ${MONO_LIBRARY}/Headers/glib-2.0/) +  SET(GLIB_CONFIG ${MONO_LIBRARY}/Libraries/glib-2.0/include/) +  SET(MONO_LIB_DIRECTORY ${MONO_LIBRARY}/Libraries) + +  IF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) +    MESSAGE("-- Found Mono for embedding") +    INCLUDE_DIRECTORIES(${MONO_GLIB_LIBRARY} ${GLIB_CONFIG}) +    LINK_DIRECTORIES(${MONO_LIB_DIRECTORY}) +  ELSE (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) +    MESSAGE("-- Mono not found for embedding")    +    MESSAGE(${MONO_LIBRARY}) +    MESSAGE(${MONO_GLIB_LIBRARY}) +    MESSAGE(${GLIB_CONFIG}) +  ENDIF (MONO_LIBRARY AND MONO_GLIB_LIBRARY AND GLIB_CONFIG) + +ELSE (DARWIN) + +  SET(MONO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)   +  SET(GLIB_2_0_PLATFORM_INCLUDE_DIR +    ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0) +  SET(GLIB_2_0_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/glib-2.0) + +  INCLUDE_DIRECTORIES( +    ${MONO_INCLUDE_DIR}  +    ${GLIB_2_0_PLATFORM_INCLUDE_DIR}  +    ${GLIB_2_0_INCLUDE_DIR}) +     +ENDIF (DARWIN)  + +SET(MONO_LIBRARIES  +    ${MONO_LIB}  +    ${M_LIBRARIES}  +    ${GLIB_2_0} +    ${GTHREAD_2_0}  +) diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 368c85acb0..08dcef2538 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -128,7 +128,7 @@ const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] =  	"jpeg",  	"animatn",  	"gesture", -	"simstate", +	"simstate"  };  // This table is meant for decoding to human readable form. Put any @@ -158,7 +158,7 @@ const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] =  	"jpeg image",  	"animation",  	"gesture", -	"simstate", +	"simstate"  };  ///---------------------------------------------------------------------------- diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h index a82996b852..45c4fa986b 100644 --- a/indra/llcommon/llstatenums.h +++ b/indra/llcommon/llstatenums.h @@ -63,7 +63,8 @@ enum  	LL_SIM_STAT_SIMPHYSICSSTEPMS,  	LL_SIM_STAT_SIMPHYSICSSHAPEMS,  	LL_SIM_STAT_SIMPHYSICSOTHERMS, -	LL_SIM_STAT_SIMPHYSICSMEMORY +	LL_SIM_STAT_SIMPHYSICSMEMORY, +	LL_SIM_STAT_SCRIPT_EPS,  };  #endif diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 2937edd853..7a6add6282 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -122,7 +122,7 @@ namespace  	{  	public:  		RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {} -		virtual ~RawInjector() {} +		virtual ~RawInjector() {delete mData;}  		const char* contentType() { return "application/octet-stream"; } @@ -153,16 +153,21 @@ namespace  			LLBufferStream ostream(channels, buffer.get());  			llifstream fstream(mFilename, std::iostream::binary | std::iostream::out); -            fstream.seekg(0, std::ios::end); -            U32 fileSize = fstream.tellg(); -            fstream.seekg(0, std::ios::beg); -			char* fileBuffer; -			fileBuffer = new char [fileSize]; -            fstream.read(fileBuffer, fileSize); -            ostream.write(fileBuffer, fileSize); -			fstream.close(); -			eos = true; -			return STATUS_DONE; +			if(fstream.is_open()) +			{ +				fstream.seekg(0, std::ios::end); +				U32 fileSize = fstream.tellg(); +				fstream.seekg(0, std::ios::beg); +				char* fileBuffer; +				fileBuffer = new char [fileSize]; +				fstream.read(fileBuffer, fileSize); +				ostream.write(fileBuffer, fileSize); +				fstream.close(); +				eos = true; +				return STATUS_DONE; +			} +			 +			return STATUS_ERROR;  		}  		const std::string mFilename; @@ -402,7 +407,7 @@ void LLHTTPClient::post(const std::string& url, const LLSD& body, ResponderPtr r  	request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout);  } -void LLHTTPClient::post(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout) +void LLHTTPClient::postRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout)  {  	request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout);  } diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index 57895aeec9..af79662be9 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -72,8 +72,12 @@ public:  	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);  	static void post(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); -	static void post(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); + +	/** Takes ownership of data and deletes it when sent */ +	static void postRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +	  	static void postFile(const std::string& url, const std::string& filename, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +	#  	static void postFile(const std::string& url, const LLUUID& uuid,  		LLAssetType::EType asset_type, ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index aa9964d46b..972a184a62 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -94,8 +94,8 @@ const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27);  const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);  const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29); -const U32 REGION_FLAGS_DENY_AGEUNVERIFIED		= (1 << 30); - +const U32 REGION_FLAGS_DENY_AGEUNVERIFIED	= (1 << 30); +const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS	= (1 << 31);  const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |  								 REGION_FLAGS_ALLOW_SET_HOME | diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index b7d0267423..5fb3708859 100755 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -71,14 +71,20 @@ LLSD getLLSD(const LLSD& input, const char* block, const char* var, S32 blocknum  	}  	if(! input[block].isArray())  	{ -		llerrs << "block " << block << " not found" << llendl; +		// NOTE: babbage: need to return default for missing blocks to allow +		// backwards/forwards compatibility - handlers must cope with default +		// values. +		llwarns << "block " << block << " not found" << llendl;  		return LLSD();  	}  	LLSD result = input[block][blocknum][var];   	if(result.isUndefined())  	{ -		llerrs << "var " << var << " not found" << llendl; +		// NOTE: babbage: need to return default for missing vars to allow +		// backwards/forwards compatibility - handlers must cope with default +		// values. +		llwarns << "var " << var << " not found" << llendl;  	}  	return result;  } diff --git a/indra/lscript/CMakeLists.txt b/indra/lscript/CMakeLists.txt index d3e3dc1103..c655aef4d9 100644 --- a/indra/lscript/CMakeLists.txt +++ b/indra/lscript/CMakeLists.txt @@ -11,7 +11,8 @@ set(lscript_HEADER_FILES      lscript_rt_interface.h      ) -add_subdirectory (lscript_compile) -add_subdirectory (lscript_execute) -add_subdirectory (lscript_library) +add_subdirectory(lscript_compile) +add_subdirectory(lscript_execute) + +add_subdirectory(lscript_library) diff --git a/indra/lscript/lscript_byteconvert.h b/indra/lscript/lscript_byteconvert.h index 89f3cc4a21..b5e09602c7 100644 --- a/indra/lscript/lscript_byteconvert.h +++ b/indra/lscript/lscript_byteconvert.h @@ -415,7 +415,7 @@ inline void set_fault(const U8 *stream, LSCRIPTRunTimeFaults fault)  			reset_hp_to_safe_spot(stream);  //		    lsa_print_heap((U8 *)stream);  	   } -       fr = LSCRIPTRunTimeFaultBits[fault]; +       fr = fault;         set_register((U8 *)stream, LREG_FR, fr);     }  } diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index 6edf2b740d..474e8a67a6 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -512,26 +512,12 @@ typedef enum e_lscript_runtime_faults  	LSRF_CHAT_OVERRUN,  	LSRF_TOO_MANY_LISTENS,  	LSRF_NESTING_LISTS, +	LSRF_CLI,  	LSRF_EOF  } LSCRIPTRunTimeFaults;  extern const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF]; 	/*Flawfinder: ignore*/ -const S32 LSCRIPTRunTimeFaultBits[LSRF_EOF] = -{ -	0,		//	LSRF_INVALID -	1,		//	LSRF_MATH -	2,		//	LSRF_STACK_HEAP_COLLISION -	3,		//	LSREF_BOUND_CHECK_ERROR -	4,		//	LSREF_HEAP_ERROR -	5,		//	LSREF_VERSION_MISMATCH -	6,		//	LSREF_MISSING_INVENTORY -	7,		//	LSRF_SANDBOX -	8,		//	LSRF_CHAT_OVERRUN -	9,		//	LSRF_TOO_MANY_LISTENS -	10,		//	LSRF_NESTING_LISTS -}; -  typedef enum e_lscript_runtime_permissions  {  	SCRIPT_PERMISSION_DEBIT, diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 14f8acb551..09008379a2 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -676,7 +676,7 @@ int yyerror(const char *fmt, ...)  //#define EMIT_CIL_ASSEMBLER  BOOL lscript_compile(const char* src_filename, const char* dst_filename, -					 const char* err_filename, BOOL is_god_like) +					 const char* err_filename, BOOL compile_to_mono, const char* class_name, BOOL is_god_like)  {  	BOOL			b_parse_ok = FALSE;  	BOOL			b_dummy = FALSE; @@ -718,6 +718,8 @@ BOOL lscript_compile(const char* src_filename, const char* dst_filename,  			}  			gScriptp->mGodLike = is_god_like; +			 +			gScriptp->setClassName(class_name);  			gScopeStringTable = new LLStringTable(16384);  #ifdef EMERGENCY_DEBUG_PRINTOUTS @@ -733,34 +735,25 @@ BOOL lscript_compile(const char* src_filename, const char* dst_filename,  #ifdef EMERGENCY_DEBUG_PRINTOUTS  				gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_ASSEMBLY, LSPRUNE_INVALID,  b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);  #endif -#ifdef EMIT_CIL_ASSEMBLER -				const char* cil_output_file_name = dst_filename? dst_filename : "lscript.cil"; -				LLFILE* cilout = LLFile::fopen(cil_output_file_name, "w"); -				if(NULL == cilout) +				if(TRUE == compile_to_mono)  				{ -					fprintf(yyout, "Error opening cil output file %s\n", cil_output_file_name); +					gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_CIL_ASSEMBLY, LSPRUNE_INVALID,  b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);  				}  				else  				{ -					gScriptp->recurse(cilout, 0, 0, LSCP_EMIT_CIL_ASSEMBLY, LSPRUNE_INVALID,  b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL); -					if(fclose(cilout) == EOF) -					{ -						fprintf(yyout, "Error closing cil output file %s\n", cil_output_file_name); -					} +					gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_BYTE_CODE, LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);  				} -#endif -				gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_BYTE_CODE, LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);  			}  			delete gScopeStringTable;  			gScopeStringTable = NULL;  #ifdef EMERGENCY_DEBUG_PRINTOUTS  			fclose(compfile);  #endif +			fclose(yyout);  		} -		fclose(yyout); +		fclose(yyin);  	} -	fclose(yyin);  	delete gAllocationManager;  	delete gScopeStringTable; @@ -768,13 +761,15 @@ BOOL lscript_compile(const char* src_filename, const char* dst_filename,  } -BOOL lscript_compile(char *filename, BOOL is_god_like = FALSE) +BOOL lscript_compile(char *filename, BOOL compile_to_mono, BOOL is_god_like = FALSE)  {  	char src_filename[MAX_STRING];  	sprintf(src_filename, "%s.lsl", filename);  	char err_filename[MAX_STRING];  	sprintf(err_filename, "%s.out", filename); -	return lscript_compile(src_filename, NULL, err_filename, is_god_like); +	char class_name[MAX_STRING]; +	sprintf(class_name, "%s", filename); +	return lscript_compile(src_filename, NULL, err_filename, compile_to_mono, class_name, is_god_like);  } diff --git a/indra/lscript/lscript_compile/lscript_error.cpp b/indra/lscript/lscript_compile/lscript_error.cpp index 309eb07dc2..5299d8c7e9 100644 --- a/indra/lscript/lscript_compile/lscript_error.cpp +++ b/indra/lscript/lscript_compile/lscript_error.cpp @@ -72,7 +72,10 @@ const char* gErrorText[LSERROR_EOF] = 	/*Flawfinder: ignore*/  	"Use of vector or quaternion method on incorrect type",  	"Lists can't be included in lists",  	"Unitialized variables can't be included in lists", -	"Declaration requires a new scope -- use { and }" +	"Declaration requires a new scope -- use { and }", +	"CIL assembler failed", +	"Bytecode transformer failed", +	"Bytecode verification failed"  };  void LLScriptGenerateErrorText::writeWarning(LLFILE *fp, LLScriptFilePosition *pos, LSCRIPTWarnings warning) @@ -98,3 +101,8 @@ void LLScriptGenerateErrorText::writeError(LLFILE *fp, S32 line, S32 col, LSCRIP  	fprintf(fp, "(%d, %d) : ERROR : %s\n", line, col, gErrorText[error]);  	mTotalErrors++;  } + +std::string getLScriptErrorString(LSCRIPTErrors error) +{ +	return gErrorText[error]; +} diff --git a/indra/lscript/lscript_compile/lscript_error.h b/indra/lscript/lscript_compile/lscript_error.h index 8c9e35d56b..50276c2006 100644 --- a/indra/lscript/lscript_compile/lscript_error.h +++ b/indra/lscript/lscript_compile/lscript_error.h @@ -124,6 +124,9 @@ typedef enum e_lscript_errors  	LSERROR_NO_LISTS_IN_LISTS,  	LSERROR_NO_UNITIALIZED_VARIABLES_IN_LISTS,  	LSERROR_NEED_NEW_SCOPE, +	LSERROR_CIL_ASSEMBLER_FAILED = 16, // Mono build error. +	LSERROR_BYTECODE_TRANSFORM_FAILED = 17, // Mono build error. +	LSERROR_BYTECODE_VERIFICATION_FAILED, // Mono build error.  	LSERROR_EOF  } LSCRIPTErrors; @@ -147,6 +150,8 @@ public:  	S32 mTotalWarnings;  }; +std::string getLScriptErrorString(LSCRIPTErrors error); +  extern LLScriptGenerateErrorText gErrorToText;  #endif diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp index 3a93f7b896..aabf0a3c38 100644 --- a/indra/lscript/lscript_compile/lscript_tree.cpp +++ b/indra/lscript/lscript_compile/lscript_tree.cpp @@ -43,7 +43,8 @@  //#define LSL_INCLUDE_DEBUG_INFO -void print_cil_box(LLFILE* fp, LSCRIPTType type) + +static void print_cil_box(LLFILE* fp, LSCRIPTType type)  {  	switch(type)  	{ @@ -51,24 +52,28 @@ void print_cil_box(LLFILE* fp, LSCRIPTType type)  		fprintf(fp, "box [mscorlib]System.Int32\n");  		break;  	case LST_FLOATINGPOINT: -		fprintf(fp, "box [mscorlib]System.Double\n"); +		fprintf(fp, "box [mscorlib]System.Single\n");  		break;  	case LST_STRING: +		// System.String is not a System.ValueType, +		// so does not need to be boxed. +		break;  	case LST_KEY: -		fprintf(fp, "box [mscorlib]System.String\n"); +		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Key\n");  		break;  	case LST_VECTOR: -		fprintf(fp, "box [LScriptLibrary]LLVector\n"); +		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Vector\n");  		break;  	case LST_QUATERNION: -		fprintf(fp, "box [LScriptLibrary]LLQuaternion\n"); +		fprintf(fp, "box [ScriptTypes]LindenLab.SecondLife.Quaternion\n");  		break;  	default: +		llassert(false);  		break;  	}  } -void print_cil_type(LLFILE* fp, LSCRIPTType type) +static void print_cil_type(LLFILE* fp, LSCRIPTType type)  {  	switch(type)  	{ @@ -79,14 +84,16 @@ void print_cil_type(LLFILE* fp, LSCRIPTType type)  		fprintf(fp, "float32");  		break;  	case LST_STRING: -	case LST_KEY:  		fprintf(fp, "string"); +		break;		 +	case LST_KEY: +		fprintf(fp, "valuetype [ScriptTypes]LindenLab.SecondLife.Key");  		break;  	case LST_VECTOR: -		fprintf(fp, "valuetype [LScriptLibrary]LLVector"); +		fprintf(fp, "class [ScriptTypes]LindenLab.SecondLife.Vector");  		break;  	case LST_QUATERNION: -		fprintf(fp, "valuetype [LScriptLibrary]LLQuaternion"); +		fprintf(fp, "class [ScriptTypes]LindenLab.SecondLife.Quaternion");  		break;  	case LST_LIST:  		fprintf(fp, "class [mscorlib]System.Collections.ArrayList"); @@ -189,6 +196,7 @@ void LLScriptConstantInteger::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		fprintf(fp, "ldc.i4 %d\n", mValue); +		type = mType;  		break;  	default:  		break; @@ -236,7 +244,13 @@ void LLScriptConstantFloat::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		fprintf(fp, "ldc.r8 %5.5f\n", mValue); // NOTE: Precision? +	        { +		        double v = (double)mValue; +			U8 * p = (U8 *)&v; // See ECMA-335 Partition VI, Appendix C.4.6 Examples, line 4 +			fprintf(fp, "ldc.r8 (%02x %02x %02x %02x %02x %02x %02x %02x)\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); +			type = mType; +		} +		break;  	default:  		break;  	} @@ -247,16 +261,34 @@ S32 LLScriptConstantFloat::getSize()  	return LSCRIPTDataSize[LST_FLOATINGPOINT];  } -void print_escape_quotes(LLFILE* fp, const char* str) +void print_escaped(LLFILE* fp, const char* str)  {    putc('"', fp);    for(const char* c = str; *c != '\0'; ++c)    { -	  if(*c == '"') +	  switch(*c)  	  { -		  putc('\\', fp); +	  case '"': +		putc('\\', fp); +		putc(*c, fp); +		break; +	  case '\n': +		putc('\\', fp); +		putc('n', fp); +		break; +	  case '\t': +		putc(' ', fp); +		putc(' ', fp); +		putc(' ', fp); +		putc(' ', fp); +		break; +	  case '\\': +		putc('\\', fp); +		putc('\\', fp); +		break; +	  default: +		putc(*c, fp);  	  } -	  putc(*c, fp);    }    putc('"', fp);  } @@ -293,7 +325,7 @@ void LLScriptConstantString::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  	case LSCP_TO_STACK:  		{  			chunk->addByte(LSCRIPTOpCodes[LOPC_PUSHARGS]); -			chunk->addBytes(mValue, (S32)strlen(mValue) + 1);	 	/*Flawfinder: ignore*/ +			chunk->addBytes(mValue, (S32)strlen(mValue) + 1);  			type = mType;  		}  		break; @@ -304,7 +336,7 @@ void LLScriptConstantString::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		fprintf(fp, "ldstr "); -		print_escape_quotes(fp, mValue); +		print_escaped(fp, mValue);  		fprintf(fp, "\n");  	default:  		break; @@ -313,10 +345,9 @@ void LLScriptConstantString::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  S32 LLScriptConstantString::getSize()  { -	return (S32)strlen(mValue) + 1;		/*Flawfinder: ignore*/ +	return (S32)strlen(mValue) + 1;  } -  void LLScriptIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -388,7 +419,7 @@ void LLScriptIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		fprintf(fp, "%s", mName); +		fprintf(fp, "'%s'", mName);  		break;  	default:  		break; @@ -428,6 +459,12 @@ S32 LLScriptSimpleAssignable::getSize()  	return 0;  } +static void print_cil_member(LLFILE* fp, LLScriptIdentifier *ident) +{ +	print_cil_type(fp, ident->mScopeEntry->mType); +	fprintf(fp, " %s::'%s'\n", gScriptp->getClassName(), ident->mScopeEntry->mIdentifier); +} +  void LLScriptSAIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -497,6 +534,19 @@ void LLScriptSAIdentifier::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			}  		}  		break; + +	case LSCP_EMIT_CIL_ASSEMBLY: +		{ +			fprintf(fp, "ldarg.0\n"); +			fprintf(fp, "ldfld "); +			print_cil_member(fp, mIdentifier); +			fprintf(fp, "\n"); +			if (mNextp) +			{ +				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			} +			break; +		}  	default:  		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		if (mNextp) @@ -553,7 +603,8 @@ S32 LLScriptSAConstant::getSize()  	return mConstant->getSize();  } -void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType) + +static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  {  	switch(srcType)  	{ @@ -567,9 +618,8 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  			fprintf(fp, "call string class [mscorlib]System.Convert::ToString(int32)\n");  			break;  		case LST_LIST: -			fprintf(fp, "box [mscorlib]System.Int32\n"); -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::CreateList()\n"); -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(object, class [mscorlib]System.Collections.ArrayList)\n"); +			print_cil_box(fp, LST_INTEGER); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		default:  			break; @@ -582,10 +632,11 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  			fprintf(fp, "conv.i4\n");  			break;  		case LST_STRING: -			fprintf(fp, "call string class [mscorlib]System.Convert::ToString(float32)\n"); +			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");  			break;  		case LST_LIST: -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n"); +			print_cil_box(fp, LST_FLOATINGPOINT); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		default:  			break; @@ -595,19 +646,22 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  		switch(targetType)  		{  		case LST_INTEGER: -			fprintf(fp, "call int32 valuetype [mscorlib]System.Int32::Parse(string)\n"); +			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::StringToInt(string)\n");  			break;  		case LST_FLOATINGPOINT: -			fprintf(fp, "call float64 valuetype [mscorlib]System.Double::Parse(string)\n"); +			fprintf(fp, "call float32 [LslLibrary]LindenLab.SecondLife.LslRunTime::StringToFloat(string)\n");  			break; +		case LST_KEY: +			fprintf(fp, "call valuetype [ScriptTypes]LindenLab.SecondLife.Key class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateKey'(string)\n"); +			break;	  		case LST_LIST: -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n"); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		case LST_VECTOR: -			fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'Parse'(string)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'ParseVector'(string)\n");  			break;  		case LST_QUATERNION: -			fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'Parse'(string)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'ParseQuaternion'(string)\n");  			break;  		default:  			break; @@ -619,9 +673,11 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  		case LST_KEY:  			break;  		case LST_STRING: +			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Key)\n");  			break;  		case LST_LIST: -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n"); +			print_cil_box(fp, LST_KEY); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		default:  			break; @@ -633,10 +689,11 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  		case LST_VECTOR:  			break;  		case LST_STRING: -			fprintf(fp, "call string valuetype [LScriptLibrary]LLVector::'ToString'(valuetype [LScriptLibrary]LLVector)\n"); +			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		case LST_LIST: -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n"); +			print_cil_box(fp, LST_VECTOR); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		default:  			break; @@ -648,10 +705,11 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  		case LST_QUATERNION:  			break;  		case LST_STRING: -			fprintf(fp, "call string valuetype [LScriptLibrary]LLQuaternion::'ToString'(valuetype [LScriptLibrary]LLQuaternion)\n"); +			fprintf(fp, "call string [LslUserScript]LindenLab.SecondLife.LslUserScript::'ToString'(valuetype [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");  			break;  		case LST_LIST: -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LScriptLibrary]LScriptInternal::CreateList(object)\n"); +			print_cil_box(fp, LST_QUATERNION); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)\n");  			break;  		default:  			break; @@ -663,7 +721,7 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  		case LST_LIST:  			break;  		case LST_STRING: -			fprintf(fp, "call string [LScriptLibrary]LScriptInternal::ListToString(class [mscorlib]System.Collections.ArrayList)\n"); +			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ListToString(class [mscorlib]System.Collections.ArrayList)\n");  			break;  		default:  			break; @@ -674,10 +732,57 @@ void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetType)  	}  } -bool is_SA_constant_integer(LLScriptSimpleAssignable* sa) +static void print_cil_numeric_cast(LLFILE* fp, LSCRIPTType currentArg, LSCRIPTType otherArg)  { -	// HACK: Downcast based on type. -	return (sa->mType == LSSAT_CONSTANT && ((LLScriptSAConstant*) sa)->mConstant->mType == LST_INTEGER); +	if((currentArg == LST_INTEGER) && ((otherArg == LST_FLOATINGPOINT) || (otherArg == LST_VECTOR))) +	{ +		print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT); +	} +} + +static void print_cil_assignment_cast(LLFILE* fp, LSCRIPTType src, +									  LSCRIPTType dest) +{ +	if (LST_STRING == src && LST_KEY == dest) +	{ +		print_cil_cast(fp, src, dest); +	} +	else if(LST_KEY == src && LST_STRING == dest) +	{ +		print_cil_cast(fp, src, dest); +	} +	else +	{ +		print_cil_numeric_cast(fp, src, dest); +	} +} +  +// HACK! Babbage: should be converted to virtual on LSCRIPTSimpleAssignableType to avoid downcasts. +LSCRIPTType get_type(LLScriptSimpleAssignable* sa) +{ +	LSCRIPTType result = LST_NULL; +	switch(sa->mType) +	{ +	case LSSAT_IDENTIFIER: +		result = ((LLScriptSAIdentifier*) sa)->mIdentifier->mScopeEntry->mType; +		break; +	case LSSAT_CONSTANT: +		result = ((LLScriptSAConstant*) sa)->mConstant->mType; +		break; +	case LSSAT_VECTOR_CONSTANT: +		result = LST_VECTOR; +		break; +	case LSSAT_QUATERNION_CONSTANT: +		result = LST_QUATERNION; +		break; +	case LSSAT_LIST_CONSTANT: +		result = LST_LIST; +		break; +	default: +		result = LST_UNDEFINED; +		break; +	} +	return result;  }  void LLScriptSAVector::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata) @@ -786,23 +891,23 @@ void LLScriptSAVector::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		// Load arguments.  		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry1)) +		if(LST_INTEGER == get_type(mEntry1))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry3)) +		if(LST_INTEGER == get_type(mEntry2))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry3)) +		if(LST_INTEGER == get_type(mEntry3))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type. -		fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'create'(float32, float32, float32)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n");  		// Next.  		if (mNextp) @@ -952,28 +1057,28 @@ void LLScriptSAQuaternion::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		// Load arguments.  		mEntry1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry1)) +		if(LST_INTEGER == get_type(mEntry1))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		mEntry2->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry2)) +		if(LST_INTEGER == get_type(mEntry2))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		mEntry3->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry3)) +		if(LST_INTEGER == get_type(mEntry3))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		mEntry4->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if(is_SA_constant_integer(mEntry4)) +		if(LST_INTEGER == get_type(mEntry4))  		{  			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT);  		}  		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type. -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'create'(float32, float32, float32, float32)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n");  		// Next.  		if (mNextp) @@ -1049,6 +1154,40 @@ void LLScriptSAList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  			}  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		{ +			// Create list. +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n"); + +			// Add elements. +			LLScriptSimpleAssignable* current_entry = mEntryList; +			LLScriptSimpleAssignable* next_entry = NULL; +			while(NULL != current_entry) +			{ +				next_entry = current_entry->mNextp; + +				// Null mNextp pointer, so only current list element is processed. +				current_entry->mNextp = NULL; +				current_entry->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + +				// Restore mNextp pointer. +				current_entry->mNextp = next_entry; + +				// Box element and store in list. +				print_cil_box(fp, get_type(current_entry)); +				fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(class [mscorlib]System.Collections.ArrayList, object)\n"); + +				// Process next element. +				current_entry = next_entry; +			} + +			// Process next list. +			if (mNextp) +			{ +				mNextp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			} +		} +		break;  	default:  		if (mEntryList)  			mEntryList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, ldata); @@ -1093,6 +1232,45 @@ void LLScriptGlobalVariable::gonext(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	}  } +// Push initialised variable of type on to stack. +static void print_cil_init_variable(LLFILE* fp, LSCRIPTType type) +{ +	switch(type) +	{ +	case LST_INTEGER: +		fprintf(fp, "ldc.i4.0\n"); +		break; +	case LST_FLOATINGPOINT: +		fprintf(fp, "ldc.r8 0\n"); +		break; +	case LST_STRING: +		fprintf(fp, "ldstr \"\"\n"); +		break; +	case LST_KEY: +		fprintf(fp, "ldstr \"\"\n"); +		fprintf(fp, "call valuetype [ScriptTypes]LindenLab.SecondLife.Key class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateKey'(string)\n"); +		break; +	case LST_VECTOR: +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n"); +		break; +	case LST_QUATERNION: +		fprintf(fp, "ldc.r8 1\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n"); +		break; +	case LST_LIST: +		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n"); +		break; +	default: +		break; +	} +} +  void LLScriptGlobalVariable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -1164,7 +1342,7 @@ void LLScriptGlobalVariable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  			// it also includes the name of the variable as well as the type  			// plus 4 bytes of offset from it's apparent address to the actual data  #ifdef LSL_INCLUDE_DEBUG_INFO -			count += strlen(mIdentifier->mName) + 1 + 1 + 4;	/*Flawfinder: ignore*/ +			count += strlen(mIdentifier->mName) + 1 + 1 + 4;  #else  			count += 1 + 1 + 4;  #endif @@ -1187,7 +1365,7 @@ void LLScriptGlobalVariable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  			chunk->addBytes(&vtype, 1);  			// null terminated name  #ifdef LSL_INCLUDE_DEBUG_INFO -			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);	/*Flawfinder: ignore*/ +			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);  #else  			chunk->addBytes(1);  #endif @@ -1257,16 +1435,27 @@ void LLScriptGlobalVariable::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  	case LSCP_EMIT_CIL_ASSEMBLY:  		// Initialisation inside ctor. +		fprintf(fp, "ldarg.0\n");  		if (mAssignable)  		{ -			fprintf(fp, "ldarg.0\n"); -			mAssignable->recurse(fp, tabs, tabsize, LSCP_EMIT_CIL_ASSEMBLY, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp, "stfld "); -			mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp," LSL::"); -			mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp, "\n"); +			// Initialise to value. +			mAssignable->recurse(fp, tabs, tabsize, LSCP_EMIT_CIL_ASSEMBLY, +								 ptype, prunearg, scope, type, basetype, +								 count, chunk, heap, stacksize, entry, +								 entrycount, NULL); +			print_cil_assignment_cast(fp, get_type(mAssignable), mType->mType); +		} +		else +		{ +			// Initialise to zero. +			print_cil_init_variable(fp, mType->mType);  		} +		// Store value. +		fprintf(fp, "stfld "); +		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp," %s::", gScriptp->getClassName()); +		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, "\n");  		break;  	default:  		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -1298,6 +1487,20 @@ S32 LLScriptEvent::getSize()  	printf("Event Base Class -- should never get here!\n");  	return 0;  } +static void checkForDuplicateHandler(LLFILE *fp, LLScriptFilePosition *pos,  +				     LLScriptScope *scope, +				     const char* name) +{ +    LLScriptScope *parent = scope->mParentScope; +    if (parent->checkEntry((char*)name)) +    { +        gErrorToText.writeError(fp, pos, LSERROR_DUPLICATE_NAME); +    } +    else +    { +        parent->addEntry(((char*)name), LIT_HANDLER, LST_NULL); +    } +}  void LLScriptStateEntryEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  { @@ -1314,11 +1517,14 @@ void LLScriptStateEntryEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  	case LSCP_EMIT_ASSEMBLY:  		fprintf(fp, "state_entry()\n");  		break; +	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "state_entry"); +	        break;  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "state_entry"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; @@ -1347,6 +1553,9 @@ void LLScriptStateExitEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		fdotabs(fp, tabs, tabsize);  		fprintf(fp, "state_exit()\n");  		break; +        case LSCP_SCOPE_PASS1: +                checkForDuplicateHandler(fp, this, scope, "state_exit"); +	        break;  	case LSCP_EMIT_ASSEMBLY:  		fprintf(fp, "state_exit()\n");  		break; @@ -1354,7 +1563,7 @@ void LLScriptStateExitEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "state_exit"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; @@ -1388,6 +1597,7 @@ void LLScriptTouchStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		break;  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "touch_start");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1412,11 +1622,18 @@ void LLScriptTouchStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "touch_start"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "touch_start( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break; +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1446,6 +1663,7 @@ void LLScriptTouchEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		break;  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "touch");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1470,11 +1688,18 @@ void LLScriptTouchEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "touch"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "touch( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break; +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1504,6 +1729,7 @@ void LLScriptTouchEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		break;  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "touch_end");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1528,11 +1754,18 @@ void LLScriptTouchEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "touch_end"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "touch_end( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break; +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1562,6 +1795,7 @@ void LLScriptCollisionStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSC  		break;  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "collision_start");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1586,11 +1820,17 @@ void LLScriptCollisionStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "collision_start"; -			chunk->addBytes(name, (S32)strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, (S32)strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, (S32)strlen(name) + 1); +			chunk->addBytes(mCount->mName, (S32)strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "collision_start( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1620,6 +1860,7 @@ void LLScriptCollisionEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		break;  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "collision");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1644,11 +1885,16 @@ void LLScriptCollisionEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "collision"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "collision( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1678,6 +1924,7 @@ void LLScriptCollisionEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		break;  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "collision_end");  		if (scope->checkEntry(mCount->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1702,11 +1949,17 @@ void LLScriptCollisionEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "collision_end"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mCount->mName, strlen(mCount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "collision_end( int32 "); +		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mCount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1735,6 +1988,7 @@ void LLScriptLandCollisionStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize,  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "land_collision_start");  		if (scope->checkEntry(mPosition->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1759,11 +2013,17 @@ void LLScriptLandCollisionStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize,  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "land_collision_start"; -			chunk->addBytes(name, strlen(name) + 1);		/*Flawfinder: ignore*/ -			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "land_collision_start( class [ScriptTypes]LindenLab.SecondLife.Vector "); +		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1794,6 +2054,7 @@ void LLScriptLandCollisionEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCR  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "land_collision");  		if (scope->checkEntry(mPosition->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1818,11 +2079,17 @@ void LLScriptLandCollisionEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCR  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "land_collision"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "land_collision( class [ScriptTypes]LindenLab.SecondLife.Vector "); +		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1852,6 +2119,7 @@ void LLScriptLandCollisionEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, L  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "land_collision_end");  		if (scope->checkEntry(mPosition->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1875,12 +2143,18 @@ void LLScriptLandCollisionEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, L  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO -			char name[] = "land_collision_end";	/*Flawfinder: ignore*/ -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);	/*Flawfinder: ignore*/ +			char name[] = "land_collision_end"; +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mPosition->mName, strlen(mPosition->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "land_collision_end( class [ScriptTypes]LindenLab.SecondLife.Vector "); +		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1910,6 +2184,7 @@ void LLScriptInventoryEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "changed");  		if (scope->checkEntry(mChange->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1934,11 +2209,17 @@ void LLScriptInventoryEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "changed"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mChange->mName, strlen(mChange->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mChange->mName, strlen(mChange->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "changed( int32 "); +		mChange->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mChange->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -1967,6 +2248,7 @@ void LLScriptAttachEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "attach");  		if (scope->checkEntry(mAttach->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -1991,11 +2273,17 @@ void LLScriptAttachEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "attach"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mAttach->mName, strlen(mAttach->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mAttach->mName, strlen(mAttach->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "attach( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mAttach->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )\n"); +		break;  	default:  		mAttach->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -2026,6 +2314,7 @@ void LLScriptDataserverEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "dataserver");  		if (scope->checkEntry(mID->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2061,12 +2350,20 @@ void LLScriptDataserverEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "dataserver"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mData->mName, strlen(mData->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); +			chunk->addBytes(mData->mName, strlen(mData->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "dataserver( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mData->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mData->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2095,14 +2392,21 @@ void LLScriptTimerEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  	case LSCP_EMIT_ASSEMBLY:  		fprintf(fp, "timer()\n");  		break; +        case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "timer"); +	  break; +  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "timer"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "timer()"); +		break;  	default:  		break;  	} @@ -2126,14 +2430,21 @@ void LLScriptMovingStartEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIP  		fdotabs(fp, tabs, tabsize);  		fprintf(fp, "moving_start()\n");  		break; +        case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "moving_start"); +	  break; +  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "moving_start"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "moving_start()"); +		break;  	default:  		break;  	} @@ -2157,14 +2468,21 @@ void LLScriptMovingEndEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		fdotabs(fp, tabs, tabsize);  		fprintf(fp, "moving_end()\n");  		break; +        case LSCP_SCOPE_PASS1: +          checkForDuplicateHandler(fp, this, scope, "moving_end"); +          break; +  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "moving_end"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "moving_end()"); +		break;  	default:  		break;  	} @@ -2191,6 +2509,7 @@ void LLScriptRTPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "run_time_perms");  		if (scope->checkEntry(mRTPermissions->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2215,11 +2534,18 @@ void LLScriptRTPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "chat"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mRTPermissions->mName, strlen(mRTPermissions->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mRTPermissions->mName, strlen(mRTPermissions->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		// NOTE: Not replicating LSL2 bug by calling RTP event hander "chat" +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "run_time_perms( int32 "); +		mRTPermissions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mRTPermissions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -2254,6 +2580,7 @@ void LLScriptChatEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompil  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +		checkForDuplicateHandler(fp, this, scope, "listen"); // note: this is actually listen in lsl source  		if (scope->checkEntry(mChannel->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2311,14 +2638,26 @@ void LLScriptChatEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompil  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "chat"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mMessage->mName, strlen(mMessage->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1); +			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); +			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); +			chunk->addBytes(mMessage->mName, strlen(mMessage->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "chat( int32 "); +		mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mMessage->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2350,6 +2689,7 @@ void LLScriptSensorEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "sensor");  		if (scope->checkEntry(mNumber->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2374,11 +2714,17 @@ void LLScriptSensorEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "sensor"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "sensor( int32 "); +		mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -2407,6 +2753,7 @@ void LLScriptObjectRezEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "object_rez");  		if (scope->checkEntry(mID->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2431,11 +2778,17 @@ void LLScriptObjectRezEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "sensor"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mID->mName, strlen(mID->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "object_rez( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -2468,6 +2821,7 @@ void LLScriptControlEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "control");  		if (scope->checkEntry(mName->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2514,13 +2868,23 @@ void LLScriptControlEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "control"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mLevels->mName, strlen(mLevels->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mEdges->mName, strlen(mEdges->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); +			chunk->addBytes(mLevels->mName, strlen(mLevels->mName) + 1); +			chunk->addBytes(mEdges->mName, strlen(mEdges->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "control( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mLevels->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mEdges->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mLevels->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2557,6 +2921,7 @@ void LLScriptLinkMessageEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIP  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "link_message");  		if (scope->checkEntry(mSender->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2614,14 +2979,26 @@ void LLScriptLinkMessageEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIP  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "link_message"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mNum->mName, strlen(mNum->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mStr->mName, strlen(mStr->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mID->mName, strlen(mID->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1); +			chunk->addBytes(mNum->mName, strlen(mNum->mName) + 1); +			chunk->addBytes(mStr->mName, strlen(mStr->mName) + 1); +			chunk->addBytes(mID->mName, strlen(mID->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "link_message( int32 "); +		mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mNum->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mStr->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mNum->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2663,6 +3040,7 @@ void LLScriptRemoteEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "remote_event");  		if (scope->checkEntry(mType->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2742,16 +3120,32 @@ void LLScriptRemoteEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "remote_event"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mType->mName, strlen(mType->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mMessageID->mName, strlen(mMessageID->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mIntVal->mName, strlen(mIntVal->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mStrVal->mName, strlen(mStrVal->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mType->mName, strlen(mType->mName) + 1); +			chunk->addBytes(mChannel->mName, strlen(mChannel->mName) + 1); +			chunk->addBytes(mMessageID->mName, strlen(mMessageID->mName) + 1); +			chunk->addBytes(mSender->mName, strlen(mSender->mName) + 1); +			chunk->addBytes(mIntVal->mName, strlen(mIntVal->mName) + 1); +			chunk->addBytes(mStrVal->mName, strlen(mStrVal->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "remote_event( int32 "); +		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mMessageID->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mSender->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mIntVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mStrVal->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mChannel->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2784,7 +3178,7 @@ void LLScriptHTTPResponseEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		mRequestId->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, ", integer ");  		mStatus->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, ", list "); +		fprintf(fp, ", class [mscorlib]System.Collections.ArrayList ");  		mMetadata->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, ", string ");  		mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2792,6 +3186,7 @@ void LLScriptHTTPResponseEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "http_response");  		if (scope->checkEntry(mRequestId->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2857,15 +3252,26 @@ void LLScriptHTTPResponseEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "http_response"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mRequestId->mName, strlen(mRequestId->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mStatus->mName, strlen(mStatus->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mMetadata->mName, strlen(mMetadata->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mRequestId->mName, strlen(mRequestId->mName) + 1); +			chunk->addBytes(mStatus->mName, strlen(mStatus->mName) + 1); +			chunk->addBytes(mMetadata->mName, strlen(mMetadata->mName) + 1); +			chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1);  #endif  		}  		break; -		 +	case LSCP_EMIT_CIL_ASSEMBLY: +	        fdotabs(fp, tabs, tabsize); +   	        fprintf(fp, "http_response( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mRequestId->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mStatus->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", class [mscorlib]System.Collections.ArrayList "); +		mMetadata->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )\n"); +		break;  	default:  		mRequestId->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mStatus->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2900,6 +3306,7 @@ void LLScriptMoneyEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "money");  		if (scope->checkEntry(mName->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -2935,12 +3342,20 @@ void LLScriptMoneyEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "money"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mAmount->mName, strlen(mAmount->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mName->mName, strlen(mName->mName) + 1); +			chunk->addBytes(mAmount->mName, strlen(mAmount->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "money( valuetype [ScriptTypes]LindenLab.SecondLife.Key "); +		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mAmount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mAmount->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -2978,6 +3393,7 @@ void LLScriptEmailEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "email");  		if (scope->checkEntry(mTime->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -3046,15 +3462,29 @@ void LLScriptEmailEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "email"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mTime->mName, strlen(mTime->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mAddress->mName, strlen(mAddress->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mSubject->mName, strlen(mSubject->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mTime->mName, strlen(mTime->mName) + 1); +			chunk->addBytes(mAddress->mName, strlen(mAddress->mName) + 1); +			chunk->addBytes(mSubject->mName, strlen(mSubject->mName) + 1); +			chunk->addBytes(mBody->mName, strlen(mBody->mName) + 1); +			chunk->addBytes(mNumber->mName, strlen(mNumber->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "email( string "); +		mTime->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mAddress->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mSubject->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", string "); +		mBody->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", int32 "); +		mNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mTime->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mAddress->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3087,6 +3517,7 @@ void LLScriptRezEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "rez");  		if (scope->checkEntry(mStartParam->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -3111,11 +3542,17 @@ void LLScriptRezEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "rez"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ -			chunk->addBytes(mStartParam->mName, strlen(mStartParam->mName) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mStartParam->mName, strlen(mStartParam->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "rez( int32 "); +		mStartParam->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mStartParam->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -3143,14 +3580,20 @@ void LLScriptNoSensorEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_ASSEMBLY:  		fprintf(fp, "no_sensor()\n");  		break; -	case LSCP_EMIT_BYTE_CODE: +        case LSCP_SCOPE_PASS1: +     	        checkForDuplicateHandler(fp, this, scope, "no_sensor"); +	        break; +  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "no_sensor"; -			chunk->addBytes(name, strlen(name) + 1); 		/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "no_sensor()"); +		break;  	default:  		break;  	} @@ -3181,6 +3624,7 @@ void LLScriptAtTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "at_target");  		if (scope->checkEntry(mTargetNumber->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -3226,14 +3670,24 @@ void LLScriptAtTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO -			char name[] = "at_target";	/*Flawfinder: ignore*/ -			chunk->addBytes(name, strlen(name) + 1);	/*Flawfinder: ignore*/ -			chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1); 	/*Flawfinder: ignore*/ -			chunk->addBytes(mTargetPosition->mName, strlen(mTargetPosition->mName) + 1); 	/*Flawfinder: ignore*/ -			chunk->addBytes(mOurPosition->mName, strlen(mOurPosition->mName) + 1);		 	/*Flawfinder: ignore*/ +			char name[] = "at_target"; +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1); +			chunk->addBytes(mTargetPosition->mName, strlen(mTargetPosition->mName) + 1); +			chunk->addBytes(mOurPosition->mName, strlen(mOurPosition->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "at_target( int32 "); +		mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", class [ScriptTypes]LindenLab.SecondLife.Vector "); +		mTargetPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", class [ScriptTypes]LindenLab.SecondLife.Vector "); +		mOurPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mTargetPosition->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3265,14 +3719,21 @@ void LLScriptNotAtTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  	case LSCP_EMIT_ASSEMBLY:  		fprintf(fp, "not_at_target()\n");  		break; +        case LSCP_SCOPE_PASS1: +	        checkForDuplicateHandler(fp, this, scope, "not_at_target"); +	        break; +  	case LSCP_EMIT_BYTE_CODE:  		{  #ifdef LSL_INCLUDE_DEBUG_INFO -			char name[] = "not_at_target";	/*Flawfinder: ignore*/ -			chunk->addBytes(name, strlen(name) + 1); 	/*Flawfinder: ignore*/ +			char name[] = "not_at_target"; +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "not_at_target()"); +		break;  	default:  		break;  	} @@ -3294,7 +3755,7 @@ void LLScriptAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  	case LSCP_PRETTY_PRINT:  	case LSCP_EMIT_ASSEMBLY:  		fdotabs(fp, tabs, tabsize); -		fprintf(fp, "at_target( integer "); +		fprintf(fp, "at_rot_target( integer ");  		mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, ", quaternion ");  		mTargetRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3303,6 +3764,7 @@ void LLScriptAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		fprintf(fp, " )\n");  		break;  	case LSCP_SCOPE_PASS1: +		checkForDuplicateHandler(fp, this, scope, "at_rot_target");  		if (scope->checkEntry(mTargetNumber->mName))  		{  			gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME); @@ -3349,13 +3811,23 @@ void LLScriptAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "at_rot_target"; -			chunk->addBytes(name, strlen(name) + 1); 	/*Flawfinder: ignore*/ -			chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1); 	/*Flawfinder: ignore*/ -			chunk->addBytes(mTargetRotation->mName, strlen(mTargetRotation->mName) + 1); 	/*Flawfinder: ignore*/ -			chunk->addBytes(mOurRotation->mName, strlen(mOurRotation->mName) + 1); 	/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1); +			chunk->addBytes(mTargetNumber->mName, strlen(mTargetNumber->mName) + 1); +			chunk->addBytes(mTargetRotation->mName, strlen(mTargetRotation->mName) + 1); +			chunk->addBytes(mOurRotation->mName, strlen(mOurRotation->mName) + 1);  #endif  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +		fdotabs(fp, tabs, tabsize); +		fprintf(fp, "at_rot_target( int32 "); +		mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", class [ScriptTypes]LindenLab.SecondLife.Quaternion "); +		mTargetRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, ", class [ScriptTypes]LindenLab.SecondLife.Quaternion "); +		mOurRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, " )"); +		break;  	default:  		mTargetNumber->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mTargetRotation->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3391,10 +3863,17 @@ void LLScriptNotAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTC  		{  #ifdef LSL_INCLUDE_DEBUG_INFO  			char name[] = "not_at_rot_target"; -			chunk->addBytes(name, strlen(name) + 1);	 	/*Flawfinder: ignore*/ +			chunk->addBytes(name, strlen(name) + 1);  #endif  		}  		break; +        case LSCP_SCOPE_PASS1: +	  checkForDuplicateHandler(fp, this, scope, "not_at_rot_target"); +	  break; + +	case LSCP_EMIT_CIL_ASSEMBLY: +		fprintf(fp, "not_at_rot_target()"); +		break;  	default:  		break;  	} @@ -3563,6 +4042,25 @@ S32 LLScriptForExpressionList::getSize()  	return 0;  } +// CIL code generation requires both caller and callee scope entries, so cannot use normal recurse signature. +// TODO: Refactor general purpose recurse calls in to pass specific virtuals using visitor pattern to select method by pass and node type. +static void print_cil_func_expression_list(LLScriptFuncExpressionList* self, LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata, LLScriptScopeEntry *callee_entry) +{ +	self->mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +	LSCRIPTType argtype = callee_entry->mFunctionArgs.getType(entrycount); +	if (argtype != self->mFirstp->mReturnType) +	{ +		print_cil_cast(fp, self->mFirstp->mReturnType, argtype); +	} +	entrycount++; +	if (self->mSecondp) +	{ +		llassert(LET_FUNC_EXPRESSION_LIST == self->mSecondp->mType); +		print_cil_func_expression_list((LLScriptFuncExpressionList*) self->mSecondp, fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL, callee_entry); + +	} +} +  void LLScriptFuncExpressionList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -3660,31 +4158,6 @@ void LLScriptFuncExpressionList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCR  			}  		}  		break; -	/* TODO: Fix conflict between global/local variable determination needing caller scope and cast determination here needs callee scope... -	case LSCP_EMIT_CIL_ASSEMBLY: -		{ -			mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			LSCRIPTType argtype = entry->mFunctionArgs.getType(entrycount); -			if (argtype != mFirstp->mReturnType) -			{ -				print_cil_cast(fp, mFirstp->mReturnType, argtype); -			} -			entrycount++; -			if (mSecondp) -			{ -				mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -				if (mSecondp->mReturnType) -				{ -					argtype = entry->mFunctionArgs.getType(entrycount); -					if (argtype != mSecondp->mReturnType) -					{ -						print_cil_cast(fp, mFirstp->mReturnType, argtype); -					} -				} -			} -		} -		break; -		*/  	default:  		mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		if (mSecondp) @@ -3753,8 +4226,13 @@ void LLScriptListExpressionList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCR  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		// Evaluate expressions in reverse order so first expression is on top of stack. -		// Results can then be popped and appended to list to result in list with correct order. +		mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		if (mFirstp->mType != LET_LIST_EXPRESSION_LIST) +		{ +			// Box value. +			print_cil_box(fp, mFirstp->mReturnType); +			++count; +		}  		if (mSecondp)  		{  			mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3762,18 +4240,9 @@ void LLScriptListExpressionList::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCR  			{  				// Box value.  				print_cil_box(fp, mSecondp->mReturnType); -  				++count;  			}  		} -		mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		if (mFirstp->mType != LET_LIST_EXPRESSION_LIST) -		{ -			// Box value. -			print_cil_box(fp, mFirstp->mReturnType); - -			++count; -		}  		break;  	default:  		mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -3793,14 +4262,22 @@ S32 LLScriptListExpressionList::getSize()  // Returns true if identifier is a parameter and false if identifier is a local variable within function_scope.  bool is_parameter(LLScriptIdentifier* identifier, LLScriptScopeEntry* function_scope)  { -	// Function offset stores offset of first local. -	// Compare variable offset with function offset to -	// determine whether variable is local or parameter. -	return (identifier->mScopeEntry->mOffset < function_scope->mOffset); +	// Function stores offset of first local. +	if(0 == function_scope->mOffset) +	{ +		// Function offset 0 -> no parameters -> identifier is a local. +		return false; +	} +	else +	{ +		// Compare variable offset with function offset to +		// determine whether variable is local or parameter. +		return (identifier->mScopeEntry->mOffset < function_scope->mOffset); +	}  }  // If assignment is to global variable, pushes this pointer on to stack. -void print_cil_load_address(LLFILE* fp, LLScriptExpression* exp, LLScriptScopeEntry* function_scope) +static void print_cil_load_address(LLFILE* fp, LLScriptExpression* exp, LLScriptScopeEntry* function_scope)  {  	LLScriptLValue *lvalue = (LLScriptLValue *) exp;  	LLScriptIdentifier *ident = lvalue->mIdentifier; @@ -3811,7 +4288,7 @@ void print_cil_load_address(LLFILE* fp, LLScriptExpression* exp, LLScriptScopeEn  		fprintf(fp, "ldarg.0\n");  	} -	// If accessor, load address of object. +	// If accessor, load value type address, consumed by ldfld.  	if(lvalue->mAccessor)  	{  		if(ident->mScopeEntry->mIDType == LIT_VARIABLE) @@ -3819,7 +4296,7 @@ void print_cil_load_address(LLFILE* fp, LLScriptExpression* exp, LLScriptScopeEn  			if(is_parameter(ident, function_scope))  			{  				// Parameter, load by name. -				fprintf(fp, "ldarga.s %s\n", ident->mScopeEntry->mIdentifier); +				fprintf(fp, "ldarga.s '%s'\n", ident->mScopeEntry->mIdentifier);  			}  			else  			{ @@ -3830,13 +4307,13 @@ void print_cil_load_address(LLFILE* fp, LLScriptExpression* exp, LLScriptScopeEn  		else if (ident->mScopeEntry->mIDType == LIT_GLOBAL)  		{  			fprintf(fp, "ldflda "); -			print_cil_type(fp, ident->mScopeEntry->mType); -			fprintf(fp, " LSL::%s\n", ident->mScopeEntry->mIdentifier); +			print_cil_member(fp, ident);  		}  	}  } -void print_cil_accessor(LLFILE* fp, LLScriptLValue *lvalue) +static void print_cil_accessor(LLFILE* fp, LLScriptLValue *lvalue) +  {  	LLScriptIdentifier *ident = lvalue->mIdentifier;  	print_cil_type(fp, lvalue->mReturnType); @@ -3845,12 +4322,6 @@ void print_cil_accessor(LLFILE* fp, LLScriptLValue *lvalue)  	fprintf(fp, "::%s\n", lvalue->mAccessor->mName);  } -void print_cil_member(LLFILE* fp, LLScriptIdentifier *ident) -{ -	print_cil_type(fp, ident->mScopeEntry->mType); -	fprintf(fp, " LSL::%s\n", ident->mScopeEntry->mIdentifier); -} -  void LLScriptLValue::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -4106,7 +4577,7 @@ void LLScriptLValue::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  			if(is_parameter(mIdentifier, entry))  			{  				// Parameter, load by name. -				fprintf(fp, "ldarg.s %s\n", mIdentifier->mScopeEntry->mIdentifier); +				fprintf(fp, "ldarg.s '%s'\n", mIdentifier->mScopeEntry->mIdentifier);  			}  			else  			{ @@ -4136,7 +4607,7 @@ S32 LLScriptLValue::getSize()  	return 0;  } -void print_asignment(LLFILE *fp, LLScriptExpression *exp) +static void print_assignment(LLFILE *fp, LLScriptExpression *exp)  {  	LLScriptLValue *lvalue = (LLScriptLValue *)exp;  	LLScriptIdentifier *ident = lvalue->mIdentifier; @@ -4164,7 +4635,7 @@ void print_asignment(LLFILE *fp, LLScriptExpression *exp)  	}  } -void print_cil_asignment(LLFILE *fp, LLScriptExpression *exp, LLScriptScopeEntry* function_scope) +static void print_cil_assignment(LLFILE *fp, LLScriptExpression *exp, LLScriptScopeEntry* function_scope)  {  	LLScriptLValue *lvalue = (LLScriptLValue *) exp;  	LLScriptIdentifier *ident = lvalue->mIdentifier; @@ -4191,7 +4662,7 @@ void print_cil_asignment(LLFILE *fp, LLScriptExpression *exp, LLScriptScopeEntry  			if(is_parameter(ident, function_scope))  			{  				// Parameter, store by name. -				fprintf(fp, "starg.s %s\n", ident->mScopeEntry->mIdentifier); +				fprintf(fp, "starg.s '%s'\n", ident->mScopeEntry->mIdentifier);  			}  			else  			{ @@ -4319,14 +4790,6 @@ void store2stack(LLScriptExpression *exp, LLScriptExpression *lv, LLScriptByteCo  	chunk->addInteger(address);  } -void print_cil_numeric_cast(LLFILE* fp, LSCRIPTType currentArg, LSCRIPTType otherArg) -{ -	if((currentArg == LST_INTEGER) && (otherArg == LST_FLOATINGPOINT)) -	{ -		print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT); -	} -} -  void LLScriptAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -4344,7 +4807,7 @@ void LLScriptAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		{  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cast(fp, mReturnType, mRightType); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4370,8 +4833,8 @@ void LLScriptAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		{  			print_cil_load_address(fp, mLValue, entry);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			print_cil_numeric_cast(fp, mRightType, mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			print_cil_assignment_cast(fp, mRightType, mReturnType); +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4387,8 +4850,15 @@ S32 LLScriptAssignment::getSize()  	return 0;  } -void print_cil_add(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_add(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  { +	if(LST_LIST == right_type && LST_LIST != left_type) +	{ +		print_cil_box(fp, left_type); +		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(class [mscorlib]System.Collections.ArrayList, object)\n"); +		return; +	} +  	switch(left_type)  	{  	case LST_INTEGER: @@ -4402,27 +4872,49 @@ void print_cil_add(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  	case LST_KEY:  		// String concatenation. -		fprintf(fp, "call string valuetype [mscorlib]System.String::Concat(string, string)"); +		fprintf(fp, "call string valuetype [LslUserScript]LindenLab.SecondLife.LslUserScript::Add(string, string)\n");  		break;  	case LST_VECTOR:  		// Vector addition. -		// TODO: Inline (requires temporary variables, which must be identified in earlier pass). -		fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'add_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Add'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  		break;  	case LST_QUATERNION:  		// Rotation addition. -		// TODO: Inline (requires temporary variables, which must be identified in earlier pass). -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'add_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Add'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");  		break;  	case LST_LIST: -		print_cil_box(fp, right_type); -		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(class [mscorlib]System.Collections.ArrayList, object)\n"); -		break; +		switch(right_type) +		{ +		case LST_LIST: +			// Concatenate lists. +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		case LST_INTEGER: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(int32, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		case LST_FLOATINGPOINT: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(float32, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		case LST_STRING: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(string, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		case LST_KEY: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(valuetype [ScriptTypes]LindenLab.SecondLife.Key, class [mscorlib]System.Collections.ArrayList)\n"); +			break;			 +		case LST_VECTOR: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(valuetype [ScriptTypes]LindenLab.SecondLife.Vector, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		case LST_QUATERNION: +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(valuetype [ScriptTypes]LindenLab.SecondLife.Quaternion, class [mscorlib]System.Collections.ArrayList)\n"); +			break; +		default: +			break; +		}  	default:  		break; @@ -4447,7 +4939,7 @@ void LLScriptAddAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "ADD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4475,12 +4967,12 @@ void LLScriptAddAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_CIL_ASSEMBLY:  		{  			print_cil_load_address(fp, mLValue, entry); -			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType); +			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			print_cil_add(fp, mLValue->mReturnType, mRightSide->mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4496,29 +4988,30 @@ S32 LLScriptAddAssignment::getSize()  	return 0;  } -void print_cil_sub(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_sub(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  {  	switch(left_type)  	{  	case LST_INTEGER: +		if(LST_INTEGER == right_type) +		{	 +			fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)\n"); +			break; +		}  	case LST_FLOATINGPOINT: -  		// Numeric subtraction. -		fprintf(fp, "sub\n"); +		fprintf(fp, "call float64 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(float64, float64)\n");  		break; -	  	case LST_VECTOR:  		// Vector subtraction. -		// TODO: Inline (requires temporary variables, which must be identified in earlier pass). -		fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'subtract_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Subtract'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  		break;  	case LST_QUATERNION:  		// Rotation subtraction. -		// TODO: Inline (requires temporary variables, which must be identified in earlier pass). -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'subtract_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Subtract'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");  		break;  	default: @@ -4546,7 +5039,7 @@ void LLScriptSubAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "SUB %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4574,12 +5067,12 @@ void LLScriptSubAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_CIL_ASSEMBLY:  		{  			print_cil_load_address(fp, mLValue, entry); -			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType); +			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			print_cil_sub(fp, mLValue->mReturnType, mRightSide->mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4595,41 +5088,93 @@ S32 LLScriptSubAssignment::getSize()  	return 0;  } -void print_cil_mul(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_neg(LLFILE* fp, LSCRIPTType type)  { -	switch(left_type) +        switch(type)  	{  	case LST_INTEGER:  	case LST_FLOATINGPOINT: +	  fprintf(fp, "neg\n"); +	  break; +	case LST_VECTOR: +	  fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Negate'(class [ScriptTypes]LindenLab.SecondLife.Vector)\n");	   +	  break; +	case LST_QUATERNION: +	  fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Negate'(class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");	   +	  break; +	default: +	  break; +	} +} -		// Numeric multiplication. -		fprintf(fp, "mul\n"); +static void print_cil_mul(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +{ +	switch(left_type) +	{ +	case LST_INTEGER: + +		switch(right_type) +		{ +		case LST_INTEGER: +		case LST_FLOATINGPOINT: + +			// Numeric multiplication. +			fprintf(fp, "mul\n"); +			break; + +		case LST_VECTOR: + +			// Vector scaling. +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Vector, float32)\n"); +			break; +		default: +			break; +		}  		break; -	 -	case LST_VECTOR: + +	case LST_FLOATINGPOINT:  		switch(right_type)  		{  		case LST_INTEGER: +		case LST_FLOATINGPOINT: -			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT); +			// Numeric multiplication. +			fprintf(fp, "mul\n"); +			break; + +		case LST_VECTOR: + +			// Vector scaling. +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Vector, float32)\n"); +			break; + +		default: +			break; +		} +		break; +		 +	case LST_VECTOR: +		switch(right_type) +		{ +		case LST_INTEGER:  		case LST_FLOATINGPOINT:  			// Vector scaling. -			fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'multiply_float'(valuetype [LScriptLibrary]LLVector, float32)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(float32, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		case LST_VECTOR:  			// Dot product. -			fprintf(fp, "call float32 valuetype [LScriptLibrary]LLVector::'multiply_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n"); +			fprintf(fp, "call float32 class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		case LST_QUATERNION:  			// Vector rotation. -			fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'multiply_quat'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLQuaternion)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		default: @@ -4640,7 +5185,7 @@ void print_cil_mul(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  	case LST_QUATERNION:  		// Rotation multiplication. -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'multiply_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");  		break;  	default: @@ -4668,7 +5213,7 @@ void LLScriptMulAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "MUL %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4677,7 +5222,7 @@ void LLScriptMulAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mLeftType = type;  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mRightType = type; -			if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType)) +			if (!legal_binary_expression(mReturnType, mLeftType, mRightType, mType) /*|| !legal_assignment(mLValue->mReturnType, mReturnType)*/)  			{  				gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH);  			} @@ -4696,12 +5241,17 @@ void LLScriptMulAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_CIL_ASSEMBLY:  		{  			print_cil_load_address(fp, mLValue, entry); -			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType); +			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			print_cil_mul(fp, mLValue->mReturnType, mRightSide->mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			if((mLValue->mReturnType == LST_INTEGER) &&  +			   (mRightSide->mReturnType == LST_FLOATINGPOINT)) +			{ +			    print_cil_cast(fp, LST_FLOATINGPOINT, LST_INTEGER); +			}  +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4717,15 +5267,20 @@ S32 LLScriptMulAssignment::getSize()  	return 0;  } -void print_cil_div(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_div(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  {  	switch(left_type)  	{  	case LST_INTEGER: +		if(LST_INTEGER == right_type) +		{ +			fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(int32, int32)\n"); +			break; +		}  	case LST_FLOATINGPOINT: -		// Numeric addition. -		fprintf(fp, "div\n"); +		// Numeric division. +		fprintf(fp, "call float64 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(float64, float64)\n");  		break;  	case LST_VECTOR: @@ -4733,19 +5288,16 @@ void print_cil_div(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  		switch(right_type)  		{  		case LST_INTEGER: - -			print_cil_cast(fp, LST_INTEGER, LST_FLOATINGPOINT); -  		case LST_FLOATINGPOINT:  			// Scale. -			fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'divide_float'(valuetype [LScriptLibrary]LLVector, float32)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Divide'(float32, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		case LST_QUATERNION:  			// Inverse rotation. -			fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'divide_quat'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLQuaternion)\n"); +			fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Divide'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  			break;  		default: @@ -4755,7 +5307,7 @@ void print_cil_div(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  	case LST_QUATERNION: -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'divide_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n");		 +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Divide'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");		  		break;  	default: @@ -4783,7 +5335,7 @@ void LLScriptDivAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "DIV %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4811,12 +5363,12 @@ void LLScriptDivAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_CIL_ASSEMBLY:  		{  			print_cil_load_address(fp, mLValue, entry); -			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cil_numeric_cast(fp, mRightSide->mReturnType, mLValue->mReturnType); +			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_numeric_cast(fp, mLValue->mReturnType, mRightSide->mReturnType);  			print_cil_div(fp, mLValue->mReturnType, mRightSide->mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4832,20 +5384,20 @@ S32 LLScriptDivAssignment::getSize()  	return 0;  } -void print_cil_mod(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_mod(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  {  	switch(left_type)  	{  	case LST_INTEGER:  		// Numeric remainder. -		fprintf(fp, "rem\n"); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Modulo(int32, int32)\n");  		break;  	case LST_VECTOR:  		// Vector cross product. -		fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'mod_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Modulo'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  		break;  	default: @@ -4873,7 +5425,7 @@ void LLScriptModAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "MOD %s, %s\n", LSCRIPTTypeNames[mRightType], LSCRIPTTypeNames[mLeftType]); -			print_asignment(fp, mLValue); +			print_assignment(fp, mLValue);  		}  		break;  	case LSCP_TYPE: @@ -4901,10 +5453,10 @@ void LLScriptModAssignment::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  	case LSCP_EMIT_CIL_ASSEMBLY:  		{  			print_cil_load_address(fp, mLValue, entry); -			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			mLValue->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			print_cil_mod(fp, mLValue->mReturnType, mRightSide->mReturnType); -			print_cil_asignment(fp, mLValue, entry); +			print_cil_assignment(fp, mLValue, entry);  		}  		break;  	default: @@ -4920,9 +5472,10 @@ S32 LLScriptModAssignment::getSize()  	return 0;  } -void print_cil_eq(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type) +static void print_cil_eq(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  { -	switch(left_type) +	 +	switch(right_type)  	{  	case LST_INTEGER:  	case LST_FLOATINGPOINT: @@ -4932,26 +5485,36 @@ void print_cil_eq(LLFILE* fp, LSCRIPTType left_type, LSCRIPTType right_type)  		break;  	case LST_STRING: -	case LST_KEY: - +	        // NOTE: babbage: strings and keys can be compared, so a cast +	        // may be required +	        print_cil_cast(fp, left_type, right_type);  		// String equality.  		fprintf(fp, "call bool valuetype [mscorlib]System.String::op_Equality(string, string)\n");  		break; +		 +	case LST_KEY: +	        // NOTE: babbage: strings and keys can be compared, so a cast  +	        // may be required +	        print_cil_cast(fp, left_type, right_type); + +		// Key equality. +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::'Equals'(valuetype [ScriptTypes]LindenLab.SecondLife.Key, valuetype [ScriptTypes]LindenLab.SecondLife.Key)\n"); +		break;  	case LST_VECTOR:  		// Vector equality. -		fprintf(fp, "call bool [LScriptLibrary]LLVector::'equals_vec'(valuetype [LScriptLibrary]LLVector, valuetype [LScriptLibrary]LLVector)\n"); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::'Equals'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n");  		break;  	case LST_QUATERNION:  		// Rotation equality. -		fprintf(fp, "call bool [LScriptLibrary]LLQuaternion::'equals_quat'(valuetype [LScriptLibrary]LLQuaternion, valuetype [LScriptLibrary]LLQuaternion)\n"); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::'Equals'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n");  		break;  	case LST_LIST: -		fprintf(fp, "call bool [LScriptLibrary]LScriptInternal::EqualsList(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n"); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Equals(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n");  		break;  	default: @@ -5002,10 +5565,10 @@ void LLScriptEquality::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		print_cil_eq(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5063,10 +5626,19 @@ void LLScriptNotEquals::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompil  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType);  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "ceq\n"); -		fprintf(fp, "ldc.i4.0\n"); -		fprintf(fp, "ceq\n"); // Compare result of first compare equal with 0 to get compare not equal. +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		if (LST_LIST == mLeftSide->mReturnType) +		{ +		    fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::NotEquals(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n"); +		} +		else +		{   +		    print_cil_eq(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		    fprintf(fp, "ldc.i4.0\n"); +		    fprintf(fp, "ceq\n"); // Compare result of first compare equal with 0 to get compare not equal. +		}      		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5081,6 +5653,14 @@ S32 LLScriptNotEquals::getSize()  	return 0;  } +static void print_cil_lte(LLFILE* fp) +{ +	// NOTE: LSL pushes operands backwards, so <= becomes >= +	fprintf(fp, "clt\n"); +	fprintf(fp, "ldc.i4.0\n"); +	fprintf(fp, "ceq\n"); +} +  void LLScriptLessEquals::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -5122,11 +5702,11 @@ void LLScriptLessEquals::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "cgt\n"); // Test greater than. -		fprintf(fp, "ldc.i4.0\n"); // Use (b == 0) implementation of boolean not. -		fprintf(fp, "ceq\n"); // Apply boolean not to greater than. If not greater than, then less or equal. +		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		print_cil_lte(fp);  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5141,6 +5721,14 @@ S32 LLScriptLessEquals::getSize()  	return 0;  } +static void print_cil_gte(LLFILE* fp) +{    +	// NOTE: LSL pushes operands backwards, so >= becomes <= +	fprintf(fp, "cgt\n"); +	fprintf(fp, "ldc.i4.0\n"); +	fprintf(fp, "ceq\n"); +} +  void LLScriptGreaterEquals::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -5182,11 +5770,11 @@ void LLScriptGreaterEquals::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "clt\n"); // Test less than. -		fprintf(fp, "ldc.i4.0\n"); // Use (b == 0) implementation of boolean not. -		fprintf(fp, "ceq\n"); // Apply boolean not to less than. If not less than, then greater or equal. +		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		print_cil_gte(fp);  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5201,6 +5789,12 @@ S32 LLScriptGreaterEquals::getSize()  	return 0;  } +static void print_cil_lt(LLFILE* fp) +{ +	// NOTE: LSL pushes operands backwards, so < becomes > +	fprintf(fp, "cgt\n"); +} +  void LLScriptLessThan::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -5242,9 +5836,11 @@ void LLScriptLessThan::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompile  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "clt\n"); +		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		print_cil_lt(fp);  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5259,6 +5855,12 @@ S32 LLScriptLessThan::getSize()  	return 0;  } +static void print_cil_gt(LLFILE* fp) +{    +    // NOTE: LSL pushes operands backwards, so > becomes < +	fprintf(fp, "clt\n"); +} +  void LLScriptGreaterThan::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -5300,9 +5902,11 @@ void LLScriptGreaterThan::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "cgt\n"); +		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType); +		print_cil_gt(fp);  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5358,10 +5962,10 @@ void LLScriptPlus::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		print_cil_add(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5418,10 +6022,10 @@ void LLScriptMinus::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		print_cil_sub(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5478,10 +6082,10 @@ void LLScriptTimes::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		print_cil_mul(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5538,10 +6142,10 @@ void LLScriptDivide::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_numeric_cast(fp, mRightSide->mReturnType, mLeftSide->mReturnType); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_numeric_cast(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		print_cil_div(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5598,8 +6202,8 @@ void LLScriptMod::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		print_cil_mod(fp, mLeftSide->mReturnType, mRightSide->mReturnType);  		break;  	default: @@ -5654,8 +6258,8 @@ void LLScriptBitAnd::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, "and\n");  		break;  	default: @@ -5710,8 +6314,8 @@ void LLScriptBitOr::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, "or\n");  		break;  	default: @@ -5766,8 +6370,8 @@ void LLScriptBitXor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, "xor\n");  		break;  	default: @@ -5822,9 +6426,15 @@ void LLScriptBooleanAnd::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "and\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		fprintf(fp, "or\n"); +                fprintf(fp, "ldc.i4.0\n"); +                fprintf(fp, "ceq\n");  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5881,6 +6491,10 @@ void LLScriptBooleanOr::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompil  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, "or\n"); +                fprintf(fp, "ldc.i4.0\n"); +                fprintf(fp, "ceq\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n");  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5934,9 +6548,9 @@ void LLScriptShiftLeft::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompil  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "shl\n"); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::ShiftLeft(int32, int32)\n");  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -5991,9 +6605,9 @@ void LLScriptShiftRight::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		mRightSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "shr\n"); +		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		fprintf(fp, "call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::ShiftRight(int32, int32)\n");  		break;  	default:  		mLeftSide->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -6076,6 +6690,12 @@ void LLScriptUnaryMinus::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompi  			chunk->addByte(typebyte);  		}  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +	    { +			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_neg(fp, mLeftType); +	    } +	    break;  	default:  		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -6219,7 +6839,7 @@ void LLScriptPreIncrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_asignment(fp, mExpression); +			print_assignment(fp, mExpression);  		}  		break;  	case LSCP_TYPE: @@ -6266,21 +6886,21 @@ void LLScriptPreIncrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			print_cil_load_address(fp, mExpression, entry);  			if (mReturnType == LST_INTEGER)  			{ -				fprintf(fp, "ldc.i4.1\n");  				mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(fp, "ldc.i4.1\n");  				fprintf(fp, "add\n");  			}  			else if (mReturnType == LST_FLOATINGPOINT)  			{ -				fprintf(fp, "ldc.r8.1\n");  				mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(fp, "ldc.r8 1\n");  				fprintf(fp, "add\n");  			}  			else  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_cil_asignment(fp, mExpression, entry); +			print_cil_assignment(fp, mExpression, entry);  		}  		break;  	default: @@ -6327,7 +6947,7 @@ void LLScriptPreDecrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_asignment(fp, mExpression); +			print_assignment(fp, mExpression);  		}  		break;  	case LSCP_TYPE: @@ -6374,21 +6994,21 @@ void LLScriptPreDecrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			print_cil_load_address(fp, mExpression, entry);  			if (mReturnType == LST_INTEGER)  			{ -				fprintf(fp, "ldc.i4.1\n");  				mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(fp, "ldc.i4.1\n");  				fprintf(fp, "sub\n");  			}  			else if (mReturnType == LST_FLOATINGPOINT)  			{ -				fprintf(fp, "ldc.r8.1\n");  				mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(fp, "ldc.r8 1\n");  				fprintf(fp, "sub\n");  			}  			else  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_cil_asignment(fp, mExpression, entry); +			print_cil_assignment(fp, mExpression, entry);  		}  		break;  	default: @@ -6555,7 +7175,7 @@ void LLScriptVectorInitializer::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  			print_cil_cast(fp, mExpression3->mReturnType, LST_FLOATINGPOINT);  		}  		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type. -		fprintf(fp, "call valuetype [LScriptLibrary]LLVector valuetype [LScriptLibrary]LLVector::'create'(float32, float32, float32)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n");  		break;  	default:  		mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -6696,7 +7316,7 @@ void LLScriptQuaternionInitializer::recurse(LLFILE *fp, S32 tabs, S32 tabsize, L  		}  		// Call named ctor, which leaves new Vector on stack, so it can be saved in to local or argument just like a primitive type. -		fprintf(fp, "call valuetype [LScriptLibrary]LLQuaternion valuetype [LScriptLibrary]LLQuaternion::'create'(float32, float32, float32, float32)\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n");  		break;  	default:  		mExpression1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -6743,14 +7363,15 @@ void LLScriptListInitializer::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		mReturnType = type = LST_LIST;  		break;  	case LSCP_TO_STACK: +	{  		if (mExpressionList)  		{  			pass = LSCP_TO_STACK; -			count = 0; -			mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			U64 list_element_count = 0; +			mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, list_element_count, chunk, heap, stacksize, entry, entrycount, NULL);  			chunk->addByte(LSCRIPTOpCodes[LOPC_STACKTOL]); -			chunk->addInteger((S32)count); -			count = 0; +			chunk->addInteger((S32)list_element_count); +			  		}  		else  		{ @@ -6758,26 +7379,26 @@ void LLScriptListInitializer::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  			chunk->addInteger(0);  		}  		break; +	}  	case LSCP_EMIT_CIL_ASSEMBLY: - +	{  		// Push boxed elements on stack. -		count = 0; +		U64 list_element_count = 0;  		if (mExpressionList)  		{ -			mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, list_element_count, chunk, heap, stacksize, entry, entrycount, NULL);  		} -		// Create list on stack, consuming first boxed element. -		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::CreateList()\n"); +		// Create list on stack. +		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n"); -		// Call AddReturnList to add remaining boxed expressions. -		for(U64 i = 0; i < count; i++) +		// Call Prepend to add remaining boxed expressions. +		for(U64 i = 0; i < list_element_count; i++)  		{ -			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LScriptLibrary]LScriptInternal::AddReturnList(object, class [mscorlib]System.Collections.ArrayList)\n"); +			fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)\n");  		} -		count = 0; -		  		break; +	}  	default:  		if (mExpressionList)  		{ @@ -6824,7 +7445,7 @@ void LLScriptPostIncrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_asignment(fp, mExpression); +			print_assignment(fp, mExpression);  			fprintf(fp, "%s\n", LSCRIPTTypePop[mReturnType]);  		}  		break; @@ -6893,24 +7514,34 @@ void LLScriptPostIncrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		{ +			// Push original value on to stack. +			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + +			// Load address if needed for store.  			print_cil_load_address(fp, mExpression, entry); + +			// Load value again. +			// TODO: Work out if sideeffects can result in 2 evaluations of expression giving different values. +			// Original LSL2 uses this method, so any bugs due to side effects will probably be identical ;-)  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp,"dup\n"); // Copy expression result to use as increment operand.  			if (mReturnType == LST_INTEGER)  			{  				fprintf(fp, "ldc.i4.1\n");  			}  			else if (mReturnType == LST_FLOATINGPOINT)  			{ -				fprintf(fp, "ldc.r8.1\n"); +				fprintf(fp, "ldc.r8 1\n");  			}  			else  			{  				fprintf(fp, "Unexpected Type\n");  			}  			fprintf(fp, "add\n"); -			print_cil_asignment(fp, mExpression, entry); -			fprintf(fp, "pop\n"); // Pop assignment result to leave original expression result on stack. TODO: Optimise away redundant pop/dup pairs. +			print_cil_assignment(fp, mExpression, entry); + +			// Pop assignment result to leave original expression result on stack.  +			// TODO: Optimise away redundant pop/dup pairs. +			fprintf(fp, "pop\n");   		}  		break;  	default: @@ -6956,7 +7587,7 @@ void LLScriptPostDecrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  			{  				fprintf(fp, "Unexpected Type\n");  			} -			print_asignment(fp, mExpression); +			print_assignment(fp, mExpression);  			fprintf(fp, "%s\n", LSCRIPTTypePop[mReturnType]);  		}  		break; @@ -7025,24 +7656,34 @@ void LLScriptPostDecrement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCo  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		{ +			// Push original value on to stack. +			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + +			// Load address if needed for store.  			print_cil_load_address(fp, mExpression, entry); + +			// Load value again. +			// TODO: Work out if sideeffects can result in 2 evaluations of expression giving different values. +			// Original LSL2 uses this method, so any bugs due to side effects will probably be identical ;-)  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp,"dup\n"); // Copy expression result to use as decrement operand.  			if (mReturnType == LST_INTEGER)  			{  				fprintf(fp, "ldc.i4.1\n");  			}  			else if (mReturnType == LST_FLOATINGPOINT)  			{ -				fprintf(fp, "ldc.r8.1\n"); +				fprintf(fp, "ldc.r8 1\n");  			}  			else  			{  				fprintf(fp, "Unexpected Type\n");  			}  			fprintf(fp, "sub\n"); -			print_cil_asignment(fp, mExpression, entry); -			fprintf(fp, "pop\n"); // Pop assignment result to leave original expression result on stack. TODO: Optimise away redundant pop/dup pairs. +			print_cil_assignment(fp, mExpression, entry); + +			// Pop assignment result to leave original expression result on stack.  +			// TODO: Optimise away redundant pop/dup pairs. +			fprintf(fp, "pop\n");   		}  		break;  	default: @@ -7058,16 +7699,19 @@ S32 LLScriptPostDecrement::getSize()  }  // Generate arg list. -void print_cil_arg_list(LLFILE *fp, LLScriptFuncExpressionList* exp_list) +static void print_cil_arg_list(LLFILE *fp, LLScriptArgString& args)  { -	// Print first argument. -	print_cil_type(fp, exp_list->mFirstp->mReturnType); - -	// Recursively print next arguments. -	if(exp_list->mSecondp != NULL) +	int i = 0; +	bool finished = (i >= args.getNumber()); +	while(! finished)  	{ -		fprintf(fp, ", "); -		print_cil_arg_list(fp, (LLScriptFuncExpressionList*) exp_list->mSecondp); +		print_cil_type(fp, args.getType(i)); +		++i; +		finished = (i >= args.getNumber()); +		if(! finished) +		{ +			fprintf(fp, ", "); +		}  	}  } @@ -7146,7 +7790,7 @@ void LLScriptFunctionCall::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  					gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);  				}  			} -			else if (argcount != strlen(mIdentifier->mScopeEntry->mFunctionArgs.mString))	 	/*Flawfinder: ignore*/ +			else if (argcount != strlen(mIdentifier->mScopeEntry->mFunctionArgs.mString))  			{  				gErrorToText.writeError(fp, this, LSERROR_FUNCTION_TYPE_ERROR);  			} @@ -7217,13 +7861,15 @@ void LLScriptFunctionCall::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			// Load args on to stack.  			if (mExpressionList)  			{ -				mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry /* Needed for is_parameter calls */, 0, NULL); +				//mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry /* Needed for is_parameter calls */, 0, NULL); +				llassert(LET_FUNC_EXPRESSION_LIST == mExpressionList->mType); +				print_cil_func_expression_list((LLScriptFuncExpressionList*) mExpressionList, fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry /* Caller entry needed for is_parameter calls */, 0, NULL, mIdentifier->mScopeEntry /* Callee entry needed for argument casting */);  			}  			// Make call.  			if (! library_call)  			{ -				fprintf(fp, "callvirt instance "); +				fprintf(fp, "call instance ");  			}  			else  			{ @@ -7233,16 +7879,18 @@ void LLScriptFunctionCall::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  			fprintf(fp, " class ");  			if (library_call)  			{ -				fprintf(fp, "[LScriptLibrary]LScriptLibrary"); +				fprintf(fp, "[LslLibrary]LindenLab.SecondLife.Library::'");  			}  			else  			{ -				fprintf(fp, "LSL"); +				// Prefix function name with g to distinguish from +				// event handlers. +				fprintf(fp, gScriptp->getClassName()); +				fprintf(fp, "::'g");  			} -			fprintf(fp, "::"); -			mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp, "("); -			if (mExpressionList) {print_cil_arg_list(fp, (LLScriptFuncExpressionList*) mExpressionList);} +			fprintf(fp, mIdentifier->mName); +			fprintf(fp, "'("); +			print_cil_arg_list(fp, mIdentifier->mScopeEntry->mFunctionArgs);  			fprintf(fp, ")\n");  		}  		break; @@ -7287,6 +7935,11 @@ void LLScriptPrint::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		chunk->addByte(LSCRIPTOpCodes[LOPC_PRINT]);  		chunk->addByte(LSCRIPTTypeByte[mLeftType]);  		break; +	case LSCP_EMIT_CIL_ASSEMBLY: +	        mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		print_cil_cast(fp, mLeftType, LST_STRING); + 	        fprintf(fp, "call void class [LslLibrary]LindenLab.SecondLife.Library::Print(string)"); +	        break;  	default:  		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -7404,8 +8057,19 @@ void LLScriptStatementSequence::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRI  		mFirstp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		if (prunearg)  		{ +			// babbage: only warn on first dead code block found. +			if(ptype != LSPRUNE_DEAD_CODE) +			{ +				gErrorToText.writeWarning(fp, this, LSWARN_DEAD_CODE); +			} +			 +			// babbage: set prune type to LSPRUNE_DEAD_CODE to mask other +			// prune errors.  			ptype = LSPRUNE_DEAD_CODE; -			gErrorToText.writeWarning(fp, this, LSWARN_DEAD_CODE); +			 +			// babbage: reset prunearg, to track whether return needed at +			// end of dead code path as CIL always needs a return/throw. +			prunearg = FALSE;  		}  		mSecondp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		break; @@ -7444,10 +8108,7 @@ void LLScriptNOOP::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  		fprintf(fp, ";\n");  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	default:  		break; @@ -7462,7 +8123,7 @@ void add_exit_pops(LLScriptByteCodeChunk *chunk, LLScriptScopeEntry *entry)  	if (entry->mLocals.mString)  	{ -		number = (S32)strlen(entry->mLocals.mString); 	/*Flawfinder: ignore*/ +		number = (S32)strlen(entry->mLocals.mString);  		for (i = number - 1; i >= 0; i--)  		{  			switch(entry->mLocals.getType(i)) @@ -7495,7 +8156,7 @@ void add_exit_pops(LLScriptByteCodeChunk *chunk, LLScriptScopeEntry *entry)  	if (entry->mFunctionArgs.mString)  	{ -		number = (S32)strlen(entry->mFunctionArgs.mString); 	/*Flawfinder: ignore*/ +		number = (S32)strlen(entry->mFunctionArgs.mString);  		for (i = number - 1; i >= 0; i--)  		{  			switch(entry->mFunctionArgs.getType(i)) @@ -7534,7 +8195,7 @@ void print_exit_pops(LLFILE *fp, LLScriptScopeEntry *entry)  	if (entry->mLocals.mString)  	{ -		number = (S32)strlen(entry->mLocals.mString); 	/*Flawfinder: ignore*/ +		number = (S32)strlen(entry->mLocals.mString);  		for (i = number - 1; i >= 0; i--)  		{  			fprintf(fp, "%s", LSCRIPTTypePop[entry->mLocals.getType(i)]); @@ -7543,7 +8204,7 @@ void print_exit_pops(LLFILE *fp, LLScriptScopeEntry *entry)  	if (entry->mFunctionArgs.mString)  	{ -		number = (S32)strlen(entry->mFunctionArgs.mString); 	/*Flawfinder: ignore*/ +		number = (S32)strlen(entry->mFunctionArgs.mString);  		for (i = number - 1; i >= 0; i--)  		{  			fprintf(fp, "%s", LSCRIPTTypePop[entry->mFunctionArgs.getType(i)]); @@ -7583,10 +8244,7 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		{  			gErrorToText.writeError(fp, this, LSERROR_STATE_CHANGE_IN_GLOBAL);  		} -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_SCOPE_PASS2:  		{ @@ -7610,10 +8268,10 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: -		fprintf(fp, "ldstr \""); -		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "\"\n"); -		fprintf(fp, "call void class [LScriptLibrary]LScriptInternal::change_state(string)\n"); +		fprintf(fp, "ldarg.0\n"); +		fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName); +		fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n"); +		fprintf(fp, "ret\n");  		break;  	default:  		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -7647,10 +8305,7 @@ void LLScriptJump::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  		fprintf(fp, "\n");  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_SCOPE_PASS2:  		{ @@ -7820,6 +8475,10 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  				mType = basetype;  			}  		} +		else if (basetype != LST_NULL) +		{ +		        gErrorToText.writeError(fp, this, LSERROR_TYPE_MISMATCH); +		}  		break;  	case LSCP_EMIT_BYTE_CODE:  		if (mExpression) @@ -7863,6 +8522,7 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  		if (mExpression)  		{  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_cast(fp, mExpression->mReturnType, mType);  		}  		fprintf(fp, "ret\n");  		break; @@ -7902,10 +8562,7 @@ void LLScriptExpressionStatement::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSC  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_EMIT_BYTE_CODE:  		mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -7951,6 +8608,58 @@ S32 LLScriptIf::getSize()  	return 0;  } +static void print_cil_if_test(LLFILE* fp, LSCRIPTType type) +{ +	switch(type) +	{ +	case LST_INTEGER: +		break; +	case LST_FLOATINGPOINT: +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ceq\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		break; +	case LST_VECTOR: +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)\n"); +		fprintf(fp, "call bool [LslUserScript]LindenLab.SecondLife.LslUserScript::'Equals'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		break; +	case LST_QUATERNION: +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 0\n"); +		fprintf(fp, "ldc.r8 1\n"); +		fprintf(fp, "call class [ScriptTypes]LindenLab.SecondLife.Quaternion class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateQuaternion'(float32, float32, float32, float32)\n"); +		fprintf(fp, "call bool [LslUserScript]LindenLab.SecondLife.LslUserScript::'Equals'(class [ScriptTypes]LindenLab.SecondLife.Quaternion, class [ScriptTypes]LindenLab.SecondLife.Quaternion)\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		break; +	case LST_KEY: +		fprintf(fp, "call bool [LslUserScript]LindenLab.SecondLife.LslUserScript::'IsNonNullUuid'(valuetype [ScriptTypes]LindenLab.SecondLife.Key)\n"); +		break;		 +	case LST_STRING: +		fprintf(fp, "ldstr \"\"\n"); +		fprintf(fp, "call bool string::op_Equality(string, string)\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		break; +	case LST_LIST: +		fprintf(fp, "call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()\n"); +		fprintf(fp, "call bool [LslUserScript]LindenLab.SecondLife.LslUserScript::Equals(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)\n"); +		fprintf(fp, "ldc.i4.0\n"); +		fprintf(fp, "ceq\n"); +		break;		 +	default: +		break; +	} + +} +  void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)  {  	if (gErrorToText.getErrors()) @@ -7976,10 +8685,7 @@ void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass p  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_TYPE:  		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -8004,6 +8710,7 @@ void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass p  		{  			S32 tjump = gTempJumpCount++;  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_if_test(fp, mExpression->mReturnType);  			fprintf(fp, "brfalse LabelTempJump%d\n", tjump);  			mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "LabelTempJump%d:\n", tjump); @@ -8093,6 +8800,7 @@ void LLScriptIfElse::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  			S32 tjump1 =  gTempJumpCount++;  			S32 tjump2 =  gTempJumpCount++;  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_if_test(fp, mExpression->mReturnType);  			fprintf(fp, "brfalse LabelTempJump%d\n", tjump1);  			mStatement1->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "br LabelTempJump%d\n", tjump2); @@ -8155,10 +8863,7 @@ void LLScriptFor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_TYPE:  		if(mSequence) @@ -8203,6 +8908,7 @@ void LLScriptFor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass  				mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "LabelTempJump%d:\n", tjump1);  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_if_test(fp, mExpression->mReturnType);  			fprintf(fp, "brfalse LabelTempJump%d\n", tjump2);  			if(mStatement)  				mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -8257,10 +8963,7 @@ void LLScriptDoWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompileP  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_TYPE:  		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -8287,6 +8990,7 @@ void LLScriptDoWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompileP  			fprintf(fp, "LabelTempJump%d:\n", tjump1);  			mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_if_test(fp, mExpression->mReturnType);  			fprintf(fp, "brtrue LabelTempJump%d\n", tjump1);  		}  		break; @@ -8331,10 +9035,7 @@ void LLScriptWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_TYPE:  		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -8367,6 +9068,7 @@ void LLScriptWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  			S32 tjump2 =  gTempJumpCount++;  			fprintf(fp, "LabelTempJump%d:\n", tjump1);  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			print_cil_if_test(fp, mExpression->mReturnType);  			fprintf(fp, "brfalse LabelTempJump%d\n", tjump2);  			mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  			fprintf(fp, "br LabelTempJump%d\n", tjump1); @@ -8429,10 +9131,7 @@ void LLScriptDeclaration::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		}  		break;  	case LSCP_PRUNE: -		if (ptype == LSPRUNE_DEAD_CODE) -			prunearg = TRUE; -		else -			prunearg = FALSE; +		prunearg = FALSE;  		break;  	case LSCP_SCOPE_PASS1:  		// Check to see if a declaration is valid here. @@ -8604,24 +9303,13 @@ void LLScriptDeclaration::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		if (mExpression)  		{  			mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			if (mIdentifier->mScopeEntry->mIDType == LIT_VARIABLE) -			{ -				if(is_parameter(mIdentifier, entry)) -				{ -					// Parameter, store by name. -					fprintf(fp, "starg.s %s\n", mIdentifier->mScopeEntry->mIdentifier); -				} -				else -				{ -					// Local, store by index. -					fprintf(fp, "stloc.s %d\n", mIdentifier->mScopeEntry->mCount); -				} -			} -			else if (mIdentifier->mScopeEntry->mIDType == LIT_GLOBAL) -			{ -				gErrorToText.writeError(fp, this, LSERROR_UNDEFINED_NAME); -			} +			print_cil_cast(fp, mExpression->mReturnType, mIdentifier->mScopeEntry->mType); +		} +		else +		{ +			print_cil_init_variable(fp, mIdentifier->mScopeEntry->mType);  		} +		fprintf(fp, "stloc.s %d\n", mIdentifier->mScopeEntry->mCount);  		break;  	default:  		if (mExpression) @@ -8751,7 +9439,7 @@ S32 LLScriptEventHandler::getSize()  U64 gCurrentHandler = 0; -void print_cil_local_init(LLFILE* fp, LLScriptScopeEntry* scopeEntry) +static void print_cil_local_init(LLFILE* fp, LLScriptScopeEntry* scopeEntry)  {  	if(scopeEntry->mLocals.getNumber() > 0)  	{ @@ -8956,6 +9644,10 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		// first determine resource counts for globals  		count = 0;  		mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + +		// Store offset of first local as with global functions, so locals and arguments can be distinguished with is_parameter when compiling to CIL. +		mScopeEntry->mOffset = (S32) count; +  		if (mStatement)  		{  			entrycount = 0; @@ -9024,8 +9716,11 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		// Method signature prefix.  		fprintf(fp, ".method public hidebysig instance default void "); -		// Mangle event handler name by prefixing it with state name. Allows state changing by finding handlers prefixed with new state name. -		fprintf(fp, entry->mIdentifier);	 	/*Flawfinder: ignore*/ +		// Mangle event handler name by prefixing it with state name. +		// Allows state changing by finding handlers prefixed with new +		// state name. Prefix disambiguates functions and event handlers. +		fprintf(fp, "e"); +		fprintf(fp, entry->mIdentifier);  		// Handler name and arguments.  		mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -9047,7 +9742,11 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom  		}  		// Function footer. -		fprintf(fp, "\nret\n"); // TODO: Check whether return needed? +		if (mbNeedTrailingReturn) +		{ +			// TODO: throw exception? +			fprintf(fp, "ret\n"); +		}  		fprintf(fp, "}\n");  		break; @@ -9161,7 +9860,7 @@ void LLScriptFunctionDec::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  			chunk->addBytes(&typereturn, 1);  			// name  #ifdef LSL_INCLUDE_DEBUG_INFO -			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);	 	/*Flawfinder: ignore*/ +			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);  #else  			chunk->addBytes(1);  #endif @@ -9176,6 +9875,10 @@ void LLScriptFunctionDec::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp  		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		fprintf(fp, " ");  		mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +		if(NULL != mNextp) +		{ +			fprintf(fp, ","); +		}  		break;  	default:  		mType->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -9398,7 +10101,7 @@ void LLScriptGlobalFunctions::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  			// null terminated function name  #ifdef LSL_INCLUDE_DEBUG_INFO -			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);	 	/*Flawfinder: ignore*/ +			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);  #else  			chunk->addBytes(1);  #endif @@ -9444,11 +10147,13 @@ void LLScriptGlobalFunctions::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  		break;  	case LSCP_EMIT_CIL_ASSEMBLY:  		{ -			// Function header. +			// Function header. Prefix function name with g to distinguish +			// from event handlers.  			fprintf(fp, ".method public hidebysig instance default ");  			print_cil_type(fp, mType ? mType->mType : LST_NULL); -			fprintf(fp, " "); -			mIdentifier->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			fprintf(fp, " 'g"); +			fprintf(fp, mIdentifier->mName); +			fprintf(fp, "'");  			if (mParameters)  			{  				fprintf(fp, "( "); @@ -9473,6 +10178,7 @@ void LLScriptGlobalFunctions::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT  			// Function footer.  			if (mbNeedTrailingReturn)  			{ +				// TODO: throw exception?  				fprintf(fp, "ret\n");  			}  			fprintf(fp, "}\n"); @@ -9587,10 +10293,12 @@ void LLScriptState::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  		{  			mIdentifier->mScopeEntry = scope->addEntry(mIdentifier->mName, LIT_STATE, LST_NULL);  		} +		mStateScope = new LLScriptScope(gScopeStringTable); +		mStateScope->addParentScope(scope);  		// now do the events  		if (mEvent)  		{ -			mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			mEvent->recurse(fp, tabs, tabsize, pass, ptype, prunearg, mStateScope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  		}  		break;  	case LSCP_SCOPE_PASS2: @@ -9649,7 +10357,7 @@ void LLScriptState::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  			// null terminated state name  #ifdef LSL_INCLUDE_DEBUG_INFO -			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);	 	/*Flawfinder: ignore*/ +			chunk->addBytes(mIdentifier->mName, strlen(mIdentifier->mName) + 1);  #else  			chunk->addBytes(1);  #endif @@ -9693,6 +10401,38 @@ void LLScriptState::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas  	gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);  } +// Converts string to a valid CIL class name and stores the result  +// in the supplied buffer, which should be at least 32 chars long. +// If the string starts with a UUID, all characters in the UUID are included +// in the generated name. +void to_class_name(char* buffer, const char* string) +{ +	strcpy(buffer, "LSL-"); +	strcat(buffer, string); +	char* current_char = buffer; +	while((*current_char) != 0) +	{ +		if(isalnum(*current_char)) +		{ +			++current_char; +		} +		else if((*current_char) == '-') +		{ +			(*current_char) = '_'; +			++current_char; +		} +		else +		{ +			(*current_char) = 0; +		} +	} +} + +void LLScriptScript::setClassName(const char* class_name) +{ +	to_class_name(mClassName, class_name); +} +  S32 LLScriptScript::getSize()  {  	return 0; @@ -9704,6 +10444,7 @@ LLScriptScript::LLScriptScript(LLScritpGlobalStorage *globals,  	mStates(states), mGlobalScope(NULL), mGlobals(NULL), mGlobalFunctions(NULL), mGodLike(FALSE)  {  	const char DEFAULT_BYTECODE_FILENAME[] = "lscript.lso"; +  	mBytecodeDest = DEFAULT_BYTECODE_FILENAME;  	LLScriptGlobalVariable	*tvar;  	LLScriptGlobalFunctions	*tfunc; @@ -9753,13 +10494,11 @@ void LLScriptScript::setBytecodeDest(const char* dst_filename)  	mBytecodeDest = ll_safe_string(dst_filename);  } -void print_cil_globals(LLFILE* fp, LLScriptGlobalVariable* global) +static void print_cil_globals(LLFILE* fp, LLScriptGlobalVariable* global)  { -	fprintf(fp, ".field private "); +	fprintf(fp, ".field public ");  	print_cil_type(fp, global->mType->mType); -	fprintf(fp, " "); -	fprintf(fp, global->mIdentifier->mName);		/*Flawfinder: ignore*/ -	fprintf(fp, "\n"); +	fprintf(fp, " '%s'\n", global->mIdentifier->mName);  	if(NULL != global->mNextp)  	{  		print_cil_globals(fp, global->mNextp); @@ -9946,72 +10685,66 @@ void LLScriptScript::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa  		}  		break;  	case LSCP_EMIT_CIL_ASSEMBLY: +		{ +			LLFILE *bcfp = LLFile::fopen(mBytecodeDest, "wb"); -		// Output dependencies. -		fprintf(fp, ".assembly extern mscorlib {.ver 1:0:5000:0}\n"); -		fprintf(fp, ".assembly extern LScriptLibrary {.ver 0:0:0:0}\n"); +			// Output dependencies. +			fprintf(bcfp, ".assembly extern mscorlib {.ver 1:0:5000:0}\n"); +			fprintf(bcfp, ".assembly extern LslLibrary {.ver 0:1:0:0}\n"); +			fprintf(bcfp, ".assembly extern LslUserScript {.ver 0:1:0:0}\n"); +			fprintf(bcfp, ".assembly extern ScriptTypes {.ver 0:1:0:0}\n"); -		// Output assembly name. -		fprintf(fp, ".assembly 'lsl' {.ver 0:0:0:0}\n"); +			// Output assembly name. +			fprintf(bcfp, ".assembly '%s' {.ver 0:0:0:0}\n", gScriptp->getClassName()); -		// Output class header. -		fprintf(fp, ".class public auto ansi beforefieldinit LSL extends [mscorlib]System.Object\n"); -		fprintf(fp, "{\n"); +			// Output class header. +			fprintf(bcfp, ".class public auto ansi serializable beforefieldinit %s extends [LslUserScript]LindenLab.SecondLife.LslUserScript\n", gScriptp->getClassName()); +			fprintf(bcfp, "{\n"); -		// Output globals as members. -		if(NULL != mGlobals) -		{ -			print_cil_globals(fp, mGlobals); -		} - -		// Output "runtime". Only needed to allow stand alone execution. Not needed when compiling to DLL and using embedded runtime. -		fprintf(fp, ".method public static  hidebysig default void Main ()  cil managed\n"); -		fprintf(fp, "{\n"); -		fprintf(fp, ".entrypoint\n"); -		fprintf(fp, ".maxstack 2\n"); -		fprintf(fp, ".locals init (class LSL V_0)\n"); -		fprintf(fp, "newobj instance void class LSL::.ctor()\n"); -		fprintf(fp, "stloc.0\n"); -		fprintf(fp, "ldloc.0\n"); -		fprintf(fp, "callvirt instance void class LSL::defaultstate_entry()\n"); -		fprintf(fp, "ret\n"); -		fprintf(fp, "}\n"); +			// Output globals as members. +			if(NULL != mGlobals) +			{ +				print_cil_globals(bcfp, mGlobals); +			} -		// Output ctor header. -		fprintf(fp, ".method public hidebysig  specialname  rtspecialname instance default void .ctor ()  cil managed\n"); -		fprintf(fp, "{\n"); -		fprintf(fp, ".maxstack 500\n"); +			// Output ctor header. +			fprintf(bcfp, ".method public hidebysig  specialname  rtspecialname instance default void .ctor ()  cil managed\n"); +			fprintf(bcfp, "{\n"); +			fprintf(bcfp, ".maxstack 500\n"); -		// Initialise globals as members in ctor. -		if (mGlobals) -		{ -			fdotabs(fp, tabs, tabsize); -			mGlobals->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp, "\n"); -		} +			// Initialise globals as members in ctor. +			if (mGlobals) +			{ +				fdotabs(bcfp, tabs, tabsize); +				mGlobals->recurse(bcfp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(bcfp, "\n"); +			} -		// Output ctor footer. -		fprintf(fp, "ldarg.0\n"); -		fprintf(fp, "call instance void valuetype [mscorlib]System.Object::.ctor()\n"); -		fprintf(fp, "ret\n"); -		fprintf(fp, "}\n"); +			// Output ctor footer. +			fprintf(bcfp, "ldarg.0\n"); +			fprintf(bcfp, "call instance void [LslUserScript]LindenLab.SecondLife.LslUserScript::.ctor()\n"); +			fprintf(bcfp, "ret\n"); +			fprintf(bcfp, "}\n"); -		// Output functions as methods. -		if (mGlobalFunctions) -		{ -			fdotabs(fp, tabs, tabsize); -			mGlobalFunctions->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -			fprintf(fp, "\n"); -		} +			// Output functions as methods. +			if (mGlobalFunctions) +			{ +				fdotabs(bcfp, tabs, tabsize); +				mGlobalFunctions->recurse(bcfp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +				fprintf(bcfp, "\n"); +			} -		// Output states as name mangled methods. -		fdotabs(fp, tabs, tabsize); -		mStates->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); -		fprintf(fp, "\n"); +			// Output states as name mangled methods. +			fdotabs(bcfp, tabs, tabsize); +			mStates->recurse(bcfp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); +			fprintf(bcfp, "\n"); -		// Output class footer. -		fprintf(fp, "}\n"); +			// Output class footer. +			fprintf(bcfp, "}\n"); +			// Close file. +			fclose(bcfp); +		}  		break;  	default:  		if (mGlobals) diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h index 4c25c097d8..57228dd24c 100644 --- a/indra/lscript/lscript_compile/lscript_tree.h +++ b/indra/lscript/lscript_compile/lscript_tree.h @@ -2197,11 +2197,11 @@ public:  	void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);  	S32 getSize(); -	LSCRIPTStateType		mType; -	LLScriptIdentifier		*mIdentifier; -	LLScriptEventHandler	*mEvent; -	LLScriptState			*mNextp; - +	LSCRIPTStateType mType; +	LLScriptIdentifier *mIdentifier; +	LLScriptEventHandler *mEvent; +	LLScriptState *mNextp; +	LLScriptScope *mStateScope;  };  class LLScritpGlobalStorage : public LLScriptFilePosition @@ -2262,6 +2262,9 @@ public:  	void setBytecodeDest(const char* dst_filename); +	void setClassName(const char* class_name); +	const char* getClassName() {return mClassName;} +  	LLScriptState			*mStates;  	LLScriptScope			*mGlobalScope;  	LLScriptGlobalVariable	*mGlobals; @@ -2270,6 +2273,7 @@ public:  private:  	std::string mBytecodeDest; +	char mClassName[MAX_STRING];  };  class LLScriptAllocationManager diff --git a/indra/lscript/lscript_compile/lscript_typecheck.cpp b/indra/lscript/lscript_compile/lscript_typecheck.cpp index 1030e8c70d..bfa5a66c7b 100644 --- a/indra/lscript/lscript_compile/lscript_typecheck.cpp +++ b/indra/lscript/lscript_compile/lscript_typecheck.cpp @@ -66,7 +66,13 @@ LSCRIPTType implicit_casts(LSCRIPTType left_side, LSCRIPTType right_side)  	{  		// shouldn't be doing an operation on void types  	case LST_NULL: -		return LST_NULL; +		switch(right_side) +		{ +		case LST_NULL: +			return LST_NULL; +		default: +			return LST_UNDEFINED; +		}  	// shouldn't be doing an operation on undefined types  	case LST_UNDEFINED:  		return LST_UNDEFINED; diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h index dd1aa97e71..f46256eb5e 100644 --- a/indra/lscript/lscript_execute.h +++ b/indra/lscript/lscript_execute.h @@ -367,20 +367,158 @@ public:  class LLScriptExecute  {  public: -	LLScriptExecute(LLFILE *fp); -	LLScriptExecute(U8 *buffer); -	~LLScriptExecute(); +	LLScriptExecute(); +	virtual ~LLScriptExecute() {;} + +	virtual S32 getVersion() = 0; +	virtual void deleteAllEvents() = 0; +	virtual void addEvent(LLScriptDataCollection* event) = 0; +	virtual U32 getEventCount() = 0; +	virtual void removeEventType(LSCRIPTStateEventType event_type) = 0; +	virtual S32 getFaults() = 0; +	virtual void setFault(LSCRIPTRunTimeFaults fault) = 0; +	virtual	U32 getFreeMemory() = 0; +	virtual S32 getParameter() = 0; +	virtual void setParameter(S32 value) = 0; +	virtual F32 getSleep() const = 0; +	virtual void setSleep(F32 value) = 0; +	virtual F32 getEnergy() const = 0; +	virtual void setEnergy(F32 value) = 0; +	virtual U64 getCurrentEvents(S32 version) = 0; +	virtual void setCurrentEvents(U64 value, S32 version) = 0; +	virtual U64 getEventHandlers(S32 version) = 0; +	virtual void setEventHandlers(U64 value, S32 version) = 0; +	virtual U64 getCurrentHandler(S32 version) = 0; +	virtual void setCurrentHandler(U64 value, S32 version) = 0; +	virtual BOOL isFinished() const = 0; +	virtual BOOL isStateChangePending() const = 0; +	virtual S32 writeState(U8 **dest, U32 header_size, U32 footer_size) = 0; // Allocate memory for header, state and footer return size of state. +	virtual U32 getEventsSavedSize() = 0; // Returns 0 if events are written with state. +	virtual S32 writeEvents(U8 *dest) = 0; // Must write and return exactly the number of bytes returned by getEventsSavedSize. +	virtual void readEvents(U8* src, S32& offset) = 0; +	virtual S32 readState(U8 *src) = 0; // Returns number of bytes read. +	virtual void reset(); +	virtual const U8* getBytecode() const = 0; +	virtual U32 getBytecodeSize() const = 0; +	virtual bool isMono() const = 0; +	virtual void error() {;} // Processing that must be performed when error flag is set and so run is not called. +	 +	// Run current event handler for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	virtual void resumeEventHandler(BOOL b_print, const LLUUID &id, F32 time_slice) = 0; + +	// Run handler for event for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	virtual void callEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice) = 0;; + +	// Run handler for next queued event for maximum of time_slice seconds.  +	// Updates current handler and current events registers. +	// Removes processed event from queue. +	virtual void callNextQueuedEventHandler(U64 event_register, S32 major_version, const LLUUID &id, F32 time_slice) = 0; + +	// Run handler for event for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	// Removes processed event from queue. +	virtual void callQueuedEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice) = 0; + +	// Switch to next state. +	// Returns new set of handled events. +	virtual U64 nextState() = 0;  + +	// Returns time taken. +	virtual F32 runQuanta(BOOL b_print, const LLUUID &id, +						  const char **errorstr,  +						  BOOL &state_transition, F32 quanta, +						  U32& events_processed, LLTimer& timer); + +	// Run smallest possible amount of code: an instruction for LSL2, a segment +	// between save tests for Mono +	void runInstructions(BOOL b_print, const LLUUID &id, +						 const char **errorstr,  +						 BOOL &state_transition, U32& events_processed, +						 F32 quanta); + +	bool isYieldDue() const; + +	void setReset(BOOL b) {mReset = b;} +	BOOL getReset() const { return mReset; } + +private: + +	BOOL mReset; +}; + +class LLScriptExecuteLSL2 : public LLScriptExecute +{ +public: +	LLScriptExecuteLSL2(LLFILE *fp); +	LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size); +	virtual ~LLScriptExecuteLSL2(); + +	virtual S32 getVersion() {return get_register(mBuffer, LREG_VN);} +	virtual void deleteAllEvents() {mEventData.mEventDataList.deleteAllData();} +	virtual void addEvent(LLScriptDataCollection* event); +	virtual U32 getEventCount() {return mEventData.mEventDataList.getLength();} +	virtual void removeEventType(LSCRIPTStateEventType event_type); +	virtual S32 getFaults() {return get_register(mBuffer, LREG_FR);} +	virtual void setFault(LSCRIPTRunTimeFaults fault) {set_fault(mBuffer, fault);} +	virtual U32 getFreeMemory(); +	virtual S32 getParameter(); +	virtual void setParameter(S32 value); +	virtual F32 getSleep() const; +	virtual void setSleep(F32 value); +	virtual F32 getEnergy() const; +	virtual void setEnergy(F32 value); +	virtual U64 getCurrentEvents(S32 version) {return get_event_register(mBuffer, LREG_CE, version);} +	virtual void setCurrentEvents(U64 value, S32 version) {return set_event_register(mBuffer, LREG_CE, value, version);} +	virtual U64 getEventHandlers(S32 version) {return get_event_register(mBuffer, LREG_ER, version);} +	virtual void setEventHandlers(U64 value, S32 version) {set_event_register(mBuffer, LREG_ER, value, version);} +	virtual U64 getCurrentHandler(S32 version); +	virtual void setCurrentHandler(U64 value, S32 version) {return set_event_register(mBuffer, LREG_IE, value, version);}	 +	virtual BOOL isFinished() const {return get_register(mBuffer, LREG_IP) == 0;} +	virtual BOOL isStateChangePending() const {return get_register(mBuffer, LREG_CS) != get_register(mBuffer, LREG_NS);} +	virtual S32 writeState(U8 **dest, U32 header_size, U32 footer_size); // Not including Events. +	virtual U32 getEventsSavedSize() {return mEventData.getSavedSize();} +	virtual S32 writeEvents(U8 *dest) {return mEventData.write2bytestream(dest);} +	virtual void readEvents(U8* src, S32& offset) {mEventData.set(src, offset);} +	virtual S32 writeBytecode(U8 **dest); +	virtual S32 readState(U8 *src); +	virtual void reset(); +	virtual const U8* getBytecode() const {return mBytecode;} +	virtual U32 getBytecodeSize() const {return mBytecodeSize;} +	virtual bool isMono() const {return false;} + +	// Run current event handler for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	virtual void resumeEventHandler(BOOL b_print, const LLUUID &id, F32 time_slice); + +	// Run handler for event for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	virtual void callEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice); + +	// Run handler for next queued event for maximum of time_slice seconds.  +	// Updates current handler and current events registers. +	// Removes processed event from queue. +	virtual void callNextQueuedEventHandler(U64 event_register, S32 major_version, const LLUUID &id, F32 time_slice); + +	// Run handler for event for a maximum of time_slice seconds. +	// Updates current handler and current events registers. +	// Removes processed event from queue. +	virtual void callQueuedEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice); + +	// Switch to next state. +	// Returns new set of handled events. +	virtual U64 nextState();   	void init(); -	U32 run(BOOL b_print, const LLUUID &id, const char **errorstr, BOOL &state_transition);  	BOOL (*mExecuteFuncs[0x100])(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id);  	U32						mInstructionCount;  	U8						*mBuffer;  	LLScriptEventData		mEventData; - -	static S64 sGlobalInstructionCount; +	U8*						mBytecode; // Initial state and bytecode. +	U32						mBytecodeSize;  private:  	void		recordBoundaryError( const LLUUID &id ); diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index aa73025b7f..e863c1668e 100644 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -31,6 +31,7 @@  #include "linden_common.h" +#include <algorithm>  #include <sstream>  #include "lscript_execute.h" @@ -45,7 +46,7 @@ void (*unary_operations[LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode);  const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] =		/*Flawfinder: ignore*/  { -	"invalid",				//	LSRF_INVALID, +	"Invalid",				//	LSRF_INVALID,  	"Math Error",			//	LSRF_MATH,  	"Stack-Heap Collision",	//	LSRF_STACK_HEAP_COLLISION,  	"Bounds Check Error",	//	LSRF_BOUND_CHECK_ERROR, @@ -55,13 +56,11 @@ const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] =		/*Flawfinder: ignore*/  	"Hit Sandbox Limit",	//	LSRF_SANDBOX,  	"Chat Overrun",			//	LSRF_CHAT_OVERRUN,  	"Too Many Listens",			  //	LSRF_TOO_MANY_LISTENS, -	"Lists may not contain lists" //	LSRF_NESTING_LISTS, +	"Lists may not contain lists", //	LSRF_NESTING_LISTS, +	"CLI Exception" // LSRF_CLI  }; -//static -S64 LLScriptExecute::sGlobalInstructionCount = 0; - -LLScriptExecute::LLScriptExecute(LLFILE *fp) +LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)  {  	U8  sizearray[4];  	S32 filesize; @@ -84,19 +83,26 @@ LLScriptExecute::LLScriptExecute(LLFILE *fp)  	init();  } -LLScriptExecute::LLScriptExecute(U8 *buffer) +LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)  { -	mBuffer = buffer; - +	mBuffer = new U8[TOP_OF_MEMORY]; +	memset(mBuffer + bytecode_size, 0, TOP_OF_MEMORY - bytecode_size); +	S32 src_offset = 0; +	S32 dest_offset = 0; +	bytestream2bytestream(mBuffer, dest_offset, bytecode, src_offset, bytecode_size); +	mBytecodeSize = bytecode_size; +	mBytecode = new U8[mBytecodeSize]; +	memcpy(mBytecode, bytecode, mBytecodeSize);  	init();  } -LLScriptExecute::~LLScriptExecute() +LLScriptExecuteLSL2::~LLScriptExecuteLSL2()  { -	delete [] mBuffer; +	delete[] mBuffer; +	delete[] mBytecode;  } -void LLScriptExecute::init() +void LLScriptExecuteLSL2::init()  {  	S32 i, j; @@ -270,7 +276,7 @@ void LLScriptExecute::init()  // Utility routine for when there's a boundary error parsing bytecode -void LLScriptExecute::recordBoundaryError( const LLUUID &id ) +void LLScriptExecuteLSL2::recordBoundaryError( const LLUUID &id )  {  	set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR);  	llwarns << "Script boundary error for ID " << id << llendl; @@ -278,7 +284,7 @@ void LLScriptExecute::recordBoundaryError( const LLUUID &id )  //	set IP to the event handler with some error checking -void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id ) +void LLScriptExecuteLSL2::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id )  {  	S32			opcode_start = get_state_event_opcoode_start( mBuffer, state, event );  	if ( opcode_start == -1 ) @@ -296,12 +302,474 @@ void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEv  S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer); -U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, const char **errorstr, BOOL &state_transition) +void LLScriptExecuteLSL2::resumeEventHandler(BOOL b_print, const LLUUID &id, F32 time_slice) +{ +	//	call opcode run function pointer with buffer and IP +	mInstructionCount++; +	S32 value = get_register(mBuffer, LREG_IP); +	S32 tvalue = value; +	S32	opcode = safe_instruction_bytestream2byte(mBuffer, tvalue); +	mExecuteFuncs[opcode](mBuffer, value, b_print, id); +	set_ip(mBuffer, value); +	add_register_fp(mBuffer, LREG_ESR, -0.1f); +	//	lsa_print_heap(mBuffer); + +	if (b_print) +	{ +		lsa_print_heap(mBuffer); +		printf("ip: 0x%X\n", get_register(mBuffer, LREG_IP)); +		printf("sp: 0x%X\n", get_register(mBuffer, LREG_SP)); +		printf("bp: 0x%X\n", get_register(mBuffer, LREG_BP)); +		printf("hr: 0x%X\n", get_register(mBuffer, LREG_HR)); +		printf("hp: 0x%X\n", get_register(mBuffer, LREG_HP)); +	} + +	// NOTE: Babbage: all mExecuteFuncs return false. +} + +void LLScriptExecuteLSL2::callEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice) +{ +	// push a zero to be popped +	lscript_push(mBuffer, 0); +	// push sp as current bp +	S32 sp = get_register(mBuffer, LREG_SP); +	lscript_push(mBuffer, sp); + +	// Update current handler and current events registers. +	set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); +	U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); +	current_events &= ~LSCRIPTStateBitField[event]; +	set_event_register(mBuffer, LREG_CE, current_events, major_version); + +	// now, push any additional stack space +	U32 current_state = get_register(mBuffer, LREG_CS); +	S32 additional_size = get_event_stack_size(mBuffer, current_state, event); +	lscript_pusharge(mBuffer, additional_size); + +	// now set the bp correctly +	sp = get_register(mBuffer, LREG_SP); +	sp += additional_size; +	set_bp(mBuffer, sp); + +	// set IP to the function +	S32			opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); +	set_ip(mBuffer, opcode_start); +} + +//void callStateExitHandler() +//{ +//	// push a zero to be popped +//	lscript_push(mBuffer, 0); +//	// push sp as current bp +//	S32 sp = get_register(mBuffer, LREG_SP); +//	lscript_push(mBuffer, sp); +// +//	// now, push any additional stack space +//	S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT); +//	lscript_pusharge(mBuffer, additional_size); +// +//	sp = get_register(mBuffer, LREG_SP); +//	sp += additional_size; +//	set_bp(mBuffer, sp); +// +//	// set IP to the event handler +//	S32			opcode_start = get_state_event_opcoode_start(mBuffer, current_state, LSTT_STATE_EXIT); +//	set_ip(mBuffer, opcode_start); +//} +// +//void callStateEntryHandler() +//{ +//	// push a zero to be popped +//	lscript_push(mBuffer, 0); +//	// push sp as current bp +//	S32 sp = get_register(mBuffer, LREG_SP); +//	lscript_push(mBuffer, sp); +// +//	event = return_first_event((S32)LSCRIPTStateBitField[LSTT_STATE_ENTRY]); +//	set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); +//	current_events &= ~LSCRIPTStateBitField[event]; +//	set_event_register(mBuffer, LREG_CE, current_events, major_version); +// +//	// now, push any additional stack space +//	S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; +//	lscript_pusharge(mBuffer, additional_size); +// +//	// now set the bp correctly +//	sp = get_register(mBuffer, LREG_SP); +//	sp += additional_size + size; +//	set_bp(mBuffer, sp); +//	// set IP to the function +//	S32			opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); +//	set_ip(mBuffer, opcode_start); +//} + +void LLScriptExecuteLSL2::callQueuedEventHandler(LSCRIPTStateEventType event, S32 major_version, const LLUUID &id, F32 time_slice) +{ +	LLScriptDataCollection* eventdata; + +	for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData()) +	{ +		if (eventdata->mType == event) +		{ +			// push a zero to be popped +			lscript_push(mBuffer, 0); +			// push sp as current bp +			S32 sp = get_register(mBuffer, LREG_SP); +			lscript_push(mBuffer, sp); + +			// Update current handler and current events registers. +			set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); +			U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); +			current_events &= ~LSCRIPTStateBitField[event]; +			set_event_register(mBuffer, LREG_CE, current_events, major_version); + +			// push any arguments that need to be pushed onto the stack +			// last piece of data will be type LST_NULL +			LLScriptLibData	*data = eventdata->mData; +			U32 size = 0; +			while (data->mType) +			{ +				size += lscript_push_variable(data, mBuffer); +				data++; +			} +			// now, push any additional stack space +			U32 current_state = get_register(mBuffer, LREG_CS); +			S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; +			lscript_pusharge(mBuffer, additional_size); + +			// now set the bp correctly +			sp = get_register(mBuffer, LREG_SP); +			sp += additional_size + size; +			set_bp(mBuffer, sp); + +			// set IP to the function +			S32			opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); +			set_ip(mBuffer, opcode_start); + +			mEventData.mEventDataList.deleteCurrentData(); +			break; +		} +	} +} + +void LLScriptExecuteLSL2::callNextQueuedEventHandler(U64 event_register, S32 major_version, const LLUUID &id, F32 time_slice) +{ +	LLScriptDataCollection* eventdata = mEventData.getNextEvent(); +	if (eventdata) +	{ +		LSCRIPTStateEventType event = eventdata->mType; + +		// make sure that we can actually handle this one +		if (LSCRIPTStateBitField[event] & event_register) +		{ +			// push a zero to be popped +			lscript_push(mBuffer, 0); +			// push sp as current bp +			S32 sp = get_register(mBuffer, LREG_SP); +			lscript_push(mBuffer, sp); + +			// Update current handler and current events registers. +			set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); +			U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); +			current_events &= ~LSCRIPTStateBitField[event]; +			set_event_register(mBuffer, LREG_CE, current_events, major_version); + +			// push any arguments that need to be pushed onto the stack +			// last piece of data will be type LST_NULL +			LLScriptLibData	*data = eventdata->mData; +			U32 size = 0; +			while (data->mType) +			{ +				size += lscript_push_variable(data, mBuffer); +				data++; +			} + +			// now, push any additional stack space +			U32 current_state = get_register(mBuffer, LREG_CS); +			S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; +			lscript_pusharge(mBuffer, additional_size); + +			// now set the bp correctly +			sp = get_register(mBuffer, LREG_SP); +			sp += additional_size + size; +			set_bp(mBuffer, sp); + +			// set IP to the function +			S32			opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); +			set_ip(mBuffer, opcode_start); +		} +		else +		{ +			llwarns << "Shit, somehow got an event that we're not registered for!" << llendl; +		} +		delete eventdata; +	} +} + +U64 LLScriptExecuteLSL2::nextState() +{ +	// copy NS to CS +	S32 next_state = get_register(mBuffer, LREG_NS); +	set_register(mBuffer, LREG_CS, next_state); + +	// copy new state's handled events into ER (SR + CS*4 + 4) +	return get_handled_events(mBuffer, next_state); +} + +//virtual  +void LLScriptExecuteLSL2::addEvent(LLScriptDataCollection* event) +{ +	mEventData.addEventData(event); +} + +//virtual  +void LLScriptExecuteLSL2::removeEventType(LSCRIPTStateEventType event_type) +{ +	mEventData.removeEventType(event_type); +} + +//virtual  +F32 LLScriptExecuteLSL2::getSleep() const +{ +	return get_register_fp(mBuffer, LREG_SLR); +} + +//virtual  +void LLScriptExecuteLSL2::setSleep(F32 value) +{ +	set_register_fp(mBuffer, LREG_SLR, value); +} + +//virtual  +U64 LLScriptExecuteLSL2::getCurrentHandler(S32 version) +{ +	return get_event_register(mBuffer, LREG_IE, version); +} + +//virtual  +F32 LLScriptExecuteLSL2::getEnergy() const +{ +	return get_register_fp(mBuffer, LREG_ESR); +} + +//virtual  +void LLScriptExecuteLSL2::setEnergy(F32 value) +{ +	set_register_fp(mBuffer, LREG_ESR, value); +} + +//virtual  +U32 LLScriptExecuteLSL2::getFreeMemory() +{ +	return get_register(mBuffer, LREG_SP) - get_register(mBuffer, LREG_HP); +} + +//virtual  +S32 LLScriptExecuteLSL2::getParameter() +{ +	return get_register(mBuffer, LREG_PR); +} + +//virtual  +void LLScriptExecuteLSL2::setParameter(S32 value) +{ +	set_register(mBuffer, LREG_PR, value); +} + + +S32 LLScriptExecuteLSL2::writeState(U8 **dest, U32 header_size, U32 footer_size) +{ +	// data format: +	// 4 bytes of size of Registers, Name and Description, and Global Variables +	// Registers, Name and Description, and Global Variables data +	// 4 bytes of size of Heap +	// Heap data +	// 4 bytes of stack size +	// Stack data + +	S32 registers_size = get_register(mBuffer, LREG_GFR); + +	if (get_register(mBuffer, LREG_HP) > TOP_OF_MEMORY) +		reset_hp_to_safe_spot(mBuffer); + +	S32 heap_size = get_register(mBuffer, LREG_HP) - get_register(mBuffer, LREG_HR); +	S32 stack_size = get_register(mBuffer, LREG_TM) - get_register(mBuffer, LREG_SP); +	S32 total_size = registers_size + LSCRIPTDataSize[LST_INTEGER] +  +						heap_size + LSCRIPTDataSize[LST_INTEGER] +  +						stack_size + LSCRIPTDataSize[LST_INTEGER]; + +	// actually allocate data +	delete[] *dest; +	*dest = new U8[header_size + total_size + footer_size]; +	memset(*dest, 0, header_size + total_size + footer_size); +	S32 dest_offset = header_size; +	S32 src_offset = 0; + +	// registers +	integer2bytestream(*dest, dest_offset, registers_size); + +	// llinfos << "Writing CE: " << getCurrentEvents() << llendl; +	bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, registers_size); + +	// heap +	integer2bytestream(*dest, dest_offset, heap_size); + +	src_offset = get_register(mBuffer, LREG_HR); +	bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, heap_size); + +	// stack +	integer2bytestream(*dest, dest_offset, stack_size); + +	src_offset = get_register(mBuffer, LREG_SP); +	bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, stack_size); + +	return total_size; +} + +S32 LLScriptExecuteLSL2::writeBytecode(U8 **dest) +{ +	// data format: +	// registers through top of heap +	// Heap data +	S32 total_size = get_register(mBuffer, LREG_HP); + +	// actually allocate data +	delete [] *dest; +	*dest = new U8[total_size]; +	S32 dest_offset = 0; +	S32 src_offset = 0; + +	bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, total_size); + +	return total_size; +} + +S32 LLScriptExecuteLSL2::readState(U8 *src) +{ +	// first, blitz heap and stack +	S32 hr = get_register(mBuffer, LREG_HR); +	S32 tm = get_register(mBuffer, LREG_TM); +	memset(mBuffer + hr, 0, tm - hr); + +	S32 src_offset = 0; +	S32 dest_offset = 0; +	S32 size; + +	// read register size +	size = bytestream2integer(src, src_offset); + +	// copy data into register area +	bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size); +//	llinfos << "Read CE: " << getCurrentEvents() << llendl; +	if (get_register(mBuffer, LREG_TM) != TOP_OF_MEMORY) +	{ +		llwarns << "Invalid state. Top of memory register does not match" +				<< " constant." << llendl; +		reset_hp_to_safe_spot(mBuffer); +		return -1; +	} +	 +	// read heap size +	size = bytestream2integer(src, src_offset); + +	// set dest offset +	dest_offset = get_register(mBuffer, LREG_HR); + +	if (dest_offset + size > TOP_OF_MEMORY) +	{ +		reset_hp_to_safe_spot(mBuffer); +		return -1; +	} + +	// copy data into heap area +	bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size); + +	// read stack size +	size = bytestream2integer(src, src_offset); + +	// set dest offset +	dest_offset = get_register(mBuffer, LREG_SP); + +	if (dest_offset + size > TOP_OF_MEMORY) +	{ +		reset_hp_to_safe_spot(mBuffer); +		return -1; +	} + +	// copy data into heap area +	bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size); + +	// Return offset to first byte after read data. +	return src_offset; +} + +void LLScriptExecuteLSL2::reset() +{ +	LLScriptExecute::reset(); + +	const U8 *src = getBytecode(); +	S32 size = getBytecodeSize(); + +	if (!src) +		return; + +	// first, blitz heap and stack +	S32 hr = get_register(mBuffer, LREG_HR); +	S32 tm = get_register(mBuffer, LREG_TM); +	memset(mBuffer + hr, 0, tm - hr); + +	S32 dest_offset = 0; +	S32 src_offset = 0; + +	bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size); +} + +LLScriptExecute::LLScriptExecute() : +	mReset(FALSE) +{ +} + +void LLScriptExecute::reset() +{ +	mReset = FALSE; +} + +bool LLScriptExecute::isYieldDue() const +{ +	if(mReset) +	{ +		return true; +	} +			 +	if(getSleep() > 0.f) +	{ +		return true; +	} + +	if(isFinished()) +	{ +		return true; +	} + +	if(isStateChangePending()) +	{ +		return true; +	} + +	return false; +} + +// Run smallest number of instructions possible:  +// a single instruction for LSL2, a segment between save tests for Mono +void LLScriptExecute::runInstructions(BOOL b_print, const LLUUID &id,  +									 const char **errorstr,  +									 BOOL &state_transition,  +									 U32& events_processed, +									 F32 quanta)  {  	//  is there a fault?  	//	if yes, print out message and exit -	state_transition = FALSE; -	S32 value = get_register(mBuffer, LREG_VN); +	S32 value = getVersion();  	S32 major_version = 0;  	if (value == LSL2_VERSION1_END_NUMBER)  	{ @@ -313,323 +781,151 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, const char **errorstr,  	}  	else  	{ -		set_fault(mBuffer, LSRF_VERSION_MISMATCH); +		setFault(LSRF_VERSION_MISMATCH);  	} -	value = get_register(mBuffer, LREG_FR); -	if (value) +	value = getFaults(); +	if (value > LSRF_INVALID && value < LSRF_EOF)  	{  		if (b_print)  		{  			printf("Error!\n");  		}  		*errorstr = LSCRIPTRunTimeFaultStrings[value]; -		return NO_DELETE_FLAG; +		return;  	}  	else  	{  		*errorstr = NULL;  	} -	//  Get IP -	//  is IP nonzero? -	value = get_register(mBuffer, LREG_IP); - -	if (value) +	if (! isFinished())  	{ -	//	if yes, we're in opcodes, execute the next opcode by: -	//	call opcode run function pointer with buffer and IP -		mInstructionCount++; -		sGlobalInstructionCount++; -		S32 tvalue = value; -		S32	opcode = safe_instruction_bytestream2byte(mBuffer, tvalue); -		S32 b_ret_val = mExecuteFuncs[opcode](mBuffer, value, b_print, id); -		set_ip(mBuffer, value); -		add_register_fp(mBuffer, LREG_ESR, -0.1f); -	//	lsa_print_heap(mBuffer); - -		if (b_print) -		{ -			lsa_print_heap(mBuffer); -			printf("ip: 0x%X\n", get_register(mBuffer, LREG_IP)); -			printf("sp: 0x%X\n", get_register(mBuffer, LREG_SP)); -			printf("bp: 0x%X\n", get_register(mBuffer, LREG_BP)); -			printf("hr: 0x%X\n", get_register(mBuffer, LREG_HR)); -			printf("hp: 0x%X\n", get_register(mBuffer, LREG_HP)); -		} -	//			update IP -		if (b_ret_val) -		{ -			return DELETE_FLAG | CREDIT_MONEY_FLAG; -		} -		else -		{ -			return NO_DELETE_FLAG; -		} +		resumeEventHandler(b_print, id, quanta); +		return;  	}  	else  	{  		// make sure that IE is zero -		set_event_register(mBuffer, LREG_IE, 0, major_version); - -	//	if no, we're in a state and waiting for an event -		S32 next_state = get_register(mBuffer, LREG_NS); -		S32 current_state = get_register(mBuffer, LREG_CS); -		U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); -		U64 event_register = get_event_register(mBuffer, LREG_ER, major_version); -	//	check NS to see if need to switch states (NS != CS) -		if (next_state != current_state) +		setCurrentHandler(0, major_version); + +		//	if no, we're in a state and waiting for an event +		U64 current_events = getCurrentEvents(major_version); +		U64 event_register = getEventHandlers(major_version); + +		//	check NS to see if need to switch states (NS != CS) +		if (isStateChangePending())  		{  			state_transition = TRUE; +  			// ok, blow away any pending events -			mEventData.mEventDataList.deleteAllData(); +			deleteAllEvents(); -	//		if yes, check state exit flag is set +			// if yes, check state exit flag is set  			if (current_events & LSCRIPTStateBitField[LSTT_STATE_EXIT])  			{ -	//			if yes, clear state exit flag -				set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[LSTT_STATE_EXIT], major_version); +				// if yes, clear state exit flag +				setCurrentHandler(LSCRIPTStateBitField[LSTT_STATE_EXIT], major_version);  				current_events &= ~LSCRIPTStateBitField[LSTT_STATE_EXIT]; -				set_event_register(mBuffer, LREG_CE, current_events, major_version); -	//			check state exit event handler -	//				if there is a handler, call it +				setCurrentEvents(current_events, major_version); + +				// check state exit event handler +				// if there is a handler, call it  				if (event_register & LSCRIPTStateBitField[LSTT_STATE_EXIT])  				{ -		//			push a zero to be popped -					lscript_push(mBuffer, 0); -		//			push sp as current bp -					S32 sp = get_register(mBuffer, LREG_SP); -					lscript_push(mBuffer, sp); - -		//			now, push any additional stack space -					S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT); -					if ( additional_size == -1 ) -					{	 -						recordBoundaryError( id ); -					} -					else -					{ -						lscript_pusharge(mBuffer, additional_size); - -						sp = get_register(mBuffer, LREG_SP); -						sp += additional_size; -						set_bp(mBuffer, sp); -		//				set IP to the event handler -						setStateEventOpcoodeStartSafely( current_state, LSTT_STATE_EXIT, id ); -					} -					return NO_DELETE_FLAG; +					++events_processed; +					callEventHandler(LSTT_STATE_EXIT, major_version, id, quanta); +					return;  				}  			} -	//		if no handler or no state exit flag switch to new state -	//		set state entry flag and clear other CE flags + +			// if no handler or no state exit flag switch to new state +			// set state entry flag and clear other CE flags  			current_events = LSCRIPTStateBitField[LSTT_STATE_ENTRY]; -			set_event_register(mBuffer, LREG_CE, current_events, major_version); -	//		copy NS to CS -			set_register(mBuffer, LREG_CS, next_state); -	//		copy new state's handled events into ER (SR + CS*4 + 4) -			U64 handled_events = get_handled_events(mBuffer, next_state); -			set_event_register(mBuffer, LREG_ER, handled_events, major_version); +			setCurrentEvents(current_events, major_version); + +			U64 handled_events = nextState(); +			setEventHandlers(handled_events, major_version);  		} -//		check to see if any current events are covered by events handled by this state (CE & ER != 0) -// now, we want to look like we were called like a function -//		0x0000:		00 00 00 00 (return ip) -//		0x0004:		bp			(current sp) -//		0x0008:		parameters -//		push sp -//		add parameter size -//		pop bp -//		set ip - -		S32 size = 0; -//			try to get next event from stack + +		// try to get next event from stack  		BOOL b_done = FALSE;  		LSCRIPTStateEventType event = LSTT_NULL; -		LLScriptDataCollection *eventdata; -		next_state = get_register(mBuffer, LREG_NS); -		current_state = get_register(mBuffer, LREG_CS); -		current_events = get_event_register(mBuffer, LREG_CE, major_version); -		event_register = get_event_register(mBuffer, LREG_ER, major_version); +		current_events = getCurrentEvents(major_version); +		event_register = getEventHandlers(major_version);  		// first, check to see if state_entry or onrez are raised and handled -		if (  (current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY]) +		if ((current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY])  			&&(current_events & event_register))  		{ -			// ok, this is easy since there isn't any data waiting, just set it -			//			push a zero to be popped -			lscript_push(mBuffer, 0); -//			push sp as current bp -			S32 sp = get_register(mBuffer, LREG_SP); -			lscript_push(mBuffer, sp); - -			event = return_first_event((S32)LSCRIPTStateBitField[LSTT_STATE_ENTRY]); -			set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); -			current_events &= ~LSCRIPTStateBitField[event]; -			set_event_register(mBuffer, LREG_CE, current_events, major_version); -//			now, push any additional stack space -			S32 additional_size = get_event_stack_size(mBuffer, current_state, event); -			if ( additional_size == -1 ) -			{	// b_done will be set, so we'll exit the loop at the bottom -				recordBoundaryError( id ); -			} -			else -			{ -				additional_size -= size; -				lscript_pusharge(mBuffer, additional_size); - -//			now set the bp correctly -				sp = get_register(mBuffer, LREG_SP); -				sp += additional_size + size; -				set_bp(mBuffer, sp); -//			set IP to the function -				setStateEventOpcoodeStartSafely( current_state, event, id ); -			} +			++events_processed; +			callEventHandler(LSTT_STATE_ENTRY, major_version, id, quanta);  			b_done = TRUE;  		} -		else if (  (current_events & LSCRIPTStateBitField[LSTT_REZ]) -				&&(current_events & event_register)) +		else if ((current_events & LSCRIPTStateBitField[LSTT_REZ]) +				 &&(current_events & event_register))  		{ -			for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData()) -			{ -				if (eventdata->mType & LSCRIPTStateBitField[LSTT_REZ]) -				{ -					//			push a zero to be popped -					lscript_push(mBuffer, 0); -		//			push sp as current bp -					S32 sp = get_register(mBuffer, LREG_SP); -					lscript_push(mBuffer, sp); - -					set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); -					current_events &= ~LSCRIPTStateBitField[event]; -					set_event_register(mBuffer, LREG_CE, current_events, major_version); - -	//				push any arguments that need to be pushed onto the stack -					// last piece of data will be type LST_NULL -					LLScriptLibData	*data = eventdata->mData; -					while (data->mType) -					{ -						size += lscript_push_variable(data, mBuffer); -						data++; -					} -		//			now, push any additional stack space -					S32 additional_size = get_event_stack_size(mBuffer, current_state, event); -					if ( additional_size == -1 ) -					{	// b_done will be set, so we'll exit the loop at the bottom -						recordBoundaryError( id ); -					} -					else -					{ -						additional_size -= size; -						lscript_pusharge(mBuffer, additional_size); - -			//			now set the bp correctly -						sp = get_register(mBuffer, LREG_SP); -						sp += additional_size + size; -						set_bp(mBuffer, sp); -			//			set IP to the function -						setStateEventOpcoodeStartSafely( current_state, event, id ); -						mEventData.mEventDataList.deleteCurrentData(); -					} -					b_done = TRUE; -					break; -				} -			} +			++events_processed; +			callQueuedEventHandler(LSTT_REZ, major_version, id, quanta); +			b_done = TRUE;  		}  		while (!b_done)  		{ -			eventdata = mEventData.getNextEvent(); -			if (eventdata) +			// Call handler for next queued event. +			if(getEventCount() > 0)  			{ -				event = eventdata->mType; - -				// make sure that we can actually handle this one -				if (LSCRIPTStateBitField[event] & event_register) -				{ -					//			push a zero to be popped -					lscript_push(mBuffer, 0); -		//			push sp as current bp -					S32 sp = get_register(mBuffer, LREG_SP); -					lscript_push(mBuffer, sp); - -					set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); -					current_events &= ~LSCRIPTStateBitField[event]; -					set_event_register(mBuffer, LREG_CE, current_events, major_version); - -	//				push any arguments that need to be pushed onto the stack -					// last piece of data will be type LST_NULL -					LLScriptLibData	*data = eventdata->mData; -					while (data->mType) -					{ -						size += lscript_push_variable(data, mBuffer); -						data++; -					} -					b_done = TRUE; -		//			now, push any additional stack space -					S32 additional_size = get_event_stack_size(mBuffer, current_state, event); -					if ( additional_size == -1 ) -					{	// b_done was just set, so we'll exit the loop at the bottom -						recordBoundaryError( id ); -					} -					else -					{ -						additional_size -= size; -						lscript_pusharge(mBuffer, additional_size); - -			//			now set the bp correctly -						sp = get_register(mBuffer, LREG_SP); -						sp += additional_size + size; -						set_bp(mBuffer, sp); -			//			set IP to the function -						setStateEventOpcoodeStartSafely( current_state, event, id ); -					} -				} -				else -				{ -					llwarns << "Shit, somehow got an event that we're not registered for!" << llendl; -				} -				delete eventdata; +				++events_processed; +				callNextQueuedEventHandler(event_register, major_version, id, quanta); +				b_done = TRUE;  			}  			else  			{ -//				if no data waiting, do it the old way: +				// if no data waiting, do it the old way:  				U64 handled_current = current_events & event_register;  				if (handled_current)  				{ -					//			push a zero to be popped -					lscript_push(mBuffer, 0); -		//			push sp as current bp -					S32 sp = get_register(mBuffer, LREG_SP); -					lscript_push(mBuffer, sp); -  					event = return_first_event((S32)handled_current); -					set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version); -					current_events &= ~LSCRIPTStateBitField[event]; -					set_event_register(mBuffer, LREG_CE, current_events, major_version); -		//			now, push any additional stack space -					S32 additional_size = get_event_stack_size(mBuffer, current_state, event); -					if ( additional_size == -1 ) -					{	// b_done will be set, so we'll exit the loop at the bottom -						recordBoundaryError( id ); -					} -					else -					{ -						additional_size -= size; -						lscript_pusharge(mBuffer, additional_size); - -			//			now set the bp correctly -						sp = get_register(mBuffer, LREG_SP); -						sp += additional_size + size; -						set_bp(mBuffer, sp); -			//			set IP to the function -						setStateEventOpcoodeStartSafely( current_state, event, id ); -					} +					++events_processed; +					callEventHandler(event, major_version, id, quanta);  				}  				b_done = TRUE;  			} -		}	// while (!b_done) -	} // end of else ...  in state processing code +		} +	} +} + +// Run for a single timeslice, or until a yield is due +F32 LLScriptExecute::runQuanta(BOOL b_print, const LLUUID &id, const char **errorstr, BOOL &state_transition, F32 quanta, U32& events_processed, LLTimer& timer) +{ +	U32 timer_checks = 0; +	F32 inloop = 0; -	return NO_DELETE_FLAG; +	// Loop while not finished, yield not due and time remaining +	// NOTE: Default implementation does not do adaptive timer skipping +	// to preserve current LSL behaviour and not break scripts that rely +	// on current execution speed. +	while(true) +	{ +		runInstructions(b_print, id, errorstr, state_transition,  +						events_processed, quanta); +		 +		static const S32 lsl_timer_check_skip = 4; +		if(isYieldDue()) +		{ +			break; +		} +		else if(timer_checks++ == lsl_timer_check_skip) +		{ +			inloop = timer.getElapsedTimeF32(); +			if(inloop > quanta) +			{ +				break; +			} +			timer_checks = 0; +		} +	} +	return inloop;  }  BOOL run_noop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) @@ -3687,6 +3983,11 @@ BOOL run_print(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)  void lscript_run(const std::string& filename, BOOL b_debug)  {  	LLTimer	timer; + +	const char *error; +	BOOL b_state; +	LLScriptExecuteLSL2 *execute = NULL; +  	if (filename.empty())  	{  		llerrs << "filename is NULL" << llendl; @@ -3694,47 +3995,35 @@ void lscript_run(const std::string& filename, BOOL b_debug)  		// to check how to abort or error out gracefully  		// from this function. XXXTBD  	} -	else +	LLFILE* file = LLFile::fopen(filename, "r");  /* Flawfinder: ignore */ +	if(file)  	{ -		const char *error; -		BOOL b_state; -		LLScriptExecute *execute = NULL; - -		LLFILE* file = LLFile::fopen(filename, "r"); -		if (file) -		{ -			execute = new LLScriptExecute(file); -			// note: LLScriptExecute() closes file for us -		} -		file = LLFile::fopen(filename, "r"); -		if (file) -		{ -			std::string parsefile("lscript.parse"); -			LLFILE* fp = LLFile::fopen(parsefile, "w");		/*Flawfinder: ignore*/ -			LLScriptLSOParse *parse = new LLScriptLSOParse(file); -			parse->printData(fp); -			delete parse; -			fclose(file); -			fclose(fp); -		} -		file = LLFile::fopen(filename, "r"); -		if (file && execute) -		{ -			timer.reset(); -			while (!execute->run(b_debug, LLUUID::null, &error, b_state)) -				; -			F32 time = timer.getElapsedTimeF32(); -			F32 ips = execute->mInstructionCount / time; -			llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl; -			llinfos << ips/1000 << "K instructions per second" << llendl; -			printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP)); -			printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP)); -			printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP)); -			printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR)); -			printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP)); -			delete execute; -			fclose(file); -		} +		execute = new LLScriptExecuteLSL2(file); +		fclose(file); +	} +	if (execute) +	{ +		timer.reset(); +		F32 time_slice = 3600.0f; // 1 hr. +		U32 events_processed = 0; + +		do { +			LLTimer timer2; +			execute->runQuanta(b_debug, LLUUID::null, &error, b_state,  +							   time_slice, events_processed, timer2); +		} while (!execute->isFinished()); + +		F32 time = timer.getElapsedTimeF32(); +		F32 ips = execute->mInstructionCount / time; +		llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl; +		llinfos << ips/1000 << "K instructions per second" << llendl; +		printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP)); +		printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP)); +		printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP)); +		printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR)); +		printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP)); +		delete execute; +		fclose(file);  	}  } diff --git a/indra/lscript/lscript_library.h b/indra/lscript/lscript_library.h index 74356256ae..a9db30670a 100644 --- a/indra/lscript/lscript_library.h +++ b/indra/lscript/lscript_library.h @@ -146,9 +146,9 @@ public:  		return FALSE;  	} -	S32 getListLength() +	S32 getListLength() const  	{ -		LLScriptLibData *data = this; +		const LLScriptLibData *data = this;  		S32 retval = 0;  		while (data->mListp)  		{ diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index b99bd64f2a..54d0154798 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -398,9 +398,8 @@ void LLScriptLibrary::init()  	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCameraPos", "v", "", "vector llGetCameraPos()\nGets current camera position for agent task has permissions for."));  	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCameraRot", "q", "", "rotation llGetCameraRot()\nGets current camera orientation for agent task has permissions for.")); -	addFunction(new LLScriptLibraryFunction(10.f, 2.f, dummy_func, "llSetPrimURL", NULL, "s", "llSetPrimURL(string url)\nUpdates the URL for the web page shown on the sides of the object.")); +	addFunction(new LLScriptLibraryFunction(10.f, 20.f, dummy_func, "llSetPrimURL", NULL, "s", "llSetPrimURL(string url)\nUpdates the URL for the web page shown on the sides of the object."));  	addFunction(new LLScriptLibraryFunction(10.f, 20.f, dummy_func, "llRefreshPrimURL", NULL, "", "llRefreshPrimURL()\nReloads the web page shown on the sides of the object.")); -	  	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llEscapeURL", "s", "s", "string llEscapeURL(string url)\nReturns and escaped/encoded version of url, replacing spaces with %20 etc."));  	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llUnescapeURL", "s", "s", "string llUnescapeURL(string url)\nReturns and unescaped/unencoded version of url, replacing %20 with spaces etc.")); @@ -458,24 +457,6 @@ void LLScriptLibrary::init()  	// existing scripts will crash.  } -	//Ventrella Follow Cam Script Stuff -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamPitch",				NULL, "f", "llSetCamPitch(-45 to 80)\n(Adjusts the angular amount that the camera aims straight ahead vs. straight down, maintaining the same distance. Analogous to 'incidence'.")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamVerticalOffset",		NULL, "f", "llSetCamVerticalOffset(-2 to 2)\nAdjusts the vertical position of the camera focus position relative to the subject")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamPositionLag",			NULL, "f", "llSetCamPositionLag(0 to 3) \nHow much the camera lags as it tries to move towards its 'ideal' position")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamFocusLag",			NULL, "f", "llSetCamFocusLag(0 to 3)\nHow much the camera lags as it tries to aim towards the subject")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamDistance",			NULL, "f", "llSetCamDistance(0.5 to 10)\nSets how far away the camera wants to be from its subject")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamBehindnessAngle",		NULL, "f", "llSetCamBehindnessAngle(0 to 180)\nSets the angle in degrees within which the camera is not constrained by changes in subject rotation")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamBehindnessLag",		NULL, "f", "llSetCamBehindnessLag(0 to 3)\nSets how strongly the camera is forced to stay behind the target if outside of behindness angle")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamPositionThreshold",	NULL, "f", "llSetCamPositionThreshold(0 to 4)\nSets the radius of a sphere around the camera's ideal position within which it is not affected by subject motion")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamFocusThreshold",		NULL, "f", "llSetCamFocusThreshold(0 to 4)\nSets the radius of a sphere around the camera's subject position within which its focus is not affected by subject motion")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamScriptControl",				NULL, "i", "llSetCamScriptControl(TRUE or FALSE)\nTurns on or off scripted control of the camera")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamPosition",			NULL, "v", "llSetCamPosition(vector)\nSets the position of the camera")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamFocus",				NULL, "v", "llSetCamFocus(vector focus)\nSets the focus (target position) of the camera")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamPositionLocked",		NULL, "i", "llSetCamPositionLocked(TRUE or FALSE)\nLocks the camera position so it will not move")); -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCamFocusLocked",			NULL, "i", "llSetCamFocusLocked(TRUE or FALSE)\nLocks the camera focus so it will not move")); - -	//addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetForSale", "i", "ii", "integer llSetForSale(integer selltype, integer price)\nSets this object for sale in mode selltype for price.  Returns TRUE if successfully set for sale.")); -  LLScriptLibraryFunction::LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, const char *desc, BOOL god_only)  		: mEnergyUse(eu), mSleepTime(st), mExecFunc(exec_func), mName(name), mReturnType(ret_type), mArgs(args), mGodOnly(god_only)  { diff --git a/indra/lscript/lscript_rt_interface.h b/indra/lscript/lscript_rt_interface.h index 3e05212c67..14559ab3e8 100644 --- a/indra/lscript/lscript_rt_interface.h +++ b/indra/lscript/lscript_rt_interface.h @@ -32,9 +32,9 @@  #ifndef LL_LSCRIPT_RT_INTERFACE_H  #define LL_LSCRIPT_RT_INTERFACE_H -BOOL lscript_compile(char *filename, BOOL is_god_like = FALSE); +BOOL lscript_compile(char *filename, BOOL compile_to_mono, BOOL is_god_like = FALSE);  BOOL lscript_compile(const char* src_filename, const char* dst_filename, -					 const char* err_filename, BOOL is_god_like = FALSE); +					 const char* err_filename, BOOL compile_to_mono, const char* class_name, BOOL is_god_like = FALSE);  void lscript_run(const std::string& filename, BOOL b_debug); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e65721e124..0fea3076c3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -66,6 +66,7 @@ set(viewer_SOURCE_FILES      llanimstatelabels.cpp      llappviewer.cpp      llassetuploadresponders.cpp +    llassetuploadqueue.cpp      llaudiosourcevo.cpp      llbbox.cpp      llbox.cpp @@ -454,6 +455,7 @@ set(viewer_HEADER_FILES      llappearance.h      llappviewer.h      llassetuploadresponders.h +    llassetuploadqueue.h      llaudiosourcevo.h      llbbox.h      llbox.h diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 7272173fed..881483e892 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,6 @@  /* Localized versions of Info.plist keys */  CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.20.6.86975"; -CFBundleGetInfoString = "Second Life version 1.20.6.86975, Copyright 2004-2008 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.20.9.87416"; +CFBundleGetInfoString = "Second Life version 1.20.9.87416, Copyright 2004-2008 Linden Research, Inc."; + diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index fa50503545..b889d45b9e 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@  		</dict>  	</array>  	<key>CFBundleVersion</key> -	<string>1.20.6.86975</string> +	<string>1.20.9.87416</string>  	<key>CSResourcesFileMapped</key>  	<true/>  </dict> diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp new file mode 100644 index 0000000000..c52c189d56 --- /dev/null +++ b/indra/newview/llassetuploadqueue.cpp @@ -0,0 +1,194 @@ +/**  + * @file llassetupload.cpp + * @brief Serializes asset upload request + * Copyright (c) 2007, Linden Research, Inc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llassetuploadqueue.h" +#include "llviewerregion.h" +#include "llviewerobjectlist.h" + +#include "llassetuploadresponders.h" +#include "llsd.h" +#include <iostream> + +class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder +{ +public: +	 +	LLAssetUploadChainResponder(const LLSD& post_data, +								const std::string& file_name, +								const LLUUID& queue_id, +								U8* data,  +								U32 data_size, +								std::string script_name, +								LLAssetUploadQueueSupplier *supplier) : +		LLUpdateTaskInventoryResponder(post_data, file_name, queue_id, LLAssetType::AT_LSL_TEXT), +		mSupplier(supplier), +		mData(data), +		mDataSize(data_size), +		mScriptName(script_name) +	{ + 	} + +	virtual ~LLAssetUploadChainResponder()  +   	{ +   		if(mSupplier) +   		{ +   			LLAssetUploadQueue *queue = mSupplier->get(); +   			if (queue) +   			{ +   				// Give ownership of supplier back to queue. +   				queue->mSupplier = mSupplier; +   				mSupplier = NULL; +   			} +   		} +   		delete mSupplier; +		delete mData; +   	} +	 +	virtual void error(U32 statusNum, const std::string& reason) +   	{ +		llwarns << "Error: " << reason << llendl; +		LLUpdateTaskInventoryResponder::error(statusNum, reason); +   		LLAssetUploadQueue *queue = mSupplier->get(); +   		if (queue) +		{ +   			queue->request(&mSupplier); +   		} +   	} + +	virtual void result(const LLSD& content) +   	{ +		LLUpdateTaskInventoryResponder::result(content); +   		LLAssetUploadQueue *queue = mSupplier->get(); +   		if (queue) +   		{ +   			// Responder is reused across 2 phase upload, +   			// so only start next upload after 2nd phase complete. +   			std::string state = content["state"]; +   			if(state == "complete") +   			{ +   				queue->request(&mSupplier); +   			} +   		}	 +   	} +	 +	virtual void uploadUpload(const LLSD& content) +	{ +		std::string uploader = content["uploader"]; + +		mSupplier->log(std::string("Compiling " + mScriptName).c_str()); +		llinfos << "Compiling " << llendl; + +		// postRaw takes ownership of mData and will delete it. +		LLHTTPClient::postRaw(uploader, mData, mDataSize, this); +		mData = NULL; +		mDataSize = 0; +	} + +	virtual void uploadComplete(const LLSD& content) +	{ +		// Bytecode save completed +		if (content["compiled"]) +		{ +			mSupplier->log("Compilation succeeded"); +			llinfos << "Compiled!" << llendl; +		} +		else +		{ +			LLSD compile_errors = content["errors"]; +			for(LLSD::array_const_iterator line	= compile_errors.beginArray(); +				line < compile_errors.endArray(); line++) +			{ +				mSupplier->log(line->asString()); +				llinfos << content["errors"] << llendl; +			} +		} +		LLUpdateTaskInventoryResponder::uploadComplete(content); +	} + +	LLAssetUploadQueueSupplier *mSupplier; +	U8* mData; +	U32 mDataSize; +	std::string mScriptName; +}; + + +LLAssetUploadQueue::LLAssetUploadQueue(LLAssetUploadQueueSupplier *supplier) : +	mSupplier(supplier) +{ +} + +//virtual  +LLAssetUploadQueue::~LLAssetUploadQueue() +{ +	delete mSupplier; +} + +// Takes ownership of supplier. +void LLAssetUploadQueue::request(LLAssetUploadQueueSupplier** supplier) +{ +	if (mQueue.empty()) +		return; + +	UploadData data = mQueue.front(); +	mQueue.pop_front(); +	 +	LLSD body; +	body["task_id"] = data.mTaskId; +	body["item_id"] = data.mItemId; +	body["is_script_running"] = data.mIsRunning; +	body["target"] = data.mIsTargetMono? "mono" : "lsl2"; + +	std::string url = ""; +	LLViewerObject* object = gObjectList.findObject(data.mTaskId); +	if (object) +	{ +		url = object->getRegion()->getCapability("UpdateScriptTaskInventory"); +		LLHTTPClient::post(url, body, +							new LLAssetUploadChainResponder( +								body, data.mFilename, data.mQueueId,  +								data.mData, data.mDataSize, data.mScriptName, *supplier)); +	} + +	*supplier = NULL; +} + +void LLAssetUploadQueue::queue(const std::string& filename, +							   const LLUUID& task_id, +							   const LLUUID& item_id, +							   BOOL is_running,  +							   BOOL is_target_mono,  +							   const LLUUID& queue_id, +							   U8* script_data, +							   U32 data_size, +							   std::string script_name) +{ +	UploadData data; +	data.mTaskId = task_id; +	data.mItemId = item_id; +	data.mIsRunning = is_running; +	data.mIsTargetMono = is_target_mono; +	data.mQueueId = queue_id; +	data.mFilename = filename; +	data.mData = script_data; +	data.mDataSize = data_size; +	data.mScriptName = script_name; +			 +	mQueue.push_back(data); + +	if(mSupplier) +	{ +		request(&mSupplier); +	}	 +} + +LLAssetUploadQueueSupplier::~LLAssetUploadQueueSupplier() +{ +} diff --git a/indra/newview/llassetuploadqueue.h b/indra/newview/llassetuploadqueue.h new file mode 100644 index 0000000000..6e4caa1b0f --- /dev/null +++ b/indra/newview/llassetuploadqueue.h @@ -0,0 +1,74 @@ +/**  + * @file llassetuploadqueue.h + * @brief Serializes asset upload request + * Copyright (c) 2007, Linden Research, Inc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * $/LicenseInfo$ + */ + +#ifndef LL_LLASSETUPLOADQUEUE_H +#define LL_LLASSETUPLOADQUEUE_H + +#include "lluuid.h" + +#include <string> +#include <deque> + +class LLAssetUploadQueueSupplier; + +class LLAssetUploadQueue +{ +public: + +	// Takes ownership of supplier. +	LLAssetUploadQueue(LLAssetUploadQueueSupplier* supplier); +	virtual ~LLAssetUploadQueue(); + +	void queue(const std::string& filename, +			   const LLUUID& task_id, +			   const LLUUID& item_id, +			   BOOL is_running,  +			   BOOL is_target_mono,  +			   const LLUUID& queue_id, +			   U8* data, +			   U32 data_size, +			   std::string script_name); + +	bool isEmpty() const {return mQueue.empty();} + +private: + +	friend class LLAssetUploadChainResponder; + +	struct UploadData +	{ +		std::string mFilename; +		LLUUID mTaskId; +		LLUUID mItemId; +		BOOL mIsRunning; +		BOOL mIsTargetMono; +		LLUUID mQueueId; +		U8* mData; +		U32 mDataSize; +		std::string mScriptName; +	}; + +	// Ownership of mSupplier passed to currently waiting responder +	// and returned to queue when no requests in progress. +	LLAssetUploadQueueSupplier* mSupplier; +	std::deque<UploadData> mQueue; + +	// Passes on ownership of mSupplier if request is made. +	void request(LLAssetUploadQueueSupplier** supplier); +}; + +class LLAssetUploadQueueSupplier +{ +public: +	virtual ~LLAssetUploadQueueSupplier(); +	virtual LLAssetUploadQueue* get() const = 0; +	virtual void log(std::string message) const = 0; +}; + +#endif // LL_LLASSETUPLOADQUEUE_H diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 3d91384f48..962066471f 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -34,6 +34,7 @@  #include "llassetuploadresponders.h"  #include "llagent.h" +#include "llcompilequeue.h"  #include "llfloaterbuycurrency.h"  #include "lleconomy.h"  #include "llfilepicker.h" @@ -73,11 +74,12 @@ LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,  }  LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, -											   const std::string& file_name) +											   const std::string& file_name,  +											   LLAssetType::EType asset_type)  	: LLHTTPClient::Responder(),  	  mPostData(post_data), -	  mAssetType(LLAssetType::AT_NONE), -	  mFileName(file_name) +	  mFileName(file_name), +	  mAssetType(asset_type)  {  } @@ -182,8 +184,8 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data  {  } -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name) -: LLAssetUploadResponder(post_data, file_name) +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, file_name, asset_type)  {  } @@ -301,8 +303,9 @@ LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& pos  }  LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, -																 const std::string& file_name) -: LLAssetUploadResponder(post_data, file_name) +																 const std::string& file_name, +																 LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, file_name, asset_type)  {  } @@ -410,8 +413,17 @@ LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_  }  LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, -															   const std::string& file_name) -: LLAssetUploadResponder(post_data, file_name) +															   const std::string& file_name,  +															   LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, file_name, asset_type) +{ +} + +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, +															   const std::string& file_name, +															   const LLUUID& queue_id,  +															   LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, file_name, asset_type), mQueueId(queue_id)  {  } @@ -422,35 +434,16 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)  	LLUUID item_id = mPostData["item_id"];  	LLUUID task_id = mPostData["task_id"]; -	LLViewerObject* object = gObjectList.findObject(task_id); -	if (!object) -	{ -		llwarns << "LLUpdateTaskInventoryResponder::uploadComplete task " << task_id -			<< " no longer exist." << llendl; -		return; -	} -	LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(item_id); -	if (!item) -	{ -		llwarns << "LLUpdateTaskInventoryResponder::uploadComplete item " -			<< item_id << " is no longer in task " << task_id -			<< "'s inventory." << llendl; -		return; -	} -	LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); -	// Update Viewer inventory -	object->updateViewerInventoryAsset(new_item, content["new_asset"]);  	dialog_refresh_all(); -	LLInventoryType::EType inventory_type = new_item->getInventoryType(); -	switch(inventory_type) +	switch(mAssetType)  	{ -		case LLInventoryType::IT_NOTECARD: +		case LLAssetType::AT_NOTECARD:  			{  				// Update the UI with the new asset.  				LLPreviewNotecard* nc; -				nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID()); +				nc = (LLPreviewNotecard*)LLPreview::find(item_id);  				if(nc)  				{  					// *HACK: we have to delete the asset in the VFS so @@ -470,28 +463,39 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)  				}  			}  			break; -		case LLInventoryType::IT_LSL: +		case LLAssetType::AT_LSL_TEXT:  			{ -				LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id); -				if (preview) +				if(mQueueId.notNull())  				{ -					// Bytecode save completed -					if (content["compiled"]) +					LLFloaterCompileQueue* queue =  +						(LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); +					if(NULL != queue)  					{ -						preview->callbackLSLCompileSucceeded( -							task_id, -							item_id, -							mPostData["is_script_running"]); +						queue->removeItemByItemID(item_id);  					} -					else +				} +				else +				{ +					LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id); +					if (preview)  					{ -						preview->callbackLSLCompileFailed(content["errors"]); +						// Bytecode save completed +						if (content["compiled"]) +						{ +							preview->callbackLSLCompileSucceeded( +								task_id, +								item_id, +								mPostData["is_script_running"]); +						} +						else +						{ +							preview->callbackLSLCompileFailed(content["errors"]); +						}  					}  				}  			}  			break; -		case LLInventoryType::IT_WEARABLE: -		default: -			break; +	default: +		break;  	}  } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 25f3f4c3b1..dc4f6e7bf0 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -42,7 +42,9 @@ public:  	LLAssetUploadResponder(const LLSD& post_data,  							const LLUUID& vfile_id,  							LLAssetType::EType asset_type); -	LLAssetUploadResponder(const LLSD& post_data, const std::string& file_name); +	LLAssetUploadResponder(const LLSD& post_data,  +							const std::string& file_name, +							LLAssetType::EType asset_type);  	~LLAssetUploadResponder();      virtual void error(U32 statusNum, const std::string& reason);  	virtual void result(const LLSD& content); @@ -52,8 +54,8 @@ public:  protected:  	LLSD mPostData; -	LLUUID mVFileID;  	LLAssetType::EType mAssetType; +	LLUUID mVFileID;  	std::string mFileName;  }; @@ -63,7 +65,8 @@ public:  	LLNewAgentInventoryResponder(const LLSD& post_data,  								const LLUUID& vfile_id,  								LLAssetType::EType asset_type); -	LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name); +	LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, +											   LLAssetType::EType asset_type);  	virtual void uploadComplete(const LLSD& content);  }; @@ -74,7 +77,8 @@ public:  								const LLUUID& vfile_id,  								LLAssetType::EType asset_type);  	LLUpdateAgentInventoryResponder(const LLSD& post_data, -								const std::string& file_name); +								const std::string& file_name, +											   LLAssetType::EType asset_type);  	virtual void uploadComplete(const LLSD& content);  }; @@ -85,8 +89,17 @@ public:  								const LLUUID& vfile_id,  								LLAssetType::EType asset_type);  	LLUpdateTaskInventoryResponder(const LLSD& post_data, -								const std::string& file_name); +								const std::string& file_name, +								LLAssetType::EType asset_type); +	LLUpdateTaskInventoryResponder(const LLSD& post_data, +								const std::string& file_name, +								const LLUUID& queue_id, +								LLAssetType::EType asset_type); +  	virtual void uploadComplete(const LLSD& content); +	 +private: +	LLUUID mQueueId;  };  #endif // LL_LLASSETUPLOADRESPONDER_H diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 3ab340f66a..30d5dc206f 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -42,6 +42,8 @@  #include "llcompilequeue.h"  #include "llagent.h" +#include "llassetuploadqueue.h" +#include "llassetuploadresponders.h"  #include "llchat.h"  #include "llviewerwindow.h"  #include "llviewerobject.h" @@ -72,20 +74,15 @@ const std::string RUN_START_STRING("set running");  const std::string NOT_RUN_QUEUE_TITLE("Set Not Running Progress");  const std::string NOT_RUN_START_STRING("set not running"); -struct LLCompileQueueData -{ -	LLUUID mQueueID; -	LLUUID mOldAssetID; -	LLCompileQueueData(const LLUUID& q_id, const LLUUID& old_asset_id) : -		mQueueID(q_id), mOldAssetID(old_asset_id) {} -}; -  struct LLScriptQueueData  {  	LLUUID mQueueID;  	std::string mScriptName; -	LLScriptQueueData(const LLUUID& q_id, const std::string& name) : -		mQueueID(q_id), mScriptName(name) {} +	LLUUID mTaskId; +	LLUUID mItemId; +	LLScriptQueueData(const LLUUID& q_id, const std::string& name, const LLUUID& task_id, const LLUUID& item_id) : +		mQueueID(q_id), mScriptName(name), mTaskId(task_id), mItemId(item_id) {} +  };  ///---------------------------------------------------------------------------- @@ -105,7 +102,8 @@ LLFloaterScriptQueue::LLFloaterScriptQueue(const std::string& name,  			  RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,  			  DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES)  { - +	mID.generate(); +	  	LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_queue.xml");  	childSetAction("close",onCloseBtn,this); @@ -113,11 +111,8 @@ LLFloaterScriptQueue::LLFloaterScriptQueue(const std::string& name,  	setTitle(title); -	if (!getHost()) -	{ -		LLRect curRect = getRect(); -		translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop); -	} +	LLRect curRect = getRect(); +	translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);  	mStartString = start_string;  	mDone = FALSE; @@ -279,14 +274,57 @@ BOOL LLFloaterScriptQueue::popNext()  ///----------------------------------------------------------------------------  // static -LLFloaterCompileQueue* LLFloaterCompileQueue::create() +LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono)  {  	S32 left, top;  	gFloaterView->getNewFloaterPosition(&left, &top);  	LLRect rect = gSavedSettings.getRect("CompileOutputRect");  	rect.translate(left - rect.mLeft, top - rect.mTop);  	LLFloaterCompileQueue* new_queue = new LLFloaterCompileQueue("queue", rect); -	new_queue->open(); 	 	/*Flawfinder: ignore*/  +	 +	class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier +	{ +	public: +	 +		LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) : +			mQueueId(queue_id) +		{ +		} +		 +		virtual LLAssetUploadQueue* get() const  +		{ +			LLFloaterCompileQueue* queue =  +				(LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); +			 +			if(NULL == queue) +			{ +				return NULL; +			} +			 +			return queue->mUploadQueue; +		} + +		virtual void log(std::string message) const +		{ +			LLFloaterCompileQueue* queue =  +				(LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); + +			if(NULL == queue) +			{ +				return; +			} + +			LLScrollListCtrl* list = queue->getChild<LLScrollListCtrl>("queue output"); +			list->addCommentText(message.c_str()); +		} +		 +	private: +		LLUUID mQueueId; +	}; +																 															  +	new_queue->mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(new_queue->getID()));															  +	new_queue->mMono = mono; +	new_queue->open();  	return new_queue;  } @@ -304,7 +342,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,  	// find all of the lsl, leaving off duplicates. We'll remove  	// all matching asset uuids on compilation success. -	typedef std::map<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map; +	typedef std::multimap<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map;  	uuid_item_map asset_item_map;  	InventoryObjectList::const_iterator it = inv->begin(); @@ -315,17 +353,12 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,  		{  			LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));  			// Check permissions before allowing the user to retrieve data. -			if (item->getPermissions().allowModifyBy(gAgent.getID())  && -				item->getPermissions().allowCopyBy(gAgent.getID()) ) +			if (item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID())  && +				item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()) )  			{  				LLPointer<LLViewerInventoryItem> script = new LLViewerInventoryItem(item);  				mCurrentScripts.put(script); - -				if (!asset_item_map.count(item->getAssetUUID())) -				{ -					// No entry, put in an entry for this supposedly permissive script -					asset_item_map[item->getAssetUUID()] = item; -				} +				asset_item_map.insert(std::make_pair(item->getAssetUUID(), item));  			}  		}  	} @@ -342,7 +375,10 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,  		for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++)  		{  			LLInventoryItem *itemp = iter->second; -			LLScriptQueueData* datap = new LLScriptQueueData(getID(), itemp->getName()); +			LLScriptQueueData* datap = new LLScriptQueueData(getID(), +												 itemp->getName(), +												 viewer_object->getID(), +												 itemp->getUUID());  			//llinfos << "ITEM NAME 2: " << names.get(i) << llendl;  			gAssetStorage->getInvItemAsset(viewer_object->getRegion()->getHost(), @@ -359,7 +395,6 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,  	}  } -  // This is the callback for when each script arrives  // static  void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, @@ -382,31 +417,58 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,  		std::string uuid_str;  		asset_id.toString(uuid_str);  		filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + llformat(".%s",LLAssetType::lookup(type)); - -		LLFILE *fp = LLFile::fopen(filename, "wb");	 /*Flawfinder: ignore*/ -		if (fp) +		 +		const bool is_running = true; +		LLViewerObject* object = gObjectList.findObject(data->mTaskId); +		if (object)  		{ -			const S32 buf_size = 65536; -			U8 copy_buf[buf_size]; -			while (file.read(copy_buf, buf_size)) 	 /*Flawfinder: ignore*/ +			std::string url = object->getRegion()->getCapability("UpdateScriptTaskInventory"); +			if(!url.empty()) +			{ +				// Read script source in to buffer. +				U32 script_size = file.getSize(); +				U8* script_data = new U8[script_size]; +				file.read(script_data, script_size); + +				queue->mUploadQueue->queue(filename, data->mTaskId,  +				data->mItemId, is_running, queue->mMono, queue->getID(), +				script_data, script_size, data->mScriptName); +			} +			else  			{ -				if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1) +				// It's now in the file, now compile it. +				buffer = std::string("Downloaded, now compiling: ") + data->mScriptName; // *TODO: Translate + +				// Write script to local file for compilation. +				LLFILE *fp = LLFile::fopen(filename, "wb");	 /*Flawfinder: ignore*/ +				if (fp)  				{ -					// return a bad file error if we can't write the whole thing -					status = LL_ERR_CANNOT_OPEN_FILE; +					const S32 buf_size = 65536; +					U8 copy_buf[buf_size]; +					 +					while (file.read(copy_buf, buf_size)) 	 /*Flawfinder: ignore*/ +					{ +						if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1) +						{ +							// return a bad file error if we can't write the whole thing +							status = LL_ERR_CANNOT_OPEN_FILE; +						} +					} + +					fclose(fp); +				} +				else +				{ +					llerrs << "Unable to find object to compile" << llendl;  				} -			} -			fclose(fp); +				// TODO: babbage: No compile if no cap. +				queue->compile(filename, data->mItemId); +					 +				// Delete it after we're done compiling? +				LLFile::remove(filename); +			}  		} - -		// *TODO: translate -		// It's now in the file, now compile it. -		buffer = std::string("Downloaded, now compiling: ") + data->mScriptName; // *TODO: Translate -		queue->compile(filename, asset_id); - -		// Delete it after we're done compiling? -		LLFile::remove(filename);  	}  	else  	{ @@ -430,9 +492,9 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,  		}  		llwarns << "Problem downloading script asset." << llendl; -		if(queue) queue->removeItemByAssetID(asset_id); +		if(queue) queue->removeItemByItemID(data->mItemId);  	} -	if(queue)  +	if(queue && (buffer.size() > 0))   	{  		LLScrollListCtrl* list = queue->getChild<LLScrollListCtrl>("queue output");  		list->addCommentText(buffer); @@ -462,9 +524,8 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void*  				(LLFloaterScriptQueue::findInstance(data->mQueueID));  	if(queue && (0 == status) && data)  	{ -		queue->updateAssetID(data->mOldAssetID, asset_id); -		queue->saveItemByAssetID(asset_id); -		queue->removeItemByAssetID(asset_id); +		queue->saveItemByItemID(data->mItemId); +		queue->removeItemByItemID(data->mItemId);  	}  	else  	{ @@ -479,7 +540,7 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void*  // compile the file given and save it out.  void LLFloaterCompileQueue::compile(const std::string& filename, -									const LLUUID& asset_id) +									const LLUUID& item_id)  {  	LLUUID new_asset_id;  	LLTransactionID tid; @@ -496,29 +557,34 @@ void LLFloaterCompileQueue::compile(const std::string& filename,  	gAssetStorage->storeAssetData(filename, tid,  								  LLAssetType::AT_LSL_TEXT,  								  &onSaveTextComplete, NULL, FALSE); -	if(!lscript_compile(filename.c_str(), dst_filename.c_str(), err_filename.c_str(), gAgent.isGodlike())) + +	const BOOL compile_to_mono = FALSE; +	if(!lscript_compile(filename.c_str(), dst_filename.c_str(), +						err_filename.c_str(), compile_to_mono, +						uuid_string.c_str(), gAgent.isGodlike()))  	{  		llwarns << "compile failed" << llendl; -		removeItemByAssetID(asset_id); +		removeItemByItemID(item_id);  	}  	else  	{  		llinfos << "compile successful." << llendl; -		// Save the bytecode -		LLCompileQueueData* data = new LLCompileQueueData(mID, asset_id); -		gAssetStorage->storeAssetData(dst_filename, tid, -									  LLAssetType::AT_LSL_BYTECODE, -									  &onSaveBytecodeComplete, -									  (void*)data, FALSE); +		 +		// Save LSL bytecode +		LLCompileQueueData* data = new LLCompileQueueData(mID, item_id); +		gAssetStorage->storeAssetData(dst_filename, new_asset_id, +									LLAssetType::AT_LSL_BYTECODE, +									&LLFloaterCompileQueue::onSaveBytecodeComplete, +									(void*)data, FALSE);  	}  } -void LLFloaterCompileQueue::removeItemByAssetID(const LLUUID& asset_id) +void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id)  {  	llinfos << "LLFloaterCompileQueue::removeItemByAssetID()" << llendl;  	for(S32 i = 0; i < mCurrentScripts.count(); )  	{ -		if(asset_id == mCurrentScripts.get(i)->getAssetUUID()) +		if(asset_id == mCurrentScripts.get(i)->getUUID())  		{  			mCurrentScripts.remove(i);  		} @@ -533,7 +599,21 @@ void LLFloaterCompileQueue::removeItemByAssetID(const LLUUID& asset_id)  	}  } -void LLFloaterCompileQueue::saveItemByAssetID(const LLUUID& asset_id) +const LLInventoryItem* LLFloaterCompileQueue::findItemByItemID(const LLUUID& asset_id) const +{ +	LLInventoryItem* result = NULL; +	S32 count = mCurrentScripts.count(); +	for(S32 i = 0; i < count; ++i) +	{ +		if(asset_id == mCurrentScripts.get(i)->getUUID()) +		{ +			result = mCurrentScripts.get(i); +		} +	} +	return result; +} + +void LLFloaterCompileQueue::saveItemByItemID(const LLUUID& asset_id)  {  	llinfos << "LLFloaterCompileQueue::saveItemByAssetID()" << llendl;  	LLViewerObject* viewer_object = gObjectList.findObject(mCurrentObjectID); @@ -542,7 +622,7 @@ void LLFloaterCompileQueue::saveItemByAssetID(const LLUUID& asset_id)  		S32 count = mCurrentScripts.count();  		for(S32 i = 0; i < count; ++i)  		{ -			if(asset_id == mCurrentScripts.get(i)->getAssetUUID()) +			if(asset_id == mCurrentScripts.get(i)->getUUID())  			{  				// *FIX: this auto-resets active to TRUE. That might  				// be a bad idea. @@ -556,20 +636,6 @@ void LLFloaterCompileQueue::saveItemByAssetID(const LLUUID& asset_id)  	}  } -// find old_asst_id, and set the asset id to new_asset_id -void LLFloaterCompileQueue::updateAssetID(const LLUUID& old_asset_id, -										  const LLUUID& new_asset_id) -{ -	S32 count = mCurrentScripts.count(); -	for(S32 i = 0; i < count; ++i) -	{ -		if(old_asset_id == mCurrentScripts.get(i)->getAssetUUID()) -		{ -			mCurrentScripts.get(i)->setAssetUUID(new_asset_id); -		} -	} -} -  ///----------------------------------------------------------------------------  /// Class LLFloaterResetQueue  ///---------------------------------------------------------------------------- @@ -582,7 +648,8 @@ LLFloaterResetQueue* LLFloaterResetQueue::create()  	LLRect rect = gSavedSettings.getRect("CompileOutputRect");  	rect.translate(left - rect.mLeft, top - rect.mTop);  	LLFloaterResetQueue* new_queue = new LLFloaterResetQueue("queue", rect); -	new_queue->open();	 /*Flawfinder: ignore*/ +	gFloaterView->addChild(new_queue); +	new_queue->open();  	return new_queue;  } diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index be7bbd5ceb..68e9a27266 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -64,6 +64,9 @@ public:  	// start() returns TRUE if the queue has started, otherwise FALSE.  	BOOL start(); +	// find an instance by ID. Return NULL if it does not exist. +	static LLFloaterScriptQueue* findInstance(const LLUUID& id); +  protected:  	LLFloaterScriptQueue(const std::string& name, const LLRect& rect,  						 const std::string& title, const std::string& start_string); @@ -92,9 +95,6 @@ protected:  	// Get this instances ID.  	const LLUUID& getID() const { return mID; }  - -	// find an instance by ID. Return NULL if it does not exist. -	static LLFloaterScriptQueue* findInstance(const LLUUID& id);  protected:  	// UI @@ -118,12 +118,29 @@ protected:  // This script queue will recompile each script.  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +struct LLCompileQueueData +{ +	LLUUID mQueueID; +	LLUUID mItemId; +	LLCompileQueueData(const LLUUID& q_id, const LLUUID& item_id) : +		mQueueID(q_id), mItemId(item_id) {} +}; + +class LLAssetUploadQueue; +  class LLFloaterCompileQueue : public LLFloaterScriptQueue  {  public:  	// Use this method to create a compile queue. Once created, it  	// will be responsible for it's own destruction. -	static LLFloaterCompileQueue* create(); +	static LLFloaterCompileQueue* create(BOOL mono); + +	static void onSaveBytecodeComplete(const LLUUID& asset_id, +									void* user_data, +									S32 status); +									 +	// remove any object in mScriptScripts with the matching uuid. +	void removeItemByItemID(const LLUUID& item_id);  protected:  	LLFloaterCompileQueue(const std::string& name, const LLRect& rect); @@ -139,6 +156,7 @@ protected:  								void* user_data, S32 status, LLExtStat ext_status);  	static void onSaveTextComplete(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status); +  	static void onSaveBytecodeComplete(const LLUUID& asset_id,  									   void* user_data,  									   S32 status, LLExtStat ext_status); @@ -149,14 +167,18 @@ protected:  	// remove any object in mScriptScripts with the matching uuid.  	void removeItemByAssetID(const LLUUID& asset_id); -	// save the items indicatd by the asset id. -	void saveItemByAssetID(const LLUUID& asset_id); +	// save the items indicated by the item id. +	void saveItemByItemID(const LLUUID& item_id); -	// find old_asst_id, and set the asset id to new_asset_id -	void updateAssetID(const LLUUID& old_asset_id, const LLUUID& new_asset_id); +	// find InventoryItem given item id. +	const LLInventoryItem* findItemByItemID(const LLUUID& item_id) const;  protected:  	LLViewerInventoryItem::item_array_t mCurrentScripts; + +private: +	BOOL mMono; // Compile to mono. +	LLAssetUploadQueue* mUploadQueue;  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 3c1b89d04b..2d0723f1eb 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -170,6 +170,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		F32 score;  		std::string name_buf;  		std::string owner_buf; +		F32 mono_score;  		msg->getU32Fast(_PREHASH_ReportData, _PREHASH_TaskLocalID, task_local_id, block);  		msg->getUUIDFast(_PREHASH_ReportData, _PREHASH_TaskID, task_id, block); @@ -192,6 +193,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		element["columns"][0]["column"] = "score";  		element["columns"][0]["value"] = llformat("%0.3f", score);  		element["columns"][0]["font"] = "SANSSERIF"; +		  		element["columns"][1]["column"] = "name";  		element["columns"][1]["value"] = name_buf;  		element["columns"][1]["font"] = "SANSSERIF"; @@ -205,6 +207,14 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)  		element["columns"][3]["value"] = formatted_time((time_t)time_stamp);  		element["columns"][3]["font"] = "SANSSERIF"; +		if (mCurrentMode == STAT_REPORT_TOP_SCRIPTS) +		{ +			msg->getF32Fast(_PREHASH_ReportData, "MonoScore", mono_score, block); +			element["columns"][4]["column"] = "Mono Time"; +			element["columns"][4]["value"] = llformat("%0.3f", mono_score); +			element["columns"][4]["font"] = "SANSSERIF"; +		} +  		list->addElement(element);  		mObjectListData.append(element); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 75e8f52cfc..71733e5cd7 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -139,6 +139,12 @@ const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;  const S32 MAX_HISTORY_COUNT = 10;  const F32 LIVE_HELP_REFRESH_TIME = 1.f; +static bool have_script_upload_cap(LLUUID& object_id) +{ +	LLViewerObject* object = gObjectList.findObject(object_id); +	return object && (! object->getRegion()->getCapability("UpdateScriptTaskInventory").empty()); +} +  /// ---------------------------------------------------------------------------  /// LLFloaterScriptSearch  /// --------------------------------------------------------------------------- @@ -173,7 +179,7 @@ private:  LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;  LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core) -	: LLFloater(std::string("script search"),rect,title), mEditorCore(editor_core) +	: LLFloater("script	search",rect,title), mEditorCore(editor_core)  {  	LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_search.xml"); @@ -306,14 +312,15 @@ LLScriptEdCore::LLScriptEdCore(  	mUserdata( userdata ),  	mForceClose( FALSE ),  	mLastHelpToken(NULL), -	mLiveHelpHistorySize(0) +	mLiveHelpHistorySize(0), +	mEnableSave(FALSE)  {  	setFollowsAll();  	setBorderVisible(FALSE);  	LLUICtrlFactory::getInstance()->buildPanel(this, "floater_script_ed_panel.xml"); -	 +  	mErrorList = getChild<LLScrollListCtrl>("lsl errors");  	mFunctions = getChild<LLComboBox>( "Insert..."); @@ -439,13 +446,13 @@ BOOL LLScriptEdCore::hasChanged(void* userdata)  	LLScriptEdCore* self = (LLScriptEdCore*)userdata;  	if (!self || !self->mEditor) return FALSE; -	return !self->mEditor->isPristine(); +	return !self->mEditor->isPristine() || self->mEnableSave;  }  void LLScriptEdCore::draw()  { -	BOOL script_changed = !mEditor->isPristine(); -	childSetEnabled("Save_btn", script_changed); +	BOOL script_changed	= hasChanged(this); +	childSetEnabled("Save_btn",	script_changed);  	if( mEditor->hasFocus() )  	{ @@ -594,7 +601,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string)  BOOL LLScriptEdCore::canClose()  { -	if(mForceClose || mEditor->isPristine()) +	if(mForceClose || !hasChanged(this))  	{  		return TRUE;  	} @@ -1133,7 +1140,9 @@ void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors)  		line++)  	{  		LLSD row; -		row["columns"][0]["value"] = line->asString(); +		std::string error_message = line->asString(); +		LLStringUtil::stripNonprintable(error_message); +		row["columns"][0]["value"] = error_message;  		row["columns"][0]["font"] = "OCRA";  		mScriptEd->mErrorList->addElement(row);  	} @@ -1247,7 +1256,7 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)  void LLPreviewLSL::saveIfNeeded()  {  	// llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl; -	if(mScriptEd->mEditor->isPristine()) +	if(!LLScriptEdCore::hasChanged(mScriptEd))  	{  		return;  	} @@ -1305,7 +1314,8 @@ void LLPreviewLSL::uploadAssetViaCaps(const std::string& url,  	llinfos << "Update Agent Inventory via capability" << llendl;  	LLSD body;  	body["item_id"] = item_id; -	LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename)); +	body["target"] = "lsl2"; +	LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT));  }  void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, @@ -1326,9 +1336,12 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename,  	std::string dst_filename = llformat("%s.lso", filepath.c_str());  	std::string err_filename = llformat("%s.out", filepath.c_str()); +	const BOOL compile_to_mono = FALSE;  	if(!lscript_compile(filename.c_str(),  						dst_filename.c_str(),  						err_filename.c_str(), +						compile_to_mono, +						asset_id.asString().c_str(),  						gAgent.isGodlike()))  	{  		llinfos << "Compile failed!" << llendl; @@ -1601,7 +1614,8 @@ LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,  	mAskedForRunningInfo(FALSE),  	mHaveRunningInfo(FALSE),  	mCloseAfterSave(FALSE), -	mPendingUploads(0) +	mPendingUploads(0), +	mIsModifiable(FALSE)  { @@ -1615,13 +1629,14 @@ LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,  	LLLiveLSLEditor::sInstances.addData(mItemID ^ mObjectID, this); - -  	LLCallbackMap::map_t factory_map;  	factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);  	LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &factory_map); - +	 +	mMonoCheckbox =	getChild<LLCheckBoxCtrl>("mono"); +	childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this); +	childSetEnabled("mono", FALSE);  	childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this);  	childSetEnabled("running", FALSE); @@ -1633,7 +1648,6 @@ LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,  	mScriptEd->mEditor->makePristine();  	loadAsset(is_new);  	mScriptEd->mEditor->setFocus(TRUE); -  	if (!getHost())  	{ @@ -1677,7 +1691,9 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)  		line++)  	{  		LLSD row; -		row["columns"][0]["value"] = line->asString(); +		std::string error_message = line->asString(); +		LLStringUtil::stripNonprintable(error_message); +		row["columns"][0]["value"] = error_message;  		row["columns"][0]["font"] = "OCRA";  		mScriptEd->mErrorList->addElement(row);  	} @@ -1712,6 +1728,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)  				mScriptEd->mEditor->setText(getString("not_allowed"));  				mScriptEd->mEditor->makePristine();  				mScriptEd->mEditor->setEnabled(FALSE); +				mScriptEd->enableSave(FALSE);  				mAssetStatus = PREVIEW_ASSET_LOADED;  			}  			else if(item && mItem.notNull()) @@ -1745,12 +1762,14 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)  				mAssetStatus = PREVIEW_ASSET_LOADED;  			} -			if(item -			   && !gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), -				   						GP_OBJECT_MANIPULATE)) +			mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY,  +										item->getPermissions(), +				   						GP_OBJECT_MANIPULATE); +			if(!mIsModifiable)  			{  				mScriptEd->mEditor->setEnabled(FALSE);  			} +			  			// This is commented out, because we don't completely  			// handle script exports yet.  			/* @@ -1784,8 +1803,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)  	else  	{  		mScriptEd->mEditor->setText(std::string(HELLO_LSL)); -		//mScriptEd->mEditor->setText(LLStringUtil::null); -		//mScriptEd->mEditor->makePristine(); +		mScriptEd->enableSave(FALSE);  		LLPermissions perm;  		perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID());  		perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER); @@ -1955,22 +1973,43 @@ void LLLiveLSLEditor::draw()  {  	LLViewerObject* object = gObjectList.findObject(mObjectID);  	LLCheckBoxCtrl* runningCheckbox = getChild<LLCheckBoxCtrl>( "running"); -		if(object && mAskedForRunningInfo && mHaveRunningInfo) +	if(object && mAskedForRunningInfo && mHaveRunningInfo)  	{  		if(object->permAnyOwner())  		{  			runningCheckbox->setLabel(getString("script_running"));  			runningCheckbox->setEnabled(TRUE); + +			if(object->permAnyOwner()) +			{ +				runningCheckbox->setLabel(getString("script_running")); +				runningCheckbox->setEnabled(TRUE); +			} +			else +			{ +				runningCheckbox->setLabel(getString("public_objects_can_not_run")); +				runningCheckbox->setEnabled(FALSE); +				// *FIX: Set it to false so that the ui is correct for +				// a box that is released to public. It could be +				// incorrect after a release/claim cycle, but will be +				// correct after clicking on it. +				runningCheckbox->set(FALSE); +				mMonoCheckbox->set(FALSE); +			}  		}  		else  		{  			runningCheckbox->setLabel(getString("public_objects_can_not_run"));  			runningCheckbox->setEnabled(FALSE); +  			// *FIX: Set it to false so that the ui is correct for  			// a box that is released to public. It could be  			// incorrect after a release/claim cycle, but will be  			// correct after clicking on it.  			runningCheckbox->set(FALSE); +			mMonoCheckbox->setEnabled(FALSE); +			// object may have fallen out of range. +			mHaveRunningInfo = FALSE;  		}  	}  	else if(!object) @@ -2044,7 +2083,7 @@ void LLLiveLSLEditor::saveIfNeeded()  	}  	// Don't need to save if we're pristine -	if(mScriptEd->mEditor->isPristine()) +	if(!LLScriptEdCore::hasChanged(mScriptEd))  	{  		return;  	} @@ -2052,6 +2091,7 @@ void LLLiveLSLEditor::saveIfNeeded()  	mPendingUploads = 0;  	// save the script +	mScriptEd->enableSave(FALSE);  	mScriptEd->mEditor->makePristine();  	mScriptEd->mErrorList->deleteAllItems(); @@ -2091,7 +2131,7 @@ void LLLiveLSLEditor::saveIfNeeded()  	fp = NULL;  	// save it out to asset server -	std::string url = gAgent.getRegion()->getCapability("UpdateScriptTaskInventory"); +	std::string url = object->getRegion()->getCapability("UpdateScriptTaskInventory");  	getWindow()->incBusyCount();  	mPendingUploads++;  	BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get(); @@ -2117,8 +2157,9 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,  	body["task_id"] = task_id;  	body["item_id"] = item_id;  	body["is_script_running"] = is_running; +	body["target"] = monoChecked() ? "mono" : "lsl2";  	LLHTTPClient::post(url, body, -		new LLUpdateTaskInventoryResponder(body, filename)); +		new LLUpdateTaskInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT));  }  void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, @@ -2141,9 +2182,12 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,  	std::string err_filename = llformat("%s.out", filepath.c_str());  	LLFILE *fp; +	const BOOL compile_to_mono = FALSE;  	if(!lscript_compile(filename.c_str(),  						dst_filename.c_str(),  						err_filename.c_str(), +						compile_to_mono, +						asset_id.asString().c_str(),  						gAgent.isGodlike()))  	{  		// load the error file into the error scrolllist @@ -2384,6 +2428,11 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)  		msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running);  		LLCheckBoxCtrl* runningCheckbox = instance->getChild<LLCheckBoxCtrl>("running");  		runningCheckbox->set(running); +		BOOL mono; +		msg->getBOOLFast(_PREHASH_Script, "Mono", mono); +		LLCheckBoxCtrl* monoCheckbox = instance->getChild<LLCheckBoxCtrl>("mono"); +		monoCheckbox->setEnabled(instance->getIsModifiable() && have_script_upload_cap(object_id)); +		monoCheckbox->set(mono);  	}  } @@ -2398,3 +2447,19 @@ void LLLiveLSLEditor::reshape(S32 width, S32 height, BOOL called_from_parent)  		gSavedSettings.setRect("PreviewScriptRect", getRect());  	}  } + +void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata) +{ +	LLLiveLSLEditor* self = static_cast<LLLiveLSLEditor*>(userdata); +	self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectID)); +	self->mScriptEd->enableSave(self->getIsModifiable()); +} + +BOOL LLLiveLSLEditor::monoChecked() const +{ +	if(NULL != mMonoCheckbox) +	{ +		return mMonoCheckbox->getValue()? TRUE : FALSE; +	} +	return FALSE; +} diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index aec4bb2ab7..ca1c527cb2 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -118,13 +118,14 @@ public:  	void selectFirstError();  	virtual BOOL handleKeyHere(KEY key, MASK mask); +	 +	void enableSave(BOOL b) {mEnableSave = b;}  protected:  	void deleteBridges();  	void setHelpPage(const std::string& help_string);  	void updateDynamicHelp(BOOL immediate = FALSE);  	void addHelpItemToHistory(const std::string& help_string); -  	static void onErrorList(LLUICtrl*, void* user_data);   	virtual const char *getTitleName() const { return "Script"; } @@ -147,6 +148,7 @@ private:  	LLKeywordToken* mLastHelpToken;  	LLFrameTimer	mLiveHelpTimer;  	S32				mLiveHelpHistorySize; +	BOOL			mEnableSave;  }; @@ -184,8 +186,9 @@ protected:  							   void* user_data, S32 status, LLExtStat ext_status);  	static void onSaveComplete(const LLUUID& uuid, void* user_data, S32 status, LLExtStat ext_status);  	static void onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status); +public:  	static LLPreviewLSL* getInstance(const LLUUID& uuid); - +protected:  	static void* createScriptEdPanel(void* userdata); @@ -195,6 +198,7 @@ protected:  	LLScriptEdCore* mScriptEd;  	// Can safely close only after both text and bytecode are uploaded  	S32 mPendingUploads; +  }; @@ -277,6 +281,15 @@ protected:  	S32 mPendingUploads;  	static LLMap<LLUUID, LLLiveLSLEditor*> sInstances; +	BOOL getIsModifiable() const { return mIsModifiable; } // Evaluated on load assert +	 +private: + +	static void	onMonoCheckboxClicked(LLUICtrl*, void* userdata); +	BOOL monoChecked() const; + +	LLCheckBoxCtrl*	mMonoCheckbox; +	BOOL mIsModifiable;  };  #endif  // LL_LLPREVIEWSCRIPT_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e37de3b2de..d24c738f2c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3381,13 +3381,13 @@ void init_stat_view()  	stat_barp->mDisplayBar = FALSE;  	stat_barp->mDisplayMean = FALSE; -	stat_barp = sim_statviewp->addStat("Script Perf", &(LLViewerStats::getInstance()->mSimLSLIPS)); -	stat_barp->setUnitLabel(" ips"); +	stat_barp = sim_statviewp->addStat("Script Events", &(LLViewerStats::getInstance()->mSimScriptEPS)); +	stat_barp->setUnitLabel(" eps");  	stat_barp->mPrecision = 0;  	stat_barp->mMinBar = 0.f; -	stat_barp->mMaxBar = 100000.f; -	stat_barp->mTickSpacing = 25000.f; -	stat_barp->mLabelSpacing = 50000.f; +	stat_barp->mMaxBar = 20000.f; +	stat_barp->mTickSpacing = 2500.f; +	stat_barp->mLabelSpacing = 5000.f;  	stat_barp->mPerSec = FALSE;  	stat_barp->mDisplayBar = FALSE;  	stat_barp->mDisplayMean = FALSE; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a095c9e159..771a71c5c5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6160,9 +6160,13 @@ class LLToolsSelectedScriptAction : public view_listener_t  	{  		std::string action = userdata.asString();  		LLFloaterScriptQueue* queue = NULL; -		if (action == "compile") +		if (action == "compile mono")  		{ -			queue = LLFloaterCompileQueue::create(); +			queue = LLFloaterCompileQueue::create(TRUE); +		} +		if (action == "compile lsl") +		{ +			queue = LLFloaterCompileQueue::create(FALSE);  		}  		else if (action == "reset")  		{ @@ -6405,16 +6409,36 @@ BOOL enable_more_than_one_selected(void* )  	return (LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);  } +static bool is_editable_selected() +{ +	return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); +} +  class LLEditableSelected : public view_listener_t  {  	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)  	{ -		bool new_value = (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); -		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); +		gMenuHolder->findControl(userdata["control"].asString())->setValue(is_editable_selected());  		return true;  	}  }; +class LLEditableSelectedMono : public view_listener_t +{ +	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) +	{ +		LLViewerRegion* region = gAgent.getRegion(); +		if(region && gMenuHolder && gMenuHolder->findControl(userdata["control"].asString())) +		{ +			bool have_cap = (! region->getCapability("UpdateScriptTaskInventory").empty()); +			bool selected = is_editable_selected() && have_cap; +			gMenuHolder->findControl(userdata["control"].asString())->setValue(selected); +			return true; +		} +		return false; +	} +}; +  class LLToolsEnableTakeCopy : public view_listener_t  {  	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -7842,4 +7866,5 @@ void initialize_menus()  	addMenu(new LLSomethingSelected(), "SomethingSelected");  	addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");  	addMenu(new LLEditableSelected(), "EditableSelected"); +	addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");  } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a082d6f1b5..d440491661 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3464,8 +3464,8 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)  		case LL_SIM_STAT_NUMSCRIPTSACTIVE:  			LLViewerStats::getInstance()->mSimActiveScripts.addValue(stat_value);  			break; -		case LL_SIM_STAT_LSLIPS: -			LLViewerStats::getInstance()->mSimLSLIPS.addValue(stat_value); +		case LL_SIM_STAT_SCRIPT_EPS: +			LLViewerStats::getInstance()->mSimScriptEPS.addValue(stat_value);  			break;  		case LL_SIM_STAT_INPPS:  			LLViewerStats::getInstance()->mSimInPPS.addValue(stat_value); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1aa7d2c3ff..8745a73e79 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2145,7 +2145,7 @@ void LLViewerObject::deleteInventoryItem(const LLUUID& item_id)  }  void LLViewerObject::doUpdateInventory( -	LLViewerInventoryItem* item, +	LLPointer<LLViewerInventoryItem>& item,  	U8 key,  	bool is_new)  { @@ -2217,7 +2217,8 @@ void LLViewerObject::doUpdateInventory(  				--mInventorySerialNum;  			}  		} -		LLViewerInventoryItem* new_item = new LLViewerInventoryItem(item); +		LLViewerInventoryItem* oldItem = item; +		LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem);  		new_item->setPermissions(perm);  		mInventory->push_front(new_item);  		doInventoryCallback(); @@ -2608,6 +2609,21 @@ void LLViewerObject::updateInventory(  	doUpdateInventory(task_item, key, is_new);  } +void LLViewerObject::updateInventoryLocal(LLInventoryItem* item, U8 key) +{ +	LLPointer<LLViewerInventoryItem> task_item = +		new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), +								  item->getAssetUUID(), item->getType(), +								  item->getInventoryType(), +								  item->getName(), item->getDescription(), +								  item->getSaleInfo(), item->getFlags(), +								  item->getCreationDate()); + +	// do the internal logic +	const bool is_new = false; +	doUpdateInventory(task_item, key, is_new); +} +  LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id)  {  	LLInventoryObject* rv = NULL; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index a143589ee9..1fd4a29238 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -384,6 +384,7 @@ public:  	// manager, so do no call updateInventory() from the selection  	// manager until we have better iterators.  	void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); +	void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.  	LLInventoryObject* getInventoryObject(const LLUUID& item_id);  	void getInventoryContents(InventoryObjectList& objects);  	LLInventoryObject* getInventoryRoot(); @@ -540,7 +541,7 @@ protected:  	// do the update/caching logic. called by saveScript and  	// updateInventory. -	void doUpdateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); +	void doUpdateInventory(LLPointer<LLViewerInventoryItem>& item, U8 key, bool is_new);  	static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index ccd3110758..446f8f026a 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -63,7 +63,7 @@ public:  	LLStat mSimFPS;  	LLStat mSimPhysicsFPS;  	LLStat mSimAgentUPS; -	LLStat mSimLSLIPS; +	LLStat mSimScriptEPS;  	LLStat mSimFrameMsec;  	LLStat mSimNetMsec; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 20a572c8e0..a39bb9faf6 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -231,8 +231,8 @@ TOOLMEDIAOPEN           CURSOR                  "toolmediaopen.cur"  //  VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,19,1,83014 - PRODUCTVERSION 1,19,1,83014 + FILEVERSION 1,20,9,87416 + PRODUCTVERSION 1,20,9,87416   FILEFLAGSMASK 0x3fL  #ifdef _DEBUG   FILEFLAGS 0x1L @@ -249,12 +249,12 @@ BEGIN          BEGIN              VALUE "CompanyName", "Linden Lab"              VALUE "FileDescription", "Second Life" -            VALUE "FileVersion", "1.19.1.83014" +            VALUE "FileVersion", "1.20.9.87416"              VALUE "InternalName", "Second Life"              VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."              VALUE "OriginalFilename", "SecondLife.exe"              VALUE "ProductName", "Second Life" -            VALUE "ProductVersion", "1.19.1.83014" +            VALUE "ProductVersion", "1.20.9.87416"          END      END      BLOCK "VarFileInfo" diff --git a/indra/test/llassetuploadqueue_tut.cpp b/indra/test/llassetuploadqueue_tut.cpp new file mode 100644 index 0000000000..7c4b8a0c9c --- /dev/null +++ b/indra/test/llassetuploadqueue_tut.cpp @@ -0,0 +1,178 @@ +/**  + * @file asset_upload_queue_tut.cpp + * @brief Tests for newview/llassetuploadqueue.cpp + * Copyright (c) 2007, Linden Research, Inc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lltut.h" + +#include "mock_http_client.h" +#include "../newview/llassetuploadqueue.cpp" + +// Mock implementation. +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD& post_data, +											   const LLUUID& vfile_id, +											   LLAssetType::EType asset_type) +{ +} + +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD& post_data, const std::string& file_name) +{ +} + +LLAssetUploadResponder::~LLAssetUploadResponder() +{ +} + +void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) +{ +} + +void LLAssetUploadResponder::result(const LLSD& content) +{ +} + +void LLAssetUploadResponder::uploadUpload(const LLSD& content) +{ +} + +void LLAssetUploadResponder::uploadComplete(const LLSD& content) +{ +} + +void LLAssetUploadResponder::uploadFailure(const LLSD& content) +{ +} + +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, +															   const LLUUID& vfile_id, +															   LLAssetType::EType asset_type) : +	LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} + +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, +															   const std::string& file_name) : +	LLAssetUploadResponder(post_data, file_name) +{ +} + +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, +															   const std::string& file_name, +															   const LLUUID& queue_id) : +	LLAssetUploadResponder(post_data, file_name) +{ +} + +void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) +{ +} + +namespace tut +{ +	class asset_upload_queue_test_data : public MockHttpClient {}; +	typedef test_group<asset_upload_queue_test_data> asset_upload_queue_test; +	typedef asset_upload_queue_test::object asset_upload_queue_object; +	tut::asset_upload_queue_test asset_upload_queue("asset_upload_queue"); + +	void queue(LLAssetUploadQueue& q, const std::string& filename) +	{ +		LLUUID task_id; +		LLUUID item_id; +		BOOL is_running = FALSE;  +		BOOL is_target_mono = TRUE;  +		LLUUID queue_id; +		q.queue(filename, task_id, item_id, is_running, is_target_mono, queue_id); +	} + +	class LLTestSupplier : public LLAssetUploadQueueSupplier +	{ +	public: + +		void set(LLAssetUploadQueue* queue) {mQueue = queue;} +		 +		virtual LLAssetUploadQueue* get() const +			{ +				return mQueue; +			} + +	private: +		LLAssetUploadQueue* mQueue;   +	}; + +	template<> template<> +	void asset_upload_queue_object::test<1>() +	{ +		setupTheServer(); +		reset(); +		LLTestSupplier* supplier = new LLTestSupplier(); +		LLAssetUploadQueue q("http://localhost:8888/test/success", supplier); +		supplier->set(&q); +		queue(q, "foo.bar"); +		ensure("upload queue not empty before request", q.isEmpty()); +		runThePump(10); +		ensure("upload queue not empty after request", q.isEmpty()); +	} + +	template<> template<> +	void asset_upload_queue_object::test<2>() +	{ +		reset(); +		LLTestSupplier* supplier = new LLTestSupplier(); +		LLAssetUploadQueue q("http://localhost:8888/test/error", supplier); +		supplier->set(&q); +		queue(q, "foo.bar"); +		ensure("upload queue not empty before request", q.isEmpty()); +		runThePump(10); +		ensure("upload queue not empty after request", q.isEmpty()); +	} + +	template<> template<> +	void asset_upload_queue_object::test<3>() +	{ +		reset(); +		LLTestSupplier* supplier = new LLTestSupplier(); +		LLAssetUploadQueue q("http://localhost:8888/test/timeout", supplier); +		supplier->set(&q); +		queue(q, "foo.bar"); +		ensure("upload queue not empty before request", q.isEmpty()); +		runThePump(10); +		ensure("upload queue not empty after request", q.isEmpty()); +	} + +	template<> template<> +	void asset_upload_queue_object::test<4>() +	{ +		reset(); +		LLTestSupplier* supplier = new LLTestSupplier(); +		LLAssetUploadQueue q("http://localhost:8888/test/success", supplier); +		supplier->set(&q); +		queue(q, "foo.bar"); +		queue(q, "baz.bar"); +		ensure("upload queue empty before request", !q.isEmpty()); +		runThePump(10); +		ensure("upload queue not empty before request", q.isEmpty()); +		runThePump(10); +		ensure("upload queue not empty after request", q.isEmpty()); +	} + +	template<> template<> +	void asset_upload_queue_object::test<5>() +	{ +		reset(); +		LLTestSupplier* supplier = new LLTestSupplier(); +		LLAssetUploadQueue q("http://localhost:8888/test/success", supplier); +		supplier->set(&q); +		queue(q, "foo.bar"); +		runThePump(10); +		ensure("upload queue not empty before request", q.isEmpty()); +		queue(q, "baz.bar"); +		ensure("upload queue not empty after request", q.isEmpty()); +		runThePump(10); +		killServer(); +	} +} diff --git a/indra/test/mock_http_client.cpp b/indra/test/mock_http_client.cpp new file mode 100644 index 0000000000..6b273ee7b5 --- /dev/null +++ b/indra/test/mock_http_client.cpp @@ -0,0 +1,66 @@ +/**  + * @file mock_http_client.cpp + * @brief Framework for testing HTTP requests + * Copyright (c) 2007, Linden Research, Inc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llsdhttpserver.h" +#include "lliohttpserver.h" + +namespace tut +{ +	class SuccessNode : public LLHTTPNode +	{ +	public: +		void get(ResponsePtr r, const LLSD& context) const +	   	{  +	   		LLSD result; +			result["state"] = "complete"; +	   		result["test"] = "test"; +	   		r->result(result); +	   	} +		void post(ResponsePtr r, const LLSD& context, const LLSD& input) const +		{ +			LLSD result; +			result["state"] = "complete"; +			result["test"] = "test"; +			r->result(result); +		} +	}; + +	class ErrorNode : public LLHTTPNode +	{ +	public: +		void get(ResponsePtr r, const LLSD& context) const +			{ r->status(599, "Intentional error"); } +		void post(ResponsePtr r, const LLSD& context, const LLSD& input) const +			{ r->status(input["status"], input["reason"]); } +	}; + +	class TimeOutNode : public LLHTTPNode +	{ +	public: +		void get(ResponsePtr r, const LLSD& context) const +		{ +            /* do nothing, the request will eventually time out */  +		} +	}; + +	LLSD storage; +	 +	class LLSDStorageNode : public LLHTTPNode +	{ +	public: +		LLSD get() const{ return storage; } +		LLSD put(const LLSD& value) const{ storage = value; return LLSD(); } +	}; + +	LLHTTPRegistration<LLSDStorageNode> gStorageNode("/test/storage"); +	LLHTTPRegistration<SuccessNode>		gSuccessNode("/test/success"); +	LLHTTPRegistration<ErrorNode>		gErrorNode("/test/error"); +	LLHTTPRegistration<TimeOutNode>		gTimeOutNode("/test/timeout"); +} diff --git a/indra/test/mock_http_client.h b/indra/test/mock_http_client.h new file mode 100644 index 0000000000..6476ea3783 --- /dev/null +++ b/indra/test/mock_http_client.h @@ -0,0 +1,174 @@ +/**  + * @file mock_http_client.cpp + * @brief Framework for testing HTTP requests + * Copyright (c) 2007, Linden Research, Inc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * $/LicenseInfo$ + */ + +#include "llsdhttpserver.h" +#include "lliohttpserver.h" +#include "llhttpclient.h" +#include "llformat.h" +#include "llpipeutil.h" +#include "llpumpio.h" + +namespace tut +{ +	struct MockHttpClient +	{ +	public: +		MockHttpClient() +		{ +			apr_pool_create(&mPool, NULL); +			mServerPump = new LLPumpIO(mPool); +			mClientPump = new LLPumpIO(mPool); +			 +			LLHTTPClient::setPump(*mClientPump); +		} +		 +		~MockHttpClient() +		{ +			delete mServerPump; +			delete mClientPump; +			apr_pool_destroy(mPool); +		} + +		void setupTheServer() +		{ +			LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888); + +			LLHTTPStandardServices::useServices(); +			LLHTTPRegistrar::buildAllServices(root); +		} +		 +		void runThePump(float timeout = 100.0f) +		{ +			LLTimer timer; +			timer.setTimerExpirySec(timeout); + +			while(!mSawCompleted && !timer.hasExpired()) +			{ +				if (mServerPump) +				{ +					mServerPump->pump(); +					mServerPump->callback(); +				} +				if (mClientPump) +				{ +					mClientPump->pump(); +					mClientPump->callback(); +				} +			} +		} + +		void killServer() +		{ +			delete mServerPump; +			mServerPump = NULL; +		} +	 +	private: +		apr_pool_t* mPool; +		LLPumpIO* mServerPump; +		LLPumpIO* mClientPump; + +		 +	protected: +		void ensureStatusOK() +		{ +			if (mSawError) +			{ +				std::string msg = +					llformat("error() called when not expected, status %d", +						mStatus);  +				fail(msg); +			} +		} +	 +		void ensureStatusError() +		{ +			if (!mSawError) +			{ +				fail("error() wasn't called"); +			} +		} +		 +		LLSD getResult() +		{ +			return mResult; +		} +	 +	protected: +		bool mSawError; +		U32 mStatus; +		std::string mReason; +		bool mSawCompleted; +		LLSD mResult; +		bool mResultDeleted; + +		class Result : public LLHTTPClient::Responder +		{ +		protected: +			Result(MockHttpClient& client) +				: mClient(client) +			{ +			} +		 +		public: +			static boost::intrusive_ptr<Result> build(MockHttpClient& client) +			{ +				return boost::intrusive_ptr<Result>(new Result(client)); +			} +			 +			~Result() +			{ +				mClient.mResultDeleted = true; +			} +			 +			virtual void error(U32 status, const std::string& reason) +			{ +				mClient.mSawError = true; +				mClient.mStatus = status; +				mClient.mReason = reason; +			} + +			virtual void result(const LLSD& content) +			{ +				mClient.mResult = content; +			} + +			virtual void completed( +							U32 status, const std::string& reason, +							const LLSD& content) +			{ +				LLHTTPClient::Responder::completed(status, reason, content); +				 +				mClient.mSawCompleted = true; +			} + +		private: +			MockHttpClient& mClient; +		}; + +		friend class Result; + +	protected: + +		void reset() +		{ +			mSawError = false; +			mStatus = 0; +			mSawCompleted = false; +			mResult.clear(); +			mResultDeleted = false; +		} + +		LLHTTPClient::ResponderPtr newResult() +		{ +			reset(); +			return Result::build(*this); +		} +	}; +} diff --git a/install.xml b/install.xml index 2475a2a5e4..d7625f1ace 100644 --- a/install.xml +++ b/install.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" ?> +<?xml version="1.0"?>  <llsd>  <map>      <key>installables</key> @@ -377,9 +377,9 @@            <key>linux</key>            <map>              <key>md5sum</key> -            <string>589a8385979d2b0561daaec2148f8b77</string> +            <string>f1161282d7fc11fbe17d0aa077ee054b</string>              <key>url</key> -            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google-linux-20080613.tar.bz2</uri> +            <uri>http://int.codex.lindenlab.com/~babbage/install_pkgs/google-linux-20080617.tar.bz2</uri>            </map>          </map>        </map> @@ -411,9 +411,9 @@            <key>linux</key>            <map>              <key>md5sum</key> -            <string>83eddf6114f1e306c61fbda16ad02f0c</string> +            <string>21c16a74f8fc9a62e3ab944a6eb7403d</string>              <key>url</key> -            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/gtk-atk-pango-glib-linux-20080613.tar.bz2</uri> +            <uri>http://int.codex.lindenlab.com/~babbage/install_pkgs/gtk-atk-pango-glib-linux-20080616.tar.bz</uri>            </map>            <key>windows</key>            <map> @@ -556,6 +556,40 @@            </map>          </map>        </map> +      <key>libmono</key> +      <map> +        <key>copyright</key> +        <string>(C) 2005 Novell, Inc. http://www.novell.com</string> +        <key>description</key> +        <string>An open source implementation of the ECMA/ISO ECMA-334 Common L\ +anguage Infrstructure (CLI) international standard</string> +        <key>license</key> +        <string>lgpl</string> +        <key>packages</key> +        <map> +          <key>linux</key> +          <map> +            <key>md5sum</key> +            <string>df73b95b0980e631ba1ecd930120699f</string> +            <key>url</key> +            <uri>http://int.codex.lindenlab.com/~daveh/install_pkgs/mono-linux-20080722.tar.bz2</uri> +          </map> +          <key>darwin</key> +          <map> +            <key>md5sum</key> +            <string>39a803fcbe6f11b72358fc78b7777b6c</string> +            <key>url</key> +            <uri>http://int.codex.lindenlab.com/~daveh/install_pkgs/mono-darwin-20080724.tar.bz2</uri> +          </map> +		  <key>windows</key> +		  <map> +		    <key>md5sum</key> +            <string>7293312a6c76e5a38ec1b58ff87828d9</string> +            <key>url</key> +            <uri>http://int.codex.lindenlab.com/~daveh/install_pkgs/mono-windows-20080723.tar.bz2</uri> +          </map> +        </map> +      </map>        <key>libpng</key>        <map>          <key>copyright</key> diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 6f49ef25b5..9c92906e58 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -5335,6 +5335,7 @@ version 2.0  		{	ObjectID		LLUUID	}  		{	ItemID			LLUUID	}  		{	Running			BOOL	} +//		{	Mono			BOOL	} Added to LLSD message  	}  } @@ -8851,4 +8852,4 @@ version 2.0  		{	ObjectLocalID	U32		}  		{	IncludeInSearch	BOOL	}  	} -} +}
\ No newline at end of file | 
