deffile.c

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

C
1,067
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "cmdscan.h"
#include "context.h"
#include "deffile.h"
#include "error.h"
#include "memory.h"
#include "message.h"


#define TRUE                    1
#define FALSE                   0

#define SET_ERROR               error = TRUE
#define CLEAR_GOT_FLAGS         exportsGotEntryName = FALSE;    \
                                exportsGotInternalName = FALSE; \
                                exportsGotOrdinal = FALSE;      \
                                exportsGotPrivate = FALSE;      \
                                exportsGotResident = FALSE;     \
                                heapGotReserve = FALSE;         \
                                heapGotCommit = FALSE;          \
                                stackGotReserve = FALSE;        \
                                stackGotCommit = FALSE;         \
                                stubGotFile = FALSE;            \
                                versionGotMajor = FALSE;        \
                                versionGotMinor = FALSE;


static int      next_token( int state, int *newCmd, int *newLine, int fileCharsOk, int atCharsOk );
static char *   get_word( void );
static void     strip_quotes( char *str );
static int      eat_comments( int *newLine );
static char *   string_convert( const char *str );


enum {
    STATE_CLEAR,                        /* general states */
    STATE_EOF,
    STATE_BASE,                         /* keyword states */
    STATE_DESCRIPTION,
    STATE_EXETYPE,
    STATE_EXPORT,
    STATE_EXPORTS,
    STATE_HEAPSIZE,
    STATE_LIBRARY,
    STATE_NAME,
    STATE_SECTIONS,
    STATE_SEGMENTS,
    STATE_STACKSIZE,
    STATE_STUB,
    STATE_VERSION,
    STATE_PRIVATE,
    STATE_PROTMODE,                     /* unsupported states */
    STATE_CODE,
    STATE_DATA,
    STATE_NONAME,
    STATE_RESIDENTNAME,
    STATE_AT,                           /* separator states, they must be together !!! */
    STATE_COMMA,
    STATE_EQUAL,
    STATE_PERIOD,
    STATE_STRING                        /* option value states */
};


static int          breakStates[] = {   /* break a command on these */
    STATE_CLEAR,
    STATE_EOF,
    STATE_DESCRIPTION,
    STATE_EXETYPE,
    STATE_EXPORT,
    STATE_EXPORTS,
    STATE_HEAPSIZE,
    STATE_LIBRARY,
    STATE_NAME,
    STATE_SECTIONS,
    STATE_SEGMENTS,
    STATE_STACKSIZE,
    STATE_STUB,
    STATE_PROTMODE,
    STATE_CODE,
    STATE_DATA,
    STATE_NONAME,
    -1
};

static char *       curToken = NULL;


#ifdef __TARGET_AXP__
/*
 *  Strip leading _ and @nn from stdcall names when alpha
 */
void FuzzyMassageAXPStdcall( char *name ) {
    char *first;
    char *last;
    first = name;
    last = name + strlen( name ) - 1;
    if( *first == '\'' ) {
        first++;
        name++;
    }
    if( *last == '\'' ) last--;
    if( *first == '_' && isdigit( *last ) ) {
        first++;
        last--;
        while( isdigit( *last ) ) {
            last--;
        }
        if( *last == '\@' ) {
            *last++ = '\'';
            *last = '\0';
            while( *first ) {
                *name++ = *first++;
            }
            *name = '\0';
        }
    }
}
#endif


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

    /*** Make a new list item ***/
    buf = AllocMem( sizeof(StringList) );
    buf->str = DupStrMem( 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.  Returns NULL on error, or a DefInfo* on success.
 */
#ifdef __TARGET_AXP__
    DefInfo *ParseDefFile( const char *filename, int dofuzzylink )
#else
    DefInfo *ParseDefFile( const char *filename )
#endif
/****************************************************************/
{
    char *              newfilename = DupStrMem( filename );
    DefInfo *           info;
    int                 alive = TRUE;
    int                 error = FALSE;
    int                 state = STATE_CLEAR;
    int                 mergeNow;
    int                 mergeNow2;
    int                 mergeType;
    int                 foundNewLine;
    char *              exportsEntryName;
    int                 exportsGotEntryName;
    char *              exportsInternalName;
    int                 exportsGotInternalName;
    char *              exportsOrdinal;
    int                 exportsGotOrdinal;
    int                 exportsGotPrivate;
    int                 exportsGotResident;
    char *              stackReserve;
    int                 stackGotReserve;
    char *              stackCommit;
    int                 stackGotCommit;
    int                 stubGotFile;
    char *              heapReserve;
    int                 heapGotReserve;
    char *              heapCommit;
    int                 heapGotCommit;
    char *              versionMajor;
    int                 versionGotMajor;
    char *              versionMinor;
    int                 versionGotMinor;
    int                 len;
    char *              str;

    /*** Initialize ***/
    strip_quotes( newfilename );
    if( OpenFileContext( newfilename ) ) {
        FreeMem( newfilename );
        return( NULL );
    }
    info = AllocMem( sizeof( DefInfo ) );
    memset( info, 0, sizeof( DefInfo ) );

    /*** Process the commands, one by one ***/
    while( alive ) {
        if( error ) {
            Warning( "Error near '%s' in %s -- aborting .def processing",
                     curToken, newfilename );
            FreeMem( info );
            FreeMem( newfilename );
            return( NULL );
        }
        switch( state ) {
          case STATE_CLEAR:
            CLEAR_GOT_FLAGS;            /* initialize locals */
            mergeType = STATE_CLEAR;
            mergeNow = FALSE;
            state = next_token(STATE_CLEAR, NULL, NULL, FALSE, !exportsGotEntryName ); /* get next command */
            break;
          case STATE_DESCRIPTION:       /* DESCRIPTION "text" */
            state = next_token(STATE_DESCRIPTION, NULL, NULL, FALSE, FALSE );
            switch( state ) {
              case STATE_STRING:
                str = string_convert( curToken );
                if( *str == '"' ) { // change " to '
                    *str ='\'';
                    str[strlen(str)-1] = '\'';
                }
                add_string( &info->description, str );
                state = STATE_CLEAR;
                break;
              default:
                SET_ERROR;
                break;
            }
            break;
          case STATE_EXPORTS:
          /* EXPORTS entryname[=internalname] [@ordinal[ NONAME ]  [DATA] [ PRIVATE ] [RESIDENTNAME] */
            state = next_token(STATE_EXPORTS, &mergeNow, &foundNewLine, FALSE, !exportsGotEntryName );
            if( mergeNow ) {
                if( !exportsGotEntryName ) {
                    mergeNow = 0;
                    break;
                }
                while( !foundNewLine ) {
                        if (next_token( STATE_EXPORTS, NULL, &foundNewLine, FALSE, FALSE )==STATE_EOF) break;
                }
                state = STATE_EXPORTS;
                break;
            }
            switch( state ) {
              case STATE_STRING:
                if( exportsGotEntryName ) {
                    SET_ERROR;
                } else {
                    exportsEntryName = DupQuoteStrMem( curToken, '\'' );
                    #ifdef __TARGET_AXP__
                    FuzzyMassageAXPStdcall( exportsEntryName );
                    #endif
                    exportsGotEntryName = 1;
                    mergeType = STATE_EXPORTS;
                    if( foundNewLine ) {
                        mergeNow = 1;
                    }
                }
                state = STATE_EXPORTS;
                break;
              case STATE_AT:
                if( !exportsGotEntryName ) {
                    SET_ERROR;
                } else {
                    state = next_token(STATE_EXPORTS, &mergeNow, &foundNewLine, FALSE, !exportsGotEntryName );
                    if( mergeNow )  break;
                    switch( state ) {
                      case STATE_STRING:
                        exportsOrdinal = DupStrMem( curToken );
                        exportsGotOrdinal = 1;
                        state = STATE_EXPORTS;
                        if( foundNewLine ) {
                            mergeNow = 1;
                        }
                        break;
                      case STATE_EOF:
                        break;
                      default:
                        SET_ERROR;
                        break;
                    }
                }
                break;
              case STATE_EQUAL:
                if( !exportsGotEntryName || exportsGotOrdinal ) {
                    SET_ERROR;
                } else {
                    state = next_token(STATE_EXPORTS, &mergeNow, &foundNewLine, FALSE, !exportsGotInternalName );
                    if( mergeNow )  break;
                    switch( state ) {
                      case STATE_STRING:
                        exportsInternalName = DupQuoteStrMem( curToken, '\'' );
                        #ifdef __TARGET_AXP__
                        FuzzyMassageAXPStdcall( exportsInternalName );
                        #endif
                        exportsGotInternalName = 1;
                        state = STATE_EXPORTS;
                        if( foundNewLine ) {
                            mergeNow = 1;
                        }
                        break;
                      case STATE_EOF:
                        break;
                      default:
                        SET_ERROR;
                        break;
                    }
                }
                break;
              case STATE_PRIVATE:
                if( !exportsGotEntryName ) {
                    SET_ERROR;
                } else {
                    exportsGotPrivate = 1;
                    mergeNow = 1;
                }
                state = STATE_EXPORTS;
                break;
              case STATE_RESIDENTNAME:
                if( !exportsGotEntryName ) {

⌨️ 快捷键说明

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