Alexandre Julliard : winebuild: Support for adding 32-bit exports in 16-bit spec files.

Alexandre Julliard julliard at winehq.org
Wed Dec 30 10:18:11 CST 2009


Module: wine
Branch: master
Commit: d097eef922d5c3e17fe67cce8011ebd2da955864
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d097eef922d5c3e17fe67cce8011ebd2da955864

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Dec 28 22:42:58 2009 +0100

winebuild: Support for adding 32-bit exports in 16-bit spec files.

---

 tools/winebuild/build.h  |    1 +
 tools/winebuild/parser.c |   79 +++++++++++++++++++++++++++++-----------------
 tools/winebuild/spec16.c |    3 ++
 3 files changed, 54 insertions(+), 29 deletions(-)

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index e47278a..64ad5b1 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -146,6 +146,7 @@ extern enum target_platform target_platform;
 
 #define FLAG_FORWARD   0x100  /* function is a forwarded name */
 #define FLAG_EXT_LINK  0x200  /* function links to an external symbol */
+#define FLAG_EXPORT32  0x400  /* 32-bit export in 16-bit spec file */
 
 #define FLAG_CPU(cpu)  (0x01000 << (cpu))
 #define FLAG_CPU_MASK  (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0))
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 57807ed..d08a190 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -228,25 +228,17 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
 {
     const char *token;
     unsigned int i;
+    int is_win32 = (spec->type == SPEC_WIN32) || (odp->flags & FLAG_EXPORT32);
 
-    switch(spec->type)
+    if (!is_win32 && odp->type == TYPE_STDCALL)
     {
-    case SPEC_WIN16:
-        if (odp->type == TYPE_STDCALL)
-        {
-            error( "'stdcall' not supported for Win16\n" );
-            return 0;
-        }
-        break;
-    case SPEC_WIN32:
-        if (odp->type == TYPE_PASCAL)
-        {
-            error( "'pascal' not supported for Win32\n" );
-            return 0;
-        }
-        break;
-    default:
-        break;
+        error( "'stdcall' not supported for Win16\n" );
+        return 0;
+    }
+    if (is_win32 && odp->type == TYPE_PASCAL)
+    {
+        error( "'pascal' not supported for Win32\n" );
+        return 0;
     }
 
     if (!(token = GetToken(0))) return 0;
@@ -288,7 +280,7 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
             return 0;
         }
 
-        if (spec->type == SPEC_WIN32)
+        if (is_win32)
         {
             if (strcmp(token, "long") &&
                 strcmp(token, "ptr") &&
@@ -296,7 +288,7 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
                 strcmp(token, "wstr") &&
                 strcmp(token, "double"))
             {
-                error( "Type '%s' not supported for Win32\n", token );
+                error( "Type '%s' not supported for Win32 function\n", token );
                 return 0;
             }
         }
@@ -325,7 +317,7 @@ static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
         odp->link_name = xstrdup( token );
         if (strchr( odp->link_name, '.' ))
         {
-            if (spec->type == SPEC_WIN16)
+            if (!is_win32)
             {
                 error( "Forwarded functions not supported for Win16\n" );
                 return 0;
@@ -421,7 +413,7 @@ static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
  *
  * Parse the optional flags for an entry point in a .spec file.
  */
-static const char *parse_spec_flags( ORDDEF *odp )
+static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp )
 {
     unsigned int i;
     const char *token;
@@ -436,7 +428,12 @@ static const char *parse_spec_flags( ORDDEF *odp )
             while (cpu_name)
             {
                 if (!strcmp( cpu_name, "win32" ))
-                    odp->flags |= FLAG_CPU_WIN32;
+                {
+                    if (spec->type == SPEC_WIN32)
+                        odp->flags |= FLAG_CPU_WIN32;
+                    else
+                        odp->flags |= FLAG_EXPORT32;
+                }
                 else if (!strcmp( cpu_name, "win64" ))
                     odp->flags |= FLAG_CPU_WIN64;
                 else
@@ -499,7 +496,13 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
     }
 
     if (!(token = GetToken(0))) goto error;
-    if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error;
+    if (*token == '-' && !(token = parse_spec_flags( spec, odp ))) goto error;
+
+    if (ordinal == -1 && spec->type != SPEC_WIN32 && !(odp->flags & FLAG_EXPORT32))
+    {
+        error( "'@' ordinals not supported for Win16\n" );
+        goto error;
+    }
 
     odp->name = xstrdup( token );
     odp->lineno = current_line;
@@ -650,7 +653,8 @@ static void assign_names( DLLSPEC *spec )
     {
         const char *name1 = all_names[i]->name ? all_names[i]->name : all_names[i]->export_name;
         const char *name2 = all_names[i+1]->name ? all_names[i+1]->name : all_names[i+1]->export_name;
-        if (!strcmp( name1, name2 ))
+        if (!strcmp( name1, name2 ) &&
+            !((all_names[i]->flags ^ all_names[i+1]->flags) & FLAG_EXPORT32))
         {
             current_line = max( all_names[i]->lineno, all_names[i+1]->lineno );
             error( "'%s' redefined\n%s:%d: First defined here\n",
@@ -737,12 +741,14 @@ static void assign_ordinals( DLLSPEC *spec )
  */
 void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
 {
+    int i;
     ORDDEF *odp;
 
     /* add an export for the NE module */
 
     odp = add_entry_point( spec32 );
     odp->type = TYPE_EXTERN;
+    odp->flags = FLAG_PRIVATE;
     odp->name = xstrdup( "__wine_spec_dos_header" );
     odp->lineno = 0;
     odp->ordinal = 1;
@@ -752,12 +758,32 @@ void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 )
     {
         odp = add_entry_point( spec32 );
         odp->type = TYPE_EXTERN;
+        odp->flags = FLAG_PRIVATE;
         odp->name = xstrdup( "__wine_spec_main_module" );
         odp->lineno = 0;
         odp->ordinal = 2;
         odp->link_name = xstrdup( ".L__wine_spec_main_module" );
     }
 
+    /* add the explicit win32 exports */
+
+    for (i = 1; i <= spec16->limit; i++)
+    {
+        ORDDEF *odp16 = spec16->ordinals[i];
+
+        if (!odp16 || !odp16->name) continue;
+        if (!(odp16->flags & FLAG_EXPORT32)) continue;
+
+        odp = add_entry_point( spec32 );
+        odp->flags = odp16->flags & ~FLAG_EXPORT32;
+        odp->type = odp16->type;
+        odp->name = xstrdup( odp16->name );
+        odp->lineno = odp16->lineno;
+        odp->ordinal = -1;
+        odp->link_name = xstrdup( odp16->link_name );
+        strcpy( odp->u.func.arg_types, odp16->u.func.arg_types );
+    }
+
     assign_names( spec32 );
     assign_ordinals( spec32 );
 }
@@ -783,11 +809,6 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
         if (!(token = GetToken(1))) continue;
         if (strcmp(token, "@") == 0)
         {
-            if (spec->type != SPEC_WIN32)
-            {
-                error( "'@' ordinals not supported for Win16\n" );
-                continue;
-            }
             if (!parse_spec_ordinal( -1, spec )) continue;
         }
         else if (IsNumberString(token))
diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c
index a0a962f..93c0822 100644
--- a/tools/winebuild/spec16.c
+++ b/tools/winebuild/spec16.c
@@ -57,6 +57,7 @@ static const char * const nop_sequence[4] =
 
 static inline int is_function( const ORDDEF *odp )
 {
+    if (odp->flags & FLAG_EXPORT32) return 0;
     return (odp->type == TYPE_CDECL ||
             odp->type == TYPE_PASCAL ||
             odp->type == TYPE_VARARGS ||
@@ -130,6 +131,7 @@ static void output_entry_table( DLLSPEC *spec )
         int selector = 0;
         ORDDEF *odp = spec->ordinals[i];
         if (!odp) continue;
+        if (odp->flags & FLAG_EXPORT32) continue;
 
         switch (odp->type)
         {
@@ -704,6 +706,7 @@ static void output_module16( DLLSPEC *spec )
     {
         ORDDEF *odp = spec->ordinals[i];
         if (!odp || !odp->name[0]) continue;
+        if (odp->flags & FLAG_EXPORT32) continue;
         output_resident_name( odp->name, i );
     }
     output( "\t.byte 0\n" );




More information about the wine-cvs mailing list