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 + -
显示快捷键?