wmc: Add support for creating resource and plain binary files.

This commit is contained in:
Alexandre Julliard 2011-01-18 16:55:37 +01:00
parent e72e7de0e5
commit ecd144b40d
6 changed files with 243 additions and 18 deletions

View File

@ -243,3 +243,76 @@ int unistrcmp(const WCHAR *s1, const WCHAR *s2)
return *s1 - *s2; return *s1 - *s2;
} }
/*******************************************************************
* buffer management
*
* Function for writing to a memory buffer.
*/
int byte_swapped = 0;
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_output_buffer(void)
{
output_buffer_size = 1024;
output_buffer_pos = 0;
output_buffer = xmalloc( output_buffer_size );
}
void flush_output_buffer( const char *name )
{
int fd = open( name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666 );
if (fd == -1) error( "Error creating %s\n", name );
if (write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos)
error( "Error writing to %s\n", name );
close( fd );
free( output_buffer );
}
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 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;
}

View File

@ -48,4 +48,19 @@ int unistrlen(const WCHAR *s);
int unistricmp(const WCHAR *s1, const WCHAR *s2); int unistricmp(const WCHAR *s1, const WCHAR *s2);
int unistrcmp(const WCHAR *s1, const WCHAR *s2); int unistrcmp(const WCHAR *s1, const WCHAR *s2);
/* buffer management */
extern int byte_swapped;
extern unsigned char *output_buffer;
extern size_t output_buffer_pos;
extern size_t output_buffer_size;
extern void init_output_buffer(void);
extern void flush_output_buffer( const char *name );
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 align_output( unsigned int align );
#endif #endif

View File

@ -48,6 +48,7 @@ static const char usage[] =
" -H file Write headerfile to file (default is inputfile.h)\n" " -H file Write headerfile to file (default is inputfile.h)\n"
" -i Inline messagetable(s)\n" " -i Inline messagetable(s)\n"
" -o file Output to file (default is inputfile.rc)\n" " -o file Output to file (default is inputfile.rc)\n"
" -O fmt Set output format (rc, res)\n"
" -u Inputfile is in unicode\n" " -u Inputfile is in unicode\n"
" -U Output unicode messagetable(s)\n" " -U Output unicode messagetable(s)\n"
" -v Show supported codepages and languages\n" " -v Show supported codepages and languages\n"
@ -117,6 +118,12 @@ int mcy_debug;
FILE *yyin; FILE *yyin;
static enum
{
FORMAT_RC,
FORMAT_RES
} output_format;
int getopt (int argc, char *const *argv, const char *optstring); int getopt (int argc, char *const *argv, const char *optstring);
static void segvhandler(int sig); static void segvhandler(int sig);
@ -165,7 +172,7 @@ int main(int argc,char *argv[])
strcat(cmdline, " "); strcat(cmdline, " ");
} }
while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF) while((optc = getopt(argc, argv, "B:cdDhH:io:O:p:uUvVW")) != EOF)
{ {
switch(optc) switch(optc)
{ {
@ -211,6 +218,15 @@ int main(int argc,char *argv[])
case 'o': case 'o':
output_name = xstrdup(optarg); output_name = xstrdup(optarg);
break; break;
case 'O':
if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC;
else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES;
else
{
fprintf(stderr, "Output format must be rc or res\n" );
lose++;
}
break;
case 'u': case 'u':
unicodein = 1; unicodein = 1;
break; break;
@ -286,10 +302,24 @@ int main(int argc,char *argv[])
exit(1); exit(1);
} }
write_h_file(header_name); #ifdef WORDS_BIGENDIAN
write_rc_file(output_name); byte_swapped = (byteorder == WMC_BO_LITTLE);
if(!rcinline) #else
byte_swapped = (byteorder == WMC_BO_BIG);
#endif
switch (output_format)
{
case FORMAT_RC:
write_h_file(header_name);
write_rc_file(output_name);
if(!rcinline)
write_bin_files(); write_bin_files();
break;
case FORMAT_RES:
write_res_file( output_name );
break;
}
output_name = NULL; output_name = NULL;
header_name = NULL; header_name = NULL;
return 0; return 0;

View File

@ -22,45 +22,49 @@ with \fI-o\fR, then \fBwmc\fR will write the output to \fBinputfile.{rc,h}\fR.
The outputfile is named \fBwmc.tab.{rc,h}\fR if no inputfile was given. The outputfile is named \fBwmc.tab.{rc,h}\fR if no inputfile was given.
.SH OPTIONS .SH OPTIONS
.TP .TP
.I \-B x .BI \-B\ x
Set output byte-order x={n[ative], l[ittle], b[ig]}. Default is n[ative]. Set output byte-order x={n[ative], l[ittle], b[ig]}. Default is n[ative].
.TP .TP
.I \-c .B \-c
Set 'custom-bit' in message-code values. Set 'custom-bit' in message-code values.
.TP .TP
.I \-d .B \-d
NON-FUNCTIONAL; Use decimal values in output NON-FUNCTIONAL; Use decimal values in output
.TP .TP
.I \-D .B \-D
Set debug flag. This results is a parser trace and a lot of extra messages. Set debug flag. This results is a parser trace and a lot of extra messages.
.TP .TP
.I \-h .B \-h
Print an informative usage message. Print an informative usage message.
.TP .TP
.I \-H file .BI \-H\ file
Write headerfile to \fIfile\fR. Default is \fIinputfile.h\fR. Write headerfile to \fIfile\fR. Default is \fIinputfile.h\fR.
.TP .TP
.I \-i .B \-i
Inline messagetable(s). This option skips the generation of all \fI.bin\fR files Inline messagetable(s). This option skips the generation of all \fI.bin\fR files
and writes all output into the \fI.rc\fR file. This encoding is parsable with and writes all output into the \fI.rc\fR file. This encoding is parsable with
wrc(1). wrc(1).
.TP .TP
.I \-o file .BI \-o\ file
Output to \fIfile\fR. Default is \fIinputfile.rc\fR. Output to \fIfile\fR. Default is \fIinputfile.rc\fR.
.TP .TP
.I \-u .BI \-O\ format
Set the output format. Supported formats are \fBrc\fR (the default)
and \fBres\fR.
.TP
.B \-u
Assume that the inputfile is in unicode. Assume that the inputfile is in unicode.
.TP .TP
.I \-U .B \-U
Write resource output in unicode formatted messagetable(s). Write resource output in unicode formatted messagetable(s).
.TP .TP
.I \-v .B \-v
Show all supported codepages and languages. Show all supported codepages and languages.
.TP .TP
.I \-V .B \-V
Print version end exit. Print version end exit.
.TP .TP
.I \-W .B \-W
Enable pedantic warnings. Enable pedantic warnings.
.SH EXTENSIONS .SH EXTENSIONS
The original syntax is extended to support codepages more smoothly. Normally, The original syntax is extended to support codepages more smoothly. Normally,

View File

@ -521,7 +521,109 @@ void write_rc_file(const char *fname)
fclose(fp); fclose(fp);
} }
static void output_bin_data( lan_blk_t *lbp )
{
unsigned int offs = 4 * (lbp->nblk * 3 + 1);
int i, j, k;
put_dword( lbp->nblk ); /* NBlocks */
for (i = 0; i < lbp->nblk; i++)
{
put_dword( lbp->blks[i].idlo ); /* Lo */
put_dword( lbp->blks[i].idhi ); /* Hi */
put_dword( offs ); /* Offs */
offs += lbp->blks[i].size;
}
for (i = 0; i < lbp->nblk; i++)
{
block_t *blk = &lbp->blks[i];
for (j = 0; j < blk->nmsg; j++)
{
int len = (2 * blk->msgs[j]->len + 3) & ~3;
put_word( len + 4 );
put_word( 1 );
for (k = 0; k < blk->msgs[j]->len; k++) put_word( blk->msgs[j]->msg[k] );
align_output( 4 );
}
}
}
void write_bin_files(void) void write_bin_files(void)
{ {
assert(rcinline == 0); lan_blk_t *lbp;
token_t *ttab;
int ntab;
int i;
get_tokentable(&ttab, &ntab);
for (lbp = lanblockhead; lbp; lbp = lbp->next)
{
char *cptr = NULL;
for (i = 0; i < ntab; i++)
{
if (ttab[i].type == tok_language && ttab[i].token == lbp->lan)
{
if (ttab[i].alias) cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias);
break;
}
}
if(!cptr)
internal_error(__FILE__, __LINE__, "Filename vanished for language 0x%0x\n", lbp->lan);
init_output_buffer();
output_bin_data( lbp );
cptr = xrealloc( cptr, strlen(cptr) + 5 );
strcat( cptr, ".bin" );
flush_output_buffer( cptr );
free(cptr);
}
}
void write_res_file( const char *name )
{
lan_blk_t *lbp;
int i, j;
init_output_buffer();
put_dword( 0 ); /* ResSize */
put_dword( 32 ); /* HeaderSize */
put_word( 0xffff ); /* ResType */
put_word( 0x0000 );
put_word( 0xffff ); /* ResName */
put_word( 0x0000 );
put_dword( 0 ); /* DataVersion */
put_word( 0 ); /* Memory options */
put_word( 0 ); /* Language */
put_dword( 0 ); /* Version */
put_dword( 0 ); /* Characteristics */
for (lbp = lanblockhead; lbp; lbp = lbp->next)
{
unsigned int data_size = 4 * (lbp->nblk * 3 + 1);
unsigned int header_size = 5 * sizeof(unsigned int) + 6 * sizeof(unsigned short);
for (i = 0; i < lbp->nblk; i++)
{
block_t *blk = &lbp->blks[i];
for (j = 0; j < blk->nmsg; j++) data_size += 4 + ((blk->msgs[j]->len * 2 + 3) & ~3);
}
put_dword( data_size ); /* ResSize */
put_dword( header_size ); /* HeaderSize */
put_word( 0xffff ); /* ResType */
put_word( 0x000b /*RT_MESSAGETABLE*/ );
put_word( 0xffff ); /* ResName */
put_word( 0x0001 );
align_output( 4 );
put_dword( 0 ); /* DataVersion */
put_word( 0x30 ); /* Memory options */
put_word( lbp->lan ); /* Language */
put_dword( 0 ); /* Version */
put_dword( 0 ); /* Characteristics */
output_bin_data( lbp );
}
flush_output_buffer( name );
} }

View File

@ -23,5 +23,6 @@
void write_h_file(const char *fname); void write_h_file(const char *fname);
void write_rc_file(const char *fname); void write_rc_file(const char *fname);
void write_bin_files(void); void write_bin_files(void);
void write_res_file( const char *name );
#endif #endif