translat.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 888 行 · 第 1/2 页

C
888
字号
/****************************************************************************
*
*                            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:  Translate Microsoft LINK to Watcom options.
*
****************************************************************************/


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cmdline.h"
#include "deffile.h"
#include "error.h"
#include "file.h"
#include "fuzzy.h"
#include "link.h"
#include "message.h"
#include "memory.h"
#include "pathconv.h"
#include "translat.h"
#include "system.h"

#define UNSUPPORTED_STR_SIZE    512

#if defined(__TARGET_386__)
    #define SYS_NT_CHARMODE     "nt"
    #define SYS_NT_WINDOWED     "nt_win"
    #define SYS_NT_DLL          "nt_dll"
    #define LIBDIR_SUFFIX       "\\lib386"
    #define NT_LIBDIR_SUFFIX    "\\lib386\\nt"
#elif defined(__TARGET_AXP__)
    #define SYS_NT_CHARMODE     "ntaxp"
    #define SYS_NT_WINDOWED     "ntaxp_win"
    #define SYS_NT_DLL          "ntaxp_dll"
    #define LIBDIR_SUFFIX       "\\libaxp"
    #define NT_LIBDIR_SUFFIX    "\\libaxp\\nt"
#elif defined(__TARGET_PPC__)
    #define SYS_NT_CHARMODE     "ntppc"
    #define SYS_NT_WINDOWED     "ntppc_win"
    #define SYS_NT_DLL          "ntppc_dll"
    #define LIBDIR_SUFFIX       "\\libppc"
    #define NT_LIBDIR_SUFFIX    "\\libppc\\nt"
#else
    #error Unrecognized CPU type
#endif


/*
 * Various flags to keep in mind while translating options.
 */
static struct XlatStatus {
    int     dll                 : 1;    /* we're building a DLL */
    int     exp                 : 1;    /* there is an .exp file */
} status;



/*
 * Initialize a struct XlatStatus.
 */
static void init_status( struct XlatStatus *status )
/**************************************************/
{
    memset( status, 0, sizeof(struct XlatStatus) );
}


/*
 * Add one more unsupported option to optStr.
 */
static void append_unsupported( char *optStr, char *opt )
/*******************************************************/
{
    if( optStr[0] != '\0' ) {
        strcat( optStr, " /" );
    } else {
        strcat( optStr, "/" );
    }
    strcat( optStr, opt );
}


/*
 * Parse unsupported options.
 */
static void unsupported_opts( const OPT_STORAGE *cmdOpts )
/********************************************************/
{
    char                opts[UNSUPPORTED_STR_SIZE];

    /*** Build a string listing all unsupported options that were used ***/
    opts[0] = '\0';
    if( cmdOpts->debugtype   )  append_unsupported( opts, "DEBUGTYPE"   );
    if( cmdOpts->exetype     )  append_unsupported( opts, "EXETYPE"     );
    if( cmdOpts->fixed       )  append_unsupported( opts, "FIXED"       );
    if( cmdOpts->machine     )  append_unsupported( opts, "MACHINE"     );
    if( cmdOpts->noentry     )  append_unsupported( opts, "NOENTRY"     );
    if( cmdOpts->order       )  append_unsupported( opts, "ORDER"       );
    if( cmdOpts->pdb         )  append_unsupported( opts, "PDB"         );
    if( cmdOpts->profile     )  append_unsupported( opts, "PROFILE"     );
    if( cmdOpts->section     )  append_unsupported( opts, "SECTION"     );
    if( cmdOpts->verbose     )  append_unsupported( opts, "VERBOSE"     );
    if( cmdOpts->vxd         )  append_unsupported( opts, "VXD"         );
    if( cmdOpts->warn        )  append_unsupported( opts, "WARN"        );

    /*** If an unsupported option was used, give a warning ***/
    if( opts[0] != '\0' ) {
        UnsupportedOptsMessage( opts );
    }
}


/*
 * Add another string to an OPT_STRING.
 */
static void add_string( OPT_STRING **p, char *str )
/*************************************************/
{
    OPT_STRING *        buf;
    OPT_STRING *        curElem;

    /*** Make a new list item ***/
    buf = AllocMem( sizeof(OPT_STRING) + strlen(str) );
    strcpy( buf->data, str );
    buf->next = NULL;

    /*** Put it at the end of the list ***/
    if( *p == NULL ) {
        *p = buf;
    } else {
        curElem = *p;
        while( curElem->next != NULL )  curElem = curElem->next;
        curElem->next = buf;
    }
}


/*
 * Parse a .def file if necessary.
 */
static void def_file_opts( OPT_STORAGE *cmdOpts )
/***********************************************/
{
    DefInfo *           info;
    StringList *        strList;
    char *              newstr;

    if( cmdOpts->def ) {
        #ifdef __TARGET_AXP__
            info = ParseDefFile( cmdOpts->def_value->data,
                                 !cmdOpts->nofuzzy );
        #else
            info = ParseDefFile( cmdOpts->def_value->data );
        #endif
        if( info != NULL ) {
            strList = info->description;
            while( strList != NULL ) {
                add_string( &cmdOpts->comment_value, strList->str );
                strList = strList->next;
            }

            strList = info->exports;
            while( strList != NULL ) {
                add_string( &cmdOpts->export_value, strList->str );
                cmdOpts->export = 1;
                strList = strList->next;
            }

            if( !cmdOpts->dll ) {
                if( info->makeDll ) {
                    cmdOpts->dll = 1;
                }
            }
            if( !cmdOpts->base ) {
                if( info->baseAddr != NULL ) {
                    add_string( &cmdOpts->base_value, info->baseAddr );
                    cmdOpts->base = 1;
                }
            }

            if( !cmdOpts->heap ) {
                if( info->heapsize != NULL ) {
                    add_string( &cmdOpts->heap_value, info->heapsize );
                    cmdOpts->heap = 1;
                }
            }


            if( !cmdOpts->internaldllname ) {
                if( info->internalDllName != NULL ) {
                    add_string( &cmdOpts->internaldllname_value, info->internalDllName );
                    cmdOpts->internaldllname = 1;
                }
            }

            if( !cmdOpts->out ) {
                if( info->name != NULL ) {
                    newstr = PathConvert( info->name, '\'' );
                    add_string( &cmdOpts->out_value, newstr );
                    cmdOpts->out = 1;
                }
            }

            if( !cmdOpts->stack ) {
                if( info->stacksize != NULL ) {
                    add_string( &cmdOpts->stack_value, info->stacksize );
                    cmdOpts->stack = 1;
                }
            }

            if( !cmdOpts->stub ) {
                if( info->stub != NULL ) {
                    add_string( &cmdOpts->stub_value, info->stub );
                    cmdOpts->stub = 1;
                }
            }

            if( !cmdOpts->version ) {
                if( info->version != NULL ) {
                    add_string( &cmdOpts->version_value, info->version );
                    cmdOpts->version = 1;
                }
            }
            FreeDefInfo(info);
        } else {
            FatalError( "Error parsing %s -- aborting",
                        cmdOpts->def_value->data );
        }
    }
}


/*
 * Called by InitFuzzy when an error occurs.
 */
static int fuzzy_init_callback( const char *filename )
/****************************************************/
{
    Warning( "Cannot extract external symbols from '%s' -- fuzzy linking may not work",
             filename );
    return( 1 );
}


/*
 * Given a symbol, fuzzy match it and create an export directive.
 * Returns a pointer to a newly allocated buffer, which the caller is
 * responsible for freeing.  This function was formerly ExportFuzzy().
 */
static char *fuzzy_export( char *export )
/***************************************/
{
    char *              internalname = NULL;
    char *              ordinal = NULL;
    char *              therest = NULL;
    char *              entryname = NULL;
    char *              exportcopy;
    char *              p = NULL;
    int                 len = 4; /* for the '.', '=', ' ', and required +1 */

    exportcopy = DupStrMem( export );
    p = strchr( exportcopy+1, '\'' );
    if( exportcopy[0] != '\''  ||  p == NULL )  Zoinks(); // the entryname must be in quotes
    p++;
    if( *p != '\0' ) { /* there is something after the entryname */
        entryname = p; // char after the entryname
        p = strchr( p, '=' );
        if( p != NULL ) { /* internalname found */
            *p = '\0';
            internalname = p + 1;
            p = strchr( internalname, ' ' );
            if( p != NULL ) { /* there is something after the internalname */
                *p = '\0';
                therest = p + 1;
            }
        }

        p = strchr( entryname, '.' );
        if( p != NULL ) { /* ordinal found */
            *p = '\0';
            ordinal = p + 1;
            if( internalname == NULL ) {
                p = strchr( ordinal, ' ' );
                if( p != NULL ) { /* there is something after the ordinal */
                    *p = '\0';
                    therest = p + 1;
                }
            }
            len += strlen( ordinal );
        }

        if( internalname == NULL  &&  ordinal == NULL ) {
            p = strchr( entryname, ' ' );
            if( p != NULL ) { /* there is something after the entryname */
                *p = '\0';
                therest = p + 1;
            }
        }

        *entryname = '\0'; /* separate the entry name from the rest of the export directive */
    }
    entryname = exportcopy;
    len += strlen( entryname );

    if( internalname == NULL ) {
        internalname = MatchFuzzy( entryname );
    } else {
        internalname = MatchFuzzy( internalname );
    }

    if( therest != NULL ) {
        strupr( therest );
        len += strlen( therest );
    }

    /*** Create and return the proper export directive ***/
    if( internalname != NULL ) {
        len += strlen( internalname );
        p = AllocMem( len );
        *p = '\0';
        strcat( p, entryname );
        if( ordinal ) {
            strcat( p, "." );
            strcat( p, ordinal );
        }
        strcat( p, "=" );
        strcat( p, internalname );
        if( therest != NULL ) {
            strcat( p, " " );
            strcat( p, therest );
        }
    } else { // no changes to export directive are required
        p = export;
    }

    FreeMem( exportcopy );
    return( p );
}


/*
 * Initialize fuzzy linking.
 */
static void init_fuzzy( OPT_STRING *objs, OPT_STRING *libs,
                        OPT_STRING *defaultlibs )
/*********************************************************/
{
    char *              envvar;
    unsigned            count;
    char *              newstr;
    char *              start;
    char *              end;
    OPT_STRING *        optStr;
    char **             objsvector;
    char **             libsvector;
    char **             libpathsvector;
    size_t              len;

    /*** Get the object file names into an array ***/
    count = 0;
    optStr = objs;
    while( optStr != NULL ) {
        count++;
        optStr = optStr->next;
    }
    objsvector = AllocMem( (count+1) * sizeof(char*) );
    count = 0;
    optStr = objs;
    while( optStr != NULL ) {
        objsvector[count] = optStr->data;
        count++;
        optStr = optStr->next;
    }
    objsvector[count] = NULL;

    /*** Get the library file names into an array ***/
    count = 0;
    optStr = libs;
    while( optStr != NULL ) {
        count++;
        optStr = optStr->next;
    }
    optStr = defaultlibs;
    while( optStr != NULL ) {
        count++;
        optStr = optStr->next;
    }
    libsvector = AllocMem( (count+1) * sizeof(char*) );
    count = 0;
    optStr = libs;
    while( optStr != NULL ) {
        libsvector[count] = optStr->data;
        count++;
        optStr = optStr->next;
    }
    optStr = defaultlibs;
    while( optStr != NULL ) {
        libsvector[count] = optStr->data;
        count++;
        optStr = optStr->next;
    }
    libsvector[count] = NULL;

    /*** Get the library paths from LIB into the 'libpathsvector' array ***/
    count = 0;
    libpathsvector = AllocMem( (count+1) * sizeof(char*) );
    envvar = getenv( "LIB" );
    if( envvar != NULL ) {
        newstr = DupStrMem( envvar );
        start = newstr;
        while( start != NULL  &&  *start != '\0' ) {
            end = strchr( start, ';' );
            if( end != NULL ) {
                while( *end == ';' ) {
                    *end = '\0';
                    end++;
                }
            }
            count++;
            libpathsvector = ReallocMem( libpathsvector, (count+1) * sizeof(char*) );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?