definition module State;

import pdState;

import
	SymbolTable, LinkerMessages;

:: *State = {
	// misc
		one_pass_link		:: !Bool
	,	normal_static_link	:: !Bool
	,	linker_messages_state:: !LinkerMessagesState
	
	// linker tables
	,	application_name	:: !String
	,	n_libraries			:: !Int
	,	n_xcoff_files 		:: !Int
	,	n_xcoff_symbols		:: !Int
	,	n_library_symbols	:: !Int
	
	,	marked_bool_a		:: !*{#Bool}
	,	marked_offset_a		:: !*{#Int}
	,	module_offset_a		:: !*{#Int}
	,	xcoff_a 			:: !{#*Xcoff}
	,	namestable			:: !*NamesTable

	// dynamic libraries
	,	library_list 		:: !LibraryList
	,	library_file_names	:: ![!String]
	
	,	pd_state			:: !*PDState

};


/*st_isLinkerErrorOccured :: !*State -> (!Bool,!*State);
st_getLinkerMessages :: !*State -> (![!String],!*State);
st_addLinkerMessage :: !LinkerMessage !*State -> !*State;
st_addLinkerMessages :: !LinkerMessages !*State -> !*State;
*/

EmptyState :: !*State;

// xcoff_a access
app_xcoff_a :: (!{#*Xcoff} -> !{#*Xcoff}) !*State -> !*State;
acc_xcoff_a :: (!{#*Xcoff} -> (!.x,!{#*Xcoff})) !*State -> (!.x,!*State);
selacc_xcoff :: !Int (!*Xcoff -> (!.x,!*Xcoff)) !*State -> (.x,!*State);
selapp_xcoff :: !Int (!*Xcoff -> !*Xcoff) !*State -> !*State;

// xcoff_a; symbol_table access
//selacc_symbol_table :: !Int (*SymbolTable -> (.x,*SymbolTable)) !*State -> (.x,!*State);
selacc_symbol_table :: !Int (!*SymbolTable -> (!.x,!*SymbolTable)) !*State -> (!.x,!*State);

// xcoff_a; symbols
//selacc_symbols :: !Int (!*SymbolArray -> (!.x,!*SymbolArray)) !*State -> (.x,!*State);
selacc_symbols :: !Int (!*SymbolArray -> (!.x,!*SymbolArray)) !*State -> (!.x,!*State);
selapp_symbols :: !Int (!*SymbolArray -> *SymbolArray) !*State -> !*State;

// xcoff_a; symbol access
sel_symbol :: !Int !Int !*State -> (!Symbol,!*State);
update_symbol :: !Symbol !Int !Int !State -> !State;

// marked_bool_a access
acc_marked_bool_a :: (!*{#Bool} -> (!.x,!*{#Bool})) !*State -> (!.x,!*State);
selacc_marked_bool_a :: !Int !*State -> (!Bool,!*State);
	
// module_offset_a access
acc_module_offset_a :: (!*{#Int} -> (!.x,!*{#Int})) !*State -> (!.x,!*State);
app_module_offset_a :: (!*{#Int} -> !*{#Int}) !*State -> !*State;
selacc_module_offset_a :: !Int !*State -> (!Int,!*State);
		
// marked_offset_a access
acc_marked_offset_a :: (!*{#Int} -> (!.x,!*{#Int})) !*State -> (!.x,!*State);	
selacc_marked_offset_a :: !Int !*State -> (!Int,!*State);	
selacc_so_marked_offset_a :: !Int !*State -> (!Int,!*State);
		
// namestable access
app_namestable :: (!*NamesTable -> !*NamesTable) !*State -> !*State;
acc_namestable :: (!*NamesTable -> (!.x,!*NamesTable)) !*State -> (!.x,!*State);

// General
select_namestable state					:== acc_namestable (\namestable -> (namestable,{})) state; 
update_namestable :: NamesTable !State -> State;
select_marked_bool_a :: !State -> (!*{#Bool},!State);
select_marked_offset_a :: !State -> (!*{#Int},!State);
select_module_offset_a :: !State -> (!*{#Int},!State);
select_xcoff_a :: !State -> (!{#*Xcoff},!State);
update_state_with_xcoff :: !*Xcoff !State -> !State;

find_name :: !String !State -> (!Int,!Int,!State);
find_address_of_label :: !String !State -> !(!Bool,!Int,!State);
address_of_label2 :: !Int !Int !State -> (!Int,!State);

// General
select_file_name file_n state :== sel_platform 
	(selacc_xcoff file_n (\xcoff=:{file_name} -> (file_name,xcoff)) state)
	(selacc_xcoff file_n sel_file_name state)	
	;
	
select_module_name file_n state :== (selacc_xcoff file_n (\xcoff=:{module_name} -> (module_name,xcoff)) state);
	
/// winos specific
/*
select_file_name file_n state :== sel_platform 
	(selacc_xcoff file_n (\xcoff=:{file_name} -> (file_name,xcoff)) state)
	(abort "select_file_name (state): macOS");
*/					
select_n_symbols file_n state :== sel_platform
	(selacc_xcoff file_n (\xcoff=:{n_symbols} -> (n_symbols,xcoff)) state)
	(abort "select_n_symbols (state): macOS");
	
selacc_bss_symbols file_n state :== sel_platform			
	(selacc_symbol_table file_n (\symbol_table=:{bss_symbols} -> (bss_symbols,symbol_table)) state)
	(selacc_symbol_table file_n (\symbol_table=:{bss_symbols} -> (bss_symbols,symbol_table)) state)
	;
	
selacc_data_symbols file_n state :== sel_platform
	(selacc_symbol_table file_n (\symbol_table=:{data_symbols} -> (data_symbols,symbol_table)) state)
	(selacc_symbol_table file_n (\symbol_table=:{data_symbols} -> (data_symbols,symbol_table)) state);

selacc_text_symbols file_n state :== sel_platform
	(selacc_symbol_table file_n (\symbol_table=:{text_symbols} -> (text_symbols,symbol_table)) state)
	(selacc_symbol_table file_n (\symbol_table=:{text_symbols} -> (text_symbols,symbol_table)) state);


// PC dummies; should be removed
//select_marked_offset index state		:== selacc_marked_offset_a index state;
//select_dll_marked_offset file_n state	:== selacc_so_marked_offset_a file_n state;
//select_module_offset index state		:== selacc_module_offset_a index state;
//select_marked_bool index state			:== selacc_marked_bool_a index state;

// macOS specific

// for xcoff:
selacc_text_relocations file_n state :== sel_platform
	(abort "selacc_text_relocations (state): winOS")
	(selacc_xcoff file_n get_text_relocations state);

selacc_data_relocations file_n state :== sel_platform
	(abort "selacc_data_relocations (state): winOS")
	(selacc_xcoff file_n get_data_relocations state);
	
selacc_header file_n state :== sel_platform
	(abort "selacc_header (state): winOS")
	(selacc_xcoff file_n get_header state);
	
selacc_n_symbols file_n state :== sel_platform
	(abort "selacc_n_symbols (state): winOS")
	(selacc_xcoff file_n get_n_symbols state);
	
selacc_text_v_address file_n state 	:== sel_platform
	(abort "selacc_text_v_address (state): winOS")
	(selacc_xcoff file_n get_text_v_address state);
	
selacc_data_v_address file_n state 	:== sel_platform
	(abort "selacc_data_v_address (state): winOS")
	(selacc_xcoff file_n get_data_v_address state);
	
selacc_toc0_symbols file_n state 	:== sel_platform
	(abort "selacc_toc0_symbols (state): winOS")
	(selacc_symbol_table file_n get_toc0_symbols state);
	
selacc_toc_symbols file_n state 	:== sel_platform
	(abort "selacc_toc_symbols (state): winOS")
	(selacc_symbol_table file_n get_toc_symbols state);

/*
selacc_text_relocations file_n state :== sel_platform
	(abort "selacc_text_relocations (state): winOS")
	(selacc_xcoff file_n (\xcoff=:{text_relocations} -> (text_relocations,xcoff)) state);

//selacc_text_relocations file_n state	:== selacc_xcoff file_n (\xcoff=:{text_relocations} -> (text_relocations,xcoff)) state;
selacc_data_relocations file_n state	:== selacc_xcoff file_n (\xcoff=:{data_relocations} -> (data_relocations,xcoff)) state;
selacc_header			file_n state 	:== selacc_xcoff file_n (\xcoff=:{header}			-> (header,xcoff)) state;
selacc_n_symbols		file_n state	:== selacc_xcoff file_n (\xcoff=:{n_symbols}		-> (n_symbols,xcoff)) state;

// for xcoff_header:
selacc_text_v_address file_n state 	:== selacc_xcoff file_n (\xcoff=:{header={text_v_address}} -> (text_v_address,xcoff)) state;
selacc_data_v_address file_n state 	:== selacc_xcoff file_n (\xcoff=:{header={data_v_address}} -> (data_v_address,xcoff)) state;

// for symbol_table:
selacc_toc0_symbols file_n state 	:== selacc_symbol_table file_n (\symbol_table=:{toc0_symbol} -> (toc0_symbol,symbol_table)) state;
selacc_toc_symbols file_n state 	:== selacc_symbol_table file_n (\symbol_table=:{toc_symbols} -> (toc_symbols,symbol_table)) state;	
*/

is_defined_symbol :: !String !*State -> !(!Bool,!Int,!Int,!*State);

// ADDED
instance AddMessage State;

app_pdstate :: (!*PDState -> !*PDState) !*State -> !*State;
acc_pdstate :: (!*PDState -> (!.x,!*PDState)) !*State -> (!.x,!*State);

