wmc: Add support for creating resource and plain binary files.
diff --git a/tools/wmc/utils.c b/tools/wmc/utils.c
index 2b29db9..88dd45f 100644
--- a/tools/wmc/utils.c
+++ b/tools/wmc/utils.c
@@ -243,3 +243,76 @@
 
 	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;
+}
diff --git a/tools/wmc/utils.h b/tools/wmc/utils.h
index 5a1faf1..bef1abf 100644
--- a/tools/wmc/utils.h
+++ b/tools/wmc/utils.h
@@ -48,4 +48,19 @@
 int unistricmp(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
diff --git a/tools/wmc/wmc.c b/tools/wmc/wmc.c
index 4c4ba28..17dfd1b 100644
--- a/tools/wmc/wmc.c
+++ b/tools/wmc/wmc.c
@@ -48,6 +48,7 @@
 	"   -H file     Write headerfile to file (default is inputfile.h)\n"
 	"   -i          Inline messagetable(s)\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          Output unicode messagetable(s)\n"
 	"   -v          Show supported codepages and languages\n"
@@ -117,6 +118,12 @@
 
 FILE *yyin;
 
+static enum
+{
+    FORMAT_RC,
+    FORMAT_RES
+} output_format;
+
 int getopt (int argc, char *const *argv, const char *optstring);
 static void segvhandler(int sig);
 
@@ -165,7 +172,7 @@
 			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)
 		{
@@ -211,6 +218,15 @@
 		case 'o':
 			output_name = xstrdup(optarg);
 			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':
 			unicodein = 1;
 			break;
@@ -286,10 +302,24 @@
 		exit(1);
 	}
 
-	write_h_file(header_name);
-	write_rc_file(output_name);
-	if(!rcinline)
+#ifdef WORDS_BIGENDIAN
+	byte_swapped = (byteorder == WMC_BO_LITTLE);
+#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();
+            break;
+        case FORMAT_RES:
+            write_res_file( output_name );
+            break;
+        }
 	output_name = NULL;
 	header_name = NULL;
 	return 0;
diff --git a/tools/wmc/wmc.man.in b/tools/wmc/wmc.man.in
index 3491125..517ac23 100644
--- a/tools/wmc/wmc.man.in
+++ b/tools/wmc/wmc.man.in
@@ -22,45 +22,49 @@
 The outputfile is named \fBwmc.tab.{rc,h}\fR if no inputfile was given.
 .SH OPTIONS
 .TP
-.I \-B x
+.BI \-B\  x
 Set output byte-order x={n[ative], l[ittle], b[ig]}. Default is n[ative].
 .TP
-.I \-c
+.B \-c
 Set 'custom-bit' in message-code values.
 .TP
-.I \-d
+.B \-d
 NON-FUNCTIONAL; Use decimal values in output
 .TP
-.I \-D
+.B \-D
 Set debug flag. This results is a parser trace and a lot of extra messages.
 .TP
-.I \-h
+.B \-h
 Print an informative usage message.
 .TP
-.I \-H file
+.BI \-H\  file
 Write headerfile to \fIfile\fR. Default is \fIinputfile.h\fR.
 .TP
-.I \-i
+.B \-i
 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
 wrc(1).
 .TP
-.I \-o file
+.BI \-o\  file
 Output to \fIfile\fR. Default is \fIinputfile.rc\fR.
 .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.
 .TP
-.I \-U
+.B \-U
 Write resource output in unicode formatted messagetable(s).
 .TP
-.I \-v
+.B \-v
 Show all supported codepages and languages.
 .TP
-.I \-V
+.B \-V
 Print version end exit.
 .TP
-.I \-W
+.B \-W
 Enable pedantic warnings.
 .SH EXTENSIONS
 The original syntax is extended to support codepages more smoothly. Normally,
diff --git a/tools/wmc/write.c b/tools/wmc/write.c
index 7f9784f..f6e6d52 100644
--- a/tools/wmc/write.c
+++ b/tools/wmc/write.c
@@ -521,7 +521,109 @@
 	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)
 {
-	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 );
 }
diff --git a/tools/wmc/write.h b/tools/wmc/write.h
index 57ce655..33b8eb5 100644
--- a/tools/wmc/write.h
+++ b/tools/wmc/write.h
@@ -23,5 +23,6 @@
 void write_h_file(const char *fname);
 void write_rc_file(const char *fname);
 void write_bin_files(void);
+void write_res_file( const char *name );
 
 #endif