conv.c

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

C
1,792
字号
/****************************************************************************
*
*                            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:  Generate *.obj and *.asm thunks for interfacing from
*               WIN386 (32-bit flat) to 16-bit Windows API function
*               (16-bit segmented). It uses Pharlap Easy OMF (32-bit)
*               for *.obj thunks.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define MAX_BUFF 256

/*
 * depth into stack from which to get parms: 3 dwords pushed
 */
#define STACK_FRAME  3*4+4

char line[] = ";****************************************************************************\n";
char blank[] = ";***                                                                      ***\n";

char GlueInc[] = "winglue.inc";

int genstubs = 0;
int quiet = 0;

typedef enum {
    PARM_PTR,
    PARM_WORD,
    PARM_DWORD,
    PARM_VOID,
    PARM_DOUBLE
} parm_types;

typedef enum {
    RETURN_PTR,
    RETURN_INT,
    RETURN_CHAR,
    RETURN_DWORD,
    RETURN_VOID
} return_types;

struct  subparm {
    struct subparm *nextparm;
    unsigned    offset;
    unsigned    parmnum;
};

/*
 * data structure containing all data about a prototype
 */
typedef struct fcn {
    struct fcn  *next;      /* link */
    char        *fn;            /* function name */
    char        *plist;         /* parameter list */
    struct subparm *subparms;   /* sub parms that need aliasing */
    int         class;          /* what class it belongs to */
    struct fcn  *next_class;/* connects to next function in same class */
    char        pcnt;           /* number of parms */
    char        returntype;     /* function return type */
    char        aliascnt;       /* number of 16-bit aliases to be created */
    unsigned    thunkindex:5;   /* ThunkStrs index */
    unsigned    thunk:1;        /* requires a thunking layer */
    unsigned    is_16:1;        /* is an _16 function */
    unsigned    is_tinyio:1;    /* is a tinyio function */
    unsigned    noregfor_16:1;  /* _16 function has no regular function */
    unsigned    need_fpusave:1; /* function requires floating point save */
    unsigned    __special_func:1;/* special @func requires extra thunking */
} fcn;

struct parmlist {
    struct parmlist     *next;
    char                parm_count;
    char                alias_count;
    char                parm_types[1];
};

char    **ThunkStrs;
char    * ThunkGenerated;
int     ThunkIndex;
int     MaxAliasCount;
struct parmlist *ParmList;

fcn     *Class, *CurrClass;      /* class list */
fcn     *Head, *Curr;            /* list of all prototypes */
fcn     *VoidHead, *VoidCurr;    /* list of all prototypes */

void *myalloc( size_t size )
{
    void        *tmp;

    tmp = calloc( 1, size );
    if( tmp == NULL ) {
        printf("Out of Memory!\n");
        exit( 1 );
    }
    return( tmp );

} /* myalloc */

void *_fmyalloc( size_t size )
{
    void     *tmp;

    tmp = malloc( size );
    if( tmp == NULL ) {
        printf("Out of Memory!\n");
        exit( 1 );
    }
    memset( tmp, 0, size );
    return( tmp );

} /* _fmyalloc */

void *_fmyrealloc( void *ptr, size_t size )
{
    void     *tmp;

    tmp = realloc( ptr, size );
    if( tmp == NULL ) {
        printf("Out of Memory!\n");
        exit( 1 );
    }
    return( tmp );
} /* _fmyrealloc */

int IsWord( char *str )
{
    if( !stricmp( str,"int" ) ||
        !stricmp( str,"char" ) ||
        !stricmp( str,"unsigned char" ) ||
        !stricmp( str,"short" ) ||
        !stricmp( str,"unsigned" ) ||
        !stricmp( str,"unsigned short" ) ||
        !stricmp( str,"unsigned int" ) ) {
        return( 1 );
    }
    return( 0 );

} /* IsWord */

/*
 * StripSpaces - remove leading and trailing spaces
 */
static char *StripSpaces( char *buff )
{
    int         i;

    i = strlen( buff ) - 1;
    while( buff[i] == ' ' ) {
        buff[i--] = '\0';
    }
    while( *buff == ' ' )  ++buff;
    return( buff );

} /* StripSpaces */

/*
 * ClassifyParm - decide if a parm is a pointer, word or dword
 */
parm_types ClassifyParm( char *buff )
{
    buff = StripSpaces( buff );
    if( IsWord( buff ) ) {
        return( PARM_WORD );
    } else if( strchr( buff, '*' ) != NULL ) {
        return( PARM_PTR );
    } else if( stricmp( buff, "void" ) == 0 ) {
        return( PARM_VOID );
    } else {
        return( PARM_DWORD );
    }

} /* ClassifyParm */

/*
 * ClassifyReturnType - decide if type is a pointer, int, void, char, or dword
 */
return_types ClassifyReturnType( char *buff )
{
    buff = StripSpaces( buff );
    if( stricmp( buff, "int" ) == 0  ||  stricmp( buff, "short" ) == 0 ) {
        return( RETURN_INT );
    } else if( stricmp( buff, "void" ) == 0 ) {
        return( RETURN_VOID );
    } else if( stricmp( buff, "char" ) == 0 ) {
        return( RETURN_CHAR );
    } else if( strchr( buff, '*' ) != NULL ) {
        return( RETURN_PTR );
    } else {
        return( RETURN_DWORD );
    }

} /* ClassifyReturnType */

void ClassifyParmList( char *plist, fcn *tmpf )
{
    int         i;
    int         j;
    int         k;
    int         parmcnt;
    struct parmlist *p;
    struct subparm  *subparm;
    char        parm_list[32];
    char        c;
    char        parmtype;

    k = 0;
    i = 0;
    parmcnt = 0;
    for(;;) {
        c = plist[i];
        if( c == '\0'  ||  c == ',' ) {
            plist[i] = '\0';
            parmtype = ClassifyParm( &plist[k] );
            if( parmtype == PARM_DOUBLE ) {
                parmtype = PARM_DWORD;
                parm_list[parmcnt++] = parmtype;
            }
            parm_list[parmcnt++] = parmtype;
            if( c == '\0' ) break;
            k = i + 1;
        } else if( c == '[' ) {
            plist[i] = '\0';
            j = i + 1;
            for(;;) {
                i++;
                c = plist[i];
                if( c == ';'  ||  c == ']' ) {
                    plist[i] = '\0';
                    subparm = myalloc( sizeof( struct subparm ) );
                    subparm->nextparm = tmpf->subparms;
                    tmpf->subparms = subparm;
                    subparm->parmnum = parmcnt;
                    subparm->offset = atoi( &plist[j] );
                    j = i + 1;
                    if( c == ']' ) break;
                }
            }
        }
        i++;
    }
    if( parmcnt == 1  &&  parm_list[0] == PARM_VOID ) {
        tmpf->pcnt = 0;
        tmpf->aliascnt = 0;
        tmpf->plist = NULL;
    } else {
        p = ParmList;
        for(;;) {
            if( p == NULL ) break;
            if( p->parm_count == parmcnt ) {
                if( memcmp( p->parm_types, parm_list, parmcnt ) == 0 ) break;
            }
            p = p->next;
        }
        if( p == NULL ) {
            p = myalloc( sizeof(struct parmlist) + parmcnt );
            p->next = ParmList;
            ParmList = p;
            p->parm_count = parmcnt;
            memcpy( p->parm_types, parm_list, parmcnt );
            p->alias_count = 0;
            for( i = 0; i < parmcnt; i++ ) {
                if( parm_list[i] == PARM_PTR ) {
                    p->alias_count++;
                }
            }
            if( p->alias_count > MaxAliasCount ) {
                MaxAliasCount = p->alias_count;
            }
        }
        tmpf->pcnt = parmcnt;
        tmpf->aliascnt = p->alias_count;
        tmpf->plist = p->parm_types;
    }
} /* ClassifyParmList */


int main( int argc, char *argv[] )
{
    char        *name,*dir;
    FILE        *f,*pf;
    char        defname[80];
    char        fname[50];
    int         i,j;

    _nheapgrow();
    j=argc-1;
    while( j > 0 ) {
        if( argv[j][0] == '-' ) {
            for(i=1;i<strlen(argv[j]);i++) {
                switch( argv[j][i] ) {
                case 'q': quiet = 1; break;
                case 's': genstubs=1; break;
                case '?':
                    printf("conv -s (gen stubs)\n");
                    exit(1);
                default:
                    fprintf(stderr,"Unrecognized switch %c",argv[j][i] );
                    break;
                }
            }
            for(i=j;i<argc;i++) {
                argv[i]=argv[i+1];
            }
            argc--;
        }
        j--;
    }

    if( argc < 2 ) {
        name = "win386";
    } else {
        name = argv[1];
    }
    if( argc < 3 ) {
        dir = "def";
    } else {
        dir = argv[2];
    }

    pf = fopen( name,"r" );
    if( pf == NULL ) {
        printf("error opening file %s\n",name );
        exit( 1 );
    }

    while( fgets( fname, 50, pf ) != NULL ) {
        fname[ strlen( fname ) - 1 ] = 0;
#ifdef __UNIX__
        sprintf( defname, "%s/%s", dir, fname );
#else
        sprintf( defname, "%s\\%s", dir, fname );
#endif
        f = fopen( defname, "r" );
        if( f == NULL ) {
            printf("error opening file %s\n", defname );
            exit( 1 );
        }
        ProcessDefFile( f );
        fclose( f );
    }
    fclose( pf );
    BuildClasses();
    GenerateCode();
    GenerateThunkC();
    GenerateCStubs();
    ClosingComments();
    return( 0 );

} /* main */

void ProcessDefFile( FILE *f )
{
    char        buff[MAX_BUFF];
    int         i,j,k;
    char        *fn;            // function name
    char        *type;          // return type
    char        *plist;         // parameter list
    fcn         *tmpf;

    while( fgets( buff, MAX_BUFF, f ) != NULL ) {

        if( buff[0] == '#' ) {
            continue;
        }

        if( buff[0] == '!' ) {
            ThunkStrs = _fmyrealloc( ThunkStrs, sizeof( char *) *
                                    (ThunkIndex + 1) );
            i = strlen( buff );
            ThunkStrs[ThunkIndex] = _fmyalloc( i-2 );
            buff[i-1] = '\0';
            _fstrcpy( ThunkStrs[ThunkIndex], &buff[1] );
            ThunkIndex++;
            continue;
        }
        /*
         * flag a function that returns a pointer to a function
         */
        if( strncmp( buff, "int (", 5 ) == 0 ) {
            printf( "Oh, oh, something returns a function!!!\n" );
            exit( 1 );
        }

        /*
         * look for opening paren
         */
        i = 0;
        while( buff[i] != '(' ) {
            i++;
        }

        /*
         * look for closing ')'
         */
        j = i;
        k = 0;                  // keep track of nested ()
        for(;;) {
            if( buff[j] == ')' ) {
                --k;
                if( k == 0 ) break;
            } else if( buff[j] == '(' ) {
                ++k;
            }
            ++j;
        }

        /*
         * back up away from opening paren to obtain function name
         */
        k = i;
        for(;;) {
            if( buff[k] == ' ' ) break;
            if( buff[k] == '*' ) break;
            if( k == 0 ) break;
            k--;

⌨️ 快捷键说明

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