note
	description: "[
		Exception for a COM error
	]"
	library: "Free implementation of ELKS library"
	status: "See notice at end of class."
	legal: "See notice at end of class."
	date: "$Date: 2020-05-19 14:32:38 +0000 (Tue, 19 May 2020) $"
	revision: "$Revision: 104260 $"

class 
	COM_FAILURE

create 
	default_create

feature {NONE} -- Initialization

	default_create
			-- Process instances of classes with no creation clause.
			-- (Default: do nothing.)
			-- (from ANY)
		do
		end

	make_with_tag_and_trace (a_tag, a_trace_string: STRING_8)
		obsolete "Use `default_create' and `set_description' instead. [2017-05-31]"
			-- Make Current with description set to a_tag.
			-- (from EXCEPTION)
		require -- from EXCEPTION
			tag_not_void: a_tag /= Void
			trace_string_not_void: a_trace_string /= Void
		do
			set_description (a_tag)
		ensure -- from EXCEPTION
			description_set: attached description as l_des and then a_tag.same_string_general (l_des)
		end
	
feature -- Access

	frozen cause: EXCEPTION
			-- The cause of current exception raised during rescue processing
			-- (from EXCEPTION)
		do
			if attached original.throwing_exception as e then
				Result := e
			else
				Result := Current
			end
		ensure -- from EXCEPTION
			cause_not_void: Result /= Void
		end

	code: INTEGER_32
			-- Exception code
		do
			Result := {EXCEP_CONST}.com_exception
		end

	description: detachable READABLE_STRING_32
			-- Detailed description of current exception.
			-- (from EXCEPTION)
		local
			l_res: STRING_32
		do
			if attached c_description as d then
				create l_res.make (d.count)
				{UTF_CONVERTER}.utf_8_0_subpointer_into_escaped_string_32 (d.managed_data, 0, d.count - 1, False, l_res)
				Result := l_res
			end
		end

	Exception_manager: EXCEPTION_MANAGER
			-- Exception manager
			-- (from EXCEPTION_MANAGER_FACTORY)
		once
			create {ISE_EXCEPTION_MANAGER} Result
		ensure -- from EXCEPTION_MANAGER_FACTORY
			instance_free: class
			exception_manager_not_void: Result /= Void
		end

	exception_trace: detachable STRING_8
		obsolete "Use `trace' instead. [2017-05-31]"
			-- String representation of current exception trace
			-- (from EXCEPTION)
		do
			Result := internal_trace
		end

	generating_type: TYPE [detachable COM_FAILURE]
			-- Type of current object
			-- (type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generating_type_not_void: Result /= Void
		end

	generator: STRING_8
			-- Name of current object's generating class
			-- (base class of the type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generator_not_void: Result /= Void
			generator_not_empty: not Result.is_empty
		end

	hresult: INTEGER_32
			-- Original HRESULT.

	hresult_code: INTEGER_32
			-- Error code of COM

	frozen line_number: INTEGER_32
			-- Line number
			-- (from EXCEPTION)

	meaning: STRING_8
		obsolete "Use `tag' instead. [2017-05-31]"
			-- A short message describing what current exception is
			-- (from EXCEPTION)
		do
			Result := Tag.as_string_8
		end

	message: detachable STRING_8
		obsolete "Use `description' instead. [2017-05-31]"
			-- Message of current exception
			-- (from EXCEPTION)
		do
			if attached c_description as l_m then
				Result := l_m.substring (1, l_m.count)
			end
		end

	frozen original: EXCEPTION
			-- The original exception directly triggered current exception
			-- (from EXCEPTION)
		local
			t: like throwing_exception
		do
			t := throwing_exception
			if t = Current or else t = Void then
				Result := Current
			elseif (attached {ROUTINE_FAILURE} Current) or else (attached {OLD_VIOLATION} Current) then
				Result := t.original
			else
				Result := Current
			end
		ensure -- from EXCEPTION
			original_not_void: Result /= Void
		end

	frozen recipient_name: detachable STRING_8
			-- Name of the routine whose execution was
			-- interrupted by current exception
			-- (from EXCEPTION)

	Tag: IMMUTABLE_STRING_32
			-- A short message describing what current exception is
		once
			create Result.make_from_string_8 ("COM error.")
		end

	trace: detachable STRING_32
			-- String representation of current exception trace
			-- (from EXCEPTION)
		local
			u: UTF_CONVERTER
		do
			if attached internal_trace as l_trace then
				Result := u.utf_8_string_8_to_escaped_string_32 (l_trace)
			end
		end

	frozen type_name: detachable STRING_8
			-- Name of the class that includes the recipient
			-- of original form of current exception
			-- (from EXCEPTION)
	
feature {EXCEPTION} -- Access

	frozen throwing_exception: detachable EXCEPTION
			-- The exception throwing current exception
			-- (from EXCEPTION)
	
feature -- Comparison

	frozen deep_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void
			-- or attached to isomorphic object structures?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_deep_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			shallow_implies_deep: standard_equal (a, b) implies Result
			both_or_none_void: (a = Void) implies (Result = (b = Void))
			same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))
			symmetric: Result implies deep_equal (b, a)
		end

	frozen equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached
			-- to objects considered equal?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.is_equal (b))
		end

	frozen is_deep_equal alias "≡≡≡" (other: COM_FAILURE): BOOLEAN
			-- Are Current and other attached to isomorphic object structures?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			shallow_implies_deep: standard_is_equal (other) implies Result
			same_type: Result implies same_type (other)
			symmetric: Result implies other.is_deep_equal (Current)
		end

	is_equal (other: COM_FAILURE): BOOLEAN
			-- Is other attached to an object considered
			-- equal to current object?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			symmetric: Result implies other ~ Current
			consistent: standard_is_equal (other) implies Result
		end

	frozen standard_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached to
			-- field-by-field identical objects of the same type?
			-- Always uses default object comparison criterion.
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.standard_is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.standard_is_equal (b))
		end

	frozen standard_is_equal alias "" (other: COM_FAILURE): BOOLEAN
			-- Is other attached to an object of the same type
			-- as current object, and field-by-field identical to it?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			same_type: Result implies same_type (other)
			symmetric: Result implies other.standard_is_equal (Current)
		end
	
feature -- Status report

	conforms_to (other: ANY): BOOLEAN
			-- Does type of current object conform to type
			-- of other (as per Eiffel: The Language, chapter 13)?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		end

	frozen is_caught: BOOLEAN
			-- If set, current exception is raised.
			-- (from EXCEPTION)
		do
			Result := not is_ignored
		ensure -- from EXCEPTION
			not_is_caught_implies_is_ignorable: not Result implies is_ignorable
			not_is_ignored: Result = not is_ignored
		end

	frozen is_ignorable: BOOLEAN
			-- Is current exception ignorable?
			-- (from EXCEPTION)
		do
			Result := Exception_manager.is_ignorable (generating_type)
		end

	frozen is_ignored: BOOLEAN
			-- If set, current exception is not raised.
			-- (from EXCEPTION)
		do
			Result := Exception_manager.is_ignored (generating_type)
		ensure -- from EXCEPTION
			is_ignored_implies_is_ignorable: Result implies is_ignorable
			not_is_caught: Result = not is_caught
		end

	frozen is_raisable: BOOLEAN
			-- Is current exception raisable by raise?
			-- (from EXCEPTION)
		do
			Result := Exception_manager.is_raisable (generating_type)
		end

	same_type (other: ANY): BOOLEAN
			-- Is type of current object identical to type of other?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			definition: Result = (conforms_to (other) and other.conforms_to (Current))
		end
	
feature -- Status setting

	hresult_facility: INTEGER_32
			-- Facility code.
		do
			Result := ccom_hresult_facility (hresult)
		end

	hresult_message: STRING_8
			-- Error message.
		local
			r: detachable STRING_8
		do
			r := exception_information
			if r /= Void then
				r := r.twin;
				r.remove_head (10);
				r.adjust
			end
			if r = Void or else r.is_empty and then hresult_code > 0 then
				r := error_message (hresult_code).out
			end
			if r = Void then
				create Result.make_empty
			else
				Result := r
			end
		ensure
			non_void_message: Result /= Void
		end

	set_hresult_code (a_code: like hresult_code)
			-- Set hresult_code with a_code.
		do
			hresult_code := a_code
		end
	
feature -- Duplication

	frozen clone (other: detachable ANY): like other
		obsolete "Use `twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- equal to other
			--
			-- For non-void other, clone calls copy;
			-- to change copying/cloning semantics, redefine copy.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.twin
			end
		ensure -- from ANY
			instance_free: class
			equal: Result ~ other
		end

	copy (other: COM_FAILURE)
			-- Update current object using fields of object attached
			-- to other, so as to yield equal objects.
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		external
			"built_in"
		ensure -- from ANY
			is_equal: Current ~ other
		end

	frozen deep_clone (other: detachable ANY): like other
		obsolete "Use `deep_twin' instead. [2017-05-31]"
			-- Void if other is void: otherwise, new object structure
			-- recursively duplicated from the one attached to other
			-- (from ANY)
		do
			if other /= Void then
				Result := other.deep_twin
			end
		ensure -- from ANY
			instance_free: class
			deep_equal: deep_equal (other, Result)
		end

	frozen deep_copy (other: COM_FAILURE)
			-- Effect equivalent to that of:
			--		copy (other . deep_twin)
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		do
			copy (other.deep_twin)
		ensure -- from ANY
			deep_equal: deep_equal (Current, other)
		end

	frozen deep_twin: COM_FAILURE
			-- New object structure recursively duplicated from Current.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			deep_twin_not_void: Result /= Void
			deep_equal: deep_equal (Current, Result)
		end

	frozen standard_clone (other: detachable ANY): like other
		obsolete "Use `standard_twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.standard_twin
			end
		ensure -- from ANY
			instance_free: class
			equal: standard_equal (Result, other)
		end

	frozen standard_copy (other: COM_FAILURE)
			-- Copy every field of other onto corresponding field
			-- of current object.
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		external
			"built_in"
		ensure -- from ANY
			is_standard_equal: standard_is_equal (other)
		end

	frozen standard_twin: COM_FAILURE
			-- New object field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			standard_twin_not_void: Result /= Void
			equal: standard_equal (Result, Current)
		end

	frozen twin: COM_FAILURE
			-- New object equal to Current
			-- twin calls copy; to change copying/twinning semantics, redefine copy.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			twin_not_void: Result /= Void
			is_equal: Result ~ Current
		end
	
feature -- Basic operations

	frozen as_attached: attached COM_FAILURE
		obsolete "Remove calls to this feature. [2017-05-31]"
			-- Attached version of Current.
			-- (Can be used during transitional period to convert
			-- non-void-safe classes to void-safe ones.)
			-- (from ANY)
		do
			Result := Current
		end

	frozen default: detachable COM_FAILURE
			-- Default value of object's type
			-- (from ANY)
		do
		end

	frozen default_pointer: POINTER
			-- Default value of type POINTER
			-- (Avoid the need to write p.default for
			-- some p of type POINTER.)
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end

	default_rescue
			-- Process exception for routines with no Rescue clause.
			-- (Default: do nothing.)
			-- (from ANY)
		do
		end

	frozen do_nothing
			-- Execute a null action.
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end
	
feature {EXCEPTION_MANAGER} -- Implementation

	exception_information: detachable STRING_8
			-- Stream holding exception information.

	set_exception_information (a_message: STRING_8)
			-- Initialize current with stream of a_message.
		require
			a_message_not_void: a_message /= Void
		local
			c_string: C_STRING
		do
			exception_information := a_message
			if hresult_code > 0 then
				create c_string.make (ccom_hresult_to_string (hresult_code))
				hresult := ccom_hresult (c_string.item)
			else
				create c_string.make (a_message)
				hresult := ccom_hresult (c_string.item)
				hresult_code := ccom_hresult_code (hresult)
			end
		end
	
feature {NONE} -- Implementation

	frozen c_strlen (ptr: POINTER): INTEGER_32
			-- Number of characters in ptr.
			-- (export status {NONE})
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					return (EIF_INTEGER_32) _tcslen ((wchar_t *) $ptr);
				#else
					return 0;
				#endif
			]"
		end

	frozen ccom_hresult (an_exception_code: POINTER): INTEGER_32
		external
			"C inline"
		alias
			"[
						#ifdef EIF_WINDOWS
							char *stopstring = NULL;
							long result = 0, high_bits = 0, low_bits = 0;
							char high_str [7];
							char *exception_code = (char *)($an_exception_code);
							  
							if (NULL != exception_code)
							{
								strncpy (high_str, exception_code, 6);
								high_str [6] = '\0';
				
								high_bits = strtol (high_str, &stopstring, 16);
								low_bits = strtol (exception_code + 6, &stopstring, 16);
								result = (high_bits << 16) + low_bits;
							}
							return (EIF_INTEGER)result;
						#else
							return 0;
						#endif
			]"
		end

	frozen ccom_hresult_code (an_hresult: INTEGER_32): INTEGER_32
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					return HRESULT_CODE($an_hresult);
				#else
					return 0;
				#endif
			]"
		end

	frozen ccom_hresult_facility (an_hresult: INTEGER_32): INTEGER_32
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					return HRESULT_FACILITY($an_hresult);
				#else
					return 0;
				#endif
			]"
		end

	frozen ccom_hresult_to_string (a_code: INTEGER_32): STRING_8
		do
			Result := a_code.to_hex_string
			Result := {STRING_8}"0x" + Result
		end

	frozen character_size: INTEGER_32
			-- Number of bytes occupied by a TCHAR.
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					return sizeof(TCHAR);
				#else
					return 0;
				#endif
			]"
		end

	frozen cwin_error_text (a_code: INTEGER_32): POINTER
			-- Get text from error a_code. It is up to the caller to free
			-- the returned buffer using cwin_local_free.
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					LPVOID result;
					FormatMessage( 
						FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
						NULL,
						$a_code,
						MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
						(LPTSTR) &result,
						0,
						NULL 
						);
					return result;
				#else
					return 0;
				#endif
			]"
		end

	frozen cwin_local_free (a_ptr: POINTER)
			-- Free a_ptr using LocalFree.
		external
			"C inline use %"eif_com_exception.h%""
		alias
			"[
				#ifdef EIF_WINDOWS
					LocalFree((HLOCAL) $a_ptr);
				#endif
			]"
		end
	
feature {EXCEPTION_MANAGER} -- Implementation

	c_description: detachable C_STRING
			-- Message, stored as C string to keep it alive and usable by the runtime trace printing.
			-- (from EXCEPTION)

	frozen internal_is_ignorable: BOOLEAN
			-- Internal is_ignorable
			-- (from EXCEPTION)

	internal_trace: detachable STRING_8
			-- String representation of the exception trace
			-- (from EXCEPTION)

	frozen set_c_description (a_des: detachable STRING_8)
			-- Set c_description with a_des. a_des is in UTF-8.
			-- (from EXCEPTION)
		do
			if a_des /= Void then
				create c_description.make (a_des)
			else
				c_description := Void
			end
		end

	frozen set_exception_trace (a_trace: like exception_trace)
			-- Set exception_trace with a_trace.
			-- (from EXCEPTION)
		do
			internal_trace := a_trace
		end

	frozen set_line_number (a_number: like line_number)
			-- Set line_number with a_number.
			-- (from EXCEPTION)
		do
			line_number := a_number
		end

	frozen set_recipient_name (a_name: like recipient_name)
			-- Set recipient_name with a_name
			-- (from EXCEPTION)
		do
			recipient_name := a_name
		end

	frozen set_throwing_exception (a_exception: detachable EXCEPTION)
			-- Set throwing_exception with a_exception.
			-- (from EXCEPTION)
		do
			throwing_exception := a_exception
		ensure -- from EXCEPTION
			throwing_exception_set: throwing_exception = a_exception
		end

	frozen set_type_name (a_type: like type_name)
			-- Set type_name with a_type
			-- (from EXCEPTION)
		do
			type_name := a_type
		end
	
feature -- Access obselete

	trace_as_string: detachable STRING_8
		obsolete "Use `trace' instead. [2017-05-31]"
			-- Exception trace represented as a string
			-- (from EXCEPTION)
		do
			if attached exception_trace as t then
				Result := t
			end
		end
	
feature {NONE} -- Accesss

	error_message (a_code: like hresult_code): STRING_32
		require
			a_code_non_negative: a_code >= 0
		local
			l_ptr: POINTER
			l_mptr: MANAGED_POINTER
			i, n: INTEGER_32
		do
			l_ptr := cwin_error_text (a_code)
			if l_ptr = default_pointer then
				Result := {STRING_32}""
			else
				from
					i := 0
					n := c_strlen (l_ptr)
					create l_mptr.make_from_pointer (l_ptr, n * character_size)
					create Result.make (n)
				until
					i = n
				loop
					Result.append_code (l_mptr.read_natural_16 (i * character_size).to_natural_32)
					i := i + 1
				end
				cwin_local_free (l_ptr)
			end
		ensure
			error_message_not_void: Result /= Void
		end
	
feature -- Element Change

	trigger (a_code: INTEGER_32)
			-- Raise exception with code code.
			-- See class ECOM_EXCEPTION_CODES in EiffelCom for possible values.
		local
			l_hresult_string: STRING_8
		do
			hresult_code := a_code
			l_hresult_string := ccom_hresult_to_string (a_code)
			set_description (l_hresult_string)
			set_exception_information (l_hresult_string)
			raise
		end
	
feature -- Output

	Io: STD_FILES
			-- Handle to standard file setup
			-- (from ANY)
		once
			create Result;
			Result.set_output_default
		ensure -- from ANY
			instance_free: class
			io_not_void: Result /= Void
		end

	out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from EXCEPTION)
		do
			Result := generating_type.out
			if attached trace as t then
				Result.append_character ('%N')
				if attached {READABLE_STRING_8} t as r then
					Result.append (r)
				elseif attached {STRING_8} Result as s then
					{UTF_CONVERTER}.escaped_utf_32_string_into_utf_8_string_8 (t, s)
				elseif attached {STRING_32} Result as s then
					s.append_string_general (t)
				end
			end
		ensure -- from ANY
			out_not_void: Result /= Void
		end

	print (o: detachable ANY)
			-- Write terse external representation of o
			-- on standard output.
			-- (from ANY)
		local
			s: READABLE_STRING_8
		do
			if attached o then
				s := o.out
				if attached {READABLE_STRING_32} s as s32 then
					Io.put_string_32 (s32)
				elseif attached {READABLE_STRING_8} s as s8 then
					Io.put_string (s8)
				else
					Io.put_string_32 (s.as_string_32)
				end
			end
		ensure -- from ANY
			instance_free: class
		end

	frozen tagged_out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			tagged_out_not_void: Result /= Void
		end
	
feature -- Platform

	Operating_environment: OPERATING_ENVIRONMENT
			-- Objects available from the operating system
			-- (from ANY)
		once
			create Result
		ensure -- from ANY
			instance_free: class
			operating_environment_not_void: Result /= Void
		end
	
feature -- Raise

	raise
			-- Raise current exception
			-- (from EXCEPTION)
		require -- from EXCEPTION
			is_raisable: is_raisable
		do
			Exception_manager.raise (Current)
		end
	
feature {NONE} -- Retrieval

	frozen internal_correct_mismatch
			-- Called from runtime to perform a proper dynamic dispatch on correct_mismatch
			-- from MISMATCH_CORRECTOR.
			-- (from ANY)
		local
			l_msg: STRING_32
			l_exc: EXCEPTIONS
		do
			if attached {MISMATCH_CORRECTOR} Current as l_corrector then
				l_corrector.correct_mismatch
			else
				create l_msg.make_from_string ("Mismatch: ".as_string_32)
				create l_exc;
				l_msg.append (generating_type.name_32);
				l_exc.raise_retrieval_exception (l_msg)
			end
		end
	
feature -- Status settings

	set_description (a_description: detachable READABLE_STRING_GENERAL)
			-- Set description with a_description.
			-- (from EXCEPTION)
		local
			u: UTF_CONVERTER
			l_upper: CELL [INTEGER_32]
			l_c: like c_description
		do
			if a_description /= Void then
				create l_c.make_empty (a_description.count)
				create l_upper.put (0);
				u.utf_32_string_into_utf_8_0_pointer (a_description, l_c.managed_data, 0, l_upper);
				l_c.set_count (l_upper.item)
				c_description := l_c
			else
				c_description := Void
			end
		ensure -- from EXCEPTION
			description_set: (attached a_description as a_des and then attached description as l_des and then a_des.same_string (l_des)) or else (a_description = Void and then description = Void)
		end

	set_message (a_message: like message)
		obsolete "Use `set_description' instead. [2017-05-31]"
			-- Set message with a_message.
			-- (from EXCEPTION)
		do
			set_description (a_message)
		ensure -- from EXCEPTION
			message_set: message ~ a_message
		end
	
invariant
		-- from ANY
	reflexive_equality: standard_is_equal (Current)
	reflexive_conformance: conforms_to (Current)

note
	copyright: "Copyright (c) 1984-2020, Eiffel Software and others"
	license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
	source: "[
		Eiffel Software
		5949 Hollister Ave., Goleta, CA 93117 USA
		Telephone 805-685-1006, Fax 805-685-6869
		Website http://www.eiffel.com
		Customer support http://support.eiffel.com
	]"

end -- class COM_FAILURE

Generated by ISE EiffelStudio