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 + -
显示快捷键?