cmdos2.c

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

C
1,220
字号
/****************************************************************************
*
*                            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:  Processing of linker options for OS/2 and Windows formats.
*
****************************************************************************/


#include <string.h>
#include <ctype.h>
#include "linkstd.h"
#include "alloc.h"
#include "command.h"
#include "cmdos2.h"
#include "exeos2.h"
#include "exepe.h"
#include "loados2.h"
#include "loadpe.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "objfree.h"
#include "cmdline.h"
#include "fileio.h"
#include "impexp.h"
#include "objpass1.h"

static void             ParseVersion( void );
static bool             GetWlibImports( void );
static bool             getimport( void );
static bool             getexport( void );
static bool             getsegflags( void );

extern bool ProcOS2Import( void )
/*******************************/
{
    return( ProcArgList( &getimport, 0 ) );
}

extern bool ProcOS2Export( void )
/*******************************/
{
    bool    retval;

    if( GetToken( SEP_EQUALS, TOK_INCLUDE_DOT ) ) {
        retval = GetWlibImports();
    } else {
        retval =  ProcArgList( &getexport, 0 );
    }
    return( retval );
}

extern bool ProcAnonExport( void )
/********************************/
{
    bool    retval;

    CmdFlags |= CF_ANON_EXPORT;
    retval = ProcOS2Export();
    CmdFlags &= ~CF_ANON_EXPORT;
    return( retval );
}

extern bool ProcOS2Segment( void )
/********************************/
{
    return( ProcArgList( &getsegflags, TOK_INCLUDE_DOT ) );
}

static bool GetWlibImports( void )
/********************************/
/* read in a wlib command file, get the import directives, and treat them
 * as exports (hey man, GO asked for it ...... ) */
{
    char *          fname;
    char *          symname;
    char *          internal;
    f_handle        handle;
    unsigned_16     ordinal;
    entry_export *  exp;

    fname = FileName( Token.this, Token.len, E_LBC, FALSE );
    handle = QOpenR( fname );
    SetCommandFile( handle, fname );
    Token.locked = TRUE;      /* make sure only this file parsed */
    while( GetToken( SEP_SPACE, 0 ) ) {
        if( Token.len <= 2 ) continue;
        if( (Token.this[0] == '+') && (Token.this[1] == '+') ) {
            Token.this += 2;
            Token.len -= 2;
            if( Token.this[0] == '\'' ) {
                Token.thumb = REJECT;
                if( !GetToken( SEP_QUOTE, 0 ) ) {
                    LnkMsg( LOC+LINE+ERR+MSG_BAD_WLIB_IMPORT, NULL );
                    RestoreCmdLine();   /* get rid of this file */
                    return( TRUE );
                }
            }
            symname = tostring();
            internal = NULL;
            if( !GetToken( SEP_DOT_EXT, 0 ) ) {
                LnkMsg( LOC+LINE+ERR+MSG_BAD_WLIB_IMPORT, NULL );
                _LnkFree( symname );
                RestoreCmdLine();       /* get rid of this file */
                return( TRUE );
            }
            ordinal = 0;
            if( GetToken( SEP_DOT_EXT, 0 ) ) {
                if( getatoi( &ordinal ) != ST_IS_ORDINAL ) {
                    if( Token.len > 0 ) {
                        internal = symname;
                        symname = tostring();
                    }
                    if( GetToken( SEP_DOT_EXT, 0 )
                        && getatoi( &ordinal ) != ST_IS_ORDINAL ) {
                        if( GetToken( SEP_DOT_EXT, 0 ) ) {
                            getatoi( &ordinal );
                        }
                    }
                }
            }
            exp = AllocExport( symname, strlen(symname) );
            exp->isanonymous = (CmdFlags & CF_ANON_EXPORT) != 0;
            if( internal != NULL ) {
                exp->sym = RefISymbol( internal );
                _LnkFree( internal );
            } else {
                exp->sym = RefISymbol( symname );
            }
            exp->sym->info |= SYM_DCE_REF;      // make sure it isn't removed
            exp->ordinal = ordinal;
            if( ordinal == 0 ) {
                exp->isresident = TRUE;   // no ord spec'd so must be resident
            }
            AddToExportList( exp );
        }
    }
    Token.locked = FALSE;
    return( TRUE );
}

static bool getimport( void )
/***************************/
{
    length_name         intname;
    length_name         modname;
    length_name         extname;
    unsigned_16         ordinal;
    ord_state           state;

    intname.name = tostring();
    intname.len = strlen( intname.name );
    if( !GetToken( SEP_NO, 0 ) ) {
        _LnkFree( intname.name );
        return( FALSE );
    }
    modname.name = tostring();
    modname.len = strlen( modname.name );
    state = ST_INVALID_ORDINAL;   // assume to extname or ordinal.
    if( GetToken( SEP_PERIOD, TOK_INCLUDE_DOT ) ) {
        state =  getatoi( &ordinal );
        if( state == ST_NOT_ORDINAL ) {
            extname.name = tostring();
            extname.len = strlen( extname.name );
        } else if( state == ST_INVALID_ORDINAL ) {
            LnkMsg( LOC+LINE+MSG_IMPORT_ORD_INVALID + ERR, NULL );
            _LnkFree( intname.name );
            _LnkFree( modname.name );
            return( TRUE );
        }
    }
    if( state == ST_IS_ORDINAL ) {
        HandleImport( &intname, &modname, &intname, ordinal );
    } else {
        if( state == ST_NOT_ORDINAL ) {
            HandleImport( &intname, &modname, &extname, NOT_IMP_BY_ORDINAL );
            _LnkFree( extname.name );
        } else {
            HandleImport( &intname, &modname, &intname, NOT_IMP_BY_ORDINAL );
        }
    }
    _LnkFree( intname.name );
    _LnkFree( modname.name );
    return( TRUE );
}

static bool getexport( void )
/***************************/
{
    entry_export *  exp;
    unsigned_16     value;

    exp = AllocExport( Token.this, Token.len );
    exp->isanonymous = (CmdFlags & CF_ANON_EXPORT) != 0;
    if( GetToken( SEP_PERIOD, TOK_INCLUDE_DOT ) ) {
        if( getatol( &exp->ordinal ) != ST_IS_ORDINAL ) {
            LnkMsg( LOC+LINE+ERR + MSG_EXPORT_ORD_INVALID, NULL );
            _LnkFree( exp );
            GetToken( SEP_EQUALS, TOK_INCLUDE_DOT );
            return( TRUE );
        }
    }
    if( GetToken( SEP_EQUALS, TOK_INCLUDE_DOT ) ) {
        exp->sym = SymXOp( ST_CREATE|ST_REFERENCE, Token.this, Token.len );
        if( GetToken( SEP_EQUALS, TOK_INCLUDE_DOT ) ) {
            exp->impname = tostring();
        }
    } else {
        exp->sym = RefISymbol( exp->name );
    }
    exp->sym->info |= SYM_DCE_REF;      //make sure it is not removed
    if( exp->ordinal == 0 ) {
        exp->isresident = TRUE;   // no ordinal spec'd so must be kept resident
    }
    exp->next = FmtData.u.os2.exports;    // put in the front of the list for
    FmtData.u.os2.exports = exp;          // now so ProcResidant can get to it.
    while( ProcOne( Exp_Keywords, SEP_NO, FALSE ) ) {}  // handle misc options
    FmtData.u.os2.exports = exp->next;       // take it off the list
    exp->iopl_words = 0;
    if(!(FmtData.type & (MK_WINDOWS|MK_PE)) &&GetToken(SEP_NO,TOK_INCLUDE_DOT)) {
        if( getatoi( &value ) == ST_IS_ORDINAL ) {
            if( value > 63 ) {
                LnkMsg( LOC+LINE+MSG_TOO_MANY_IOPL_WORDS+ ERR, NULL );
            } else {
                exp->iopl_words = value;
            }
        } else {
            Token.thumb = REJECT;    // reprocess the token.
        }
    }
    AddToExportList( exp );
    return( TRUE );
}

extern bool ProcExpResident( void )
/*********************************/
{
    FmtData.u.os2.exports->isresident = TRUE;
    return( TRUE );
}

extern bool ProcPrivate( void )
/******************************/
{
    FmtData.u.os2.exports->isprivate = TRUE;
    return( TRUE );
}

extern bool ProcOS2Alignment( void )
/**********************************/
/* process Alignment option */
{
    ord_state           ret;
    unsigned_32         value;

    if( !HaveEquals(0) ) return( FALSE );
    ret = getatol( &value );
    if( ret != ST_IS_ORDINAL || value == 0 ) {
        return( FALSE );
    }
    FmtData.u.os2.segment_shift = blog_32( value - 1 ) + 1;     //round up.
    return( TRUE );
}

extern bool ProcObjAlign( void )
/******************************/
/* process ObjAlign option */
{
    ord_state           ret;
    unsigned_32         value;

    if( !HaveEquals(0) ) return( FALSE );
    ret = getatol( &value );
    if( ret != ST_IS_ORDINAL || value == 0 ) {
        return( FALSE );
    }                                            /* value not a power of 2 */
    if( value < 16 || value > (256*1024UL*1024) || (value & (value-1)) ) {
        LnkMsg( LOC+LINE+WRN+MSG_VALUE_INCORRECT, "s", "objalign" );
        value = 64*1024;
    }
    FmtData.objalign = value;
    ChkBase(value);
    return( TRUE );
}

extern bool ProcModName( void )
/*****************************/
{
    if( !HaveEquals(TOK_INCLUDE_DOT) ) return( FALSE );
    FmtData.u.os2.res_module_name = totext();
    return( TRUE );
}

extern bool ProcNewFiles( void )
/******************************/
{
    FmtData.u.os2.flags |= LONG_FILENAMES;
    return( TRUE );
}

extern bool ProcProtMode( void )
/******************************/
{
    FmtData.u.os2.flags |= PROTMODE_ONLY;
    return( TRUE );
}

extern bool ProcOldLibrary( void )
/********************************/
{
    if( !HaveEquals(TOK_INCLUDE_DOT | TOK_IS_FILENAME) ) return( FALSE );
    FmtData.u.os2.old_lib_name = FileName( Token.this, Token.len, E_DLL, FALSE );
    return( TRUE );
}

extern bool ProcOS2HeapSize( void )
/*********************************/
{
    ord_state           ret;
    unsigned_32         value;

    if( !HaveEquals(0) ) return( FALSE );
    ret = getatol( &value );
    if( ret != ST_IS_ORDINAL || value == 0 ) {
        LnkMsg( LOC+LINE+WRN+MSG_VALUE_INCORRECT, "s", "heapsize" );
    } else {
        FmtData.u.os2.heapsize = value;
    }
    return( TRUE );
}

extern bool ProcDescription( void )
/*********************************/
{
    if( !GetToken( SEP_NO, TOK_INCLUDE_DOT ) ) {
        return( FALSE );
    }
    FmtData.u.os2.description = tostring();
    return( TRUE );
}

extern bool ProcCommitStack( void )
/*********************************/
{
    return( GetLong( &FmtData.u.pe.stackcommit ) );
}

extern bool ProcCommitHeap( void )
/********************************/
{
    return( GetLong( &FmtData.u.pe.heapcommit ) );
}

static bool AddCommit( void )
/***************************/
{
    Token.thumb = REJECT;
    if( ProcOne( CommitKeywords, SEP_NO, FALSE ) == FALSE ) return( FALSE );
    return( TRUE );
}

extern bool ProcCommit( void )
/****************************/
// set NT stack commit and heap sizes.
{
    return( ProcArgList( AddCommit, TOK_INCLUDE_DOT ) );
}

extern bool ProcRWRelocCheck( void )
/**********************************/
// check for segment relocations pointing to read/write data segments
{
    FmtData.u.os2.chk_seg_relocs = TRUE;
    return( TRUE );
}

extern bool ProcSelfRelative( void )
/**********************************/
{
    FmtData.u.os2.gen_rel_relocs = TRUE;
    return( TRUE );
}

extern bool ProcInternalRelocs( void )
/************************************/

⌨️ 快捷键说明

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