/
mud++0.33/etc/
mud++0.33/etc/guilds/
mud++0.33/help/propert/
mud++0.33/mudC/
mud++0.33/player/
mud++0.33/src/
mud++0.33/src/bcppbuilder/
mud++0.33/src/unix/
mud++0.33/src/vm/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net
MUD++ development mailing list    mudpp-list@mailhost.net
------------------------------------------------------------------------------
asmlinker.cpp
*/

#include "string.h"
#include "io.h"
#include "asmlinker.h"
#include "asmobjfile.h"

// I use new/delete for files because it was done this way in previous
// linker. When I'll be sure of design I'll change it to references

// Todo: track all identical IMPORTS and reduce them to one
// it will speed up the linker and reduce image size

int AsmLinker::link( char * imagename, int count, char * names[] )
{
	char buf[ BUF ];
	int i,j, size,tmp;
	int code_offset = 0;
	int consts_offset =0;
	int consts_number = 0;
	int relocs_number = 0;
	asmobjconst oconst;
	asmimageheader header;
	AsmObjFile * obj;
	Output * code;
	Output * const_defs;
	Output * consts;
	Output * reloc;
	Output * headerfile;
	vmfilefun vmff;

	sprintf( buf, "%s.code", imagename);
	code = new Output(buf);
	sprintf( buf, "%s.reloc", imagename);
	reloc = new Output(buf);
	sprintf( buf, "%s.const_def", imagename);
	const_defs = new Output(buf);
	sprintf( buf, "%s.consts", imagename);
	consts = new Output(buf);
	sprintf( buf, "%s.header", imagename);
	headerfile = new Output(buf);


	for ( i =0; i < count; i++ )
	{
		StaticInput inf(names[i]);
		obj = new AsmObjFile();
		obj->readFrom( inf );
		
		// RELOCATION TABLE
		size = obj->relocation_table.length();
		for ( j = 0; j < size; j++ )
		{
			tmp = obj->relocation_table[j] + code_offset;
			reloc->write( &tmp, sizeof(int));
		}

		// CODE PART
		size = obj->relocation_table.length();
		for ( j = 0; j < size; j++ )
		{
			obj->relocCell(obj->relocation_table[j], consts_number);
		}
		code->write( obj->getConstMem(), obj->getUsedBytesize() );


		// CONSTANTS
		size = obj->constants_def.length();
		for ( j=0; j< size; j++ )
		{
			switch ( obj->constants_def[j].type )
			{
				case VMT_CONST_STRING:
				case VMT_FUN_IMPORT:
				case VMT_INTERFACE_IMPORT:
				case VMT_STATIC_IMPORT:
					continue;

				case VMT_FUN_EXPORT:
					tmp = obj->constants_def[j].offset;
					vmff = *((vmfilefun*)obj->constants.getStruct(tmp));
					vmff.start += code_offset;
					vmff.end += code_offset;
					vmff.name += consts_number;
					obj->constants.setStruct(tmp, &vmff, sizeof(vmfilefun));
					continue;

				default:
					continue;
			}
		}
		consts->write( obj->constants.getConstMem(), obj->constants.getUsedBytesize() );

		// CONSTANTS DEFINITIONS
		size = obj->constants_def.length();
		for ( j=0; j < size; j++ )
		{
			oconst = obj->constants_def[j];
			oconst.offset += consts_offset;
			const_defs->write( &oconst, sizeof(asmobjconst) );
		}

	
		consts_number += obj->constants_def.length();
		relocs_number += obj->relocation_table.length();
		code_offset   += obj->getUsedSize();
		consts_offset += obj->constants.getUsedSize();
		delete obj;
	}

	delete code;
	delete consts;
	delete const_defs;
	delete reloc;

 	header.code_length = code_offset;
	header.constants_length = consts_offset;
	header.relocs_count = relocs_number;
	header.constants_count = consts_number;

	headerfile->write( &header, sizeof(asmimageheader) );
	delete headerfile;

	return 0;
}