wmc: Add support for creating resource and plain binary files.
This commit is contained in:
parent
e72e7de0e5
commit
ecd144b40d
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue