objutil.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 582 行
C
582 行
/****************************************************************************
*
* 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: emit object code
*
****************************************************************************/
#include "ftnstd.h"
#include "progsw.h"
#include "sdfile.h"
#include "global.h"
#include "fcgbls.h"
#include "errcod.h"
#include "omodes.h"
#include "cioconst.h"
#include "fcodes.h"
#include "fio.h"
#include "fmemmgr.h"
#include "emitobj.h"
#include "ferror.h"
#include <string.h>
#include <process.h>
#include <unistd.h>
#if defined( __386__ )
#define PAGE_SIZE (16*1024)
#else
#define PAGE_SIZE (1*1024)
#endif
#define _PageNumber( v_ptr ) ((v_ptr) / PAGE_SIZE)
#define _PageOffset( v_ptr ) (ObjCode + \
( (v_ptr) - ( (v_ptr) / PAGE_SIZE ) * PAGE_SIZE ))
#define _MakeVirtual( page, obj_ptr ) ((page) * PAGE_SIZE + \
( (obj_ptr) - ObjCode ))
static file_attr PageFileAttrs = { REC_FIXED | SEEK };
static char *PageFileName = { "__wfc__.vm" };
static char PageFileBuff[MAX_FILE];
static int CurrPage;
static int MaxPage;
static unsigned_8 PageFlags;
static file_handle PageFile;
static char *ObjPtr;
static char *ObjCode;
static char *ObjEnd;
extern file_handle SDOpen(char *,int);
extern void SDClose(file_handle);
extern void SDSeek(file_handle,int,int);
extern uint SDRead(file_handle,byte *,uint);
extern void SDWrite(file_handle,byte *,int);
extern bool SDError(file_handle,char *);
extern bool SDEof(file_handle);
extern void SDScratch(char *);
extern void SDSetAttr(file_attr);
#define PF_INIT 0x00 // initial page flags
#define PF_DIRTY 0x01 // page has been updated
void InitObj( void ) {
//=================
// Allocate memory for object code.
char *fn;
char *tmp;
int len;
int idx;
ObjCode = NULL; // in case FMemAlloc() fails
ObjCode = FMemAlloc( PAGE_SIZE );
ObjEnd = ObjCode + PAGE_SIZE;
ObjPtr = ObjCode;
*(unsigned_16 *)ObjPtr = FC_END_OF_SEQUENCE; // in case no source code in file
PageFile = NULL;
if( ( ProgSw & PS_DONT_GENERATE ) == 0 ) {
fn = PageFileBuff;
len = 0;
tmp = getenv( "TMP" );
if( tmp != NULL ) {
strcpy( fn, tmp );
len += strlen( fn );
fn += len;
if( ( fn[-1] != ':' ) && ( fn[-1] != '\\' ) && ( fn[-1] != '/' ) ) {
*fn = '\\';
++fn;
++len;
}
}
strcpy( fn, PageFileName );
len += strlen( fn );
PageFileBuff[ len + 1 ] = NULLCHAR;
for( idx = 0; idx <= 25; idx++ ) {
PageFileBuff[ len ] = 'a' + idx;
if( access( PageFileBuff, 0 ) == -1 ) break;
}
if( idx == 26 ) {
Error( SM_OUT_OF_VM_FILES, PageFileName );
} else {
SDSetAttr( PageFileAttrs );
PageFile = SDOpen( PageFileBuff, UPDATE_FILE );
ChkIOErr( PageFile, SM_OPENING_FILE );
}
}
PageFlags = PF_INIT;
CurrPage = 0;
MaxPage = 0;
}
static void ChkIOErr( file_handle fp, int error ) {
//=====================================================
// Check for i/o errors to page file.
char err_msg[ERR_BUFF_SIZE+1];
if( SDError( fp, err_msg ) ) {
Error( error, PageFileName, err_msg );
}
}
void FiniObj( void ) {
//=======================
// Release memory allocated for object code.
if( ObjCode != NULL ) {
FMemFree( ObjCode );
ObjCode = NULL;
}
if( PageFile != NULL ) {
SDClose( PageFile );
PageFile = NULL;
SDScratch( PageFileBuff );
}
}
static void LoadPage( unsigned_16 page ) {
//============================================
// Load a page into memory.
if( page != CurrPage ) {
DumpCurrPage();
SDSeek( PageFile, page, PAGE_SIZE );
ChkIOErr( PageFile, SM_IO_READ_ERR );
SDRead( PageFile, ObjCode, PAGE_SIZE );
// If we seek to the end of the last page in the disk
// file (which is the start of a non-existent page file),
// we will get end-of-file when we do the read.
if( !SDEof( PageFile ) ) {
ChkIOErr( PageFile, SM_IO_READ_ERR );
}
CurrPage = page;
PageFlags = PF_INIT;
}
}
static void NewPage( void ) {
//===============================
// Page for F-Codes is full. Dump it to disk and start a new one.
if( CurrPage < MaxPage ) {
LoadPage( CurrPage + 1 );
} else {
DumpCurrPage();
PageFlags = PF_INIT;
CurrPage++;
}
ObjPtr = ObjCode;
}
static void DumpCurrPage( void ) {
//====================================
// Dump current page to disk.
if( PageFlags & PF_DIRTY ) {
if( CurrPage > MaxPage ) {
MaxPage = CurrPage;
}
SDSeek( PageFile, CurrPage, PAGE_SIZE );
ChkIOErr( PageFile, SM_IO_WRITE_ERR );
SDWrite( PageFile, ObjCode, PAGE_SIZE );
ChkIOErr( PageFile, SM_IO_WRITE_ERR );
PageFlags &= ~PF_DIRTY;
}
}
obj_ptr ObjTell( void ) {
//=======================
// Return pointer to next F-Code.
obj_ptr curr_obj;
curr_obj = CurrPage;
return( _MakeVirtual( curr_obj, ObjPtr ) );
}
obj_ptr ObjSeek( obj_ptr new_obj ) {
//==================================
// Seek to specifed location in F-Code stream.
obj_ptr curr_obj;
curr_obj = CurrPage;
curr_obj = _MakeVirtual( curr_obj, ObjPtr );
LoadPage( _PageNumber( new_obj ) );
ObjPtr = _PageOffset( new_obj );
return( curr_obj );
}
unsigned_16 ObjOffset( obj_ptr prev_obj ) {
//=============================================
// Return offset from ObjPtr to given pointer.
obj_ptr curr_obj;
curr_obj = CurrPage;
return( _MakeVirtual( curr_obj, ObjPtr ) - prev_obj );
}
void AlignEven( void ) {
//=========================
// Align ObjPtr on an even boundary.
if( (int)ObjPtr & 0x0001 ) {
OutByte( 0 );
}
}
static void SplitValue( void *ptr, int size, int part_1 ) {
//=============================================================
// Split value across pages.
memcpy( ObjPtr, ptr, part_1 );
PageFlags |= PF_DIRTY;
NewPage();
memcpy( ObjPtr, (char *)ptr + part_1, size - part_1 );
PageFlags |= PF_DIRTY;
ObjPtr += size - part_1;
}
void OutPtr( pointer val ) {
//=============================
// Output a pointer to object memory.
if( ( ProgSw & ( PS_ERROR | PS_DONT_GENERATE ) ) == 0 ) {
if( ObjEnd - ObjPtr < sizeof( pointer ) ) {
if( ObjPtr < ObjEnd ) { // value overlaps pages
SplitValue( &val, sizeof( pointer ), ObjEnd - ObjPtr );
return;
}
NewPage();
}
*(pointer *)ObjPtr = val;
ObjPtr += sizeof( pointer );
PageFlags |= PF_DIRTY;
}
}
void OutU16( unsigned_16 val ) {
//=================================
// Output 16-bit value to object memory.
if( ( ProgSw & ( PS_ERROR | PS_DONT_GENERATE ) ) == 0 ) {
if( ObjEnd - ObjPtr < sizeof( unsigned_16 ) ) {
if( ObjPtr < ObjEnd ) { // value overlaps pages
SplitValue( &val, sizeof( unsigned_16 ), ObjEnd - ObjPtr );
return;
}
NewPage();
}
*(unsigned_16 *)ObjPtr = val;
ObjPtr += sizeof( unsigned_16 );
PageFlags |= PF_DIRTY;
}
}
void OutInt( inttarg val ) {
//=============================
// Output target integer value to object memory.
#if _CPU == 8086
OutU16( val );
#else // _CPU == 386
OutConst32( val );
#endif
}
void OutConst32( signed_32 val ) {
//===================================
// Output 32-bit constant to object memory.
if( ( ProgSw & ( PS_ERROR | PS_DONT_GENERATE ) ) == 0 ) {
if( ObjEnd - ObjPtr < sizeof( signed_32 ) ) {
if( ObjPtr < ObjEnd ) { // value overlaps pages
SplitValue( &val, sizeof( signed_32 ), ObjEnd - ObjPtr );
return;
}
NewPage();
}
*(signed_32 *)ObjPtr = val;
ObjPtr += sizeof( signed_32 );
PageFlags |= PF_DIRTY;
}
}
void OutObjPtr( obj_ptr val ) {
//================================
// Output object code pointer to object memory.
if( ( ProgSw & ( PS_ERROR | PS_DONT_GENERATE ) ) == 0 ) {
if( ObjEnd - ObjPtr < sizeof( obj_ptr ) ) {
if( ObjPtr < ObjEnd ) { // value overlaps pages
SplitValue( &val, sizeof( obj_ptr ), ObjEnd - ObjPtr );
return;
}
NewPage();
}
*(obj_ptr *)ObjPtr = val;
ObjPtr += sizeof( obj_ptr );
PageFlags |= PF_DIRTY;
}
}
void OutByte( byte val ) {
//===========================
// Output a byte to object memory.
if( ( ProgSw & ( PS_ERROR | PS_DONT_GENERATE ) ) == 0 ) {
if( ObjEnd - ObjPtr < sizeof( byte ) ) {
NewPage();
}
*(byte *)ObjPtr = val;
ObjPtr += sizeof( byte );
PageFlags |= PF_DIRTY;
}
}
void InitFCode( void ) {
//=========================
// Setup for accessing F-Codes from object memory.
LoadPage( 0 );
ObjPtr = ObjCode;
}
static void JoinValue( void *ptr, int size, int part_1 ) {
//============================================================
// Join value that is split across pages.
memcpy( ptr, ObjPtr, part_1 );
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
memcpy( (char *)ptr + part_1, ObjPtr, size - part_1 );
ObjPtr += size - part_1;
}
void *GetPtr( void ) {
//=======================
// Get a pointer from object memory.
pointer val;
if( ObjEnd - ObjPtr < sizeof( pointer ) ) {
if( ObjPtr < ObjEnd ) { // value split across pages
JoinValue( &val, sizeof( pointer ), ObjEnd - ObjPtr );
return( val );
}
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
}
val = *(pointer *)ObjPtr;
ObjPtr += sizeof( pointer );
return( val );
}
unsigned_16 GetU16( void ) {
//==============================
// Get an unsigned 16-bit value from object memory.
unsigned_16 val;
if( ObjEnd - ObjPtr < sizeof( unsigned_16 ) ) {
if( ObjPtr < ObjEnd ) { // value split across pages
JoinValue( &val, sizeof( unsigned_16 ), ObjEnd - ObjPtr );
return( val );
}
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
}
val = *(unsigned_16 *)ObjPtr;
ObjPtr += sizeof( unsigned_16 );
return( val );
}
signed_32 GetConst32( void ) {
//==================================
// Get 32-bit constant from object memory.
signed_32 val;
if( ObjEnd - ObjPtr < sizeof( signed_32 ) ) {
if( ObjPtr < ObjEnd ) { // value split across pages
JoinValue( &val, sizeof( signed_32 ), ObjEnd - ObjPtr );
return( val );
}
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
}
val = *(signed_32 *)ObjPtr;
ObjPtr += sizeof( signed_32 );
return( val );
}
inttarg GetInt( void ) {
//======================
// Get integer from object memory.
#if _CPU == 8086
return( GetU16() );
#else // _CPU == 386
return( GetConst32() );
#endif
}
obj_ptr GetObjPtr( void ) {
//=========================
// Get object code pointer from object memory.
obj_ptr val;
if( ObjEnd - ObjPtr < sizeof( obj_ptr ) ) {
if( ObjPtr < ObjEnd ) { // value split across pages
JoinValue( &val, sizeof( obj_ptr ), ObjEnd - ObjPtr );
return( val );
}
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
}
val = *(obj_ptr *)ObjPtr;
ObjPtr += sizeof( obj_ptr );
return( val );
}
byte GetByte( void ) {
//=======================
// Get a byte from object memory.
byte val;
if( ObjEnd - ObjPtr < sizeof( byte ) ) {
LoadPage( CurrPage + 1 );
ObjPtr = ObjCode;
}
val = *(byte *)ObjPtr;
ObjPtr += sizeof( byte );
return( val );
}
obj_ptr FCodeSeek( obj_ptr new_obj ) {
//====================================
// Set ObjPtr to specified location.
obj_ptr curr_obj;
curr_obj = CurrPage;
curr_obj = _MakeVirtual( curr_obj, ObjPtr );
LoadPage( _PageNumber( new_obj ) );
ObjPtr = _PageOffset( new_obj );
return( curr_obj );
}
obj_ptr FCodeTell( int offset ) {
//===============================
// Return current ObjPtr + offset.
obj_ptr new_obj;
new_obj = CurrPage;
if( ObjEnd - ObjPtr < offset ) {
new_obj = _MakeVirtual( new_obj + 1,
ObjCode + offset - ( ObjEnd - ObjPtr ) );
} else {
new_obj = _MakeVirtual( new_obj, ObjPtr + offset );
}
return( new_obj );
}
void FCSeek( void ) {
//======================
// Seek to ObjPtr + offset.
FCodeSeek( FCodeTell( GetU16() ) );
}
FCODE GetFCode( void ) {
//========================
// Get an F-Code from object memory.
return( GetU16() );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?