Alexandre Julliard : winebuild: Add helper functions for writing binary data to a file.

Alexandre Julliard julliard at winehq.org
Fri Aug 14 09:01:01 CDT 2009


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Aug 14 13:26:09 2009 +0200

winebuild: Add helper functions for writing binary data to a file.

---

 tools/winebuild/build.h |   12 +++++++
 tools/winebuild/res32.c |   63 +++++++----------------------------
 tools/winebuild/utils.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 50 deletions(-)

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index f9e9b1d..ad57122 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -270,11 +270,23 @@ extern const char *input_buffer_filename;
 extern const unsigned char *input_buffer;
 extern size_t input_buffer_pos;
 extern size_t input_buffer_size;
+extern unsigned char *output_buffer;
+extern size_t output_buffer_pos;
+extern size_t output_buffer_size;
 
 extern void init_input_buffer( const char *file );
+extern void init_output_buffer(void);
+extern void flush_output_buffer(void);
 extern unsigned char get_byte(void);
 extern unsigned short get_word(void);
 extern unsigned int get_dword(void);
+extern void put_data( const void *data, size_t size );
+extern void put_byte( unsigned char val );
+extern void put_word( unsigned short val );
+extern void put_dword( unsigned int val );
+extern void put_qword( unsigned int val );
+extern void put_pword( unsigned int val );
+extern void align_output( unsigned int align );
 
 /* global variables */
 
diff --git a/tools/winebuild/res32.c b/tools/winebuild/res32.c
index 3f9303f..78de2ac 100644
--- a/tools/winebuild/res32.c
+++ b/tools/winebuild/res32.c
@@ -80,9 +80,6 @@ struct res_tree
     unsigned int     nb_types;             /* total number of types */
 };
 
-static unsigned char *file_out_pos;   /* current position in output resource file */
-static unsigned char *file_out_end;   /* end of output buffer */
-
 /* size of a resource directory with n entries */
 #define RESOURCE_DIR_SIZE        (4 * sizeof(unsigned int))
 #define RESOURCE_DIR_ENTRY_SIZE  (2 * sizeof(unsigned int))
@@ -152,25 +149,6 @@ static void get_string( struct string_id *str )
     }
 }
 
-/* put a word into the resource file */
-static void put_word( unsigned short val )
-{
-    if (byte_swapped) val = (val << 8) | (val >> 8);
-    *(unsigned short *)file_out_pos = val;
-    file_out_pos += sizeof(unsigned short);
-    assert( file_out_pos <= file_out_end );
-}
-
-/* put a dword into the resource file */
-static void put_dword( unsigned int val )
-{
-    if (byte_swapped)
-        val = ((val << 24) | ((val << 8) & 0x00ff0000) | ((val >> 8) & 0x0000ff00) | (val >> 24));
-    *(unsigned int *)file_out_pos = val;
-    file_out_pos += sizeof(unsigned int);
-    assert( file_out_pos <= file_out_end );
-}
-
 /* put a string into the resource file */
 static void put_string( const struct string_id *str )
 {
@@ -516,26 +494,15 @@ static unsigned int get_resource_header_size( const struct resource *res )
 /* output the resources into a .o file */
 void output_res_o_file( DLLSPEC *spec )
 {
-    unsigned int i, total_size;
-    unsigned char *data;
+    unsigned int i;
     char *res_file = NULL;
     int fd, err;
 
     if (!spec->nb_resources) fatal_error( "--resources mode needs at least one resource file as input\n" );
     if (!output_file_name) fatal_error( "No output file name specified\n" );
 
-    total_size = 32;  /* header */
-
-    for (i = 0; i < spec->nb_resources; i++)
-    {
-        total_size += (get_resource_header_size( &spec->resources[i] ) + 3) & ~3;
-        total_size += (spec->resources[i].data_size + 3) & ~3;
-    }
-    data = xmalloc( total_size );
-
     byte_swapped = 0;
-    file_out_pos = data;
-    file_out_end = data + total_size;
+    init_output_buffer();
 
     put_dword( 0 );      /* ResSize */
     put_dword( 32 );     /* HeaderSize */
@@ -557,34 +524,30 @@ void output_res_o_file( DLLSPEC *spec )
         put_dword( (header_size + 3) & ~3 );
         put_string( &spec->resources[i].type );
         put_string( &spec->resources[i].name );
-        if ((unsigned long)file_out_pos & 2) put_word( 0 );
+        align_output( 4 );
         put_dword( 0 );
         put_word( spec->resources[i].mem_options );
         put_word( spec->resources[i].lang );
         put_dword( 0 );
         put_dword( 0 );
-        memcpy( file_out_pos, spec->resources[i].data, spec->resources[i].data_size );
-        file_out_pos += spec->resources[i].data_size;
-        while ((unsigned long)file_out_pos & 3) *file_out_pos++ = 0;
+        put_data( spec->resources[i].data, spec->resources[i].data_size );
+        align_output( 4 );
     }
-    assert( file_out_pos == file_out_end );
 
     /* if the output file name is a .res too, don't run the results through windres */
     if (strendswith( output_file_name, ".res"))
     {
-        if ((fd = open( output_file_name, O_WRONLY|O_CREAT|O_TRUNC, 0666 )) == -1)
-            fatal_error( "Cannot create %s\n", output_file_name );
+        flush_output_buffer();
+        return;
     }
-    else
-    {
-        res_file = get_temp_file_name( output_file_name, ".res" );
-        if ((fd = open( res_file, O_WRONLY|O_CREAT|O_TRUNC, 0600 )) == -1)
-            fatal_error( "Cannot create %s\n", res_file );
-    }
-    if (write( fd, data, total_size ) != total_size)
+
+    res_file = get_temp_file_name( output_file_name, ".res" );
+    if ((fd = open( res_file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600 )) == -1)
+        fatal_error( "Cannot create %s\n", res_file );
+    if (write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos)
         fatal_error( "Error writing to %s\n", res_file );
     close( fd );
-    free( data );
+    free( output_buffer );
 
     if (res_file)
     {
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 2b6cec7..d11bd32 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -387,6 +387,18 @@ const char *input_buffer_filename;
 const unsigned char *input_buffer;
 size_t input_buffer_pos;
 size_t input_buffer_size;
+unsigned char *output_buffer;
+size_t output_buffer_pos;
+size_t output_buffer_size;
+
+static void check_output_buffer_space( size_t size )
+{
+    if (output_buffer_pos + size >= output_buffer_size)
+    {
+        output_buffer_size = max( output_buffer_size * 2, output_buffer_pos + size );
+        output_buffer = xrealloc( output_buffer, output_buffer_size );
+    }
+}
 
 void init_input_buffer( const char *file )
 {
@@ -411,6 +423,20 @@ void init_input_buffer( const char *file )
     byte_swapped = 0;
 }
 
+void init_output_buffer(void)
+{
+    output_buffer_size = 1024;
+    output_buffer_pos = 0;
+    output_buffer = xmalloc( output_buffer_size );
+}
+
+void flush_output_buffer(void)
+{
+    if (fwrite( output_buffer, 1, output_buffer_pos, output_file ) != output_buffer_pos)
+        fatal_error( "Error writing to %s\n", output_file_name );
+    free( output_buffer );
+}
+
 unsigned char get_byte(void)
 {
     if (input_buffer_pos >= input_buffer_size)
@@ -443,6 +469,63 @@ unsigned int get_dword(void)
     return ret;
 }
 
+void put_data( const void *data, size_t size )
+{
+    check_output_buffer_space( size );
+    memcpy( output_buffer + output_buffer_pos, data, size );
+    output_buffer_pos += size;
+}
+
+void put_byte( unsigned char val )
+{
+    check_output_buffer_space( 1 );
+    output_buffer[output_buffer_pos++] = val;
+}
+
+void put_word( unsigned short val )
+{
+    if (byte_swapped) val = (val << 8) | (val >> 8);
+    put_data( &val, sizeof(val) );
+}
+
+void put_dword( unsigned int val )
+{
+    if (byte_swapped)
+        val = ((val << 24) | ((val << 8) & 0x00ff0000) | ((val >> 8) & 0x0000ff00) | (val >> 24));
+    put_data( &val, sizeof(val) );
+}
+
+void put_qword( unsigned int val )
+{
+    if (byte_swapped)
+    {
+        put_dword( 0 );
+        put_dword( val );
+    }
+    else
+    {
+        put_dword( val );
+        put_dword( 0 );
+    }
+}
+
+/* pointer-sized word */
+void put_pword( unsigned int val )
+{
+    if (get_ptr_size() == 8) put_qword( val );
+    else put_dword( val );
+}
+
+void align_output( unsigned int align )
+{
+    size_t size = align - (output_buffer_pos % align);
+
+    if (size == align) return;
+    check_output_buffer_space( size );
+    memset( output_buffer + output_buffer_pos, 0, size );
+    output_buffer_pos += size;
+}
+
 /* output a standard header for generated files */
 void output_standard_file_header(void)
 {




More information about the wine-cvs mailing list