code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2025 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_texts.h
//
// These are text strings used through out the library
//

#ifndef AS_TEXTS_H
#define AS_TEXTS_H

// Compiler messages

#define TXT_s_ALREADY_DECLARED                      "'%s' is already declared"
#define TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED "Abstract class '%s' cannot be instantiated"
#define TXT_ACCESSING_PRIVATE_PROP_s                "Accessing private property '%s' of parent class"
#define TXT_ALL_CODE_PATHS_MUST_INIT_MEMBER         "Initialization after return. All code paths must initialize the members"
#define TXT_ARG_NOT_LVALUE                          "Output argument expression is not assignable"
#define TXT_ATTR_s_INFORMED_MULTIPLE_TIMES          "Attribute '%s' informed multiple times"
#define TXT_AUTO_NOT_ALLOWED                        "Auto is not allowed here"

#define TXT_BOTH_MUST_BE_SAME                     "Can't find unambiguous implicit conversion to make both expressions have the same type"
#define TXT_BOTH_CONDITIONS_MUST_CALL_CONSTRUCTOR "Both conditions must call constructor"
#define TXT_BOTH_CONDITIONS_MUST_INIT_MEMBER_s    "Both conditions must initialize member '%s'"
#define TXT_BASE_DOESNT_HAVE_DEF_CONSTR           "Base class doesn't have default constructor. Make explicit call to base constructor"
#define TXT_BASE_DOESNT_HAVE_CPY_CONSTR_OR_DEF_CONSTR  "Base class doesn't have copy constructor or default constructor and assign operator. Make explicit call to base constructor"

#define TXT_CANDIDATES_ARE                         "Candidates are:"
#define TXT_CANNOT_CALL_CONSTRUCTOR_IN_LOOPS       "Can't call a constructor in loops"
#define TXT_CANNOT_CALL_CONSTRUCTOR_IN_SWITCH      "Can't call a constructor in switch"
#define TXT_CANNOT_CALL_CONSTRUCTOR_TWICE          "Can't call a constructor multiple times"
#define TXT_CANNOT_CREATE_DELEGATE                 "Can't create delegate"
#define TXT_CANNOT_CREATE_DELEGATE_FOR_NOREF_TYPES "Can't create delegate for types that do not support handles"
#define TXT_CANNOT_DELETE_NON_AUTO_FUNC            "Cannot flag function that will not be auto generated as deleted"
#define TXT_CANNOT_DEFINE_FUNC_THAT_IS_DELETED     "Conflict with explicit declaration of function and deleted function"
#define TXT_CANNOT_FORM_ARRAY_OF_s                 "Can't form arrays of subtype '%s'"
#define TXT_CANNOT_IMPLEMENT_SELF                  "Can't implement itself, or another interface that implements this interface"
#define TXT_CANNOT_IMPLICITLY_CALL_EXPLICIT_COPY_CONSTR   "Can't implicitly call explicit copy constructor"
#define TXT_CANNOT_INHERIT_FROM_s_FINAL            "Can't inherit from class '%s' marked as final"
#define TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES   "Can't inherit from multiple classes"
#define TXT_CANNOT_INHERIT_FROM_SELF               "Can't inherit from itself, or another class that inherits from this class"
#define TXT_CANNOT_INIT_MEMBERS_IN_LOOPS           "Can't initialize the members in loops"
#define TXT_CANNOT_INIT_MEMBERS_IN_SWITCH          "Can't initialize the members in switch"
#define TXT_CANNOT_PASS_CLASS_METHOD_AS_ARG        "Can't pass class method as arg directly. Use a delegate object instead"
#define TXT_CANNOT_RESOLVE_AUTO                    "Unable to resolve auto type"
#define TXT_CANNOT_ACCESS_NON_STATIC_MEMBER_s      "Cannot access non-static member '%s' like this"
#define TXT_CANNOT_RETURN_REF_TO_LOCAL             "Can't return reference to local value."
#define TXT_CANT_CONSTRUCT_s_USE_REF_CAST          "Can't construct handle '%s'. Use ref cast instead"
#define TXT_CANT_IMPLICITLY_CONVERT_s_TO_s         "Can't implicitly convert from '%s' to '%s'."
#define TXT_CANT_RETURN_VALUE                      "Can't return value when return type is 'void'"
#define TXT_CHANGE_SIGN                            "Implicit conversion changed sign of value"
#define TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT       "A class cannot be both abstract and final"
#define TXT_COMPILING_s                            "Compiling %s"
#define TXT_COMPILING_AUTO_s                       "Compiling auto generated %s"
#define TXT_COMPOUND_ASGN_ON_VALUE_TYPE            "Compound assignments with property accessors on value types are not supported"
#define TXT_COMPOUND_ASGN_WITH_IDX_PROP            "Compound assignments with indexed property accessors are not supported"
#define TXT_COMPOUND_ASGN_REQUIRE_GET_SET          "Compound assignments with property accessors require both get and set accessors"
#define TXT_PROP_ACCESS_s_DOES_NOT_EXPECT_INDEX    "Implemented property accessor '%s' does not expect index argument"
#define TXT_PROP_ACCESS_s_EXPECTS_INDEX            "Implemented property accessor '%s' expects index argument"

#define TXT_DATA_TYPE_CANT_BE_s                     "Data type can't be '%s'"
#define TXT_DECL_IN_SWITCH                          "Variables cannot be declared in switch cases, except inside statement blocks"
#define TXT_DEFAULT_MUST_BE_LAST                    "The default case must be the last one"
#define TXT_DEF_ARG_MISSING_IN_FUNC_s               "All subsequent parameters after the first default value must have default values in function '%s'"
#define TXT_DEF_ARG_TYPE_DOESNT_MATCH               "The type of the default argument expression doesn't match the function parameter type"
#define TXT_DELETED_FUNC_CANT_HAVE_IMPL             "Deleted functions cannot have implementation"
#define TXT_DERIVED_METHOD_MUST_HAVE_SAME_RETTYPE_s "The method in the derived class must have the same return type as in the base class: '%s'"
#define TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM            "The destructor must not have any parameters"
#define TXT_DESTRUCTOR_s_s_NAME_ERROR               "The name of the destructor '%s::~%s' must be the same as the class"
#define TXT_DISALLOW_ASSIGN_ON_REF_TYPE             "Value assignment on reference types is not allowed. Did you mean to do a handle assignment?"
#define TXT_DISALLOW_COMPOUND_ASSIGN_ON_REF_TYPE    "Compound assignment on reference types is not allowed"
#define TXT_DUPLICATE_NAMED_ARG                     "Duplicate named argument"
#define TXT_DUPLICATE_SWITCH_CASE                   "Duplicate switch case"

#define TXT_ELSE_WITH_EMPTY_STATEMENT         "Else with empty statement"
#define TXT_EMPTY_LIST_ELEMENT_IS_NOT_ALLOWED "Empty list element is not allowed"
#define TXT_EMPTY_SWITCH                      "Empty switch statement"
#define TXT_EXPECTED_s                        "Expected '%s'"
#define TXT_EXPECTED_CONSTANT                 "Expected constant"
#define TXT_EXPECTED_DATA_TYPE                "Expected data type"
#define TXT_EXPECTED_EXPRESSION_VALUE         "Expected expression value"
#define TXT_EXPECTED_IDENTIFIER               "Expected identifier"
#define TXT_EXPECTED_LIST                     "Expected a list enclosed by { } to match pattern"
#define TXT_EXPECTED_METHOD_OR_PROPERTY       "Expected method or property"
#define TXT_EXPECTED_ONE_OF                   "Expected one of: "
#define TXT_EXPECTED_OPERATOR                 "Expected operator"
#define TXT_EXPECTED_s_OR_s                   "Expected '%s' or '%s'"
#define TXT_EXPECTED_POST_OPERATOR            "Expected post operator"
#define TXT_EXPECTED_PRE_OPERATOR             "Expected pre operator"
#define TXT_EXPECTED_STRING                   "Expected string"
#define TXT_EXPR_DOESNT_EVAL_TO_FUNC          "Expression doesn't evaluate to a function"
#define TXT_EXPR_MUST_BE_BOOL_s               "Expression must be of boolean type, instead found '%s'"
#define TXT_EXPR_s_IS_DATA_TYPE               "Expression '%s' is a data type"
#define TXT_EXTERNAL_SHARED_s_NOT_FOUND       "External shared entity '%s' not found"
#define TXT_EXTERNAL_SHARED_s_CANNOT_REDEF    "External shared entity '%s' cannot redefine the original entity"

#define TXT_FAILED_TO_COMPILE_DEF_ARG_d_IN_FUNC_s "Failed while compiling default arg for parameter %d in function '%s'"
#define TXT_FAILED_TO_CREATE_TEMP_OBJ             "Previous error occurred while attempting to create a temporary copy of object"
#define TXT_FLOAT_CONV_TO_INT_CAUSE_TRUNC         "Float value truncated in implicit conversion to integer"
#define TXT_FOUND_MULTIPLE_ENUM_VALUES            "Found multiple matching enum values"
#define TXT_FUNCTION_ALREADY_EXIST                "A function with the same name and parameters already exists"
#define TXT_FUNCTION_s_NOT_FOUND                  "Function '%s' not found"

#define TXT_GET_SET_ACCESSOR_TYPE_MISMATCH_FOR_s "The property '%s' has mismatching types for the get and set accessors"
#define TXT_GLOBAL_VARS_NOT_ALLOWED              "Global variables have been disabled by the application"

#define TXT_HANDLE_ASSIGN_ON_NON_HANDLE_PROP     "It is not allowed to perform a handle assignment on a non-handle property"
#define TXT_HANDLE_COMPARISON                    "The operand is implicitly converted to handle in order to compare them"
#define TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED      "Handle to handle is not allowed"
#define TXT_s_HIDES_VAR_IN_OUTER_SCOPE           "Variable '%s' hides another variable of same name in outer scope"

#define TXT_IDENTIFIER_s_NOT_DATA_TYPE              "Identifier '%s' is not a data type"
#define TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS "Identifier '%s' is not a data type in global namespace"
#define TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s      "Identifier '%s' is not a data type in namespace '%s' or parent"
#define TXT_IF_WITH_EMPTY_STATEMENT                 "If with empty statement"
#define TXT_ILLEGAL_MEMBER_TYPE                     "Illegal member type"
// TODO: Should be TXT_ILLEGAL_OPERATION_ON_s
#define TXT_ILLEGAL_OPERATION                      "Illegal operation on this datatype"
#define TXT_ILLEGAL_OPERATION_ON_s                 "Illegal operation on '%s'"
#define TXT_ILLEGAL_TARGET_TYPE_FOR_REF_CAST       "Illegal target type for reference cast"
#define TXT_ILLEGAL_VARIABLE_NAME_s                "Illegal variable name '%s'."
#define TXT_INHERITED_PRIVATE_PROP_ACCESS_s        "Illegal access to inherited private property '%s'"
#define TXT_INIT_LIST_CANNOT_BE_USED_WITH_s        "Initialization lists cannot be used with '%s'"
#define TXT_INSTANCING_INVLD_TMPL_TYPE_s_s         "Attempting to instantiate invalid template type '%s<%s>'"
#define TXT_INSTEAD_FOUND_s                        "Instead found '%s'"
#define TXT_INSTEAD_FOUND_IDENTIFIER_s             "Instead found identifier '%s'"
#define TXT_INSTEAD_FOUND_KEYWORD_s                "Instead found reserved keyword '%s'"
#define TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED     "Interface '%s' cannot be instantiated"
#define TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE "Interfaces can only implement other interfaces"
#define TXT_INVALID_BREAK                          "Invalid 'break'"
#define TXT_INVALID_CHAR_LITERAL                   "Invalid character literal"
#define TXT_INVALID_CONTINUE                       "Invalid 'continue'"
#define TXT_INVALID_ESCAPE_SEQUENCE                "Invalid escape sequence"
#define TXT_INVALID_EXPRESSION_AMBIGUOUS_NAME      "Invalid expression: ambiguous name"
#define TXT_INVALID_EXPRESSION_LAMBDA              "Invalid expression: stand-alone anonymous function"
#define TXT_INVALID_OP_ON_METHOD                   "Invalid operation on method"
#define TXT_INVALID_REF_PROP_ACCESS                "Invalid reference. Property accessors cannot be used in combined read/write operations"
#define TXT_INVALID_SCOPE                          "Invalid scope resolution"
#define TXT_INVALID_SIG_FOR_VIRTPROP               "Invalid signature for virtual property"
#define TXT_INVALID_TYPE                           "Invalid type"
#define TXT_INVALID_UNICODE_FORMAT_EXPECTED_d      "Invalid unicode escape sequence, expected %d hex digits"
#define TXT_INVALID_UNICODE_VALUE                  "Invalid unicode code point"
#define TXT_INVALID_UNICODE_SEQUENCE_IN_SRC        "Invalid unicode sequence in source"
#define TXT_INVALID_USE_OF_NAMED_ARGS              "Invalid use of named arguments"

#define TXT_MEMBER_s_ACCESSED_BEFORE_INIT           "The member '%s' is accessed before the initialization"
#define TXT_METHOD_CANNOT_OVERRIDE_s                "Method '%s' declared as final and cannot be overridden"
#define TXT_METHOD_CANT_HAVE_NAME_OF_CLASS          "The method cannot be named with the class name"
#define TXT_METHOD_s_DOES_NOT_OVERRIDE              "Method '%s' marked as override but does not replace any base class or interface method"
#define TXT_METHOD_s_s_HAS_NO_RETURN_TYPE           "Method '%s::%s' is missing the return type, nor is it the same name as object to be a constructor"
#define TXT_METHOD_s_NOT_PART_OF_OBJECT_s           "Method '%s' is not part of object '%s'"
#define TXT_MISSING_IMPLEMENTATION_OF_s             "Missing implementation of '%s'"
#define TXT_MISSING_DEFINITION_OF_s                 "Missing definition of '%s'"
#define TXT_MISSING_OR_INVALID_DEFINITON_OF_s       "Missing or invalid definition of '%s'"
#define TXT_MIXIN_CANNOT_BE_DECLARED_AS_s           "Mixin class cannot be declared as '%s'"
#define TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR           "Mixin classes cannot have constructors or destructors"
#define TXT_MIXIN_CLASS_CANNOT_INHERIT              "Mixin class cannot inherit from classes"
#define TXT_MIXIN_CANNOT_HAVE_CHILD_TYPES           "Mixin classes cannot have child types"
#define TXT_MORE_THAN_ONE_MATCHING_OP               "Found more than one matching operator"
#define TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s       "Multiple matching signatures to '%s'"
#define TXT_MULTIPLE_PROP_GET_ACCESSOR_FOR_s        "Found multiple get accessors for property '%s'"
#define TXT_MULTIPLE_PROP_SET_ACCESSOR_FOR_s        "Found multiple set accessors for property '%s'"
#define TXT_MULTILINE_STRINGS_NOT_ALLOWED           "Multiline strings are not allowed in this application"
#define TXT_MUST_BE_OBJECT                          "Only objects have constructors"
#define TXT_MUST_RETURN_VALUE                       "Must return a value"

#define TXT_NAMESPACE_s_DOESNT_EXIST               "Namespace '%s' doesn't exist."
#define TXT_NAME_CONFLICT_s_EXTENDED_TYPE          "Name conflict. '%s' is an extended data type."
#define TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY        "Name conflict. '%s' is a global property."
#define TXT_NAME_CONFLICT_s_IS_NAMED_TYPE          "Name conflict. '%s' is a named type."
#define TXT_NAME_CONFLICT_s_IS_FUNCDEF             "Name conflict. '%s' is a funcdef."
#define TXT_NAME_CONFLICT_s_IS_FUNCTION            "Name conflict. '%s' is a global function."
#define TXT_NAME_CONFLICT_s_IS_MIXIN               "Name conflict. '%s' is a mixin class."
#define TXT_NAME_CONFLICT_s_IS_VIRTPROP            "Name conflict. '%s' is a virtual property."
#define TXT_NAME_CONFLICT_s_STRUCT                 "Name conflict. '%s' is a class."
#define TXT_NAME_CONFLICT_s_INTF                   "Name conflict. '%s' is an interface."
#define TXT_NAME_CONFLICT_s_OBJ_PROPERTY           "Name conflict. '%s' is an object property."
#define TXT_NAME_CONFLICT_s_METHOD                 "Name conflict. '%s' is a class method."
#define TXT_NAME_CONFLICT_s_ALREADY_USED           "Name conflict. '%s' is already used."
#define TXT_NAMED_ARGS_WITH_OLD_SYNTAX             "Detected named argument with old syntax"
#define TXT_NO_APPROPRIATE_INDEX_OPERATOR          "No appropriate indexing operator found"
#define TXT_NO_APPROPRIATE_OPHNDLASSIGN_s          "No appropriate opHndlAssign method found in '%s' for handle assignment"
#define TXT_NO_APPROPRIATE_OPEQUALS                "No appropriate opEquals method found"
#define TXT_NO_CONVERSION_s_TO_s                   "No conversion from '%s' to '%s' available."
#define TXT_NO_CONVERSION_s_TO_MATH_TYPE           "No conversion from '%s' to math type available."
#define TXT_NO_DEFAULT_ARRAY_TYPE                  "The application doesn't support the default array type."
#define TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s           "No default constructor for object of type '%s'."
#define TXT_NO_DEFAULT_COPY_OP_FOR_s               "No appropriate opAssign method found in '%s' for value assignment"
#define TXT_NO_COPY_CONSTRUCTOR_FOR_s              "No copy constructor for object of type '%s'."
#define TXT_NO_MATCHING_SIGNATURES_TO_s            "No matching signatures to '%s'"
#define TXT_NO_MATCHING_OP_FOUND_FOR_TYPE_s        "No matching operator that takes the type '%s' found"
#define TXT_NO_MATCHING_OP_FOUND_FOR_TYPES_s_AND_s "No matching operator that takes the types '%s' and '%s' found"
#define TXT_NO_MATCHING_SYMBOL_s                   "No matching symbol '%s'"
#define TXT_NON_CONST_METHOD_ON_CONST_OBJ          "Non-const method call on read-only object reference"
#define TXT_NONTERMINATED_STRING                   "Non-terminated string literal"
#define TXT_NOT_A_FUNC_s_IS_TYPE_s                 "Expression doesn't form a function call. '%s' evaluates to the non-function type '%s'"
#define TXT_NOT_ALL_PATHS_RETURN                   "Not all paths return a value"
#define TXT_NOT_ENOUGH_VALUES_FOR_LIST             "Not enough values to match pattern"
#define TXT_s_NOT_DECLARED                         "'%s' is not declared"
#define TXT_NOT_EXACT                              "Implicit conversion of value is not exact"
#define TXT_s_NOT_A_FOREACH_TYPE                   "Type '%s' is not valid type for foreach loops"
#define TXT_s_NOT_INITIALIZED                      "'%s' is not initialized."
#define TXT_NOT_LVALUE                             "Expression is not an l-value"
#define TXT_s_NOT_MEMBER_OF_s                      "'%s' is not a member of '%s'"
#define TXT_NOT_VALID_REFERENCE                    "Not a valid reference"
#define TXT_NOT_VALID_LVALUE                       "Not a valid lvalue"
#define TXT_NOTHING_WAS_BUILT                      "Nothing was built in the module"
#define TXT_AMBIGUOUS_SYMBOL_NAME_s                "Ambiguous symbol name '%s'"

#define TXT_OBJECT_DOESNT_SUPPORT_INDEX_OP          "Type '%s' doesn't support the indexing operator"
#define TXT_OBJECT_HANDLE_NOT_SUPPORTED             "Object handle is not supported for this type"
#define TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT          "Only object types that support object handles can use &inout. Use &in or &out instead"
#define TXT_ONLY_ONE_ARGUMENT_IN_CAST               "A cast operator has one argument"
#define TXT_ONLY_ONE_FUNCTION_ALLOWED               "The code must contain one and only one function"
#define TXT_ONLY_ONE_VARIABLE_ALLOWED               "The code must contain one and only one global variable"
#define TXT_OPERANDS_MUST_BE_HANDLES                "Both operands must be handles when comparing identity"
#define TXT_OVERLOAD_CONFLICTS_DUE_TO_DEFAULT_ARGS  "The overloaded functions are identical on initial parameters without default arguments"

#define TXT_PARAMETER_ALREADY_DECLARED                 "Parameter already declared"
#define TXT_PARAMETER_CANT_BE_s                        "Parameter type can't be '%s', because the type cannot be instantiated."
#define TXT_POS_ARG_AFTER_NAMED_ARG                    "Positional arguments cannot be passed after named arguments"
#define TXT_POTENTIAL_MATCHING_NON_CONST_METHOD_HIDDEN "Potentially matching non-const method is hidden on read-only object reference"
#define TXT_PREV_ERROR_WHILE_COMP_LIST_FOR_TYPE_s      "Previous error occurred while attempting to compile initialization list for type '%s'"
#define TXT_PRIVATE_METHOD_CALL_s                      "Illegal call to private method '%s'"
#define TXT_PRIVATE_PROP_ACCESS_s                      "Illegal access to private property '%s'"
#define TXT_PROTECTED_METHOD_CALL_s                    "Illegal call to protected method '%s'"
#define TXT_PROTECTED_PROP_ACCESS_s                    "Illegal access to protected property '%s'"
#define TXT_PROP_ACCESS_WITH_INDEX_ONE_ARG             "Property accessor with index must have 1 and only 1 index argument"
#define TXT_PROPERTY_ACCESSOR_DISABLED                 "Property accessors have been disabled by the application"
#define TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED      "Property accessor must be implemented"
#define TXT_PROPERTY_CANT_BE_CONST                     "Class properties cannot be declared as const"
#define TXT_PROPERTY_HAS_NO_GET_ACCESSOR               "The property has no get accessor"
#define TXT_PROPERTY_HAS_NO_SET_ACCESSOR               "The property has no set accessor"
#define TXT_PROPERTY_WITHOUT_ACCESSOR                  "Virtual property must have at least one get or set accessor"

#define TXT_REF_CANT_BE_TO_LOCAL_VAR            "Resulting reference cannot be returned. Returned references must not refer to local variables."
#define TXT_REF_CANT_BE_RETURNED_DEFERRED_PARAM "Resulting reference cannot be returned. There are deferred arguments that may invalidate it."
#define TXT_REF_CANT_BE_RETURNED_LOCAL_VARS     "Resulting reference cannot be returned. The expression uses objects that during cleanup may invalidate it."
#define TXT_REF_IS_READ_ONLY                    "Reference is read-only"
#define TXT_REF_IS_TEMP                         "Reference is temporary"
#define TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL      "Reference types cannot be passed by value in function parameters"
#define TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL    "Reference types cannot be returned by value from functions"
#define TXT_RETURN_CANT_BE_s                    "Return type can't be '%s'"

#define TXT_SHARED_CANNOT_ACCESS_NON_SHARED_VAR_s      "Shared code cannot access non-shared global variable '%s'"
#define TXT_SHARED_CANNOT_CALL_NON_SHARED_FUNC_s       "Shared code cannot call non-shared function '%s'"
#define TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s       "Shared type cannot implement non-shared interface '%s'"
#define TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s    "Shared class cannot inherit from non-shared class '%s'"
#define TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s        "Shared code cannot use non-shared type '%s'"
#define TXT_SHARED_s_DOESNT_MATCH_ORIGINAL             "Shared type '%s' doesn't match the original declaration in other module"
#define TXT_SECTION_IS_EMPTY                           "The script section is empty"
#define TXT_SIGNED_UNSIGNED_MISMATCH                   "Signed/Unsigned mismatch"
#define TXT_STRINGS_NOT_RECOGNIZED                     "Strings are not recognized by the application"
#define TXT_SWITCH_CASE_MUST_BE_CONSTANT               "Case expressions must be literal constants"
#define TXT_SWITCH_MUST_BE_INTEGRAL                    "Switch expressions must be integral numbers"

#define TXT_TMPL_s_EXPECTS_d_SUBTYPES          "Template '%s' expects %d sub type(s)"
#define TXT_TOO_MANY_JUMP_LABELS               "The function has too many jump labels to handle. Split the function into smaller ones."
#define TXT_TOO_MANY_VALUES_FOR_LIST           "Too many values to match pattern"
#define TXT_TYPE_s_CANNOT_BE_REFERENCE         "Type '%s' cannot be a reference"
#define TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE    "Type '%s' is not available for this module"
#define TXT_TYPE_s_NOT_TEMPLATE                "Type '%s' is not a template type"

#define TXT_UNEXPECTED_END_OF_FILE             "Unexpected end of file"
#define TXT_UNEXPECTED_TOKEN_s                 "Unexpected token '%s'"
#define TXT_UNEXPECTED_VAR_DECL                "Unexpected variable declaration"
#define TXT_UNINITIALIZED_GLOBAL_VAR_s         "Use of uninitialized global variable '%s'."
#define TXT_UNKNOWN_SCOPE_s                    "Unknown scope '%s'"
#define TXT_UNREACHABLE_CODE                   "Unreachable code"
#define TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE "Virtual property contains unrecognized aspect"
#define TXT_UNUSED_SCRIPT_NODE                 "Unused script node"

#define TXT_VALUE_TOO_LARGE_FOR_TYPE      "Value is too large for data type"
#define TXT_VOID_CANT_BE_OPERAND          "Void cannot be an operand in expressions"

#define TXT_WARNINGS_TREATED_AS_ERROR     "Warnings are treated as errors by the application"
#define TXT_WHERE_s_IS_s                  "Where '%s' is '%s'"
#define TXT_WHILE_PARSING_ARG_LIST        "While parsing argument list"
#define TXT_WHILE_PARSING_EXPRESSION      "While parsing expression"
#define TXT_WHILE_PARSING_INIT_LIST       "While parsing initialization list"
#define TXT_WHILE_PARSING_NAMESPACE       "While parsing namespace"
#define TXT_WHILE_PARSING_STATEMENT_BLOCK "While parsing statement block"
#define TXT_WHILE_INCLUDING_MIXIN         "Previous error occurred while including mixin"

// Global variable initialization

#define TXT_FAILED_TO_INITIALIZE_s      "Failed to initialize global variable '%s'"
#define TXT_EXCEPTION_s_IN_s            "Exception '%s' in '%s'"

// Engine message

#define TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT        "Autohandles cannot be used with types that have been registered with NOCOUNT"
#define TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY "First parameter to template factory must be a reference. This will be used to pass the object type of the template"
#define TXT_INVALID_CONFIGURATION                        "Invalid configuration. Verify the registered application interface."
#define TXT_VALUE_TYPE_MUST_HAVE_SIZE                    "A value type must be registered with a non-zero size"
#define TXT_TYPE_s_IS_MISSING_BEHAVIOURS                 "Type '%s' is missing behaviours"
#define TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE                   "The behaviour is not compatible with the type"
#define TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR              "A garbage collected ref type must have the addref, release, and all gc behaviours"
#define TXT_VALUE_GC_REQUIRE_GC_BEHAVIOUR                "A garbage collected value type must have the gc enum references behaviour"
#define TXT_SCOPE_REQUIRE_REL_BEHAVIOUR                  "A scoped reference type must have the release behaviour"
#define TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR                "A reference type must have the addref and release behaviours"
#define TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR       "A non-pod value type must have at least one constructor and the destructor behaviours"
#define TXT_CANNOT_PASS_TYPE_s_BY_VAL                    "Can't pass type '%s' by value unless the application type is informed in the registration"
#define TXT_CANNOT_RET_TYPE_s_BY_VAL                     "Can't return type '%s' by value unless the application type is informed in the registration"
// TODO: Should be something like "This platform requires that AngelScript knows the exact content of the type '%s' in order to pass by value to application in native calling convention"
#define TXT_DONT_SUPPORT_TYPE_s_BY_VAL                   "Don't support passing type '%s' by value to application in native calling convention on this platform"
// TODO: Should be something like "This platform requires that AngelScript knows the exact content of the type '%s' in order to return by value from application in native calling convention"
#define TXT_DONT_SUPPORT_RET_TYPE_s_BY_VAL               "Don't support returning type '%s' by value from application in native calling convention on this platform"
#define TXT_d_GC_CANNOT_FREE_OBJ_OF_TYPE_s               "Object {%d}. GC cannot destroy an object of type '%s' as it doesn't know how many references to there are."
#define TXT_d_GC_CANNOT_FREE_OBJ_OF_TYPE_s_REF_COUNT_d   "Object {%d}. GC cannot destroy an object of type '%s' as it can't see all references. Current ref count is %d."
#define TXT_OBJECT_TYPE_s_DOESNT_EXIST                   "Object type '%s' doesn't exist"
#define TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER   "Cannot register. The template type instance '%s' has already been generated."
#define TXT_TEMPLATE_TYPE_s_DOESNT_EXIST                 "Template type '%s' doesn't exist"
#define TXT_TEMPLATE_SUBTYPE_s_DOESNT_EXIST              "Template subtype '%s' doesn't exist"
#define TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS   "Template list factory expects two reference parameters. The last is the pointer to the initialization buffer"
#define TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM             "List factory expects only one reference parameter. The pointer to the initialization buffer will be passed in this parameter"
#define TXT_FAILED_READ_SUBTYPE_OF_TEMPLATE_s            "Failed to read subtype of template type '%s'"
#define TXT_FAILED_IN_FUNC_s_s_d                         "Failed in call to function '%s' (Code: %s, %d)"
#define TXT_FAILED_IN_FUNC_s_WITH_s_s_d                  "Failed in call to function '%s' with '%s' (Code: %s, %d)"
#define TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_s_d            "Failed in call to function '%s' with '%s' and '%s' (Code: %s, %d)"
#define TXT_GC_RECEIVED_NULL_PTR                         "AddScriptObjectToGC called with null pointer"
#define TXT_EXCEPTION_IN_NESTED_CALL                     "An exception occurred in a nested call"
#define TXT_TYPE_s_IS_STILL_USED_BY_FUNC_s               "Type '%s' is still used by function '%s'"
#define TXT_PREV_TYPE_IS_NAMED_s                         "The builtin type in previous message is named '%s'"
#define TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d               "The function in previous message is named '%s'. The func type is %d"
#define TXT_RESURRECTING_SCRIPTOBJECT_s                  "The script object of type '%s' is being resurrected illegally during destruction"
#define TXT_INVALID_BYTECODE_d                           "LoadByteCode failed. The bytecode is invalid. Number of bytes read from stream: %d"
#define TXT_NO_JIT_IN_FUNC_s                             "Function '%s' appears to have been compiled without JIT entry points"
#define TXT_ENGINE_REF_COUNT_ERROR_DURING_SHUTDOWN       "Uh oh! The engine's reference count is increasing while it is being destroyed. Make sure references needed for clean-up are immediately released"
#define TXT_MODULE_IS_IN_USE                             "The module is still in use and cannot be rebuilt. Discard it and request another module"
#define TXT_EXTRNL_REF_TO_MODULE_s                       "There is an external reference to an object in module '%s', preventing it from being deleted"
#define TXT_FUNC_s_RELEASED_BEFORE_CLEANUP               "The engine was shutdown before the context released. Function '%s' cannot be cleaned up"

// Internal names

#define TXT_PROPERTY                      "Property"
#define TXT_SYSTEM_FUNCTION               "System function"
#define TXT_VARIABLE_DECL                 "Variable declaration"

// Exceptions

#define TXT_STACK_OVERFLOW                "Stack overflow"
#define TXT_NULL_POINTER_ACCESS           "Null pointer access"
#define TXT_DIVIDE_BY_ZERO                "Divide by zero"
#define TXT_DIVIDE_OVERFLOW               "Overflow in integer division"
#define TXT_POW_OVERFLOW                  "Overflow in exponent operation"
#define TXT_UNRECOGNIZED_BYTE_CODE        "Unrecognized byte code"
#define TXT_INVALID_CALLING_CONVENTION    "Invalid calling convention"
#define TXT_UNBOUND_FUNCTION              "Unbound function called"
#define TXT_OUT_OF_BOUNDS                 "Out of range"
#define TXT_EXCEPTION_CAUGHT              "Caught an exception from the application"
#define TXT_MISMATCH_IN_VALUE_ASSIGN      "Mismatching types in value assignment"
#define TXT_TOO_MANY_NESTED_CALLS         "Too many nested calls"

// Error codes
#define ERROR_NAME(x) #x
static const char*const errorNames[] =
{
	ERROR_NAME(asSUCCESS),
	ERROR_NAME(asERROR),
	ERROR_NAME(asCONTEXT_ACTIVE),
	ERROR_NAME(asCONTEXT_NOT_FINISHED),
	ERROR_NAME(asCONTEXT_NOT_PREPARED),
	ERROR_NAME(asINVALID_ARG),
	ERROR_NAME(asNO_FUNCTION),
	ERROR_NAME(asNOT_SUPPORTED),
	ERROR_NAME(asINVALID_NAME),
	ERROR_NAME(asNAME_TAKEN),
	ERROR_NAME(asINVALID_DECLARATION),
	ERROR_NAME(asINVALID_OBJECT),
	ERROR_NAME(asINVALID_TYPE),
	ERROR_NAME(asALREADY_REGISTERED),
	ERROR_NAME(asMULTIPLE_FUNCTIONS),
	ERROR_NAME(asNO_MODULE),
	ERROR_NAME(asNO_GLOBAL_VAR),
	ERROR_NAME(asINVALID_CONFIGURATION),
	ERROR_NAME(asINVALID_INTERFACE),
	ERROR_NAME(asCANT_BIND_ALL_FUNCTIONS),
	ERROR_NAME(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED),
	ERROR_NAME(asWRONG_CONFIG_GROUP),
	ERROR_NAME(asCONFIG_GROUP_IS_IN_USE),
	ERROR_NAME(asILLEGAL_BEHAVIOUR_FOR_TYPE),
	ERROR_NAME(asWRONG_CALLING_CONV),
	ERROR_NAME(asBUILD_IN_PROGRESS),
	ERROR_NAME(asINIT_GLOBAL_VARS_FAILED),
	ERROR_NAME(asOUT_OF_MEMORY),
	ERROR_NAME(asMODULE_IS_IN_USE)
};

#endif


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2014 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_thread.cpp
//
// Functions for multi threading support
//

#include "as_config.h"
#include "as_thread.h"
#include "as_atomic.h"

BEGIN_AS_NAMESPACE

//=======================================================================

// Singleton
static asCThreadManager *threadManager = 0;

//======================================================================

// Global API functions
extern "C"
{

AS_API int asThreadCleanup()
{
	return asCThreadManager::CleanupLocalData();
}

AS_API asIThreadManager *asGetThreadManager()
{
	return threadManager;
}

AS_API int asPrepareMultithread(asIThreadManager *externalThreadMgr)
{
	return asCThreadManager::Prepare(externalThreadMgr);
}

AS_API void asUnprepareMultithread()
{
	asCThreadManager::Unprepare();
}

AS_API void asAcquireExclusiveLock()
{
	if( threadManager )
	{
		ACQUIREEXCLUSIVE(threadManager->appRWLock);
	}
}

AS_API void asReleaseExclusiveLock()
{
	if( threadManager )
	{
		RELEASEEXCLUSIVE(threadManager->appRWLock);
	}
}

AS_API void asAcquireSharedLock()
{
	if( threadManager )
	{
		ACQUIRESHARED(threadManager->appRWLock);
	}
}

AS_API void asReleaseSharedLock()
{
	if( threadManager )
	{
		RELEASESHARED(threadManager->appRWLock);
	}
}

}

//======================================================================

#if !defined(AS_NO_THREADS) && defined(_MSC_VER) && defined(AS_WINDOWS_THREADS) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
__declspec(thread) asCThreadLocalData *asCThreadManager::tld = 0;
#endif

asCThreadManager::asCThreadManager()
{
	// We're already in the critical section when this function is called

#ifdef AS_NO_THREADS
	tld = 0;
#else
	// Allocate the thread local storage
	#if defined AS_POSIX_THREADS
		pthread_key_t pKey;
		pthread_key_create(&pKey, 0);
		tlsKey = (asDWORD)pKey;
	#elif defined AS_WINDOWS_THREADS
		#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
			tld = 0;
		#else
			tlsKey = (asDWORD)TlsAlloc();
		#endif
	#endif
#endif
	refCount = 1;
}

int asCThreadManager::Prepare(asIThreadManager *externalThreadMgr)
{
	// Don't allow an external thread manager if there
	// is already a thread manager defined
	if( externalThreadMgr && threadManager )
		return asINVALID_ARG;

	// The critical section cannot be declared globally, as there is no
	// guarantee for the order in which global variables are initialized
	// or uninitialized.

	// For this reason it's not possible to prevent two threads from calling
	// AddRef at the same time, so there is a chance for a race condition here.

	// To avoid the race condition when the thread manager is first created,
	// the application must make sure to call the global asPrepareForMultiThread()
	// in the main thread before any other thread creates a script engine.
	if( threadManager == 0 && externalThreadMgr == 0 )
		threadManager = asNEW(asCThreadManager);
	else
	{
		// If an application uses different dlls each dll will get it's own memory
		// space for global variables. If multiple dlls then uses AngelScript's
		// global thread support functions it is then best to share the thread
		// manager to make sure all dlls use the same critical section.
		if( externalThreadMgr )
			threadManager = reinterpret_cast<asCThreadManager*>(externalThreadMgr);

		ENTERCRITICALSECTION(threadManager->criticalSection);
		threadManager->refCount++;
		LEAVECRITICALSECTION(threadManager->criticalSection);
	}

	// Success
	return 0;
}

void asCThreadManager::Unprepare()
{
	asASSERT(threadManager);

	if( threadManager == 0 )
		return;

	// It's necessary to protect this section so no
	// other thread attempts to call AddRef or Release
	// while clean up is in progress.
	ENTERCRITICALSECTION(threadManager->criticalSection);
	if( --threadManager->refCount == 0 )
	{
		// Make sure the local data is destroyed, at least for the current thread
		CleanupLocalData();

		// As the critical section will be destroyed together
		// with the thread manager we must first clear the global
		// variable in case a new thread manager needs to be created;
		asCThreadManager *mgr = threadManager;
		threadManager = 0;

		// Leave the critical section before it is destroyed
		LEAVECRITICALSECTION(mgr->criticalSection);

		asDELETE(mgr,asCThreadManager);
	}
	else
		LEAVECRITICALSECTION(threadManager->criticalSection);
}

asCThreadManager::~asCThreadManager()
{
#ifndef AS_NO_THREADS
	// Deallocate the thread local storage
	#if defined AS_POSIX_THREADS
		pthread_key_delete((pthread_key_t)tlsKey);
	#elif defined AS_WINDOWS_THREADS
		#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
			tld = 0;
		#else
			TlsFree((DWORD)tlsKey);
		#endif
	#endif
#else
	if( tld )
	{
		asDELETE(tld,asCThreadLocalData);
	}
	tld = 0;
#endif
}

int asCThreadManager::CleanupLocalData()
{
	if( threadManager == 0 )
		return 0;

#ifndef AS_NO_THREADS
#if defined AS_POSIX_THREADS
	asCThreadLocalData *tld = (asCThreadLocalData*)pthread_getspecific((pthread_key_t)threadManager->tlsKey);
#elif defined AS_WINDOWS_THREADS
	#if !defined(_MSC_VER) || !(WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
		asCThreadLocalData *tld = (asCThreadLocalData*)TlsGetValue((DWORD)threadManager->tlsKey);
	#endif
#endif

	if( tld == 0 )
		return 0;

	if( tld->activeContexts.GetLength() == 0 )
	{
		asDELETE(tld,asCThreadLocalData);
		#if defined AS_POSIX_THREADS
			pthread_setspecific((pthread_key_t)threadManager->tlsKey, 0);
		#elif defined AS_WINDOWS_THREADS
			#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
				tld = 0;
			#else
				TlsSetValue((DWORD)threadManager->tlsKey, 0);
			#endif
		#endif
		return 0;
	}
	else
		return asCONTEXT_ACTIVE;

#else
	if( threadManager->tld )
	{
		if( threadManager->tld->activeContexts.GetLength() == 0 )
		{
			asDELETE(threadManager->tld,asCThreadLocalData);
			threadManager->tld = 0;
		}
		else
			return asCONTEXT_ACTIVE;
	}
	return 0;
#endif
}

asCThreadLocalData *asCThreadManager::GetLocalData()
{
	if( threadManager == 0 )
		return 0;

#ifndef AS_NO_THREADS
#if defined AS_POSIX_THREADS
	asCThreadLocalData *tld = (asCThreadLocalData*)pthread_getspecific((pthread_key_t)threadManager->tlsKey);
	if( tld == 0 )
	{
		tld = asNEW(asCThreadLocalData)();
		pthread_setspecific((pthread_key_t)threadManager->tlsKey, tld);
	}
#elif defined AS_WINDOWS_THREADS
	#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
		if( tld == 0 )
			tld = asNEW(asCThreadLocalData)();
	#else
		asCThreadLocalData *tld = (asCThreadLocalData*)TlsGetValue((DWORD)threadManager->tlsKey);
		if( tld == 0 )
		{
 			tld = asNEW(asCThreadLocalData)();
			TlsSetValue((DWORD)threadManager->tlsKey, tld);
 		}
	#endif
#endif

	return tld;
#else
	if( threadManager->tld == 0 )
		threadManager->tld = asNEW(asCThreadLocalData)();

	return threadManager->tld;
#endif
}

//=========================================================================

asCThreadLocalData::asCThreadLocalData()
{
}

asCThreadLocalData::~asCThreadLocalData()
{
}

//=========================================================================

#ifndef AS_NO_THREADS
asCThreadCriticalSection::asCThreadCriticalSection()
{
#if defined AS_POSIX_THREADS
	pthread_mutex_init(&cs, 0);
#elif defined AS_WINDOWS_THREADS
#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
	// Only the Ex version is available on Windows Store
	InitializeCriticalSectionEx(&cs, 4000, 0);
#else
	// Only the non-Ex version is available on WinXP and older
	// MinGW also only defines this version
	InitializeCriticalSection(&cs);
#endif
#endif
}

asCThreadCriticalSection::~asCThreadCriticalSection()
{
#if defined AS_POSIX_THREADS
	pthread_mutex_destroy(&cs);
#elif defined AS_WINDOWS_THREADS
	DeleteCriticalSection(&cs);
#endif
}

void asCThreadCriticalSection::Enter()
{
#if defined AS_POSIX_THREADS
	pthread_mutex_lock(&cs);
#elif defined AS_WINDOWS_THREADS
	EnterCriticalSection(&cs);
#endif
}

void asCThreadCriticalSection::Leave()
{
#if defined AS_POSIX_THREADS
	pthread_mutex_unlock(&cs);
#elif defined AS_WINDOWS_THREADS
	LeaveCriticalSection(&cs);
#endif
}

bool asCThreadCriticalSection::TryEnter()
{
#if defined AS_POSIX_THREADS
	return !pthread_mutex_trylock(&cs);
#elif defined AS_WINDOWS_THREADS
	return TryEnterCriticalSection(&cs) ? true : false;
#else
	return true;
#endif
}

asCThreadReadWriteLock::asCThreadReadWriteLock()
{
#if defined AS_POSIX_THREADS
	int r = pthread_rwlock_init(&lock, 0);
	asASSERT( r == 0 );
	UNUSED_VAR(r);
#elif defined AS_WINDOWS_THREADS
#if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
	// Only the Ex versions are available on Windows Store

	// Create a semaphore to allow up to maxReaders simultaneous readers
	readLocks = CreateSemaphoreExW(NULL, maxReaders, maxReaders, 0, 0, 0);
	// Create a critical section to synchronize writers
	InitializeCriticalSectionEx(&writeLock, 4000, 0);
#else
	readLocks = CreateSemaphoreW(NULL, maxReaders, maxReaders, 0);
	InitializeCriticalSection(&writeLock);
#endif
#endif
}

asCThreadReadWriteLock::~asCThreadReadWriteLock()
{
#if defined AS_POSIX_THREADS
	pthread_rwlock_destroy(&lock);
#elif defined AS_WINDOWS_THREADS
	DeleteCriticalSection(&writeLock);
	CloseHandle(readLocks);
#endif
}

void asCThreadReadWriteLock::AcquireExclusive()
{
#if defined AS_POSIX_THREADS
	pthread_rwlock_wrlock(&lock);
#elif defined AS_WINDOWS_THREADS
	// Synchronize writers, so only one tries to lock out the readers
	EnterCriticalSection(&writeLock);

	// Lock all reader out from the semaphore. Do this one by one,
	// so the lock doesn't have to wait until there are no readers at all.
	// If we try to lock all at once it is quite possible the writer will
	// never succeed.
	for( asUINT n = 0; n < maxReaders; n++ )
		WaitForSingleObjectEx(readLocks, INFINITE, FALSE);

	// Allow another writer to lock. It will only be able to
	// lock the readers when this writer releases them anyway.
	LeaveCriticalSection(&writeLock);
#endif
}

void asCThreadReadWriteLock::ReleaseExclusive()
{
#if defined AS_POSIX_THREADS
	pthread_rwlock_unlock(&lock);
#elif defined AS_WINDOWS_THREADS
	// Release all readers at once
	ReleaseSemaphore(readLocks, maxReaders, 0);
#endif
}

void asCThreadReadWriteLock::AcquireShared()
{
#if defined AS_POSIX_THREADS
	pthread_rwlock_rdlock(&lock);
#elif defined AS_WINDOWS_THREADS
	// Lock a reader slot
	WaitForSingleObjectEx(readLocks, INFINITE, FALSE);
#endif
}

void asCThreadReadWriteLock::ReleaseShared()
{
#if defined AS_POSIX_THREADS
	pthread_rwlock_unlock(&lock);
#elif defined AS_WINDOWS_THREADS
	// Release the reader slot
	ReleaseSemaphore(readLocks, 1, 0);
#endif
}

#endif

//========================================================================

END_AS_NAMESPACE

repo_name: Antidote/openrpgeditor

license: mit


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2017 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_thread.h
//
// Classes for multi threading support
//

#ifndef AS_THREAD_H
#define AS_THREAD_H

#include "as_config.h"
#include "as_string.h"
#include "as_array.h"
#include "as_map.h"
#include "as_criticalsection.h"

BEGIN_AS_NAMESPACE

class asCThreadLocalData;

class asCThreadManager : public asIThreadManager
{
public:
	static asCThreadLocalData *GetLocalData();
	static int CleanupLocalData();

	static int  Prepare(asIThreadManager *externalThreadMgr);
	static void Unprepare();

	// This read/write lock can be used by the application to provide simple synchronization
	DECLAREREADWRITELOCK(appRWLock)

protected:
	asCThreadManager();
	~asCThreadManager();

	// No need to use the atomic int here, as it will only be
	// updated within the thread manager's critical section
	int refCount;

#ifndef AS_NO_THREADS
#if defined(_MSC_VER) && defined(AS_WINDOWS_THREADS) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP)
	// On Windows Store we must use MSVC specific thread variables for thread
	// local storage, as the TLS API isn't available. On desktop we can't use
	// this as it may cause problems if the library is used in a dll.
	// ref: http://msdn.microsoft.com/en-us/library/2s9wt68x.aspx
	// ref: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
	__declspec(thread) static asCThreadLocalData *tld;
#else
	asDWORD tlsKey;
#endif
	DECLARECRITICALSECTION(criticalSection)
#else
	asCThreadLocalData *tld;
#endif
};

//======================================================================

class asIScriptContext;

class asCThreadLocalData
{
public:
	asCArray<asIScriptContext *> activeContexts;
	asCString string;

protected:
	friend class asCThreadManager;

	asCThreadLocalData();
	~asCThreadLocalData();
};

END_AS_NAMESPACE

#endif


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2025 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_tokendef.h
//
// Definitions for tokens identifiable by the tokenizer
//

#ifndef AS_TOKENDEF_H
#define AS_TOKENDEF_H

#include "as_config.h"

BEGIN_AS_NAMESPACE

enum eTokenType
{
	ttUnrecognizedToken,

	ttEnd,                 // End of file

	// White space and comments
	ttWhiteSpace,          // ' ', '\t', '\r', '\n', UTF8 byte-order-mark
	ttOnelineComment,      // // \n
	ttMultilineComment,    // /* */

	// Atoms
	ttIdentifier,                  // abc123
	ttIntConstant,                 // 1234
	ttFloatConstant,               // 12.34e56f
	ttDoubleConstant,              // 12.34e56
	ttStringConstant,              // "123"
	ttMultilineStringConstant,     //
	ttHeredocStringConstant,       // """text"""
	ttNonTerminatedStringConstant, // "123
	ttBitsConstant,                // 0xFFFF

	// Math operators
	ttPlus,                // +
	ttMinus,               // -
	ttStar,                // *
	ttSlash,               // /
	ttPercent,             // %
	ttStarStar,            // **

	ttHandle,              // @

	ttAddAssign,           // +=
	ttSubAssign,           // -=
	ttMulAssign,           // *=
	ttDivAssign,           // /=
	ttModAssign,           // %=
	ttPowAssign,           // **=

	ttOrAssign,            // |=
	ttAndAssign,           // &=
	ttXorAssign,           // ^=
	ttShiftLeftAssign,     // <<=
	ttShiftRightLAssign,   // >>=
	ttShiftRightAAssign,   // >>>=

	ttInc,                 // ++
	ttDec,                 // --

	ttDot,                 // .
	ttVariadic,            // ...
	ttScope,               // ::

	// Statement tokens
	ttAssignment,          // =
	ttEndStatement,        // ;
	ttListSeparator,       // ,
	ttStartStatementBlock, // {
	ttEndStatementBlock,   // }
	ttOpenParenthesis,     // (
	ttCloseParenthesis,    // )
	ttOpenBracket,         // [
	ttCloseBracket,        // ]
	ttAmp,                 // &

	// Bitwise operators
	ttBitOr,               // |
	ttBitNot,              // ~
	ttBitXor,              // ^
	ttBitShiftLeft,        // <<
	ttBitShiftRight,       // >>     // TODO: In Java this is the arithmetical shift
	ttBitShiftRightArith,  // >>>    // TODO: In Java this is the logical shift

	// Compare operators
	ttEqual,               // ==
	ttNotEqual,            // !=
	ttLessThan,            // <
	ttGreaterThan,         // >
	ttLessThanOrEqual,     // <=
	ttGreaterThanOrEqual,  // >=

	ttQuestion,            // ?
	ttColon,               // :

	// Reserved keywords
	ttIf,                  // if
	ttElse,                // else
	ttFor,                 // for
	ttForEach,             // foreach
	ttWhile,               // while
	ttBool,                // bool
	ttFuncDef,             // funcdef
	ttImport,              // import
	ttInt,                 // int
	ttInt8,                // int8
	ttInt16,               // int16
	ttInt64,               // int64
	ttInterface,           // interface
	ttIs,                  // is
	ttNotIs,               // !is
	ttUInt,                // uint
	ttUInt8,               // uint8
	ttUInt16,              // uint16
	ttUInt64,              // uint64
	ttFloat,               // float
	ttVoid,                // void
	ttTrue,                // true
	ttFalse,               // false
	ttReturn,              // return
	ttNot,                 // not
	ttAnd,                 // and, &&
	ttOr,                  // or, ||
	ttXor,                 // xor, ^^
	ttBreak,               // break
	ttContinue,            // continue
	ttConst,               // const
	ttDo,                  // do
	ttDouble,              // double
	ttSwitch,              // switch
	ttCase,                // case
	ttDefault,             // default
	ttIn,                  // in
	ttOut,                 // out
	ttInOut,               // inout
	ttNull,                // null
	ttClass,               // class
	ttTypedef,             // typedef
	ttEnum,                // enum
	ttCast,                // cast
	ttPrivate,             // private
	ttProtected,           // protected
	ttNamespace,           // namespace
	ttMixin,               // mixin
	ttAuto,                // auto
	ttTry,                 // try
	ttCatch,               // catch
	ttUsing                // using
};

struct sTokenWord
{
	const char *word;
	size_t      wordLength;
	eTokenType  tokenType;
};

#define asTokenDef(str, tok) {str, sizeof(str)-1, tok}

sTokenWord const tokenWords[] =
{
	asTokenDef("+"         , ttPlus),
	asTokenDef("+="        , ttAddAssign),
	asTokenDef("++"        , ttInc),
	asTokenDef("-"         , ttMinus),
	asTokenDef("-="        , ttSubAssign),
	asTokenDef("--"        , ttDec),
	asTokenDef("*"         , ttStar),
	asTokenDef("*="        , ttMulAssign),
	asTokenDef("/"         , ttSlash),
	asTokenDef("/="        , ttDivAssign),
	asTokenDef("%"         , ttPercent),
	asTokenDef("%="        , ttModAssign),
	asTokenDef("**"        , ttStarStar),
	asTokenDef("**="       , ttPowAssign),
	asTokenDef("="         , ttAssignment),
	asTokenDef("=="        , ttEqual),
	asTokenDef("."         , ttDot),
	asTokenDef("..."       , ttVariadic),
	asTokenDef("|"         , ttBitOr),
	asTokenDef("|="        , ttOrAssign),
	asTokenDef("||"        , ttOr),
	asTokenDef("&"         , ttAmp),
	asTokenDef("&="        , ttAndAssign),
	asTokenDef("&&"        , ttAnd),
	asTokenDef("^"         , ttBitXor),
	asTokenDef("^="        , ttXorAssign),
	asTokenDef("^^"        , ttXor),
	asTokenDef("<"         , ttLessThan),
	asTokenDef("<="        , ttLessThanOrEqual),
	asTokenDef("<<"        , ttBitShiftLeft),
	asTokenDef("<<="       , ttShiftLeftAssign),
	asTokenDef(">"         , ttGreaterThan),
	asTokenDef(">="        , ttGreaterThanOrEqual),
	asTokenDef(">>"        , ttBitShiftRight),
	asTokenDef(">>="       , ttShiftRightLAssign),
	asTokenDef(">>>"       , ttBitShiftRightArith),
	asTokenDef(">>>="      , ttShiftRightAAssign),
	asTokenDef("~"         , ttBitNot),
	asTokenDef(";"         , ttEndStatement),
	asTokenDef(","         , ttListSeparator),
	asTokenDef("{"         , ttStartStatementBlock),
	asTokenDef("}"         , ttEndStatementBlock),
	asTokenDef("("         , ttOpenParenthesis),
	asTokenDef(")"         , ttCloseParenthesis),
	asTokenDef("["         , ttOpenBracket),
	asTokenDef("]"         , ttCloseBracket),
	asTokenDef("?"         , ttQuestion),
	asTokenDef(":"         , ttColon),
	asTokenDef("::"        , ttScope),
	asTokenDef("!"         , ttNot),
	asTokenDef("!="        , ttNotEqual),
	asTokenDef("!is"       , ttNotIs),
	asTokenDef("@"         , ttHandle),
	asTokenDef("and"       , ttAnd),
	asTokenDef("auto"      , ttAuto),
	asTokenDef("bool"      , ttBool),
	asTokenDef("break"     , ttBreak),
	asTokenDef("case"      , ttCase),
	asTokenDef("cast"      , ttCast),
	asTokenDef("catch"     , ttCatch),
	asTokenDef("class"     , ttClass),
	asTokenDef("const"     , ttConst),
	asTokenDef("continue"  , ttContinue),
	asTokenDef("default"   , ttDefault),
	asTokenDef("do"        , ttDo),
#ifdef  AS_USE_DOUBLE_AS_FLOAT
	asTokenDef("double"    , ttFloat),
#else
	asTokenDef("double"    , ttDouble),
#endif
	asTokenDef("else"      , ttElse),
	asTokenDef("enum"      , ttEnum),
	asTokenDef("false"     , ttFalse),
	asTokenDef("float"     , ttFloat),
	asTokenDef("for"       , ttFor),
	asTokenDef("foreach"   , ttForEach),
	asTokenDef("funcdef"   , ttFuncDef),
	asTokenDef("if"        , ttIf),
	asTokenDef("import"    , ttImport),
	asTokenDef("in"        , ttIn),
	asTokenDef("inout"     , ttInOut),
	asTokenDef("int"       , ttInt),
	asTokenDef("int8"      , ttInt8),
	asTokenDef("int16"     , ttInt16),
	asTokenDef("int32"     , ttInt),
	asTokenDef("int64"     , ttInt64),
	asTokenDef("interface" , ttInterface),
	asTokenDef("is"        , ttIs),
	asTokenDef("mixin"     , ttMixin),
	asTokenDef("namespace" , ttNamespace),
	asTokenDef("not"       , ttNot),
	asTokenDef("null"      , ttNull),
	asTokenDef("or"        , ttOr),
	asTokenDef("out"       , ttOut),
	asTokenDef("private"   , ttPrivate),
	asTokenDef("protected" , ttProtected),
	asTokenDef("return"    , ttReturn),
	asTokenDef("switch"    , ttSwitch),
	asTokenDef("true"      , ttTrue),
	asTokenDef("try"       , ttTry),
	asTokenDef("typedef"   , ttTypedef),
	asTokenDef("uint"      , ttUInt),
	asTokenDef("uint8"     , ttUInt8),
	asTokenDef("uint16"    , ttUInt16),
	asTokenDef("uint32"    , ttUInt),
	asTokenDef("uint64"    , ttUInt64),
	asTokenDef("using"     , ttUsing),
	asTokenDef("void"      , ttVoid),
	asTokenDef("while"     , ttWhile),
	asTokenDef("xor"       , ttXor),
};

const unsigned int numTokenWords = sizeof(tokenWords)/sizeof(sTokenWord);

const char * const whiteSpace = " \t\r\n";

// Some keywords that are not considered tokens by the parser
// These only have meaning in specific situations. Outside these
// situations they are treated as normal identifiers.
const char * const THIS_TOKEN      = "this";
const char * const FROM_TOKEN      = "from";
const char * const SUPER_TOKEN     = "super";
const char * const SHARED_TOKEN    = "shared";
const char * const FINAL_TOKEN     = "final";
const char * const OVERRIDE_TOKEN  = "override";
const char * const GET_TOKEN       = "get";
const char * const SET_TOKEN       = "set";
const char * const ABSTRACT_TOKEN  = "abstract";
const char * const FUNCTION_TOKEN  = "function";
const char * const IF_HANDLE_TOKEN = "if_handle_then_const";
const char * const EXTERNAL_TOKEN  = "external";
const char * const EXPLICIT_TOKEN  = "explicit";
const char * const PROPERTY_TOKEN  = "property";
const char * const DELETE_TOKEN    = "delete";

END_AS_NAMESPACE

#endif


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2024 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_tokenizer.cpp
//
// This class identifies tokens from the script code
//

#include "as_config.h"
#include "as_scriptengine.h"
#include "as_tokenizer.h"
#include "as_tokendef.h"

#if !defined(AS_NO_MEMORY_H)
#include <memory.h>
#endif
#include <string.h> // strcmp()

BEGIN_AS_NAMESPACE

asCTokenizer::asCTokenizer()
{
	engine = 0;
	memset(keywordTable, 0, sizeof(keywordTable));

	InitJumpTable();
}

asCTokenizer::~asCTokenizer()
{
	FreeJumpTable();
}

void asCTokenizer::FreeJumpTable()
{
	// Deallocate the jump table
	for (asUINT n = 0; n < 256; n++)
	{
		if (keywordTable[n])
			asDELETEARRAY(keywordTable[n]);
	}
	memset(keywordTable, 0, sizeof(keywordTable));
}

void asCTokenizer::InitJumpTable()
{
	FreeJumpTable();

	// Initialize the jump table
	for (asUINT n = 0; n < numTokenWords; n++)
	{
		const sTokenWord& current = tokenWords[n];

		// Check if a token must be skipped due to engine properties
		if (current.tokenType == ttForEach && engine && !engine->ep.foreachSupport)
			continue;

		unsigned char start = current.word[0];

		// Create new jump table entry if none exists
		if (!keywordTable[start])
		{
			// Surely there won't ever be more than 32 keywords starting with
			// the same character. Right?
			keywordTable[start] = asNEWARRAY(const sTokenWord*, 32);
			memset(keywordTable[start], 0, sizeof(sTokenWord*) * 32);
		}

		// Add the token sorted from longest to shortest so
		// we check keywords greedily.
		const sTokenWord** tok = keywordTable[start];
		unsigned insert = 0, index = 0;
		while (tok[index])
		{
			if (tok[index]->wordLength >= current.wordLength)
				++insert;
			++index;
		}

		while (index > insert)
		{
			tok[index] = tok[index - 1];
			--index;
		}

		tok[insert] = &current;
	}
}

// static
const char *asCTokenizer::GetDefinition(int tokenType)
{
	if( tokenType == ttUnrecognizedToken			) return "<unrecognized token>";
	if( tokenType == ttEnd							) return "<end of file>";
	if( tokenType == ttWhiteSpace					) return "<white space>";
	if( tokenType == ttOnelineComment				) return "<one line comment>";
	if( tokenType == ttMultilineComment				) return "<multiple lines comment>";
	if( tokenType == ttIdentifier					) return "<identifier>";
	if( tokenType == ttIntConstant					) return "<integer constant>";
	if( tokenType == ttFloatConstant				) return "<float constant>";
	if( tokenType == ttDoubleConstant				) return "<double constant>";
	if( tokenType == ttStringConstant				) return "<string constant>";
	if( tokenType == ttMultilineStringConstant      ) return "<multiline string constant>";
	if( tokenType == ttNonTerminatedStringConstant	) return "<nonterminated string constant>";
	if( tokenType == ttBitsConstant					) return "<bits constant>";
	if( tokenType == ttHeredocStringConstant		) return "<heredoc string constant>";

	for( asUINT n = 0; n < numTokenWords; n++ )
		if( tokenWords[n].tokenType == tokenType )
			return tokenWords[n].word;

	return 0;
}

bool asCTokenizer::IsDigitInRadix(char ch, int radix) const
{
	if( ch >= '0' && ch <= '9' ) return (ch -= '0') < radix;
	if( ch >= 'A' && ch <= 'Z' ) return (ch -= 'A'-10) < radix;
	if( ch >= 'a' && ch <= 'z' ) return (ch -= 'a'-10) < radix;
	return false;
}

eTokenType asCTokenizer::GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc) const
{
	asASSERT(source != 0);
	asASSERT(tokenLength != 0);

	eTokenType tokenType;
	size_t     tlen;
	asETokenClass t = ParseToken(source, sourceLength, tlen, tokenType);
	if( tc          ) *tc          = t;
	if( tokenLength ) *tokenLength = tlen;

	return tokenType;
}

asETokenClass asCTokenizer::ParseToken(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	if( IsWhiteSpace(source, sourceLength, tokenLength, tokenType) ) return asTC_WHITESPACE;
	if( IsComment(source, sourceLength, tokenLength, tokenType)    ) return asTC_COMMENT;
	if( IsConstant(source, sourceLength, tokenLength, tokenType)   ) return asTC_VALUE;
	if( IsIdentifier(source, sourceLength, tokenLength, tokenType) ) return asTC_IDENTIFIER;
	if( IsKeyWord(source, sourceLength, tokenLength, tokenType)    ) return asTC_KEYWORD;

	// If none of the above this is an unrecognized token
	// We can find the length of the token by advancing
	// one step and trying to identify a token there
	tokenType   = ttUnrecognizedToken;
	tokenLength = 1;

	return asTC_UNKNOWN;
}

bool asCTokenizer::IsWhiteSpace(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	// Treat UTF8 byte-order-mark (EF BB BF) as whitespace
	if( sourceLength >= 3 &&
		asBYTE(source[0]) == 0xEFu &&
		asBYTE(source[1]) == 0xBBu &&
		asBYTE(source[2]) == 0xBFu )
	{
		tokenType   = ttWhiteSpace;
		tokenLength = 3;
		return true;
	}

	// Group all other white space characters into one
	size_t n;
	int numWsChars = (int)strlen(whiteSpace);
	for( n = 0; n < sourceLength; n++ )
	{
		bool isWhiteSpace = false;
		for( int w = 0; w < numWsChars; w++ )
		{
			if( source[n] == whiteSpace[w] )
			{
				isWhiteSpace = true;
				break;
			}
		}
		if( !isWhiteSpace )	break;
	}

	if( n > 0 )
	{
		tokenType   = ttWhiteSpace;
		tokenLength = n;
		return true;
	}

	return false;
}

bool asCTokenizer::IsComment(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	if( sourceLength < 2 )
		return false;

	if( source[0] != '/' )
		return false;

	if( source[1] == '/' )
	{
		// One-line comment

		// Find the length
		size_t n;
		for( n = 2; n < sourceLength; n++ )
		{
			if( source[n] == '\n' )
				break;
		}

		tokenType   = ttOnelineComment;
		tokenLength = n < sourceLength ? n+1 : n;

		return true;
	}

	if( source[1] == '*' )
	{
		// Multi-line comment

		// Find the length
		size_t n;
		for( n = 2; n < sourceLength-1; )
		{
			if( source[n++] == '*' && source[n] == '/' )
				break;
		}

		tokenType   = ttMultilineComment;
		tokenLength = n+1;

		return true;
	}

	return false;
}

bool asCTokenizer::IsConstant(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	// Starting with number
	if( (source[0] >= '0' && source[0] <= '9') || (source[0] == '.' && sourceLength > 1 && source[1] >= '0' && source[1] <= '9') )
	{
		// Is it a based number?
		if( source[0] == '0' && sourceLength > 1 )
		{
			// Determine the radix for the constant
			int radix = 0;
			switch( source[1] )
 			{
			case 'b': case 'B': radix =  2; break;
			case 'o': case 'O': radix =  8; break;
			case 'd': case 'D': radix = 10; break;
			case 'x': case 'X': radix = 16; break;
 			}

			if( radix )
			{
				size_t n;
				for( n = 2; n < sourceLength; n++ )
					if( !IsDigitInRadix(source[n], radix) )
						break;

				tokenType   = ttBitsConstant;
				tokenLength = n;
				return true;
			}
		}

		size_t n;
		for( n = 0; n < sourceLength; n++ )
		{
			if( source[n] < '0' || source[n] > '9' )
				break;
		}

		if( n < sourceLength && (source[n] == '.' || source[n] == 'e' || source[n] == 'E') )
		{
			if( source[n] == '.' )
			{
				n++;
				for( ; n < sourceLength; n++ )
				{
					if( source[n] < '0' || source[n] > '9' )
						break;
				}
			}

			if( n < sourceLength && (source[n] == 'e' || source[n] == 'E') )
			{
				n++;
				if( n < sourceLength && (source[n] == '-' || source[n] == '+') )
					n++;

				for( ; n < sourceLength; n++ )
				{
					if( source[n] < '0' || source[n] > '9' )
						break;
				}
			}

			if( n < sourceLength && (source[n] == 'f' || source[n] == 'F') )
			{
				tokenType   = ttFloatConstant;
				tokenLength = n + 1;
			}
			else
			{
#ifdef AS_USE_DOUBLE_AS_FLOAT
				tokenType   = ttFloatConstant;
#else
				tokenType   = ttDoubleConstant;
#endif
				tokenLength = n;
			}
			return true;
		}

		tokenType   = ttIntConstant;
		tokenLength = n;
		return true;
	}

	// String constant between double or single quotes
	if( source[0] == '"' || source[0] == '\'' )
	{
		// Is it a normal string constant or a heredoc string constant?
		if( sourceLength >= 6 && source[0] == '"' && source[1] == '"' && source[2] == '"' )
		{
			// Heredoc string constant (spans multiple lines, no escape sequences)

			// Find the length
			size_t n;
			for( n = 3; n < sourceLength-2; n++ )
			{
				if (source[n] == '"' && source[n + 1] == '"' && source[n + 2] == '"')
				{
					tokenType = ttHeredocStringConstant;
					tokenLength = n + 3;
					return true;
				}
			}

			tokenType   = ttNonTerminatedStringConstant;
			tokenLength = n+2;
		}
		else
		{
			// Normal string constant
			tokenType = ttStringConstant;
			char quote = source[0];
			bool evenSlashes = true;
			size_t n;
			for( n = 1; n < sourceLength; n++ )
			{
#ifdef AS_DOUBLEBYTE_CHARSET
				// Double-byte characters are only allowed for ASCII
				if( (source[n] & 0x80) && engine->ep.scanner == 0 )
				{
					// This is a leading character in a double byte character,
					// include both in the string and continue processing.
					n++;
					continue;
				}
#endif

				if( source[n] == '\n' )
					tokenType = ttMultilineStringConstant;
				if( source[n] == quote && evenSlashes )
				{
					tokenLength = n+1;
					return true;
				}
				if( source[n] == '\\' ) evenSlashes = !evenSlashes; else evenSlashes = true;
			}

			tokenType   = ttNonTerminatedStringConstant;
			tokenLength = n;
		}

		return true;
	}

	return false;
}

bool asCTokenizer::IsIdentifier(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	// char is unsigned by default on some architectures, e.g. ppc and arm
	// Make sure the value is always treated as signed in the below comparisons
	signed char c = source[0];

	// Starting with letter or underscore
	if( (c >= 'a' && c <= 'z') ||
		(c >= 'A' && c <= 'Z') ||
		c == '_' ||
		(c < 0 && engine->ep.allowUnicodeIdentifiers) )
	{
		tokenType   = ttIdentifier;
		tokenLength = 1;

		for( size_t n = 1; n < sourceLength; n++ )
		{
			c = source[n];
			if( (c >= 'a' && c <= 'z') ||
				(c >= 'A' && c <= 'Z') ||
				(c >= '0' && c <= '9') ||
				c == '_' ||
				(c < 0 && engine->ep.allowUnicodeIdentifiers) )
				tokenLength++;
			else
				break;
		}

		// Make sure the identifier isn't a reserved keyword
		if( IsKeyWord(source, tokenLength, tokenLength, tokenType) )
			return false;

		return true;
	}

	return false;
}

bool asCTokenizer::IsKeyWord(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
{
	unsigned char start = source[0];
	const sTokenWord **ptr = keywordTable[start];

	if( !ptr )
		return false;

	for( ; *ptr; ++ptr )
	{
		size_t wlen = (*ptr)->wordLength;
		if( sourceLength >= wlen && strncmp(source, (*ptr)->word, wlen) == 0 )
		{
			// Tokens that end with a character that can be part of an
			// identifier require an extra verification to guarantee that
			// we don't split an identifier token, e.g. the "!is" token
			// and the tokens "!" and "isTrue" in the "!isTrue" expression.
			if( wlen < sourceLength &&
				((source[wlen-1] >= 'a' && source[wlen-1] <= 'z') ||
				 (source[wlen-1] >= 'A' && source[wlen-1] <= 'Z') ||
				 (source[wlen-1] >= '0' && source[wlen-1] <= '9')) &&
				((source[wlen] >= 'a' && source[wlen] <= 'z') ||
				 (source[wlen] >= 'A' && source[wlen] <= 'Z') ||
				 (source[wlen] >= '0' && source[wlen] <= '9') ||
				 (source[wlen] == '_')) )
			{
				// The token doesn't really match, even though
				// the start of the source matches the token
				continue;
			}

			tokenType = (*ptr)->tokenType;
			tokenLength = wlen;
			return true;
		}
	}

	return false;
}

END_AS_NAMESPACE


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2024 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_tokenizer.cpp
//
// This class identifies tokens from the script code
//

#ifndef AS_TOKENIZER_H
#define AS_TOKENIZER_H

#include "as_config.h"
#include "as_tokendef.h"
#include "as_map.h"
#include "as_string.h"

BEGIN_AS_NAMESPACE

class asCTokenizer
{
public:
	eTokenType GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc = 0) const;

	static const char *GetDefinition(int tokenType);

protected:
	friend class asCScriptEngine;

	asCTokenizer();
	~asCTokenizer();

	asETokenClass ParseToken(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsWhiteSpace(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsComment(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsConstant(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsKeyWord(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsIdentifier(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
	bool IsDigitInRadix(char ch, int radix) const;

	void InitJumpTable();
	void FreeJumpTable();

	const asCScriptEngine *engine;

	const sTokenWord **keywordTable[256];
};

END_AS_NAMESPACE

#endif


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2025 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_typeinfo.cpp
//

#include "as_config.h"
#include "as_typeinfo.h"
#include "as_scriptengine.h"

BEGIN_AS_NAMESPACE

asCTypeInfo::asCTypeInfo()
{
	externalRefCount.set(0);
	internalRefCount.set(1); // start with one internal ref-count
	engine = 0;
	module = 0;
	size = 0;
	flags = 0;
	typeId = -1; // start as -1 to signal that it hasn't been defined

	scriptSectionIdx = -1;
	declaredAt = 0;

	accessMask = 0xFFFFFFFF;
	nameSpace = 0;
}

asCTypeInfo::asCTypeInfo(asCScriptEngine *in_engine)
{
	externalRefCount.set(0);
	internalRefCount.set(1); // start with one internal ref count
	engine = in_engine;
	module = 0;
	size = 0;
	flags = 0;
	typeId = -1; // start as -1 to signal that it hasn't been defined

	scriptSectionIdx = -1;
	declaredAt = 0;

	accessMask = 0xFFFFFFFF;
	nameSpace = engine->nameSpaces[0];
}

asCTypeInfo::~asCTypeInfo()
{
}

// interface
int asCTypeInfo::AddRef() const
{
	return externalRefCount.atomicInc();
}

// interface
int asCTypeInfo::Release() const
{
	int r = externalRefCount.atomicDec();

	if (r == 0)
	{
		// There are no more external references, if there are also no
		// internal references then it is time to delete the object type
		if (internalRefCount.get() == 0)
		{
			// If the engine is no longer set, then it has already been
			// released and we must take care of the deletion ourselves
			asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
		}
	}

	return r;
}

int asCTypeInfo::AddRefInternal()
{
	return internalRefCount.atomicInc();
}

int asCTypeInfo::ReleaseInternal()
{
	int r = internalRefCount.atomicDec();

	if (r == 0)
	{
		// There are no more internal references, if there are also no
		// external references then it is time to delete the object type
		if (externalRefCount.get() == 0)
		{
			// If the engine is no longer set, then it has already been
			// released and we must take care of the deletion ourselves
			asDELETE(const_cast<asCTypeInfo*>(this), asCTypeInfo);
		}
	}

	return r;
}

// interface
asIScriptModule *asCTypeInfo::GetModule() const
{
	return module;
}

void *asCTypeInfo::SetUserData(void *data, asPWORD type)
{
	// As a thread might add a new new user data at the same time as another
	// it is necessary to protect both read and write access to the userData member
	ACQUIREEXCLUSIVE(engine->engineRWLock);

	// It is not intended to store a lot of different types of userdata,
	// so a more complex structure like a associative map would just have
	// more overhead than a simple array.
	for (asUINT n = 0; n < userData.GetLength(); n += 2)
	{
		if (userData[n] == type)
		{
			void *oldData = reinterpret_cast<void*>(userData[n + 1]);
			userData[n + 1] = reinterpret_cast<asPWORD>(data);

			RELEASEEXCLUSIVE(engine->engineRWLock);

			return oldData;
		}
	}

	userData.PushLast(type);
	userData.PushLast(reinterpret_cast<asPWORD>(data));

	RELEASEEXCLUSIVE(engine->engineRWLock);

	return 0;
}

void *asCTypeInfo::GetUserData(asPWORD type) const
{
	// There may be multiple threads reading, but when
	// setting the user data nobody must be reading.
	ACQUIRESHARED(engine->engineRWLock);

	for (asUINT n = 0; n < userData.GetLength(); n += 2)
	{
		if (userData[n] == type)
		{
			RELEASESHARED(engine->engineRWLock);
			return reinterpret_cast<void*>(userData[n + 1]);
		}
	}

	RELEASESHARED(engine->engineRWLock);

	return 0;
}

// interface
const char *asCTypeInfo::GetName() const
{
	return name.AddressOf();
}

// interface
const char *asCTypeInfo::GetNamespace() const
{
	if( nameSpace )
		return nameSpace->name.AddressOf();

	return 0;
}

// interface
asQWORD asCTypeInfo::GetFlags() const
{
	return flags;
}

// interface
asUINT asCTypeInfo::GetSize() const
{
	return size;
}

// interface
int asCTypeInfo::GetTypeId() const
{
	if (typeId == -1)
	{
		// We need a non const pointer to create the asCDataType object.
		// We're not breaking anything here because this function is not
		// modifying the object, so this const cast is safe.
		asCTypeInfo *ot = const_cast<asCTypeInfo*>(this);

		// The engine will define the typeId for this object type
		engine->GetTypeIdFromDataType(asCDataType::CreateType(ot, false));
	}

	return typeId;
}

// interface
asIScriptEngine *asCTypeInfo::GetEngine() const
{
	return engine;
}

// interface
const char *asCTypeInfo::GetConfigGroup() const
{
	asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(this);
	if (group == 0)
		return 0;

	return group->groupName.AddressOf();
}

// interface
asDWORD asCTypeInfo::GetAccessMask() const
{
	return accessMask;
}

// interface
int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect, bool *out_isConst) const
{
	UNUSED_VAR(index);
	if (out_name) *out_name = 0;
	if (out_typeId) *out_typeId = 0;
	if (out_isPrivate) *out_isPrivate = false;
	if (out_isProtected) *out_isProtected = false;
	if (out_offset) *out_offset = 0;
	if (out_isReference) *out_isReference = false;
	if (out_accessMask) *out_accessMask = 0;
	if (out_compositeOffset) *out_compositeOffset = 0;
	if (out_isCompositeIndirect) *out_isCompositeIndirect = false;
	if (out_isConst) *out_isConst = false;
	return -1;
}

// internal
asCObjectType *CastToObjectType(asCTypeInfo *ti)
{
	// Allow call on null pointer
	if (ti == 0) return 0;

	// TODO: type: Should List pattern have its own type class?
	if ((ti->flags & (asOBJ_VALUE | asOBJ_REF | asOBJ_LIST_PATTERN)) && !(ti->flags & asOBJ_FUNCDEF))
		return reinterpret_cast<asCObjectType*>(ti);

	return 0;
}

// internal
asCEnumType *CastToEnumType(asCTypeInfo *ti)
{
	// Allow call on null pointer
	if (ti == 0) return 0;

	if (ti->flags & (asOBJ_ENUM))
		return reinterpret_cast<asCEnumType*>(ti);

	return 0;
}

// internal
asCTypedefType *CastToTypedefType(asCTypeInfo *ti)
{
	// Allow call on null pointer
	if (ti == 0) return 0;

	if (ti->flags & (asOBJ_TYPEDEF))
		return reinterpret_cast<asCTypedefType*>(ti);

	return 0;
}

// internal
asCFuncdefType *CastToFuncdefType(asCTypeInfo *ti)
{
	// Allow call on null pointer
	if (ti == 0) return 0;

	if (ti->flags & (asOBJ_FUNCDEF))
		return reinterpret_cast<asCFuncdefType*>(ti);

	return 0;
}

// internal
void asCTypeInfo::CleanUserData()
{
	asASSERT(engine);
	for (asUINT n = 0; n < userData.GetLength(); n += 2)
	{
		if (userData[n + 1])
		{
			for (asUINT c = 0; c < engine->cleanTypeInfoFuncs.GetLength(); c++)
				if (engine->cleanTypeInfoFuncs[c].type == userData[n])
					engine->cleanTypeInfoFuncs[c].cleanFunc(this);
		}
	}
	userData.SetLength(0);
}

// internal
bool asCTypeInfo::IsShared() const
{
	// Types that can be declared by scripts need to have the explicit flag asOBJ_SHARED
	if (flags & (asOBJ_SCRIPT_OBJECT | asOBJ_ENUM)) return flags & asOBJ_SHARED ? true : false;

	// Otherwise we assume the type to be shared
	return true;
}

////////////////////////////////////////////////////////////////////////////////////////

asCEnumType::~asCEnumType()
{
	asUINT n;
	for (n = 0; n < enumValues.GetLength(); n++)
	{
		if (enumValues[n])
			asDELETE(enumValues[n], asSEnumValue);
	}
	enumValues.SetLength(0);
}

// interface
asUINT asCEnumType::GetEnumValueCount() const
{
	return enumValues.GetLength();
}

// interface
const char *asCEnumType::GetEnumValueByIndex(asUINT index, int *outValue) const
{
	if (outValue)
		*outValue = 0;

	if (index >= enumValues.GetLength())
		return 0;

	if (outValue)
		*outValue = enumValues[index]->value;

	return enumValues[index]->name.AddressOf();
}

//////////////////////////////////////////////////////////////////////////////////////////

asCTypedefType::~asCTypedefType()
{
	DestroyInternal();
}

void asCTypedefType::DestroyInternal()
{
	if (engine == 0) return;

	// Release the object types held by the alias
	if (aliasForType.GetTypeInfo())
			aliasForType.GetTypeInfo()->ReleaseInternal();

	aliasForType = asCDataType::CreatePrimitive(ttVoid, false);

	CleanUserData();

	// Remove the type from the engine
	if (typeId != -1)
		engine->RemoveFromTypeIdMap(this);

	// Clear the engine pointer to mark the object type as invalid
	engine = 0;
}

// interface
int asCTypedefType::GetTypedefTypeId() const
{
	return engine->GetTypeIdFromDataType(aliasForType);
}

//////////////////////////////////////////////////////////////////////////////////////////

asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : asCTypeInfo(en)
{
	asASSERT(func->funcType == asFUNC_FUNCDEF);
	asASSERT(func->funcdefType == 0);

	// A function pointer is special kind of reference type
	// It must be possible to garbage collect, as funcdefs can form circular references if used as delegates
	flags       = asOBJ_REF | asOBJ_GC | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0);
	name        = func->name;
	nameSpace   = func->nameSpace;
	module      = func->module;
	accessMask  = func->accessMask;
	funcdef     = func; // reference already counted by the asCScriptFunction constructor
	parentClass = 0;

	func->funcdefType = this;
}

asCFuncdefType::~asCFuncdefType()
{
	DestroyInternal();
}

void asCFuncdefType::DestroyInternal()
{
	if (engine == 0) return;

	// Release the funcdef
	if( funcdef )
		funcdef->ReleaseInternal();
	funcdef = 0;

	// Detach from parent class
	if (parentClass)
	{
		parentClass->childFuncDefs.RemoveValue(this);
		parentClass = 0;
	}

	CleanUserData();

	// Remove the type from the engine
	if (typeId != -1)
		engine->RemoveFromTypeIdMap(this);

	// Clear the engine pointer to mark the object type as invalid
	engine = 0;
}

// interface
asIScriptFunction *asCFuncdefType::GetFuncdefSignature() const
{
	return funcdef;
}

// interface
asITypeInfo *asCFuncdefType::GetParentType() const
{
	return parentClass;
}

END_AS_NAMESPACE


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2025 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_typeinfo.h
//

#ifndef AS_TYPEINFO_H
#define AS_TYPEINFO_H

#include "as_config.h"
#include "as_string.h"
#include "as_atomic.h"
#include "as_datatype.h"

BEGIN_AS_NAMESPACE

class asCScriptEngine;
class asCModule;
class asCObjectType;
class asCEnumType;
class asCTypedefType;
class asCFuncdefType;
struct asSNameSpace;

// TODO: type: asCPrimitiveType shall be implemented to represent primitives (void, int, double, etc)

// TODO: type: asCTypeInfo should have an internal virtual method GetBehaviours. For asCObjectType it
//             should return the beh member. For asCFuncdefType it should return the beh member of
//             engine->functionBehaviours. This will allow the code that needs the behaviour to handle
//             both object types and funcdefs the same way

class asCTypeInfo : public asITypeInfo
{
public:
	//=====================================
	// From asITypeInfo
	//=====================================
	asIScriptEngine *GetEngine() const;
	const char      *GetConfigGroup() const;
	asDWORD          GetAccessMask() const;
	asIScriptModule *GetModule() const;

	// Memory management
	int AddRef() const;
	int Release() const;

	// Type info
	const char      *GetName() const;
	const char      *GetNamespace() const;
	asITypeInfo     *GetBaseType() const { return 0; }
	bool             DerivesFrom(const asITypeInfo *objType) const { UNUSED_VAR(objType); return 0; }
	asQWORD          GetFlags() const;
	asUINT           GetSize() const;
	int              GetTypeId() const;
	int              GetSubTypeId(asUINT subtypeIndex = 0) const { UNUSED_VAR(subtypeIndex); return -1; }
	asITypeInfo     *GetSubType(asUINT subtypeIndex = 0) const { UNUSED_VAR(subtypeIndex); return 0; }
	asUINT           GetSubTypeCount() const { return 0; }

	// Interfaces
	asUINT           GetInterfaceCount() const { return 0; }
	asITypeInfo     *GetInterface(asUINT index) const { UNUSED_VAR(index); return 0; }
	bool             Implements(const asITypeInfo *objType) const { UNUSED_VAR(objType); return false; }

	// Factories
	asUINT             GetFactoryCount() const { return 0; }
	asIScriptFunction *GetFactoryByIndex(asUINT index) const { UNUSED_VAR(index); return 0; }
	asIScriptFunction *GetFactoryByDecl(const char *decl) const { UNUSED_VAR(decl); return 0; }

	// Methods
	asUINT             GetMethodCount() const { return 0; }
	asIScriptFunction *GetMethodByIndex(asUINT index, bool getVirtual) const { UNUSED_VAR(index); UNUSED_VAR(getVirtual); return 0; }
	asIScriptFunction *GetMethodByName(const char *in_name, bool getVirtual) const { UNUSED_VAR(in_name); UNUSED_VAR(getVirtual); return 0; }
	asIScriptFunction *GetMethodByDecl(const char *decl, bool getVirtual) const { UNUSED_VAR(decl); UNUSED_VAR(getVirtual); return 0; }

	// Properties
	asUINT      GetPropertyCount() const { return 0; }
	int         GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask, int *compositeOffset, bool *isCompositeIndirect, bool *isConst) const;
	const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const { UNUSED_VAR(index); UNUSED_VAR(includeNamespace); return 0; }

	// Behaviours
	asUINT             GetBehaviourCount() const { return 0; }
	asIScriptFunction *GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const { UNUSED_VAR(index); UNUSED_VAR(outBehaviour); return 0; }

	// Child types
	asUINT       GetChildFuncdefCount() const { return 0; }
	asITypeInfo *GetChildFuncdef(asUINT index) const { UNUSED_VAR(index); return 0; }
	asITypeInfo *GetParentType() const { return 0; }

	// Enums
	virtual asUINT      GetEnumValueCount() const { return 0; }
	virtual const char *GetEnumValueByIndex(asUINT index, int *outValue) const { UNUSED_VAR(index); if (outValue) *outValue = 0; return 0; }

	// Typedef
	virtual int GetTypedefTypeId() const { return asERROR; }

	// Funcdef
	virtual asIScriptFunction *GetFuncdefSignature() const { return 0; }

	// User data
	void *SetUserData(void *data, asPWORD type);
	void *GetUserData(asPWORD type) const;

	//===========================================
	// Internal
	//===========================================
public:
	asCTypeInfo(asCScriptEngine *engine);
	virtual ~asCTypeInfo();

	// Keep an internal reference counter to separate references coming from
	// application or script objects and references coming from the script code
	virtual int AddRefInternal();
	virtual int ReleaseInternal();

	virtual void DestroyInternal() {}

	void CleanUserData();

	bool IsShared() const;

	// These can be safely used on null pointers (which will return null)
	friend asCObjectType  *CastToObjectType(asCTypeInfo *);
	friend asCEnumType    *CastToEnumType(asCTypeInfo *);
	friend asCTypedefType *CastToTypedefType(asCTypeInfo *);
	friend asCFuncdefType *CastToFuncdefType(asCTypeInfo *);

	asCString                    name;
	asSNameSpace                *nameSpace;
	int                          size;
	mutable int                  typeId;
	asQWORD                      flags;
	asDWORD                      accessMask;

	// Store the script section where the code was declared
	int                             scriptSectionIdx;
	// Store the location where the function was declared (row in the lower 20 bits, and column in the upper 12)
	int                             declaredAt;

	asCScriptEngine  *engine;
	asCModule        *module;
	asCArray<asPWORD> userData;

protected:
	friend class asCScriptEngine;
	friend class asCConfigGroup;
	friend class asCModule;
	friend class asCObjectType;
	asCTypeInfo();

	mutable asCAtomic externalRefCount;
	asCAtomic         internalRefCount;
};

struct asSEnumValue
{
	asCString name;
	int       value;
};

class asCEnumType : public asCTypeInfo
{
public:
	asCEnumType(asCScriptEngine *engine) : asCTypeInfo(engine) {}
	~asCEnumType();

	asCArray<asSEnumValue*> enumValues;

	asUINT      GetEnumValueCount() const;
	const char *GetEnumValueByIndex(asUINT index, int *outValue) const;

protected:
	asCEnumType() : asCTypeInfo() {}
};

class asCTypedefType : public asCTypeInfo
{
public:
	asCTypedefType(asCScriptEngine *engine) : asCTypeInfo(engine) {}
	~asCTypedefType();

	void DestroyInternal();

	asCDataType aliasForType; // increase refCount for typeinfo inside datatype

	int GetTypedefTypeId() const;

protected:
	asCTypedefType() : asCTypeInfo() {}
};

class asCFuncdefType : public asCTypeInfo
{
public:
	asCFuncdefType(asCScriptEngine *engine, asCScriptFunction *func);
	~asCFuncdefType();

	asIScriptFunction *GetFuncdefSignature() const;
	asITypeInfo       *GetParentType() const;

	void DestroyInternal();
	asCScriptFunction *funcdef;     // increases refCount
	asCObjectType     *parentClass; // doesn't increase refCount

protected:
	asCFuncdefType() : asCTypeInfo(), funcdef(0), parentClass(0) {}
};

END_AS_NAMESPACE

#endif


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2012 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_variablescope.cpp
//
// A manager class for variable declarations
//

#include "as_config.h"

#ifndef AS_NO_COMPILER

#include "as_variablescope.h"

BEGIN_AS_NAMESPACE

asCVariableScope::asCVariableScope(asCVariableScope *parent)
{
	this->parent    = parent;
	Reset();
}

asCVariableScope::~asCVariableScope()
{
	Reset();
}

void asCVariableScope::Reset()
{
	isBreakScope = false;
	isContinueScope = false;

	for( asUINT n = 0; n < variables.GetLength(); n++ )
		if( variables[n] )
		{
			asDELETE(variables[n],sVariable);
		}
	variables.SetLength(0);
}

int asCVariableScope::DeclareVariable(const char *name, const asCDataType &type, int stackOffset, bool onHeap)
{
	// TODO: optimize: Improve linear search
	// See if the variable is already declared
	if( strcmp(name, "") != 0 )
	{
		for( asUINT n = 0; n < variables.GetLength(); n++ )
		{
			if( variables[n]->name == name )
				return -1;
		}
	}

	sVariable *var = asNEW(sVariable);
	if( var == 0 )
	{
		// Out of memory. Return without allocating the var
		return -2;
	}
	var->name           = name;
	var->type           = type;
	var->stackOffset    = stackOffset;
	var->isInitialized  = false;
	var->isPureConstant = false;
	var->onHeap         = onHeap;

	// Parameters are initialized
	if( stackOffset <= 0 )
		var->isInitialized = true;

	variables.PushLast(var);

	return 0;
}

sVariable *asCVariableScope::GetVariable(const char *name)
{
	// TODO: optimize: Improve linear search
	// Find the variable
	for( asUINT n = 0; n < variables.GetLength(); n++ )
	{
		if( variables[n]->name == name )
			return variables[n];
	}

	if( parent )
		return parent->GetVariable(name);

	return 0;
}

sVariable *asCVariableScope::GetVariableByOffset(int offset)
{
	// TODO: optimize: Improve linear search
	// Find the variable
	for( asUINT n = 0; n < variables.GetLength(); n++ )
	{
		if( variables[n]->stackOffset == offset )
			return variables[n];
	}

	if( parent )
		return parent->GetVariableByOffset(offset);

	return 0;
}

END_AS_NAMESPACE

#endif // AS_NO_COMPILER


code:
/*
   AngelCode Scripting Library
   Copyright (c) 2003-2012 Andreas Jonsson

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this library can be located at:
   http://www.angelcode.com/angelscript/

   Andreas Jonsson
   andreas@angelcode.com
*/

//
// as_variablescope.h
//
// A manager class for variable declarations
//

#ifndef AS_VARIABLESCOPE_H
#define AS_VARIABLESCOPE_H

#include "as_config.h"

#ifndef AS_NO_COMPILER

#include "as_array.h"
#include "as_string.h"
#include "as_datatype.h"

BEGIN_AS_NAMESPACE

struct sVariable
{
	asCString   name;
	asCDataType type;
	int         stackOffset;
	bool        isInitialized;
	bool        isPureConstant;
	asQWORD     constantValue;
	bool        onHeap;
};

class asCVariableScope
{
public:
	asCVariableScope(asCVariableScope *parent);
	~asCVariableScope();

	void Reset();

	int DeclareVariable(const char *name, const asCDataType &type, int stackOffset, bool isObjectOnHeap);
	sVariable *GetVariable(const char *name);
	sVariable *GetVariableByOffset(int offset);

	asCVariableScope *parent;

	bool isBreakScope;
	bool isContinueScope;

	asCArray<sVariable *> variables;
};

END_AS_NAMESPACE

#endif // AS_NO_COMPILER

#endif


code:
<title>AngelScript - Changes</title>

AngelScript Change Log

Version 0.95 - 2003/06/17

Fixed bug in constant declaration

Improved byte code for string manipulation

Added data type: bits

new operators: ~ | & ^ << >> >>> |= &= ^= <<= >>= >>>=

added bits constants: 0xFFA

Fixed a bug in the call stack

Version 0.85 - 2003/06/04

stack positions are re-used when variables goes out of scope

bstr is now copied instead of reference counted

concatenation operators for bstr: + +=

comparison operators for bstr: == != < > <= >=

If script is aborted or an exception occurs the engine cleans up the stack

Engine now executes until finished or until aborted

Arguments can now be sent by reference instead of by value

Version 0.7 - 2003/05/28

Added ?: operator

Added compound assignments: += -= *= /= %=

New data type: bstr (byte string)

Added support for string constants

Character sequences: \n \r \0 \\ \" \x00

Version 0.55 - 2003/05/19

removed include from AngelScript

AngelScript no longer loads the scriptcode from disk

the host application can add several pieces of code that will be compiled as one

Version 0.5 - 2003/05/15

declaration of global constants through directive: const

added do-while statement

fixed bug in AngelScript

Version 0.4 - 2003/05/09

AngelScript now allows for application defined datatypes

fixed potential bug in AngelScript

Version 0.3 - 2003/04/23

Modulo operator %

minor changes in the virtual machine

fixed bug in compiler

Version 0.25 - 2003/04/15

Added ++ --

Boolean expressions are no longer fully evaluated

Added break continue

Version 0.2 - 2003/04/09

using cdecl calling convention

Version 0.1 - 2003/03/28

Simple scripting with int float