implementation module temp;

import
	StdEnv;
	


from PmFiles import UndefSymbol, UndefModule, EmptyUndefSymbol,EmptyUndefModule;
from StdPathname import Pathname;
from PmProject import setDynamicInfo,ProjectDynamicInfo,getDynamicInfo,Project, getStaticInfo, ProjectStaticInfo, List, OptionsTableEntry, Conversions;
from UtilStrictLists import AppendLists,Append,LLength,Head,Filter,StrictListToList,IsEmptyList;

import

	LinkerOffsets,
	State,
	SymbolTable,
	ReadObject;
	
	import IdataSection;

	
import
	DynamicLink, xcoff;
	
from Relocations import relocate_text;

	
// NEEEEWWWWW
from SortSymbols import sort_modules;
from ExtString import CharIndexFunc, starts, ends, IWORD, ILONG;
from ExtFile import ExtractPathAndFile, ExtractPathFileAndExtension, FileExists;
from Environments import Environment, ReplaceEnvironmentVar;
from DynamicLinkerOffsets import Dcompute_imported_library_symbol_offsets;
	
	
import SearchObject;

// copy of WriteXCoffFile
class Output2 a
where
{
	WriteOutput2 :: !WriteOutput2Record !*a -> *a;
	
	ChangeState :: !ChangeStateRecord !*a -> (!*State,*a)
};

instance Output2 Int
where {

	WriteOutput2 :: !WriteOutput2Record !*Int -> *Int;
	WriteOutput2 /*kind offset string*/ {file_or_memory,offset,string} mem_ptr
		= mwrites file_or_memory offset string mem_ptr;
		
	ChangeState {file_n,module_n,state} pe_file
		= (state,pe_file)
};

:: WriteOutput2Record = {
	file_or_memory	:: !Int,
	offset			:: !Int,
	string			:: !{#Char}
	};
	
:: *ChangeStateRecord = {
	file_n			:: !Int,
	module_n		:: !Int,
	state			:: !*State
	};


write_code_to_pe_files :: !Int !Bool !Int !Int (!Int,!Int) !State /*!Bool*/ !*a !*Files -> (!*a,!State,!*Files) | Output2 a;
write_code_to_pe_files n_xcoff_files do_relocations file_n first_symbol_n offset0 state /*one_pass_link*/ pe_file files
	| file_n >= n_xcoff_files
		= (pe_file,state,files);
	
	# (file_name, state)
		= select_file_name file_n state;
	# (n_symbols, state)
		= select_n_symbols file_n state;
	# (ok,xcoff_file,files)	
		= fopen file_name FReadData files;
	| not ok
		= abort ("Cannot read file: "+++ file_name);

		# (file_n,first_symbol_n,state,offset,xcoff_file,pe_file) 
			= write_code file_name file_n do_relocations first_symbol_n offset0 state xcoff_file pe_file;
			
		# (ok,files) 				
			= fclose xcoff_file files;
		| not ok
			= abort ("Error while reading file: "+++file_name);

			# (pe_file,state,files)	
				= write_code_to_pe_files n_xcoff_files do_relocations (inc file_n) /*(first_symbol_n+n_symbols)*/ first_symbol_n offset state /*one_pass_link*/ pe_file files;
			
			= (pe_file,state,files);
where
{
	/*
	** file_n < n_xcoff_files
	*/
	write_code file_name file_n do_relocations first_symbol_n offset0 state xcoff_file pe_file
		#! (state,offset,xcoff_file,pe_file) 
			= write_code_to_pe_file file_n do_relocations first_symbol_n offset0 state xcoff_file pe_file;
		| next_file_n == n_xcoff_files
			= (file_n,first_symbol_n,state,offset,xcoff_file,pe_file);
					
			#! (file_name2, state)
				= select_file_name next_file_n  state
			# (n_symbols, state)
				= select_n_symbols file_n state;
			| file_name2 == file_name
				= write_code file_name next_file_n do_relocations (first_symbol_n+n_symbols) offset state xcoff_file pe_file;
				
				= (file_n,first_symbol_n + n_symbols,state,offset,xcoff_file,pe_file);
			
			
		where
		{
			next_file_n 
				= inc file_n
		
		}
				
				
}			

write_code_to_pe_file :: !Int !Bool !Int (!Int,!Int) !State !*File !*a -> (!State,(!Int,!Int),!*File,!*a) | Output2 a;
write_code_to_pe_file file_n do_relocations first_symbol_n (text_offset0,data_offset0) state xcoff_file pe_file	
	#! (text_symbols,state)		
		= selacc_text_symbols file_n state;
	#! (state,text_offset,xcoff_file,pe_file)
		= write_text_to_pe_file Text text_symbols text_offset0 state xcoff_file pe_file;
		
	#! (data_symbols,state)
		= selacc_data_symbols file_n state;
	#! (state,data_offset,xcoff_file,pe_file)
		= write_text_to_pe_file Data data_symbols data_offset0 state xcoff_file pe_file;
			
	= (state,(text_offset,data_offset),xcoff_file,pe_file);
	{
		zz Text = 0;
		zz Data = 1;
	
		write_text_to_pe_file :: !SymbolIndexListKind !SymbolIndexList !Int !State !*File !*a -> (!State,!Int,!*File,!*a) | Output2 a;
		write_text_to_pe_file _ EmptySymbolIndex offset0 state xcoff_file pe_file
			= (state,offset0,xcoff_file,pe_file);
		write_text_to_pe_file mode1 (SymbolIndex module_n symbol_list) offset0 state xcoff_file pe_file
			# (symbol, state) 
			  	= sel_symbol file_n module_n state;
			# (marked, state)
				= selacc_marked_bool_a (first_symbol_n+module_n) state;
			| marked 
				# (state, offset1,xcoff_file,pe_file) 
					= write_text_module_to_pe_file symbol offset0 state xcoff_file pe_file;
				= write_text_to_pe_file mode1 symbol_list offset1 state xcoff_file pe_file;
				= write_text_to_pe_file mode1 symbol_list offset0 state xcoff_file pe_file;
			{}{
				write_text_module_to_pe_file :: !Symbol !Int !State !*File !*a -> !(!State,!Int,!*File,!*a) | Output2 a;
				write_text_module_to_pe_file (Module _ virtual_module_offset length virtual_address file_offset n_relocations relocations)
						offset0 state xcoff_file pe_file
				
				# (real_module_offset,state) 
					= selacc_module_offset_a o_i state; 
					
				// debug
				# (file_name, state)
					= select_file_name file_n state;

					
				# (ok,xcoff_file)			
					= fseek xcoff_file file_offset FSeekSet;
				|not ok
						# (file_name, state1)
							= select_file_name file_n state;
					= abort ("write_text_module_to_pe_file: could not seek in file " +++ file_name +++
					         "\n This error results because the application is staically linked");
	 
				# (text_a0,xcoff_file)	
					= freads xcoff_file length;
					
				| size text_a0==length
					#! write_output_record
						= { WriteOutput2Record |
							file_or_memory	= (zz mode1),
							offset			= offset0,
							string			= (write_nop_bytes (aligned_offset0-offset0) text_a1)
						  };
					#! pe_file
						= WriteOutput2 write_output_record pe_file;
					#! change_state_record =
						{ ChangeStateRecord |
							file_n		= file_n,
							module_n	= module_n,
							state		= state1
						}
						
					#! (state2, pe_file)
						= ChangeState change_state_record pe_file; 					
					= (state2,aligned_offset0+length,xcoff_file,pe_file);			
						{						
							aligned_offset0=(offset0+alignment_mask) bitand (bitnot alignment_mask);
							alignment_mask=dec (1<<alignment);
							alignment=2;
							
							(text_a1,state1) 
								= case (do_relocations) of 
								{
									True
										-> 	relocate_text 0 n_relocations file_n virtual_module_offset real_module_offset 
	
	first_symbol_n state text_a0
	virtual_address
	relocations

									_	-> (text_a0,state); 
								}
						}
					
				{
					o_i=first_symbol_n+module_n;
				}
			}
			

	
	}



	
write_nop_bytes :: !Int !{#Char} -> !{#Char};
write_nop_bytes n string 
	= (createArray n (toChar 0x90)) +++ string;

	

select_data_or_code_symbols :: !SymbolIndexListKind !Int !State -> (!SymbolIndexList,!State);
select_data_or_code_symbols Text file_n state = selacc_text_symbols file_n state;
select_data_or_code_symbols Data file_n state = selacc_data_symbols file_n state;
