From 47497cb26a4667db874e96942d3a3af173886260 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 14 Aug 2009 13:26:09 +0200 Subject: [PATCH] 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 f9e9b1d8c7b..ad571224116 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 3f9303f5c67..78de2ac3b26 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 2b6cec7ebd8..d11bd328b2c 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) {