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