write.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,166 行 · 第 1/3 页
C
1,166 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Write translated object module.
*
****************************************************************************/
#include "asmglob.h"
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include "asmsym.h"
#include "asmins.h"
#include "asmalloc.h"
#include "fatal.h"
#include "asmdefs.h"
#include "asmeval.h"
#include "objio.h"
#include "objprs.h"
#include "fixup.h"
#include "autodept.h"
#include "mangle.h"
#include "namemgr.h" // WOMP callback NameGet routine declaration
#include "directiv.h"
#include "queues.h"
#include "womputil.h"
#include "asmlabel.h"
#include "asminput.h"
#include "myassert.h"
// use separate fixupp and fixupp32 records
// fixupp32 record is used only for FIX_OFFSET386 and FIX_POINTER386 fixup
// it is for better compatibility with MASM
#define SEPARATE_FIXUPP_16_32 1
extern void CheckForOpenConditionals( void );
extern void set_cpu_parameters( void );
extern void set_fpu_parameters( void );
extern void CheckProcOpen( void );
extern void CmdlParamsInit( void );
extern void PrintStats( void );
extern symbol_queue Tables[]; // tables of definitions
extern struct fixup *FixupListHead; // head of list of fixups ( from WOMP )
extern struct fixup *FixupListTail;
extern uint_32 BufSize;
extern obj_rec *ModendRec; // Record for Modend
extern int MacroExitState;
extern int in_prologue;
int MacroLocalVarCounter = 0; // counter for temp. var names
char Parse_Pass; // phase of parsing
char write_to_file; // write if there is no error
unsigned long LineNumber;
char Modend; // end of module is reached
int_8 DefineProc; // TRUE if the definition of procedure
// has not ended
dir_node *CurrProc; // current procedure
int_8 Use32; // if 32-bit code is use
unsigned long PassTotal; // Total number of ledata bytes generated
int_8 PhaseError;
char EndDirectiveFound = FALSE;
extern uint segdefidx; // Number of Segment definition
extern uint extdefidx; // Number of Extern definition
static char **NameArray;
global_vars Globals = { 0, 0, 0, 0, 0, 0, 0 };
static FNAME *FNames = NULL;
static unsigned long lastLineNumber;
const FNAME *AddFlist( char const *name )
/***************************************/
{
FNAME *flist;
FNAME *last;
int index;
char *fname;
char buff[2*_MAX_PATH];
index = 0;
fname = _getFilenameFullPath( buff, name, sizeof( buff ) );
last = FNames;
for( flist = last; flist != NULL; flist = flist->next ) {
if( strcmp( name, flist->name ) == 0 )
return( flist );
if( strcmp( fname, flist->fullname ) == 0 )
return( flist );
index++;
last = flist;
}
flist = (FNAME *)AsmAlloc( sizeof( FNAME ) );
flist->name = (char *)AsmAlloc( strlen( name ) + 1 );
strcpy( flist->name, name );
flist->fullname = (char *)AsmAlloc( strlen( fname ) + 1 );
strcpy( flist->fullname, fname );
flist->mtime = _getFilenameTimeStamp( fname );
flist->next = NULL;
if( FNames == NULL ) {
FNames = flist;
} else {
last->next = flist;
}
return( flist );
}
static void FreeFlist( void )
/***************************/
{
const FNAME *curr;
const FNAME *last;
for( curr = FNames; curr != NULL; ) {
AsmFree( curr->fullname );
AsmFree( curr->name );
last = curr;
curr = curr->next;
AsmFree( (void *)last );
}
FNames = NULL;
return;
}
static void write_init( void )
/****************************/
{
BufSize = 0;
FixupListHead = NULL;
FixupListTail = NULL;
ModendRec = NULL;
CurrProc = NULL;
DefineProc = FALSE;
Use32 = FALSE;
write_to_file = TRUE;
IdxInit();
LnameInsert( "" );
ModuleInit();
FixInit();
}
static void write_fini( void )
/****************************/
{
FixFini();
FreeFlist();
}
void OutSelect( bool starts )
/***************************/
{
obj_rec *objr;
unsigned long curr;
if( starts ) {
if( !Options.output_comment_data_in_code_records || Globals.data_in_code
|| !Globals.code_seg )
return;
Globals.sel_start = GetCurrAddr();
Globals.data_in_code = TRUE;
} else {
if( !Options.output_comment_data_in_code_records || !Globals.data_in_code )
return;
Globals.sel_idx = GetSegIdx( &CurrSeg->seg->sym );
Globals.data_in_code = FALSE;
if( (Parse_Pass > PASS_1) && !PhaseError ) {
objr = ObjNewRec( CMD_COMENT );
objr->d.coment.attr = 0x80;
objr->d.coment.class = CMT_DISASM_DIRECTIVE;
ObjAllocData( objr, 11 );
curr = GetCurrAddr();
if( (Globals.sel_start > 0xffffUL) || (curr > 0xffffUL) ) {
ObjPut8( objr, DDIR_SCAN_TABLE_32 );
ObjPutIndex( objr, Globals.sel_idx );
ObjPut32( objr, Globals.sel_start );
ObjPut32( objr, GetCurrAddr() );
} else {
ObjPut8( objr, DDIR_SCAN_TABLE );
ObjPutIndex( objr, Globals.sel_idx );
ObjPut16( objr, Globals.sel_start );
ObjPut16( objr, GetCurrAddr() );
}
ObjTruncRec( objr );
write_record( objr, TRUE );
}
Globals.sel_idx = 0;
Globals.sel_start = 0;
}
}
static void write_end_of_pass1( void )
/************************************/
{
obj_rec *objr;
objr = ObjNewRec( CMD_COMENT );
objr->d.coment.attr = 0x00;
objr->d.coment.class = CMT_MS_END_PASS_1;
ObjAttachData( objr, "\x001", 1 );
write_record( objr, TRUE );
}
static void write_dosseg( void )
/******************************/
{
obj_rec *objr;
objr = ObjNewRec( CMD_COMENT );
objr->d.coment.attr = 0x80;
objr->d.coment.class = CMT_DOSSEG;
ObjAttachData( objr, "", 0 );
write_record( objr, TRUE );
}
static void write_lib( void )
/***************************/
{
obj_rec *objr;
struct dir_node *curr;
char *name;
for( curr = Tables[TAB_LIB].head; curr; curr = curr->next ) {
name = curr->sym.name;
objr = ObjNewRec( CMD_COMENT );
objr->d.coment.attr = 0x80;
objr->d.coment.class = CMT_DEFAULT_LIBRARY;
ObjAttachData( objr, name, strlen( name ) );
write_record( objr, TRUE );
}
}
static void write_one_export( dir_node *dir )
/*******************************************/
{
obj_rec *objr;
char *name;
proc_info *info;
info = dir->e.procinfo;
if( info->visibility == VIS_EXPORT ) {
objr = ObjNewRec( CMD_COMENT );
objr->d.coment.attr = 0x00;
objr->d.coment.class = CMT_DLL_ENTRY;
name = Mangle( &dir->sym, NULL );
ObjAllocData( objr, 4 + strlen( name ) );
ObjPut8( objr, 2 );
ObjPut8( objr, 0 ); // temporary
ObjPutName( objr, name, strlen( name ) );
ObjPut8( objr, 0 );
write_record( objr, TRUE );
AsmFree( name );
}
}
static void write_export( void )
/******************************/
{
dir_node *dir;
for( dir = Tables[TAB_PROC].head; dir != NULL; dir = dir->next ) {
write_one_export( dir );
}
}
static void write_grp( void )
/***************************/
{
dir_node *curr;
dir_node *segminfo;
seg_list *seg;
obj_rec *grp;
unsigned long line_num;
char writeseg;
unsigned i = 1;
line_num = LineNumber;
for( curr = Tables[TAB_GRP].head; curr; curr = curr->next, i++ ) {
grp = ObjNewRec( CMD_GRPDEF );
/**/myassert( grp != NULL );
grp->d.grpdef.idx = curr->e.grpinfo->idx;
/* we might need up to 3 bytes for each seg in dgroup and 1 byte for
the group name index */
ObjAllocData( grp, 1 + 3 * curr->e.grpinfo->numseg );
ObjPut8( grp, GetLnameIdx( curr->sym.name ) );
for( seg = curr->e.grpinfo->seglist; seg; seg = seg->next ) {
writeseg = TRUE;
segminfo = (dir_node *)(seg->seg);
if( ( segminfo->sym.state != SYM_SEG ) || ( segminfo->sym.segment == NULL ) ) {
LineNumber = curr->line_num;
AsmErr( SEG_NOT_DEFINED, segminfo->sym.name );
write_to_file = FALSE;
LineNumber = line_num;
} else {
ObjPut8( grp, GRP_SEGIDX );
ObjPutIndex( grp, segminfo->e.seginfo->segrec->d.segdef.idx);
}
}
if( write_to_file ) {
ObjTruncRec( grp );
write_record( grp, TRUE );
} else {
ObjKillRec( grp );
}
}
}
static void write_seg( void )
/***************************/
{
dir_node *curr;
obj_rec *objr;
uint seg_index;
uint total_segs = 0;
for( curr = Tables[TAB_SEG].head; curr; curr = curr->next ) {
if( ( curr->sym.segment == NULL )
&& ( curr->e.seginfo->group == NULL ) )
AsmErr( SEG_NOT_DEFINED, curr->sym.name );
total_segs++;
}
for( seg_index = 1; seg_index <= total_segs; seg_index++ ) {
/* find segment by index */
for( curr = Tables[TAB_SEG].head; curr; curr = curr->next ) {
if( GetSegIdx( curr->sym.segment ) == seg_index ) {
break;
}
}
if( curr == NULL )
continue;
if( curr->sym.state != SYM_SEG ) {
AsmErr( SEG_NOT_DEFINED, curr->sym.name );
continue;
}
objr = curr->e.seginfo->segrec;
objr->is_32 = TRUE;
objr->d.segdef.ovl_name_idx = 1;
objr->d.segdef.seg_name_idx = GetLnameIdx( curr->sym.name );
write_record( objr, FALSE );
if( curr->e.seginfo->iscode == SEGTYPE_ISCODE ) {
obj_rec *rec;
rec = ObjNewRec( CMD_COMENT );
rec->d.coment.attr = CMT_TNP;
rec->d.coment.class = CMT_LINKER_DIRECTIVE;
ObjAllocData( rec, 3 );
ObjPut8( rec, LDIR_OPT_FAR_CALLS );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?