Commit 617839d5 authored by Alexandre Julliard's avatar Alexandre Julliard

Added varargs support for 16-bit entry points.

Added -ret16 entry point flag to allow 16-bit cdecl and varargs function to return 16-bit values too.
parent 4ff79add
......@@ -347,26 +347,19 @@ BOOL WINAPI IsDebuggerPresent(void)
/***********************************************************************
* _DebugOutput (KERNEL.328)
*/
void WINAPIV _DebugOutput( void )
void WINAPIV _DebugOutput( WORD flags, LPCSTR spec, VA_LIST16 valist )
{
VA_LIST16 valist;
WORD flags;
SEGPTR spec;
char caller[101];
/* Decode caller address */
if (!GetModuleName16( GetExePtr(CURRENT_STACK16->cs), caller, sizeof(caller) ))
sprintf( caller, "%04X:%04X", CURRENT_STACK16->cs, CURRENT_STACK16->ip );
/* Build debug message string */
VA_START16( valist );
flags = VA_ARG16( valist, WORD );
spec = VA_ARG16( valist, SEGPTR );
/* FIXME: cannot use wvsnprintf16 from kernel */
/* wvsnprintf16( temp, sizeof(temp), MapSL(spec), valist ); */
/* wvsnprintf16( temp, sizeof(temp), spec, valist ); */
/* Output */
FIXME("%s %04x %s\n", caller, flags, debugstr_a(MapSL(spec)) );
FIXME("%s %04x %s\n", caller, flags, debugstr_a(spec) );
}
/***********************************************************************
......
......@@ -267,7 +267,7 @@
325 pascal16 LogParamError(word ptr ptr) LogParamError16
326 pascal16 IsRomFile(word) IsRomFile16
327 pascal -register K327() HandleParamError
328 pascal16 _DebugOutput() _DebugOutput
328 varargs -ret16 _DebugOutput(word str) _DebugOutput
329 pascal16 K329(str word) DebugFillBuffer
332 variable THHOOK(0 0 0 0 0 0 0 0)
334 pascal16 IsBadReadPtr(segptr word) IsBadReadPtr16
......
......@@ -194,7 +194,7 @@ void RELAY_DebugCallFrom16( CONTEXT86 *context )
if (!call) return; /* happens for the two snoop register relays */
if (!RELAY_ShowDebugmsgRelay(funstr)) return;
DPRINTF( "%04lx:Call %s(",GetCurrentThreadId(),funstr);
VA_START16( args16 );
args16 = (char *)(frame + 1);
if (call->lret == 0xcb66) /* cdecl */
{
......@@ -276,7 +276,6 @@ void RELAY_DebugCallFrom16( CONTEXT86 *context )
}
DPRINTF( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
VA_END16( args16 );
if (call->arg_types[0] & ARG_REGISTER)
DPRINTF(" AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
......
......@@ -45,7 +45,7 @@
204 pascal ICClose(word) ICClose16
205 pascal ICSendMessage(word word long long) ICSendMessage16
206 pascal16 ICOpenFunction(long long word segptr) ICOpenFunction16
207 pascal _ICMessage() ICMessage16
207 varargs _ICMessage(word word word) ICMessage16
212 pascal ICGetInfo(word segptr long) ICGetInfo16
213 pascal16 ICLocate(long long ptr ptr word) ICLocate16
224 cdecl _ICCompress(word long segptr segptr segptr segptr segptr segptr long long long segptr segptr) ICCompress16
......
......@@ -25,8 +25,8 @@
#include "msvideo_private.h"
#include "winver.h"
#include "winnls.h"
#include "vfw16.h"
#include "stackframe.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
......@@ -139,23 +139,13 @@ LRESULT WINAPI ICClose16(HIC16 hic)
/***********************************************************************
* _ICMessage [MSVIDEO.207]
*/
LRESULT VFWAPIV ICMessage16(void)
LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist )
{
HIC16 hic;
UINT16 msg;
UINT16 cb;
LPWORD lpData;
SEGPTR segData;
LRESULT ret;
UINT16 i;
VA_LIST16 valist;
VA_START16(valist);
hic = VA_ARG16(valist, HIC16);
msg = VA_ARG16(valist, UINT16);
cb = VA_ARG16(valist, UINT16);
lpData = HeapAlloc(GetProcessHeap(), 0, cb);
TRACE("0x%08lx, %u, %u, ...)\n", (DWORD) hic, msg, cb);
......@@ -165,7 +155,6 @@ LRESULT VFWAPIV ICMessage16(void)
lpData[i] = VA_ARG16(valist, WORD);
}
VA_END16(valist);
segData = MapLS(lpData);
ret = ICSendMessage16(hic, msg, segData, (DWORD) cb);
UnMapLS(segData);
......
......@@ -113,7 +113,7 @@ LRESULT VFWAPI ICGetInfo16(HIC16,ICINFO16 *,DWORD);
BOOL16 VFWAPI ICInfo16(DWORD,DWORD,ICINFO16 *);
HIC16 VFWAPI ICLocate16(DWORD,DWORD,LPBITMAPINFOHEADER,
LPBITMAPINFOHEADER,WORD);
LRESULT VFWAPIV ICMessage16(void);
LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist );
HIC16 VFWAPI ICOpen16(DWORD,DWORD,UINT16);
HIC16 VFWAPI ICOpenFunction16(DWORD,DWORD,UINT16,FARPROC16);
LRESULT VFWAPI ICSendMessage16(HIC16,UINT16,DWORD,DWORD);
......
......@@ -387,7 +387,7 @@
416 pascal16 TrackPopupMenu(word word s_word s_word s_word word ptr) TrackPopupMenu16
417 pascal GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
418 pascal16 SetMenuItemBitmaps(word word word word word) SetMenuItemBitmaps16
420 pascal16 _wsprintf() wsprintf16
420 varargs -ret16 _wsprintf(ptr str) wsprintf16
421 pascal16 wvsprintf(ptr str ptr) wvsprintf16
422 pascal16 DlgDirSelectEx(word ptr word word) DlgDirSelectEx16
423 pascal16 DlgDirSelectComboBoxEx(word ptr word word) DlgDirSelectComboBoxEx16
......
......@@ -32,7 +32,6 @@
#include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "stackframe.h"
#include "wine/debug.h"
......@@ -284,8 +283,7 @@ static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
/***********************************************************************
* wvsnprintf16 (Not a Windows API)
*/
static INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec,
LPCVOID args )
static INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec, VA_LIST16 args )
{
WPRINTF_FORMAT format;
LPSTR p = buffer;
......@@ -592,7 +590,7 @@ static INT wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args )
/***********************************************************************
* wvsprintf (USER.421)
*/
INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, LPCVOID args )
INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 args )
{
INT16 res;
......@@ -625,17 +623,11 @@ INT WINAPI wvsprintfW( LPWSTR buffer, LPCWSTR spec, va_list args )
/***********************************************************************
* _wsprintf (USER.420)
*/
INT16 WINAPIV wsprintf16(void)
INT16 WINAPIV wsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 valist )
{
VA_LIST16 valist;
INT16 res;
SEGPTR buffer, spec;
VA_START16( valist );
buffer = VA_ARG16( valist, SEGPTR );
spec = VA_ARG16( valist, SEGPTR );
res = wvsnprintf16( MapSL(buffer), 1024, MapSL(spec), valist );
VA_END16( valist );
res = wvsnprintf16( buffer, 1024, spec, valist );
return ( res == -1 ) ? 1024 : res;
}
......
......@@ -73,15 +73,7 @@ typedef struct _STACK16FRAME
#define CURRENT_DS (CURRENT_STACK16->ds)
/* varargs lists on the 16-bit stack */
typedef void *VA_LIST16;
#define __VA_ROUNDED16(type) \
((sizeof(type) + sizeof(WORD) - 1) / sizeof(WORD) * sizeof(WORD))
#define VA_START16(list) ((list) = (VA_LIST16)(CURRENT_STACK16 + 1))
#define VA_ARG16(list,type) \
(((list) = (VA_LIST16)((char *)(list) + __VA_ROUNDED16(type))), \
*((type *)(void *)((char *)(list) - __VA_ROUNDED16(type))))
#define VA_END16(list) ((void)0)
......
......@@ -39,6 +39,14 @@ typedef UINT16 *LPUINT16;
#define MAKESEGPTR(seg,off) ((SEGPTR)MAKELONG(off,seg))
typedef WORD *VA_LIST16;
#define __VA_ROUNDED16(type) \
((sizeof(type) + sizeof(WORD) - 1) / sizeof(WORD) * sizeof(WORD))
#define VA_ARG16(list,type) \
(((list) = (VA_LIST16)((char *)(list) + __VA_ROUNDED16(type))), \
*((type *)(void *)((char *)(list) - __VA_ROUNDED16(type))))
#define HFILE_ERROR16 ((HFILE16)-1)
#define DECLARE_HANDLE16(a) \
......
......@@ -937,7 +937,7 @@ HWND16 WINAPI WindowFromDC16(HDC16);
HWND16 WINAPI WindowFromPoint16(POINT16);
BOOL16 WINAPI WinHelp16(HWND16,LPCSTR,UINT16,DWORD);
UINT16 WINAPI WNetAddConnection16(LPCSTR,LPCSTR,LPCSTR);
INT16 WINAPI wvsprintf16(LPSTR,LPCSTR,LPCVOID);
INT16 WINAPI wvsprintf16(LPSTR,LPCSTR,VA_LIST16);
BOOL16 WINAPI DrawState16A(HDC16,HBRUSH16,DRAWSTATEPROC16,LPARAM,WPARAM16,INT16,INT16,INT16,INT16,UINT16);
BOOL16 WINAPI IsDialogMessage16(HWND16,MSG16*);
INT16 WINAPI GetCommError16(INT16,LPCOMSTAT16);
......
......@@ -34,8 +34,7 @@
typedef enum
{
TYPE_VARIABLE, /* variable */
TYPE_PASCAL_16, /* pascal function with 16-bit return (Win16) */
TYPE_PASCAL, /* pascal function with 32-bit return (Win16) */
TYPE_PASCAL, /* pascal function (Win16) */
TYPE_ABS, /* absolute value (Win16) */
TYPE_STUB, /* unimplemented stub */
TYPE_STDCALL, /* stdcall function (Win32) */
......@@ -98,11 +97,12 @@ typedef struct
/* entry point flags */
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
#define FLAG_NONAME 0x02 /* don't import function by name */
#define FLAG_RET64 0x04 /* function returns a 64-bit value */
#define FLAG_I386 0x08 /* function is i386 only */
#define FLAG_REGISTER 0x10 /* use register calling convention */
#define FLAG_INTERRUPT 0x20 /* function is an interrupt handler */
#define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */
#define FLAG_RET16 0x04 /* function returns a 16-bit value */
#define FLAG_RET64 0x08 /* function returns a 64-bit value */
#define FLAG_I386 0x10 /* function is i386 only */
#define FLAG_REGISTER 0x20 /* use register calling convention */
#define FLAG_INTERRUPT 0x40 /* function is an interrupt handler */
#define FLAG_PRIVATE 0x80 /* function is private (cannot be imported) */
#define FLAG_FORWARD 0x100 /* function is a forwarded name */
......
......@@ -44,7 +44,6 @@ static FILE *input_file;
static const char * const TypeNames[TYPE_NBTYPES] =
{
"variable", /* TYPE_VARIABLE */
"pascal16", /* TYPE_PASCAL_16 */
"pascal", /* TYPE_PASCAL */
"equate", /* TYPE_ABS */
"stub", /* TYPE_STUB */
......@@ -58,6 +57,7 @@ static const char * const FlagNames[] =
{
"norelay", /* FLAG_NORELAY */
"noname", /* FLAG_NONAME */
"ret16", /* FLAG_RET16 */
"ret64", /* FLAG_RET64 */
"i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */
......@@ -212,14 +212,9 @@ static int ParseExportFunction( ORDDEF *odp )
error( "'stdcall' not supported for Win16\n" );
return 0;
}
if (odp->type == TYPE_VARARGS)
{
error( "'varargs' not supported for Win16\n" );
return 0;
}
break;
case SPEC_WIN32:
if ((odp->type == TYPE_PASCAL) || (odp->type == TYPE_PASCAL_16))
if (odp->type == TYPE_PASCAL)
{
error( "'pascal' not supported for Win32\n" );
return 0;
......@@ -456,8 +451,17 @@ static int ParseOrdinal(int ordinal)
if (odp->type >= TYPE_NBTYPES)
{
error( "Expected type after ordinal, found '%s' instead\n", token );
goto error;
/* special case for backwards compatibility */
if (!strcmp( token, "pascal16" ))
{
odp->type = TYPE_PASCAL;
odp->flags |= FLAG_RET16;
}
else
{
error( "Expected type after ordinal, found '%s' instead\n", token );
goto error;
}
}
if (!(token = GetToken(0))) goto error;
......@@ -473,7 +477,6 @@ static int ParseOrdinal(int ordinal)
case TYPE_VARIABLE:
if (!ParseVariable( odp )) goto error;
break;
case TYPE_PASCAL_16:
case TYPE_PASCAL:
case TYPE_STDCALL:
case TYPE_VARARGS:
......
......@@ -250,7 +250,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
{
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_VARARGS:
case TYPE_STUB:
selector = 1; /* Code selector */
break;
......@@ -344,12 +344,14 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
int short_ret = 0;
int reg_func = 0;
int usecdecl = 0;
int varargs = 0;
const char *args = profile + 7;
char *ret_type;
/* Parse function type */
if (!strncmp( "c_", profile, 2 )) usecdecl = 1;
else if (!strncmp( "v_", profile, 2 )) varargs = usecdecl = 1;
else if (strncmp( "p_", profile, 2 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
......@@ -382,7 +384,8 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
ret_type = reg_func? "void" : short_ret ? "unsigned short" : "unsigned int";
fprintf( outfile, "typedef %s (__stdcall *proc_%s_t)( ", ret_type, profile );
fprintf( outfile, "typedef %s (%s*proc_%s_t)( ",
ret_type, usecdecl ? "" : "__stdcall ", profile );
args = profile + 7;
for ( i = 0; args[i]; i++ )
{
......@@ -395,7 +398,7 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
case 'p': case 't': fprintf( outfile, "void *" ); break;
}
}
if ( reg_func )
if (reg_func || varargs)
fprintf( outfile, "%svoid *", i? ", " : "" );
else if ( !i )
fprintf( outfile, "void" );
......@@ -447,6 +450,8 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char
}
if ( reg_func )
fprintf( outfile, "%s context", i? ",\n" : "" );
else if (varargs)
fprintf( outfile, "%s args + %d", i? ",\n" : "", argsize );
fprintf( outfile, " );\n}\n\n" );
}
......@@ -459,10 +464,11 @@ static const char *get_function_name( const ORDDEF *odp )
static char buffer[80];
sprintf( buffer, "%s_%s_%s",
(odp->type == TYPE_CDECL) ? "c" : "p",
(odp->type == TYPE_PASCAL) ? "p" :
(odp->type == TYPE_VARARGS) ? "v" : "c",
(odp->flags & FLAG_REGISTER) ? "regs" :
(odp->flags & FLAG_INTERRUPT) ? "intr" :
(odp->type == TYPE_PASCAL_16) ? "word" : "long",
(odp->flags & FLAG_RET16) ? "word" : "long",
odp->u.func.arg_types );
return buffer;
}
......@@ -476,23 +482,20 @@ static int Spec16TypeCompare( const void *e1, const void *e2 )
const ORDDEF *odp1 = *(const ORDDEF **)e1;
const ORDDEF *odp2 = *(const ORDDEF **)e2;
int retval;
int type1 = odp1->type;
int type2 = odp2->type;
int type1 = (odp1->type == TYPE_CDECL) ? 0
: (odp1->type == TYPE_PASCAL_16) ? 1 : 2;
if (type1 == TYPE_STUB) type1 = TYPE_CDECL;
if (type2 == TYPE_STUB) type2 = TYPE_CDECL;
int type2 = (odp2->type == TYPE_CDECL) ? 0
: (odp2->type == TYPE_PASCAL_16) ? 1 : 2;
if ((retval = type1 - type2) != 0) return retval;
if (odp1->flags & FLAG_REGISTER) type1 += 4;
if (odp1->flags & FLAG_INTERRUPT) type1 += 8;
if (odp2->flags & FLAG_REGISTER) type2 += 4;
if (odp2->flags & FLAG_INTERRUPT) type2 += 8;
type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
retval = type1 - type2;
if ( !retval )
retval = strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
if ((retval = type1 - type2) != 0) return retval;
return retval;
return strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
}
......@@ -598,7 +601,7 @@ void BuildSpec16File( FILE *outfile )
{
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_VARARGS:
case TYPE_STUB:
typelist[nFuncs++] = odp;
......@@ -638,7 +641,7 @@ void BuildSpec16File( FILE *outfile )
{
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_VARARGS:
fprintf( outfile, "extern void %s();\n", odp->link_name );
break;
default:
......@@ -682,7 +685,7 @@ void BuildSpec16File( FILE *outfile )
int j, argsize = 0;
strcpy( profile, get_function_name( typelist[i] ));
if ( typelist[i]->type != TYPE_CDECL )
if ( typelist[i]->type == TYPE_PASCAL )
for ( arg = typelist[i]->u.func.arg_types; *arg; arg++ )
switch ( *arg )
{
......@@ -717,13 +720,13 @@ void BuildSpec16File( FILE *outfile )
arg_types[j / 10] |= type << (3 * (j % 10));
}
if (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) arg_types[0] |= ARG_REGISTER;
if (typelist[i]->type == TYPE_PASCAL_16) arg_types[0] |= ARG_RET16;
if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
#ifdef __i386__
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
make_c_identifier(dll_file_name), profile,
(typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs":
typelist[i]->type == TYPE_PASCAL_16? "word" : "long" );
(typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
if (argsize)
fprintf( outfile, " 0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n",
code_selector, argsize, arg_types[0], arg_types[1] );
......@@ -759,7 +762,7 @@ void BuildSpec16File( FILE *outfile )
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_VARARGS:
case TYPE_STUB:
type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
assert( type );
......
......@@ -225,6 +225,9 @@ only).
.B -noname
The entry point will be imported by ordinal instead of by name.
.TP
.B -ret16
The function returns a 16-bit value (Win16 only).
.TP
.B -ret64
The function returns a 64-bit value (Win32 only).
.TP
......@@ -261,17 +264,21 @@ should be one of:
.B stdcall
for a normal Win32 function
.TP
.B pascal
for a normal Win16 function
.TP
.B cdecl
for a Win32 function using the C calling convention
for a Win16 or Win32 function using the C calling convention
.TP
.B varargs
for a Win32 function taking a variable number of arguments
.TP
.B pascal
for a Win16 function returning a 32-bit value
for a Win16 or Win32 function using the C calling convention with a
variable number of arguments
.TP
.B pascal16
for a Win16 function returning a 16-bit value.
for a Win16 function returning a 16-bit value; this type is
deprecated, use
.B pascal -ret16
instead
.RE
.PP
.I args
......@@ -331,13 +338,13 @@ shows how long lines can be split using a backslash:
100 pascal CreateWindow(ptr ptr long s_word s_word s_word \\
s_word word word word ptr) WIN_CreateWindow
.PP
To declare a function using a variable number of arguments in Win16,
specify the function as taking no arguments. The arguments are then
available with CURRENT_STACK16->args. In Win32, specify the function
as
To declare a function using a variable number of arguments, specify
the function as
.B varargs
and declare it with a '...' parameter in the C file. See the
wsprintf* functions in user.exe.spec and user32.spec for an example.
and declare it in the C file with a '...' parameter for a Win32
function, or with an extra VA_LIST16 argument for a Win16 function.
See the wsprintf* functions in user.exe.spec and user32.spec for an
example.
.SS "Variable ordinals"
Syntax:
.br
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment