fcenable.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 609 行 · 第 1/2 页
C
609 行
/****************************************************************************
*
* 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: Far call optimization enabling utility.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <fcntl.h>
#include <setjmp.h>
#include <process.h>
#include <io.h>
#include <sys/utime.h>
#include "fcenable.h"
#include "banner.h"
extern void MemInit( void );
extern void MemFini( void );
extern void * MemAlloc( unsigned );
extern void MemFree( void * );
extern void CleanRecStuff( void );
extern int ReadRec( void );
extern void ProcessRec( void );
extern void InitRecStuff( void );
extern void FlushBuffer( void );
extern void FinalCleanup( void );
extern void FileCleanup( void );
extern void * Rec1;
extern int PageLen;
#define NOFILE -1
#define STDOUT_HANDLE 1
typedef enum {
EX_NONE,
EX_GOT_SEG,
EX_GOT_START,
EX_GOT_DASH,
EX_GOT_COLON
} EX_STATE;
int InFile;
int OutFile;
name_list * ClassList = NULL;
name_list * SegList = NULL;
exclude_list * ExcludeList = NULL;
static bool MakeBackup = TRUE;
static bool NewOption;
static EX_STATE ExcludeState;
static exclude_list * ExEntry;
static char * HelpMsg =
"Usage: FCENABLE { [options] [files] }\n"
"This allows WLINK to do far call optimization on non-WATCOM object files\n"
"Options are:\n"
"-b don't produce a backup file\n"
"-c <class_list> allow optimization for specified classes (default CODE)\n"
"-s <seg_list> allow optimization for specified segments\n"
"-x <exclude_list> exclude specified area when optimizing\n"
"class_list ::= class_name {,class_name}\n"
"seg_list ::= seg_name {,seg_name}\n"
"exclude_list ::= exclude {,exclude}\n"
"exclude ::= seg_name start_offset (-end_offset | :length)\n"
"files can be object files, concatenated object files, or library files\n"
"file names may contain wild cards\n"
;
#define TEMP_OBJ_NAME "_@FCOBJ_.%$%"
#define TEMP_LIB_NAME "_@FCLIB_.%$%"
#define DEF_CLASS "CODE"
// forward declarations
static void ProcessFiles( char ** );
static void ProcFile( char * fname );
// the spawn & suicide support.
static void *SpawnStack;
static int Spawn1( void (*fn)(), void *data1 )
/********************************************/
{
void * save_env;
jmp_buf env;
int status;
save_env = SpawnStack;
SpawnStack = env;
status = setjmp( env );
if( status == 0 ) {
(*fn)( data1 );
}
SpawnStack = save_env; /* unwind */
return( status );
}
static void Suicide( void )
/*************************/
{
if( SpawnStack != NULL ) {
longjmp( SpawnStack, 1 );
}
}
static int QOpen( char *filename, int access, int permission )
/************************************************************/
{
int result;
result = open( filename, access, permission );
if( result == ERROR ) {
IOError( "problem opening file" );
}
return( result );
}
static void QRemove( char *filename )
/***********************************/
{
if( remove( filename ) != 0 ) {
IOError( "problem removing file" );
}
}
extern int main(int argc, char **argv )
/*************************************/
{
int retval;
MemInit();
put( banner1w( "Far Call Optimization Enabling Utility", _FCENABLE_VERSION_ ) "\n" );
put( banner2( "1990" ) "\n" );
put( banner3 "\n" );
put( banner3a "\n" );
InitRecStuff();
InFile = NOFILE;
OutFile = NOFILE;
ClassList = MemAlloc( sizeof( name_list ) + sizeof( DEF_CLASS ) - 1 );
ClassList->next = NULL;
ClassList->lnameidx = 0;
memcpy( ClassList->name, DEF_CLASS, sizeof( DEF_CLASS ) - 1 );
if( ( argc < 2 ) || ( argv[1][0] == '?' ) ) {
put( HelpMsg );
} else {
argv++; // skip the program name
retval = Spawn1( ProcessFiles, argv );
}
FinalCleanup();
MemFini();
return( retval );
}
static void ProcList( bool (*fn)(char *,int), char ***argv )
/**********************************************************/
// this processes a list of comma-separated strings, being as forgiving about
// spaces as possible.
{
char * item;
char * comma;
bool checksep; // TRUE iff we should check for a separator.
(**argv)++; // skip the option character.
checksep = FALSE;
while( **argv != NULL ) {
item = **argv;
if( checksep ) { // separator needed to continue list
if( *item != ',' ) break;
item++;
}
comma = strchr( item, ',' );
while( comma != NULL ) { // while commas inside string
if( !fn( item, comma - item ) ) {
Warning( "ignoring unexpected comma" );
}
item = comma + 1;
comma = strchr( item, ',' );
}
if( *item != '\0' ) {
checksep = fn( item, strlen( item ) );
} else { // we had a comma at end of string, so no sep needed
checksep = FALSE;
}
(*argv)++;
}
if( ExcludeState != EX_NONE ) {
Warning( "incomplete exclude option specified" );
MemFree( ExEntry );
ExcludeState = EX_NONE;
}
}
static void MakeListItem( name_list **list, char *item, int len )
/***************************************************************/
{
name_list * entry;
entry = MemAlloc( sizeof( name_list ) + len );
entry->next = NULL;
entry->lnameidx = 0;
memcpy( entry->name, item, len );
*(entry->name + len) = '\0';
LinkList( list, entry );
}
static bool ProcClass( char *item, int len )
/******************************************/
{
if( NewOption ) {
FreeList( ClassList );
NewOption = FALSE;
ClassList = NULL;
}
MakeListItem( &ClassList, item, len );
return( TRUE ); // TRUE == check for a list separator
}
static bool ProcSeg( char *item, int len )
/****************************************/
{
if( NewOption ) {
FreeList( SegList );
NewOption = FALSE;
SegList = NULL;
}
MakeListItem( &SegList, item, len );
return( TRUE ); // TRUE == check for a list separator
}
static bool ProcExclude( char *item, int len )
/********************************************/
{
char * endptr;
while( len > 0 ) {
switch( ExcludeState ) {
case EX_NONE:
ExEntry = MemAlloc( sizeof( exclude_list ) + len );
ExEntry->next = NULL;
ExEntry->segidx = 0;
ExEntry->lnameidx = 0;
memcpy( ExEntry->name, item, len );
*(ExEntry->name + len ) = '\0';
ExcludeState = EX_GOT_SEG;
return( FALSE );
case EX_GOT_SEG:
ExEntry->start_off = strtoul( item, &endptr, 16 );
len -= endptr - item;
item = endptr;
ExcludeState = EX_GOT_START;
break;
case EX_GOT_START:
if( *item == '-' ) {
ExcludeState = EX_GOT_DASH;
} else if( *item == ':' ) {
ExcludeState = EX_GOT_COLON;
} else {
Warning( "invalid range separator" );
ExcludeState = EX_NONE;
MemFree( ExEntry );
return( TRUE );
}
item++;
len--;
break;
default: // EX_GOT_DASH or EX_GOT_COLON
ExEntry->end_off = strtoul( item, NULL, 16 );
if( ExcludeState == EX_GOT_COLON ) {
ExEntry->end_off += ExEntry->start_off;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?