conv.c

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

C
1,792
字号
        }
        if( k == 0 ) {          /* no function name and/or no type */
            fprintf( stderr, "ERR: %s", buff );
            continue;
        }
        //  int function(long,int);
        //  ^  ^        ^        ^
        //  |  |        |        |
        //  0  k        i        j

        type = &buff[0];        // return type
        if( buff[k] == '*' ) {
            buff[k-1] = '*';
        }
        buff[k] = '\0';
        fn = &buff[k+1];        // function name
        buff[i] = '\0';
        plist = &buff[i+1];     // parameter list
        buff[j] = '\0';

        /*
         * save all data but parms
         */
        tmpf = _fmyalloc( sizeof( fcn ) );
        tmpf->returntype = ClassifyReturnType( type );

        tmpf->need_fpusave = 0;
        if( *fn == '^' ) {
            fn++;
            tmpf->need_fpusave = 1;
        }
        tmpf->__special_func = 0;
        if( *fn == '@' ) {
            *fn = '#';
            tmpf->__special_func = 1;
        }
        if( *fn == '#' ) {
            fn++;
            tmpf->thunk = 1;
            tmpf->thunkindex = ThunkIndex - 1;
        } else {
            tmpf->thunk = 0;
        }
        tmpf->fn = myalloc( strlen( fn ) + 1 );
        strcpy( tmpf->fn, fn );
        if( !strncmp( fn,"_Tiny", 5 ) || !strncmp( fn, "_nTiny", 6 ) ) {
            tmpf->is_tinyio = 1;
        } else {
            tmpf->is_tinyio = 0;
            tmpf->noregfor_16 = 0;
            if( !strncmp( fn, "_16", 3 ) ) {
                tmpf->is_16 = 1;
            } else {
                tmpf->is_16 = 0;
            }
        }
        ClassifyParmList( plist, tmpf );

        /*
         * chain this guy into our list
         */
        if( tmpf->returntype == RETURN_VOID ) {
            if( VoidHead == NULL ) {
                VoidCurr = VoidHead = tmpf;
            } else {
                VoidCurr->next = tmpf;
                VoidCurr = tmpf;
            }
        } else {
            if( Head == NULL ) {
                Curr = Head = tmpf;
            } else {
                Curr->next = tmpf;
                Curr = tmpf;
            }
        }
    }
}

void BuildClasses()
{
    int         j;
    int         class_count;
    fcn         *tmpf;
    fcn         *cl;

    /*
     * attach void list to end: Having the void list on the end ensures
     * that void's will be put in a class with a non-void.  Otherwise,
     * if a void came before a non-void, then the non-void would be
     * put in the same class as the void.  In English, a function
     * with a return value would not get a return value at all.
     */
    if( Curr != NULL ) {
        Curr->next = VoidHead;
    } else {
        Head = VoidHead;
    }
    Curr = VoidCurr;

    /*
     * build classes : functions with the same parameter list and
     * the same return type (word/dword) are put together so that
     * we only have to generate the code for them once.  Void functions
     * are thrown in with whoever has the same parameter types as they
     * do (return value is ignored).
     */
    CurrClass = Class = Head;
    class_count = 0;
    Class->class = class_count++;
    tmpf = Head->next;
    while( tmpf != NULL ) {
        j = 0;
        cl = Class;
        while( cl != NULL ) {
            /*
             * same number of parameters, and need fpu save?
             */
            if( tmpf->pcnt == cl->pcnt ) {
                if( tmpf->plist == cl->plist ) {
                    tmpf->class = cl->class;
                    j = 1;
                    break;
                }
            }
            cl = cl->next_class;
        }

        if( j == 0 ) {
            tmpf->class = class_count++;
            CurrClass->next_class = tmpf;
            CurrClass = tmpf;
        }
        tmpf = tmpf->next;
    }

    if( !quiet ) {
        printf( "Total Classes: %d\n", class_count );
    }
} /* BuildClasses */

/*
 * ClosingComments
 */
void ClosingComments( void )
{
    fcn         *tmpf;

    tmpf = Head;
    while( tmpf != NULL ) {
        if( tmpf->fn[0] == '_' && tmpf->fn[1] == '_' ) {
            if( !quiet ) {
                printf("stub for '%s' requires intervention\n", tmpf->fn );
            }
        }
        tmpf = tmpf->next;
    }

} /* ClosingComments */

/*
 * GenerateThunkC - generate dllthunk.c
 */
void GenerateThunkC( void )
{
    FILE        *f;

    f = fopen( "dllthunk.c", "w" );
    fprintf( f, "/*\n * This file automatically generated by CONV.EXE\n */\n" );
    fprintf( f, "#include <windows.h>\n" );
    fprintf( f, "#include <stdio.h>\n\n" );
    fprintf( f, "void DLLLoadFail( char *str )\n{\n" );
    fprintf( f, "    MessageBox( NULL, \"DLL Load Failed\", str, MB_OK );\n" );
    fprintf( f, "}\n\n" );
    fclose( f );

} /* GenerateThunkC */

#define OBJBUF_SIZE     512
static int objFile;
static int objBufIndex;
static char objBuf[OBJBUF_SIZE];

static void writeObjBuf()
{
    if( objBufIndex != 0 ) {
        write( objFile, objBuf, objBufIndex );
        objBufIndex = 0;
    }
}

static void writeObj( void *p, int len )
{
    int         n;

    for(;;) {
        n = min( OBJBUF_SIZE - objBufIndex, len );
        memcpy( &objBuf[objBufIndex], p, n );
        objBufIndex += n;
        if( objBufIndex == OBJBUF_SIZE ) {
            writeObjBuf();
        }
        len -= n;
        if( len == 0 ) break;
        p = (char *)p + n;
    }
}

static void emitBYTE( int byte )
{
    char        b;

    b = byte;
    writeObj( &b, 1 );
}

static void emitWORD( int word )
{
    writeObj( &word, 2 );
}

static void emitDWORD( long dword )
{
    writeObj( &dword, 4 );
}

static void emitSTRING( char *data )
{
    char        len;
    len = strlen( data );
    writeObj( &len, 1 );
    writeObj( data, len );
}

static void emitTHEADR( int modindex )
{
    int         len;
    char        buff[20];

    sprintf( buff,"win%d", modindex );
    emitBYTE( 0x80 );
    len = 2+strlen( buff );
    emitWORD( len );
    emitSTRING( buff );
    emitBYTE( 0 );
}

static void emitCOMMENT( void )
{
    emitBYTE( 0x88 );
    emitWORD( 8 );
    emitBYTE( 0x80 );
    emitBYTE( 0xAA );
    emitBYTE( 0x38 );
    emitBYTE( 0x30 );
    emitBYTE( 0x33 );
    emitBYTE( 0x38 );
    emitBYTE( 0x36 );
    emitBYTE( 0x0 );
}

static void emitLNAMES( void )
{
    int len;

    emitBYTE( 0x96 );
    len = 1 + 1+ strlen( "" ) + 1+ strlen( "_TEXT" ) + 1 + strlen( "CODE" );
    emitWORD( len );
    emitSTRING( "" );
    emitSTRING( "_TEXT" );
    emitSTRING( "CODE" );
    emitBYTE( 0 );
}

static void emitSEGDEF( unsigned long segment_length )
{
    emitBYTE( 0x98 );
    emitWORD( 9 );              /* len */
    emitBYTE( 0x48 );           /* attributes */
    emitDWORD( segment_length );/* length of segment (# of bytes of code) */
    emitBYTE( 2 );              /* seg name index */
    emitBYTE( 3 );              /* class name index */
    emitBYTE( 1 );              /* ovl name index */
    emitBYTE( 0 );
}


static void emitPUBDEF( char *name )
{
    int len;

    emitBYTE( 0x90 );
    len = 2 + 1 + strlen( name ) + 6;
    emitWORD( len );
    emitBYTE( 0 );              /* group index */
    emitBYTE( 1 );              /* seg index */
    emitSTRING( name );
    emitWORD( 0 );              /* frame num? */
    emitWORD( 0 );              /* offset */
    emitBYTE( 0 );              /* type */
    emitBYTE( 0 );
}

static void emitEXTDEF( char *func )
{
    int         len;

    emitBYTE( 0x8c );
    len = strlen( func ) + 1 + 1 + 1;
    emitWORD( len );
    emitSTRING( func );
    emitBYTE( 0 );                      /* type */
    emitBYTE( 0 );
}

static char *getThunkName( fcn *tmpf )
{
    char        *name;

    if( tmpf->thunk == 0 )  return( NULL );
    if( tmpf->is_16 ) {
        name = &tmpf->fn[3];
    } else {
        name = tmpf->fn;
    }
    return( name );
}

static int sizeofThunkName( fcn *tmpf )
{
    char        *name;

    name = getThunkName( tmpf );
    if( name == NULL )  return( 0 );
    return( strlen( name ) + 1 + 1 );
}

static void emitThunkName( fcn *tmpf )
{
    char        *name;

    emitBYTE( tmpf->thunkindex );
    name = getThunkName( tmpf );
    for(;;) {
        emitBYTE( *name );
        if( *name == '\0' ) break;
        ++name;
    }
}

static void emitSaveFPU( fcn *tmpf )
{
    if( tmpf->need_fpusave ) {
        emitBYTE( 0xFF );       /* call dword ptr [__addr] */
        emitBYTE( 0x15 );
        emitDWORD( 0 );
    }
}

static int sizeofSubParms( struct subparm *p )
{
    int         size;

    if( p == NULL ) return( 0 );
    size = 2 + 3;               // for "push count" and "add esp,nnn"
    while( p != NULL ) {
        size += 5;
        p = p->nextparm;
    }
    return( size );
}

static void emitSubParms( struct subparm *p )
{
    int         count;

    count = 0;
    while( p != NULL ) {
        count++;
        emitBYTE( 0x6a );               /* push offset */
        emitBYTE( p->offset );
        emitBYTE( 0xff );
        emitBYTE( 0x77 );
        emitBYTE( 0x10 + p->parmnum * 4 );
        p = p->nextparm;
    }
    if( count != 0 ) {
        emitBYTE( 0x6a );               /* push count */
        emitBYTE( count );
    }
}

static void cleanupSubParms( struct subparm *p )
{
    int         count;

    count = 4;
    while( p != NULL ) {
        count += 8;
        p = p->nextparm;
    }
    emitBYTE( 0x83 );   /* add esp,nnn */
    emitBYTE( 0xC4 );
    emitBYTE( count );
}

/*************************** NOTE **********************************/
/***  If you change the instructions generated by these thunks  ****/
/***  make sure DLLPATCH.ASM is modified accordingly, since it  ****/
/***  tries to locate the DLL index and DLL name at the end of  ****/
/***  the function.                                             ****/
/*******************************************************************/

static void emitnormalThunk( char *proc, fcn *tmpf, int index )
{
    int         size;
    int         segsize;
    int         subparmsize;

    size = sizeofThunkName( tmpf );
    segsize = size + 29;
    if( tmpf->need_fpusave )  segsize += 2 * 6;
    if( tmpf->returntype == RETURN_INT )  segsize += 3;
    subparmsize = sizeofSubParms( tmpf->subparms );
    segsize += subparmsize;
    if( subparmsize != 0 ) {
        subparmsize -= 3;       // adjust for relocation offsets
    }
    emitSEGDEF( segsize );
    emitPUBDEF( proc );
    emitEXTDEF( "_LocalPtr" );
    if( tmpf->returntype == RETURN_PTR ) {
        if( subparmsize == 0 ) {
            emitEXTDEF( "__WIN16THUNK3ADDR" );
        } else {
            emitEXTDEF( "__WIN16THUNK6ADDR" );
        }
    } else {
        if( subparmsize == 0 ) {
            emitEXTDEF( "__WIN16THUNK1ADDR" );
        } else {
            emitEXTDEF( "__WIN16THUNK5ADDR" );
        }
    }
    if( tmpf->need_fpusave ) {
        emitEXTDEF( "__FSTENV" );
        emitEXTDEF( "__FLDENV" );
    }

⌨️ 快捷键说明

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