#include <stddef.h>
#include "globals.h"
#include "omfint.h"
#include "omfspec.h"
#include "myassert.h"
#ifdef __I86__
#define FFQUAL __near
#else
#define FFQUAL
#endif
#pragma pack( push, 1 )
struct outbuff {
unsigned in_buf;
uint_8 cmd;
uint_16 reclen;
uint_8 buffer[OBJ_BUFFER_SIZE];
};
#pragma pack( pop )
static void safeWrite( FILE *file, const uint_8 *buf, unsigned len )
{
if( fwrite( buf, 1, len, file ) != len )
WriteError();
}
#if 0#endif
static void WBegRec( struct outbuff *out, uint_8 command )
{
out->in_buf = 0;
out->cmd = command;
}
static void WEndRec( struct outbuff *out )
{
uint_8 checksum;
uint_8 *p;
uint_8 *end;
myassert( out && out->cmd );
out->reclen = out->in_buf + 1;
checksum = out->cmd + ( out->reclen & 0xff ) + (( out->reclen ) >> 8);
for( p = out->buffer, end = p + out->in_buf; p < end; ) {
checksum += *p++;
}
checksum = - checksum;
*p = checksum;
safeWrite( CurrFile[OBJ], &out->cmd, out->in_buf + 4 );
#if 0#endif
}
static void PutByte( struct outbuff *out, uint_8 value )
{
out->buffer[ out->in_buf++ ] = value;
}
static void PutIndex( struct outbuff *out, uint_16 index )
{
if( index > 0x7f ) {
PutByte( out, 0x80 | ( index >> 8 ) );
}
PutByte( out, index & 0xff );
}
static void PutWord( struct outbuff *out, uint_16 value )
{
WriteU16( out->buffer + out->in_buf, value );
out->in_buf += sizeof( uint_16 );
}
static void PutDword( struct outbuff *out, uint_32 value )
{
WriteU32( out->buffer + out->in_buf, value );
out->in_buf += sizeof( uint_32 );
}
static void PutMem( struct outbuff *out, const uint_8 *buf, unsigned length )
{
if( length <= OBJ_BUFFER_SIZE - 1 - out->in_buf ) {
memcpy( &out->buffer[ out->in_buf ], buf, length );
out->in_buf += length;
} else {
DebugMsg(("PutMem: buffer overflow error [length=%u, free=%u]\n", length, OBJ_BUFFER_SIZE - 1 - out->in_buf ));
Fatal( INTERNAL_ERROR, __FILE__, __LINE__ );
}
}
static int FFQUAL writeMisc( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->data != NULL );
WBegRec( out, objr->command );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeMisc32( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->data != NULL );
WBegRec( out, objr->command | objr->is_32 );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeComent( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->data != NULL );
WBegRec( out, CMD_COMENT );
PutByte( out, objr->d.coment.attr );
PutByte( out, objr->d.coment.cmt_class );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeSegdef( struct outbuff *out, const struct omf_rec *objr )
{
int is32;
uint_8 acbp;
uint_8 align;
myassert( objr->command == CMD_SEGDEF );
is32 = objr->is_32;
WBegRec( out, CMD_SEGDEF + is32 );
acbp = ( objr->d.segdef.combine << 2 ) | objr->d.segdef.use_32;
align = objr->d.segdef.align;
#if 1
acbp |= align << 5;
#else#endif
if( is32 == 0 && objr->d.segdef.seg_length == 0x10000 ) {
acbp |= 0x02;
}
PutByte( out, acbp );
if( align == SEGDEF_ALIGN_ABS ) {
PutWord( out, objr->d.segdef.abs.frame );
PutByte( out, objr->d.segdef.abs.offset );
}
if( is32 ) {
PutDword( out, objr->d.segdef.seg_length );
} else {
PutWord( out, objr->d.segdef.seg_length );
}
PutIndex( out, objr->d.segdef.seg_lname_idx );
PutIndex( out, objr->d.segdef.class_lname_idx );
PutIndex( out, objr->d.segdef.ovl_lname_idx );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeLedata( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_LEDATA || objr->command == CMD_LIDATA );
WBegRec( out, objr->command + objr->is_32 );
PutIndex( out, objr->d.ledata.idx );
if( objr->is_32 ) {
PutDword( out, objr->d.ledata.offset );
} else {
PutWord( out, objr->d.ledata.offset );
}
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeTheadr( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_THEADR );
return( writeMisc( out, objr ) );
}
static int FFQUAL writeModend( struct outbuff *out, const struct omf_rec *objr )
{
int is32;
uint_8 mtype;
myassert( objr->command == CMD_MODEND );
is32 = ( ( objr->is_32 && objr->d.modend.start_addrs ) ? TRUE : FALSE );
WBegRec( out, CMD_MODEND + is32 );
mtype = objr->d.modend.main_module ? 0x80 : 0;
if( objr->d.modend.start_addrs ) {
mtype |= 0x41;
PutByte( out, mtype );
PutMem( out, objr->data, objr->length );
} else
PutByte( out, mtype );
WEndRec( out );
return( 0 );
}
static void PutBase( struct outbuff *out, const struct base_info *base )
{
PutIndex( out, base->grp_idx );
PutIndex( out, base->seg_idx );
if( base->grp_idx == 0 && base->seg_idx == 0 ) {
PutWord( out, base->frame );
}
}
static int FFQUAL writePubdef( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_PUBDEF || objr->command == CMD_LPUBDEF );
WBegRec( out, objr->command + objr->is_32 );
PutBase( out, &objr->d.pubdef.base );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeLinnum( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_LINNUM );
WBegRec( out, CMD_LINNUM + objr->is_32 );
PutBase( out, &objr->d.linnum.base );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
#if COMDATSUPP
static int FFQUAL writeComdat( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_COMDAT );
WBegRec( out, objr->command + objr->is_32 );
PutByte( out, objr->d.comdat.flags );
PutByte( out, objr->d.comdat.attributes );
PutByte( out, objr->d.comdat.align );
if( objr->is_32 ) {
PutDword( out, objr->d.comdat.offset );
} else {
PutWord( out, objr->d.comdat.offset );
}
PutIndex( out, objr->d.comdat.type_idx );
if( ( objr->d.comdat.attributes & COMDAT_ALLOC_MASK ) == COMDAT_EXPLICIT ) {
PutBase( out, &objr->d.comdat.base );
}
PutIndex( out, objr->d.comdat.public_lname_idx );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
static int FFQUAL writeLinsym( struct outbuff *out, const struct omf_rec *objr )
{
myassert( objr->command == CMD_LINSYM );
WBegRec( out, CMD_LINSYM + objr->is_32 );
PutByte( out, objr->d.linsym.flags );
PutIndex( out, objr->d.linsym.public_lname_idx );
PutMem( out, objr->data, objr->length );
WEndRec( out );
return( 0 );
}
#endif
static int FFQUAL writeUnexp( struct outbuff *out, const struct omf_rec *objr )
{
DebugMsg(("unexpected OMF record type 0x%02X\n", objr->command ));
Fatal( INTERNAL_ERROR, __FILE__, __LINE__ );
return( 0 );
}
typedef int FFQUAL (*pobj_filter)( struct outbuff *, const struct omf_rec * );
static const pobj_filter myFuncs[] = {
writeUnexp,
writeMisc,
writeMisc32,
writeSegdef,
writeLedata,
writeComent,
writeTheadr,
writeModend,
writePubdef,
writeLinnum,
#if COMDATSUPP
writeComdat,
writeLinsym
#endif
};
enum omffiltfuncs {
OFF_UNEXP,
OFF_MISC,
OFF_MISC32,
OFF_SEGDEF,
OFF_LEDATA,
OFF_COMENT,
OFF_THEADR,
OFF_MODEND,
OFF_PUBDEF,
OFF_LINNUM,
#if COMDATSUPP
OFF_COMDAT,
OFF_LINSYM
#endif
};
static const uint_8 func_index[] = {
OFF_THEADR, 0, 0, 0,
OFF_COMENT, OFF_MODEND, OFF_MISC, 0,
OFF_PUBDEF, 0, OFF_LINNUM, OFF_MISC,
OFF_SEGDEF, OFF_MISC, OFF_MISC32, 0,
OFF_LEDATA, OFF_LEDATA, 0, 0,
0, 0, 0, 0,
OFF_MISC, OFF_MISC32, OFF_MISC, OFF_PUBDEF,
OFF_MISC, 0, OFF_MISC, 0,
#if COMDATSUPP
0, OFF_COMDAT, OFF_LINSYM, OFF_MISC,
#else
0, 0, 0, OFF_MISC,
#endif
OFF_MISC32, OFF_MISC
};
#define JUMP_INDEX(cmd) ( ( ( cmd ) - CMD_MIN_CMD ) >> 1 )
void omf_write_record( const struct omf_rec *objr )
{
struct outbuff out;
myassert( objr != NULL && objr->command >= CMD_MIN_CMD && objr->command <= CMD_MAX_CMD + 1 );
DebugMsg1(("omf_write_record( cmd=%X data=%p length=%u )\n", objr->command, objr->data, objr->length ));
myFuncs[ func_index[JUMP_INDEX(objr->command) ] ] ( &out, objr );
}