Updated windres tool
[external/binutils.git] / binutils / resrc.c
1 /* resrc.c -- read and write Windows rc files.
2    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5    Rewritten by Kai Tietz, Onevision.
6
7    This file is part of GNU Binutils.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22    02110-1301, USA.  */
23
24 /* This file contains functions that read and write Windows rc files.
25    These are text files that represent resources.  */
26
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include "bucomm.h"
30 #include "libiberty.h"
31 #include "safe-ctype.h"
32 #include "windres.h"
33
34 #include <assert.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40
41 #ifdef HAVE_SYS_WAIT_H
42 #include <sys/wait.h>
43 #else /* ! HAVE_SYS_WAIT_H */
44 #if ! defined (_WIN32) || defined (__CYGWIN__)
45 #ifndef WIFEXITED
46 #define WIFEXITED(w)    (((w)&0377) == 0)
47 #endif
48 #ifndef WIFSIGNALED
49 #define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
50 #endif
51 #ifndef WTERMSIG
52 #define WTERMSIG(w)     ((w) & 0177)
53 #endif
54 #ifndef WEXITSTATUS
55 #define WEXITSTATUS(w)  (((w) >> 8) & 0377)
56 #endif
57 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
58 #ifndef WIFEXITED
59 #define WIFEXITED(w)    (((w) & 0xff) == 0)
60 #endif
61 #ifndef WIFSIGNALED
62 #define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
63 #endif
64 #ifndef WTERMSIG
65 #define WTERMSIG(w)     ((w) & 0x7f)
66 #endif
67 #ifndef WEXITSTATUS
68 #define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
69 #endif
70 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
71 #endif /* ! HAVE_SYS_WAIT_H */
72
73 #ifndef STDOUT_FILENO
74 #define STDOUT_FILENO 1
75 #endif
76
77 #if defined (_WIN32) && ! defined (__CYGWIN__)
78 #define popen _popen
79 #define pclose _pclose
80 #endif
81
82 /* The default preprocessor.  */
83
84 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
85
86 /* We read the directory entries in a cursor or icon file into
87    instances of this structure.  */
88
89 struct icondir
90 {
91   /* Width of image.  */
92   bfd_byte width;
93   /* Height of image.  */
94   bfd_byte height;
95   /* Number of colors in image.  */
96   bfd_byte colorcount;
97   union
98   {
99     struct
100     {
101       /* Color planes.  */
102       unsigned short planes;
103       /* Bits per pixel.  */
104       unsigned short bits;
105     } icon;
106     struct
107     {
108       /* X coordinate of hotspot.  */
109       unsigned short xhotspot;
110       /* Y coordinate of hotspot.  */
111       unsigned short yhotspot;
112     } cursor;
113   } u;
114   /* Bytes in image.  */
115   unsigned long bytes;
116   /* File offset of image.  */
117   unsigned long offset;
118 };
119
120 /* The name of the rc file we are reading.  */
121
122 char *rc_filename;
123
124 /* The line number in the rc file.  */
125
126 int rc_lineno;
127
128 /* The pipe we are reading from, so that we can close it if we exit.  */
129
130 FILE *cpp_pipe;
131
132 /* The temporary file used if we're not using popen, so we can delete it
133    if we exit.  */
134
135 static char *cpp_temp_file;
136
137 /* Input stream is either a file or a pipe.  */
138
139 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
140
141 /* As we read the rc file, we attach information to this structure.  */
142
143 static rc_res_directory *resources;
144
145 /* The number of cursor resources we have written out.  */
146
147 static int cursors;
148
149 /* The number of font resources we have written out.  */
150
151 static int fonts;
152
153 /* Font directory information.  */
154
155 rc_fontdir *fontdirs;
156
157 /* Resource info to use for fontdirs.  */
158
159 rc_res_res_info fontdirs_resinfo;
160
161 /* The number of icon resources we have written out.  */
162
163 static int icons;
164
165 /* The windres target bfd .  */
166
167 static windres_bfd wrtarget =
168 {
169   (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
170 };
171
172 /* Local functions for rcdata based resource definitions.  */
173
174 static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
175                                 rc_rcdata_item *);
176 static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
177                                 rc_rcdata_item *);
178 static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
179                                   rc_rcdata_item *);
180 static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
181                                   rc_rcdata_item *);
182 static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
183                                    rc_rcdata_item *);
184 static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
185                                         rc_rcdata_item *);
186 static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
187 static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
188
189 static int run_cmd (char *, const char *);
190 static FILE *open_input_stream (char *);
191 static FILE *look_for_default
192   (char *, const char *, int, const char *, const char *);
193 static void close_input_stream (void);
194 static void unexpected_eof (const char *);
195 static int get_word (FILE *, const char *);
196 static unsigned long get_long (FILE *, const char *);
197 static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
198 static void define_fontdirs (void);
199 \f
200 /* Run `cmd' and redirect the output to `redir'.  */
201
202 static int
203 run_cmd (char *cmd, const char *redir)
204 {
205   char *s;
206   int pid, wait_status, retcode;
207   int i;
208   const char **argv;
209   char *errmsg_fmt, *errmsg_arg;
210   char *temp_base = choose_temp_base ();
211   int in_quote;
212   char sep;
213   int redir_handle = -1;
214   int stdout_save = -1;
215
216   /* Count the args.  */
217   i = 0;
218
219   for (s = cmd; *s; s++)
220     if (*s == ' ')
221       i++;
222
223   i++;
224   argv = alloca (sizeof (char *) * (i + 3));
225   i = 0;
226   s = cmd;
227
228   while (1)
229     {
230       while (*s == ' ' && *s != 0)
231         s++;
232
233       if (*s == 0)
234         break;
235
236       in_quote = (*s == '\'' || *s == '"');
237       sep = (in_quote) ? *s++ : ' ';
238       argv[i++] = s;
239
240       while (*s != sep && *s != 0)
241         s++;
242
243       if (*s == 0)
244         break;
245
246       *s++ = 0;
247
248       if (in_quote)
249         s++;
250     }
251   argv[i++] = NULL;
252
253   /* Setup the redirection.  We can't use the usual fork/exec and redirect
254      since we may be running on non-POSIX Windows host.  */
255
256   fflush (stdout);
257   fflush (stderr);
258
259   /* Open temporary output file.  */
260   redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
261   if (redir_handle == -1)
262     fatal (_("can't open temporary file `%s': %s"), redir,
263            strerror (errno));
264
265   /* Duplicate the stdout file handle so it can be restored later.  */
266   stdout_save = dup (STDOUT_FILENO);
267   if (stdout_save == -1)
268     fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
269
270   /* Redirect stdout to our output file.  */
271   dup2 (redir_handle, STDOUT_FILENO);
272
273   pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
274                   &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
275
276   /* Restore stdout to its previous setting.  */
277   dup2 (stdout_save, STDOUT_FILENO);
278
279   /* Close response file.  */
280   close (redir_handle);
281
282   if (pid == -1)
283     {
284       fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
285       return 1;
286     }
287
288   retcode = 0;
289   pid = pwait (pid, &wait_status, 0);
290
291   if (pid == -1)
292     {
293       fatal (_("wait: %s"), strerror (errno));
294       retcode = 1;
295     }
296   else if (WIFSIGNALED (wait_status))
297     {
298       fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
299       retcode = 1;
300     }
301   else if (WIFEXITED (wait_status))
302     {
303       if (WEXITSTATUS (wait_status) != 0)
304         {
305           fatal (_("%s exited with status %d"), cmd,
306                  WEXITSTATUS (wait_status));
307           retcode = 1;
308         }
309     }
310   else
311     retcode = 1;
312
313   return retcode;
314 }
315
316 static FILE *
317 open_input_stream (char *cmd)
318 {
319   if (istream_type == ISTREAM_FILE)
320     {
321       char *fileprefix;
322
323       fileprefix = choose_temp_base ();
324       cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
325       sprintf (cpp_temp_file, "%s.irc", fileprefix);
326       free (fileprefix);
327
328       if (run_cmd (cmd, cpp_temp_file))
329         fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
330
331       cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
332       if (cpp_pipe == NULL)
333         fatal (_("can't open temporary file `%s': %s"),
334                cpp_temp_file, strerror (errno));
335
336       if (verbose)
337         fprintf (stderr,
338                  _("Using temporary file `%s' to read preprocessor output\n"),
339                  cpp_temp_file);
340     }
341   else
342     {
343       cpp_pipe = popen (cmd, FOPEN_RT);
344       if (cpp_pipe == NULL)
345         fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
346       if (verbose)
347         fprintf (stderr, _("Using popen to read preprocessor output\n"));
348     }
349
350   xatexit (close_input_stream);
351   return cpp_pipe;
352 }
353
354 /* look for the preprocessor program */
355
356 static FILE *
357 look_for_default (char *cmd, const char *prefix, int end_prefix,
358                   const char *preprocargs, const char *filename)
359 {
360   char *space;
361   int found;
362   struct stat s;
363
364   strcpy (cmd, prefix);
365
366   sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
367   space = strchr (cmd + end_prefix, ' ');
368   if (space)
369     *space = 0;
370
371   if (
372 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
373       strchr (cmd, '\\') ||
374 #endif
375       strchr (cmd, '/'))
376     {
377       found = (stat (cmd, &s) == 0
378 #ifdef HAVE_EXECUTABLE_SUFFIX
379                || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
380 #endif
381                );
382
383       if (! found)
384         {
385           if (verbose)
386             fprintf (stderr, _("Tried `%s'\n"), cmd);
387           return NULL;
388         }
389     }
390
391   strcpy (cmd, prefix);
392
393   sprintf (cmd + end_prefix, "%s %s %s",
394            DEFAULT_PREPROCESSOR, preprocargs, filename);
395
396   if (verbose)
397     fprintf (stderr, _("Using `%s'\n"), cmd);
398
399   cpp_pipe = open_input_stream (cmd);
400   return cpp_pipe;
401 }
402
403 /* Read an rc file.  */
404
405 rc_res_directory *
406 read_rc_file (const char *filename, const char *preprocessor,
407               const char *preprocargs, int language, int use_temp_file)
408 {
409   char *cmd;
410
411   istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
412
413   if (preprocargs == NULL)
414     preprocargs = "";
415   if (filename == NULL)
416     filename = "-";
417
418   if (preprocessor)
419     {
420       cmd = xmalloc (strlen (preprocessor)
421                      + strlen (preprocargs)
422                      + strlen (filename)
423                      + 10);
424       sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
425
426       cpp_pipe = open_input_stream (cmd);
427     }
428   else
429     {
430       char *dash, *slash, *cp;
431
432       preprocessor = DEFAULT_PREPROCESSOR;
433
434       cmd = xmalloc (strlen (program_name)
435                      + strlen (preprocessor)
436                      + strlen (preprocargs)
437                      + strlen (filename)
438 #ifdef HAVE_EXECUTABLE_SUFFIX
439                      + strlen (EXECUTABLE_SUFFIX)
440 #endif
441                      + 10);
442
443
444       dash = slash = 0;
445       for (cp = program_name; *cp; cp++)
446         {
447           if (*cp == '-')
448             dash = cp;
449           if (
450 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
451               *cp == ':' || *cp == '\\' ||
452 #endif
453               *cp == '/')
454             {
455               slash = cp;
456               dash = 0;
457             }
458         }
459
460       cpp_pipe = 0;
461
462       if (dash)
463         {
464           /* First, try looking for a prefixed gcc in the windres
465              directory, with the same prefix as windres */
466
467           cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
468                                        preprocargs, filename);
469         }
470
471       if (slash && ! cpp_pipe)
472         {
473           /* Next, try looking for a gcc in the same directory as
474              that windres */
475
476           cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
477                                        preprocargs, filename);
478         }
479
480       if (! cpp_pipe)
481         {
482           /* Sigh, try the default */
483
484           cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
485         }
486
487     }
488
489   free (cmd);
490
491   rc_filename = xstrdup (filename);
492   rc_lineno = 1;
493   if (language != -1)
494     rcparse_set_language (language);
495   yyparse ();
496   rcparse_discard_strings ();
497
498   close_input_stream ();
499
500   if (fontdirs != NULL)
501     define_fontdirs ();
502
503   free (rc_filename);
504   rc_filename = NULL;
505
506   return resources;
507 }
508
509 /* Close the input stream if it is open.  */
510
511 static void
512 close_input_stream (void)
513 {
514   if (istream_type == ISTREAM_FILE)
515     {
516       if (cpp_pipe != NULL)
517         fclose (cpp_pipe);
518
519       if (cpp_temp_file != NULL)
520         {
521           int errno_save = errno;
522
523           unlink (cpp_temp_file);
524           errno = errno_save;
525           free (cpp_temp_file);
526         }
527     }
528   else
529     {
530       if (cpp_pipe != NULL)
531         pclose (cpp_pipe);
532     }
533
534   /* Since this is also run via xatexit, safeguard.  */
535   cpp_pipe = NULL;
536   cpp_temp_file = NULL;
537 }
538
539 /* Report an error while reading an rc file.  */
540
541 void
542 yyerror (const char *msg)
543 {
544   fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
545 }
546
547 /* Issue a warning while reading an rc file.  */
548
549 void
550 rcparse_warning (const char *msg)
551 {
552   fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
553 }
554
555 /* Die if we get an unexpected end of file.  */
556
557 static void
558 unexpected_eof (const char *msg)
559 {
560   fatal (_("%s: unexpected EOF"), msg);
561 }
562
563 /* Read a 16 bit word from a file.  The data is assumed to be little
564    endian.  */
565
566 static int
567 get_word (FILE *e, const char *msg)
568 {
569   int b1, b2;
570
571   b1 = getc (e);
572   b2 = getc (e);
573   if (feof (e))
574     unexpected_eof (msg);
575   return ((b2 & 0xff) << 8) | (b1 & 0xff);
576 }
577
578 /* Read a 32 bit word from a file.  The data is assumed to be little
579    endian.  */
580
581 static unsigned long
582 get_long (FILE *e, const char *msg)
583 {
584   int b1, b2, b3, b4;
585
586   b1 = getc (e);
587   b2 = getc (e);
588   b3 = getc (e);
589   b4 = getc (e);
590   if (feof (e))
591     unexpected_eof (msg);
592   return (((((((b4 & 0xff) << 8)
593               | (b3 & 0xff)) << 8)
594             | (b2 & 0xff)) << 8)
595           | (b1 & 0xff));
596 }
597
598 /* Read data from a file.  This is a wrapper to do error checking.  */
599
600 static void
601 get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
602 {
603   rc_uint_type got; // $$$d
604
605   got = (rc_uint_type) fread (p, 1, c, e);
606   if (got == c)
607     return;
608
609   fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got);
610 }
611 \f
612 /* Define an accelerator resource.  */
613
614 void
615 define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
616                     rc_accelerator *data)
617 {
618   rc_res_resource *r;
619
620   r = define_standard_resource (&resources, RT_ACCELERATOR, id,
621                                 resinfo->language, 0);
622   r->type = RES_TYPE_ACCELERATOR;
623   r->u.acc = data;
624   r->res_info = *resinfo;
625 }
626
627 /* Define a bitmap resource.  Bitmap data is stored in a file.  The
628    first 14 bytes of the file are a standard header, which is not
629    included in the resource data.  */
630
631 #define BITMAP_SKIP (14)
632
633 void
634 define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
635                const char *filename)
636 {
637   FILE *e;
638   char *real_filename;
639   struct stat s;
640   bfd_byte *data;
641   rc_uint_type i;
642   rc_res_resource *r;
643
644   e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
645
646   if (stat (real_filename, &s) < 0)
647     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
648            strerror (errno));
649
650   data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
651
652   for (i = 0; i < BITMAP_SKIP; i++)
653     getc (e);
654
655   get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
656
657   fclose (e);
658   free (real_filename);
659
660   r = define_standard_resource (&resources, RT_BITMAP, id,
661                                 resinfo->language, 0);
662
663   r->type = RES_TYPE_BITMAP;
664   r->u.data.length = s.st_size - BITMAP_SKIP;
665   r->u.data.data = data;
666   r->res_info = *resinfo;
667 }
668
669 /* Define a cursor resource.  A cursor file may contain a set of
670    bitmaps, each representing the same cursor at various different
671    resolutions.  They each get written out with a different ID.  The
672    real cursor resource is then a group resource which can be used to
673    select one of the actual cursors.  */
674
675 void
676 define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
677                const char *filename)
678 {
679   FILE *e;
680   char *real_filename;
681   int type, count, i;
682   struct icondir *icondirs;
683   int first_cursor;
684   rc_res_resource *r;
685   rc_group_cursor *first, **pp;
686
687   e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
688
689   /* A cursor file is basically an icon file.  The start of the file
690      is a three word structure.  The first word is ignored.  The
691      second word is the type of data.  The third word is the number of
692      entries.  */
693
694   get_word (e, real_filename);
695   type = get_word (e, real_filename);
696   count = get_word (e, real_filename);
697   if (type != 2)
698     fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
699
700   /* Read in the icon directory entries.  */
701
702   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
703
704   for (i = 0; i < count; i++)
705     {
706       icondirs[i].width = getc (e);
707       icondirs[i].height = getc (e);
708       icondirs[i].colorcount = getc (e);
709       getc (e);
710       icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
711       icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
712       icondirs[i].bytes = get_long (e, real_filename);
713       icondirs[i].offset = get_long (e, real_filename);
714
715       if (feof (e))
716         unexpected_eof (real_filename);
717     }
718
719   /* Define each cursor as a unique resource.  */
720
721   first_cursor = cursors;
722
723   for (i = 0; i < count; i++)
724     {
725       bfd_byte *data;
726       rc_res_id name;
727       rc_cursor *c;
728
729       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
730         fatal (_("%s: fseek to %lu failed: %s"), real_filename,
731                icondirs[i].offset, strerror (errno));
732
733       data = (bfd_byte *) res_alloc (icondirs[i].bytes);
734
735       get_data (e, data, icondirs[i].bytes, real_filename);
736
737       c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
738       c->xhotspot = icondirs[i].u.cursor.xhotspot;
739       c->yhotspot = icondirs[i].u.cursor.yhotspot;
740       c->length = icondirs[i].bytes;
741       c->data = data;
742
743       ++cursors;
744
745       name.named = 0;
746       name.u.id = cursors;
747
748       r = define_standard_resource (&resources, RT_CURSOR, name,
749                                     resinfo->language, 0);
750       r->type = RES_TYPE_CURSOR;
751       r->u.cursor = c;
752       r->res_info = *resinfo;
753     }
754
755   fclose (e);
756   free (real_filename);
757
758   /* Define a cursor group resource.  */
759
760   first = NULL;
761   pp = &first;
762   for (i = 0; i < count; i++)
763     {
764       rc_group_cursor *cg;
765
766       cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
767       cg->next = NULL;
768       cg->width = icondirs[i].width;
769       cg->height = 2 * icondirs[i].height;
770
771       /* FIXME: What should these be set to?  */
772       cg->planes = 1;
773       cg->bits = 1;
774
775       cg->bytes = icondirs[i].bytes + 4;
776       cg->index = first_cursor + i + 1;
777
778       *pp = cg;
779       pp = &(*pp)->next;
780     }
781
782   free (icondirs);
783
784   r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
785                                 resinfo->language, 0);
786   r->type = RES_TYPE_GROUP_CURSOR;
787   r->u.group_cursor = first;
788   r->res_info = *resinfo;
789 }
790
791 /* Define a dialog resource.  */
792
793 void
794 define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
795                const rc_dialog *dialog)
796 {
797   rc_dialog *copy;
798   rc_res_resource *r;
799
800   copy = (rc_dialog *) res_alloc (sizeof *copy);
801   *copy = *dialog;
802
803   r = define_standard_resource (&resources, RT_DIALOG, id,
804                                 resinfo->language, 0);
805   r->type = RES_TYPE_DIALOG;
806   r->u.dialog = copy;
807   r->res_info = *resinfo;
808 }
809
810 /* Define a dialog control.  This does not define a resource, but
811    merely allocates and fills in a structure.  */
812
813 rc_dialog_control *
814 define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
815                 rc_uint_type y, rc_uint_type width, rc_uint_type height,
816                 const rc_res_id class, rc_uint_type style,
817                 rc_uint_type exstyle)
818 {
819   rc_dialog_control *n;
820
821   n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
822   n->next = NULL;
823   n->id = id;
824   n->style = style;
825   n->exstyle = exstyle;
826   n->x = x;
827   n->y = y;
828   n->width = width;
829   n->height = height;
830   n->class = class;
831   n->text = iid;
832   n->data = NULL;
833   n->help = 0;
834
835   return n;
836 }
837
838 rc_dialog_control *
839 define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
840                      rc_uint_type y, rc_uint_type style,
841                      rc_uint_type exstyle, rc_uint_type help,
842                      rc_rcdata_item *data, rc_dialog_ex *ex)
843 {
844   rc_dialog_control *n;
845   rc_res_id tid;
846   rc_res_id cid;
847
848   if (style == 0)
849     style = SS_ICON | WS_CHILD | WS_VISIBLE;
850   res_string_to_id (&tid, "");
851   cid.named = 0;
852   cid.u.id = CTL_STATIC;
853   n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
854   n->text = iid;
855   if (help && ! ex)
856     rcparse_warning (_("help ID requires DIALOGEX"));
857   if (data && ! ex)
858     rcparse_warning (_("control data requires DIALOGEX"));
859   n->help = help;
860   n->data = data;
861
862   return n;
863 }
864
865 /* Define a font resource.  */
866
867 void
868 define_font (rc_res_id id, const rc_res_res_info *resinfo,
869              const char *filename)
870 {
871   FILE *e;
872   char *real_filename;
873   struct stat s;
874   bfd_byte *data;
875   rc_res_resource *r;
876   long offset;
877   long fontdatalength;
878   bfd_byte *fontdata;
879   rc_fontdir *fd;
880   const char *device, *face;
881   rc_fontdir **pp;
882
883   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
884
885   if (stat (real_filename, &s) < 0)
886     fatal (_("stat failed on font file `%s': %s"), real_filename,
887            strerror (errno));
888
889   data = (bfd_byte *) res_alloc (s.st_size);
890
891   get_data (e, data, s.st_size, real_filename);
892
893   fclose (e);
894   free (real_filename);
895
896   r = define_standard_resource (&resources, RT_FONT, id,
897                                 resinfo->language, 0);
898
899   r->type = RES_TYPE_FONT;
900   r->u.data.length = s.st_size;
901   r->u.data.data = data;
902   r->res_info = *resinfo;
903
904   /* For each font resource, we must add an entry in the FONTDIR
905      resource.  The FONTDIR resource includes some strings in the font
906      file.  To find them, we have to do some magic on the data we have
907      read.  */
908
909   offset = ((((((data[47] << 8)
910                 | data[46]) << 8)
911               | data[45]) << 8)
912             | data[44]);
913   if (offset > 0 && offset < s.st_size)
914     device = (char *) data + offset;
915   else
916     device = "";
917
918   offset = ((((((data[51] << 8)
919                 | data[50]) << 8)
920               | data[49]) << 8)
921             | data[48]);
922   if (offset > 0 && offset < s.st_size)
923     face = (char *) data + offset;
924   else
925     face = "";
926
927   ++fonts;
928
929   fontdatalength = 58 + strlen (device) + strlen (face);
930   fontdata = (bfd_byte *) res_alloc (fontdatalength);
931   memcpy (fontdata, data, 56);
932   strcpy ((char *) fontdata + 56, device);
933   strcpy ((char *) fontdata + 57 + strlen (device), face);
934
935   fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
936   fd->next = NULL;
937   fd->index = fonts;
938   fd->length = fontdatalength;
939   fd->data = fontdata;
940
941   for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
942     ;
943   *pp = fd;
944
945   /* For the single fontdirs resource, we always use the resource
946      information of the last font.  I don't know what else to do.  */
947   fontdirs_resinfo = *resinfo;
948 }
949
950 static void
951 define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
952                     rc_rcdata_item *data)
953 {
954   rc_res_resource *r;
955   rc_uint_type len_data;
956   bfd_byte *pb_data;
957
958   r = define_standard_resource (&resources, RT_FONT, id,
959                                 resinfo->language, 0);
960
961   pb_data = rcdata_render_as_buffer (data, &len_data);
962
963   r->type = RES_TYPE_FONT;
964   r->u.data.length = len_data;
965   r->u.data.data = pb_data;
966   r->res_info = *resinfo;
967 }
968
969 /* Define the fontdirs resource.  This is called after the entire rc
970    file has been parsed, if any font resources were seen.  */
971
972 static void
973 define_fontdirs (void)
974 {
975   rc_res_resource *r;
976   rc_res_id id;
977
978   id.named = 0;
979   id.u.id = 1;
980
981   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
982
983   r->type = RES_TYPE_FONTDIR;
984   r->u.fontdir = fontdirs;
985   r->res_info = fontdirs_resinfo;
986 }
987
988 static bfd_byte *
989 rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
990 {
991   const rc_rcdata_item *d;
992   bfd_byte *ret = NULL, *pret;
993   rc_uint_type len = 0;
994
995   for (d = data; d != NULL; d = d->next)
996     len += rcdata_copy (d, NULL);
997   if (len != 0)
998     {
999       ret = pret = (bfd_byte *) res_alloc (len);
1000       for (d = data; d != NULL; d = d->next)
1001         pret += rcdata_copy (d, pret);
1002     }
1003   if (plen)
1004     *plen = len;
1005   return ret;
1006 }
1007
1008 static void
1009 define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
1010                        rc_rcdata_item *data)
1011 {
1012   rc_res_resource *r;
1013   rc_fontdir *fd, *fd_first, *fd_cur;
1014   rc_uint_type len_data;
1015   bfd_byte *pb_data;
1016   rc_uint_type c;
1017
1018   fd_cur = fd_first = NULL;
1019   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
1020
1021   pb_data = rcdata_render_as_buffer (data, &len_data);
1022
1023   if (pb_data)
1024     {
1025       rc_uint_type off = 2;
1026       c = windres_get_16 (&wrtarget, pb_data, len_data);
1027       for (; c > 0; c--)
1028         {
1029           size_t len;
1030           rc_uint_type safe_pos = off;
1031           const struct bin_fontdir_item *bfi;
1032
1033           bfi = (const struct bin_fontdir_item *) pb_data + off;
1034           fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
1035           fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
1036           fd->data = pb_data + off;
1037           off += 56;
1038           len = strlen ((char *) bfi->device_name) + 1;
1039           off += (rc_uint_type) len;
1040           off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
1041           fd->length = (off - safe_pos);
1042           fd->next = NULL;
1043           if (fd_first == NULL)
1044             fd_first = fd;
1045           else
1046             fd_cur->next = fd;
1047           fd_cur = fd;
1048         }
1049     }
1050   r->type = RES_TYPE_FONTDIR;
1051   r->u.fontdir = fd_first;
1052   r->res_info = *resinfo;
1053 }
1054
1055 static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1056                                         rc_rcdata_item *data)
1057 {
1058   rc_res_resource *r;
1059   rc_uint_type len_data;
1060   bfd_byte *pb_data;
1061
1062   r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
1063
1064   pb_data = rcdata_render_as_buffer (data, &len_data);
1065   r->type = RES_TYPE_MESSAGETABLE;
1066   r->u.data.length = len_data;
1067   r->u.data.data = pb_data;
1068   r->res_info = *resinfo;
1069 }
1070
1071 /* Define an icon resource.  An icon file may contain a set of
1072    bitmaps, each representing the same icon at various different
1073    resolutions.  They each get written out with a different ID.  The
1074    real icon resource is then a group resource which can be used to
1075    select one of the actual icon bitmaps.  */
1076
1077 void
1078 define_icon (rc_res_id id, const rc_res_res_info *resinfo,
1079              const char *filename)
1080 {
1081   FILE *e;
1082   char *real_filename;
1083   int type, count, i;
1084   struct icondir *icondirs;
1085   int first_icon;
1086   rc_res_resource *r;
1087   rc_group_icon *first, **pp;
1088
1089   e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
1090
1091   /* The start of an icon file is a three word structure.  The first
1092      word is ignored.  The second word is the type of data.  The third
1093      word is the number of entries.  */
1094
1095   get_word (e, real_filename);
1096   type = get_word (e, real_filename);
1097   count = get_word (e, real_filename);
1098   if (type != 1)
1099     fatal (_("icon file `%s' does not contain icon data"), real_filename);
1100
1101   /* Read in the icon directory entries.  */
1102
1103   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
1104
1105   for (i = 0; i < count; i++)
1106     {
1107       icondirs[i].width = getc (e);
1108       icondirs[i].height = getc (e);
1109       icondirs[i].colorcount = getc (e);
1110       getc (e);
1111       icondirs[i].u.icon.planes = get_word (e, real_filename);
1112       icondirs[i].u.icon.bits = get_word (e, real_filename);
1113       icondirs[i].bytes = get_long (e, real_filename);
1114       icondirs[i].offset = get_long (e, real_filename);
1115
1116       if (feof (e))
1117         unexpected_eof (real_filename);
1118     }
1119
1120   /* Define each icon as a unique resource.  */
1121
1122   first_icon = icons;
1123
1124   for (i = 0; i < count; i++)
1125     {
1126       bfd_byte *data;
1127       rc_res_id name;
1128
1129       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1130         fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1131                icondirs[i].offset, strerror (errno));
1132
1133       data = (bfd_byte *) res_alloc (icondirs[i].bytes);
1134
1135       get_data (e, data, icondirs[i].bytes, real_filename);
1136
1137       ++icons;
1138
1139       name.named = 0;
1140       name.u.id = icons;
1141
1142       r = define_standard_resource (&resources, RT_ICON, name,
1143                                     resinfo->language, 0);
1144       r->type = RES_TYPE_ICON;
1145       r->u.data.length = icondirs[i].bytes;
1146       r->u.data.data = data;
1147       r->res_info = *resinfo;
1148     }
1149
1150   fclose (e);
1151   free (real_filename);
1152
1153   /* Define an icon group resource.  */
1154
1155   first = NULL;
1156   pp = &first;
1157   for (i = 0; i < count; i++)
1158     {
1159       rc_group_icon *cg;
1160
1161       /* For some reason, at least in some files the planes and bits
1162          are zero.  We instead set them from the color.  This is
1163          copied from rcl.  */
1164
1165       cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1166       cg->next = NULL;
1167       cg->width = icondirs[i].width;
1168       cg->height = icondirs[i].height;
1169       cg->colors = icondirs[i].colorcount;
1170
1171       if (icondirs[i].u.icon.planes)
1172         cg->planes = icondirs[i].u.icon.planes;
1173       else
1174         cg->planes = 1;
1175
1176       if (icondirs[i].u.icon.bits)
1177         cg->bits = icondirs[i].u.icon.bits;
1178       else
1179         {
1180           cg->bits = 0;
1181
1182           while ((1L << cg->bits) < cg->colors)
1183             ++cg->bits;
1184         }
1185
1186       cg->bytes = icondirs[i].bytes;
1187       cg->index = first_icon + i + 1;
1188
1189       *pp = cg;
1190       pp = &(*pp)->next;
1191     }
1192
1193   free (icondirs);
1194
1195   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1196                                 resinfo->language, 0);
1197   r->type = RES_TYPE_GROUP_ICON;
1198   r->u.group_icon = first;
1199   r->res_info = *resinfo;
1200 }
1201
1202 static void
1203 define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1204                           rc_rcdata_item *data)
1205 {
1206   rc_res_resource *r;
1207   rc_group_icon *cg, *first, *cur;
1208   rc_uint_type len_data;
1209   bfd_byte *pb_data;
1210
1211   pb_data = rcdata_render_as_buffer (data, &len_data);
1212
1213   cur = NULL;
1214   first = NULL;
1215
1216   while (len_data >= 6)
1217     {
1218       int c, i;
1219       unsigned short type;
1220       type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1221       if (type != 1)
1222         fatal (_("unexpected group icon type %d"), type);
1223       c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1224       len_data -= 6;
1225       pb_data += 6;
1226
1227       for (i = 0; i < c; i++)
1228         {
1229           if (len_data < 14)
1230             fatal ("too small group icon rcdata");
1231           cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1232           cg->next = NULL;
1233           cg->width = pb_data[0];
1234           cg->height = pb_data[1];
1235           cg->colors = pb_data[2];
1236           cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1237           cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1238           cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1239           cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1240           if (! first)
1241             first = cg;
1242           else
1243             cur->next = cg;
1244           cur = cg;
1245           pb_data += 14;
1246           len_data -= 14;
1247         }
1248     }
1249   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1250                                 resinfo->language, 0);
1251   r->type = RES_TYPE_GROUP_ICON;
1252   r->u.group_icon = first;
1253   r->res_info = *resinfo;
1254 }
1255
1256 static void
1257 define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1258                             rc_rcdata_item *data)
1259 {
1260   rc_res_resource *r;
1261   rc_group_cursor *cg, *first, *cur;
1262   rc_uint_type len_data;
1263   bfd_byte *pb_data;
1264
1265   pb_data = rcdata_render_as_buffer (data, &len_data);
1266
1267   first = cur = NULL;
1268
1269   while (len_data >= 6)
1270     {
1271       int c, i;
1272       unsigned short type;
1273       type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1274       if (type != 2)
1275         fatal (_("unexpected group cursor type %d"), type);
1276       c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1277       len_data -= 6;
1278       pb_data += 6;
1279
1280       for (i = 0; i < c; i++)
1281         {
1282           if (len_data < 14)
1283             fatal ("too small group icon rcdata");
1284           cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
1285           cg->next = NULL;
1286           cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
1287           cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1288           cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1289           cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1290           cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1291           cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1292           if (! first)
1293             first = cg;
1294           else
1295             cur->next = cg;
1296           cur = cg;
1297           pb_data += 14;
1298           len_data -= 14;
1299         }
1300     }
1301
1302   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1303                                 resinfo->language, 0);
1304   r->type = RES_TYPE_GROUP_CURSOR;
1305   r->u.group_cursor = first;
1306   r->res_info = *resinfo;
1307 }
1308
1309 static void
1310 define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1311                       rc_rcdata_item *data)
1312 {
1313   rc_cursor *c;
1314   rc_res_resource *r;
1315   rc_uint_type len_data;
1316   bfd_byte *pb_data;
1317
1318   pb_data = rcdata_render_as_buffer (data, &len_data);
1319
1320   c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
1321   c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
1322   c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1323   c->length = len_data - BIN_CURSOR_SIZE;
1324   c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
1325
1326   r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
1327   r->type = RES_TYPE_CURSOR;
1328   r->u.cursor = c;
1329   r->res_info = *resinfo;
1330 }
1331
1332 static void
1333 define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1334                       rc_rcdata_item *data)
1335 {
1336   rc_res_resource *r;
1337   rc_uint_type len_data;
1338   bfd_byte *pb_data;
1339
1340   pb_data = rcdata_render_as_buffer (data, &len_data);
1341
1342   r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
1343   r->type = RES_TYPE_BITMAP;
1344   r->u.data.length = len_data;
1345   r->u.data.data = pb_data;
1346   r->res_info = *resinfo;
1347 }
1348
1349 static void
1350 define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1351                     rc_rcdata_item *data)
1352 {
1353   rc_res_resource *r;
1354   rc_uint_type len_data;
1355   bfd_byte *pb_data;
1356
1357   pb_data = rcdata_render_as_buffer (data, &len_data);
1358
1359   r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
1360   r->type = RES_TYPE_ICON;
1361   r->u.data.length = len_data;
1362   r->u.data.data = pb_data;
1363   r->res_info = *resinfo;
1364 }
1365
1366 /* Define a menu resource.  */
1367
1368 void
1369 define_menu (rc_res_id id, const rc_res_res_info *resinfo,
1370              rc_menuitem *menuitems)
1371 {
1372   rc_menu *m;
1373   rc_res_resource *r;
1374
1375   m = (rc_menu *) res_alloc (sizeof (rc_menu));
1376   m->items = menuitems;
1377   m->help = 0;
1378
1379   r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1380   r->type = RES_TYPE_MENU;
1381   r->u.menu = m;
1382   r->res_info = *resinfo;
1383 }
1384
1385 /* Define a menu item.  This does not define a resource, but merely
1386    allocates and fills in a structure.  */
1387
1388 rc_menuitem *
1389 define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
1390                  rc_uint_type state, rc_uint_type help,
1391                  rc_menuitem *menuitems)
1392 {
1393   rc_menuitem *mi;
1394
1395   mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
1396   mi->next = NULL;
1397   mi->type = type;
1398   mi->state = state;
1399   mi->id = menuid;
1400   mi->text = unichar_dup (text);
1401   mi->help = help;
1402   mi->popup = menuitems;
1403   return mi;
1404 }
1405
1406 /* Define a messagetable resource.  */
1407
1408 void
1409 define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
1410                      const char *filename)
1411 {
1412   FILE *e;
1413   char *real_filename;
1414   struct stat s;
1415   bfd_byte *data;
1416   rc_res_resource *r;
1417
1418   e = open_file_search (filename, FOPEN_RB, "messagetable file",
1419                         &real_filename);
1420
1421   if (stat (real_filename, &s) < 0)
1422     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1423            strerror (errno));
1424
1425   data = (bfd_byte *) res_alloc (s.st_size);
1426
1427   get_data (e, data, s.st_size, real_filename);
1428
1429   fclose (e);
1430   free (real_filename);
1431
1432   r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1433                                 resinfo->language, 0);
1434
1435   r->type = RES_TYPE_MESSAGETABLE;
1436   r->u.data.length = s.st_size;
1437   r->u.data.data = data;
1438   r->res_info = *resinfo;
1439 }
1440
1441 /* Define an rcdata resource.  */
1442
1443 void
1444 define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1445                rc_rcdata_item *data)
1446 {
1447   rc_res_resource *r;
1448
1449   r = define_standard_resource (&resources, RT_RCDATA, id,
1450                                 resinfo->language, 0);
1451   r->type = RES_TYPE_RCDATA;
1452   r->u.rcdata = data;
1453   r->res_info = *resinfo;
1454 }
1455
1456 /* Create an rcdata item holding a string.  */
1457
1458 rc_rcdata_item *
1459 define_rcdata_string (const char *string, rc_uint_type len)
1460 {
1461   rc_rcdata_item *ri;
1462   char *s;
1463
1464   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1465   ri->next = NULL;
1466   ri->type = RCDATA_STRING;
1467   ri->u.string.length = len;
1468   s = (char *) res_alloc (len);
1469   memcpy (s, string, len);
1470   ri->u.string.s = s;
1471
1472   return ri;
1473 }
1474
1475 /* Create an rcdata item holding a unicode string.  */
1476
1477 rc_rcdata_item *
1478 define_rcdata_unistring (const unichar *string, rc_uint_type len)
1479 {
1480   rc_rcdata_item *ri;
1481   unichar *s;
1482
1483   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1484   ri->next = NULL;
1485   ri->type = RCDATA_WSTRING;
1486   ri->u.wstring.length = len;
1487   s = (unichar *) res_alloc (len * sizeof (unichar));
1488   memcpy (s, string, len * sizeof (unichar));
1489   ri->u.wstring.w = s;
1490
1491   return ri;
1492 }
1493
1494 /* Create an rcdata item holding a number.  */
1495
1496 rc_rcdata_item *
1497 define_rcdata_number (rc_uint_type val, int dword)
1498 {
1499   rc_rcdata_item *ri;
1500
1501   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1502   ri->next = NULL;
1503   ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1504   ri->u.word = val;
1505
1506   return ri;
1507 }
1508
1509 /* Define a stringtable resource.  This is called for each string
1510    which appears in a STRINGTABLE statement.  */
1511
1512 void
1513 define_stringtable (const rc_res_res_info *resinfo,
1514                     rc_uint_type stringid, const unichar *string)
1515 {
1516   rc_res_id id;
1517   rc_res_resource *r;
1518
1519   id.named = 0;
1520   id.u.id = (stringid >> 4) + 1;
1521   r = define_standard_resource (&resources, RT_STRING, id,
1522                                 resinfo->language, 1);
1523
1524   if (r->type == RES_TYPE_UNINITIALIZED)
1525     {
1526       int i;
1527
1528       r->type = RES_TYPE_STRINGTABLE;
1529       r->u.stringtable = ((rc_stringtable *)
1530                           res_alloc (sizeof (rc_stringtable)));
1531       for (i = 0; i < 16; i++)
1532         {
1533           r->u.stringtable->strings[i].length = 0;
1534           r->u.stringtable->strings[i].string = NULL;
1535         }
1536
1537       r->res_info = *resinfo;
1538     }
1539
1540   r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string);
1541   r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string);
1542 }
1543
1544 void
1545 define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
1546                 rc_toolbar_item *items)
1547 {
1548   rc_toolbar *t;
1549   rc_res_resource *r;
1550
1551   t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1552   t->button_width = width;
1553   t->button_height = height;
1554   t->nitems = 0;
1555   t->items = items;
1556   while (items != NULL)
1557   {
1558     t->nitems+=1;
1559     items = items->next;
1560   }
1561   r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
1562   r->type = RES_TYPE_TOOLBAR;
1563   r->u.toolbar = t;
1564   r->res_info = *resinfo;
1565 }
1566
1567 /* Define a user data resource where the data is in the rc file.  */
1568
1569 void
1570 define_user_data (rc_res_id id, rc_res_id type,
1571                   const rc_res_res_info *resinfo,
1572                   rc_rcdata_item *data)
1573 {
1574   rc_res_id ids[3];
1575   rc_res_resource *r;
1576   bfd_byte *pb_data;
1577   rc_uint_type len_data;
1578
1579   /* We have to check if the binary data is parsed specially.  */
1580   if (type.named == 0)
1581     {
1582       switch (type.u.id)
1583       {
1584       case RT_FONTDIR:
1585         define_fontdir_rcdata (id, resinfo, data);
1586         return;
1587       case RT_FONT:
1588         define_font_rcdata (id, resinfo, data);
1589         return;
1590       case RT_ICON:
1591         define_icon_rcdata (id, resinfo, data);
1592         return;
1593       case RT_BITMAP:
1594         define_bitmap_rcdata (id, resinfo, data);
1595         return;
1596       case RT_CURSOR:
1597         define_cursor_rcdata (id, resinfo, data);
1598         return;
1599       case RT_GROUP_ICON:
1600         define_group_icon_rcdata (id, resinfo, data);
1601         return;
1602       case RT_GROUP_CURSOR:
1603         define_group_cursor_rcdata (id, resinfo, data);
1604         return;
1605       case RT_MESSAGETABLE:
1606         define_messagetable_rcdata (id, resinfo, data);
1607         return;
1608       default:
1609         /* Treat as normal user-data.  */
1610         break;
1611       }
1612     }
1613   ids[0] = type;
1614   ids[1] = id;
1615   ids[2].named = 0;
1616   ids[2].u.id = resinfo->language;
1617
1618   r = define_resource (& resources, 3, ids, 0);
1619   r->type = RES_TYPE_USERDATA;
1620   r->u.userdata = ((rc_rcdata_item *)
1621                    res_alloc (sizeof (rc_rcdata_item)));
1622   r->u.userdata->next = NULL;
1623   r->u.userdata->type = RCDATA_BUFFER;
1624   pb_data = rcdata_render_as_buffer (data, &len_data);
1625   r->u.userdata->u.buffer.length = len_data;
1626   r->u.userdata->u.buffer.data = pb_data;
1627   r->res_info = *resinfo;
1628 }
1629
1630 void
1631 define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
1632                     const char *filename)
1633 {
1634   rc_rcdata_item *ri;
1635   FILE *e;
1636   char *real_filename;
1637   struct stat s;
1638   bfd_byte *data;
1639
1640   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1641
1642
1643   if (stat (real_filename, &s) < 0)
1644     fatal (_("stat failed on file `%s': %s"), real_filename,
1645            strerror (errno));
1646
1647   data = (bfd_byte *) res_alloc (s.st_size);
1648
1649   get_data (e, data, s.st_size, real_filename);
1650
1651   fclose (e);
1652   free (real_filename);
1653
1654   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1655   ri->next = NULL;
1656   ri->type = RCDATA_BUFFER;
1657   ri->u.buffer.length = s.st_size;
1658   ri->u.buffer.data = data;
1659
1660   define_rcdata (id, resinfo, ri);
1661 }
1662
1663 /* Define a user data resource where the data is in a file.  */
1664
1665 void
1666 define_user_file (rc_res_id id, rc_res_id type,
1667                   const rc_res_res_info *resinfo, const char *filename)
1668 {
1669   FILE *e;
1670   char *real_filename;
1671   struct stat s;
1672   bfd_byte *data;
1673   rc_res_id ids[3];
1674   rc_res_resource *r;
1675
1676   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1677
1678   if (stat (real_filename, &s) < 0)
1679     fatal (_("stat failed on file `%s': %s"), real_filename,
1680            strerror (errno));
1681
1682   data = (bfd_byte *) res_alloc (s.st_size);
1683
1684   get_data (e, data, s.st_size, real_filename);
1685
1686   fclose (e);
1687   free (real_filename);
1688
1689   ids[0] = type;
1690   ids[1] = id;
1691   ids[2].named = 0;
1692   ids[2].u.id = resinfo->language;
1693
1694   r = define_resource (&resources, 3, ids, 0);
1695   r->type = RES_TYPE_USERDATA;
1696   r->u.userdata = ((rc_rcdata_item *)
1697                    res_alloc (sizeof (rc_rcdata_item)));
1698   r->u.userdata->next = NULL;
1699   r->u.userdata->type = RCDATA_BUFFER;
1700   r->u.userdata->u.buffer.length = s.st_size;
1701   r->u.userdata->u.buffer.data = data;
1702   r->res_info = *resinfo;
1703 }
1704
1705 /* Define a versioninfo resource.  */
1706
1707 void
1708 define_versioninfo (rc_res_id id, rc_uint_type language,
1709                     rc_fixed_versioninfo *fixedverinfo,
1710                     rc_ver_info *verinfo)
1711 {
1712   rc_res_resource *r;
1713
1714   r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1715   r->type = RES_TYPE_VERSIONINFO;
1716   r->u.versioninfo = ((rc_versioninfo *)
1717                       res_alloc (sizeof (rc_versioninfo)));
1718   r->u.versioninfo->fixed = fixedverinfo;
1719   r->u.versioninfo->var = verinfo;
1720   r->res_info.language = language;
1721 }
1722
1723 /* Add string version info to a list of version information.  */
1724
1725 rc_ver_info *
1726 append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language,
1727                            rc_ver_stringinfo *strings)
1728 {
1729   rc_ver_info *vi, **pp;
1730
1731   vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
1732   vi->next = NULL;
1733   vi->type = VERINFO_STRING;
1734   unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language);
1735   vi->u.string.strings = strings;
1736
1737   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1738     ;
1739   *pp = vi;
1740
1741   return verinfo;
1742 }
1743
1744 /* Add variable version info to a list of version information.  */
1745
1746 rc_ver_info *
1747 append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
1748                         rc_ver_varinfo *var)
1749 {
1750   rc_ver_info *vi, **pp;
1751
1752   vi = (rc_ver_info *) res_alloc (sizeof *vi);
1753   vi->next = NULL;
1754   vi->type = VERINFO_VAR;
1755   vi->u.var.key = unichar_dup (key);
1756   vi->u.var.var = var;
1757
1758   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1759     ;
1760   *pp = vi;
1761
1762   return verinfo;
1763 }
1764
1765 /* Append version string information to a list.  */
1766
1767 rc_ver_stringinfo *
1768 append_verval (rc_ver_stringinfo *strings, const unichar *key,
1769                const unichar *value)
1770 {
1771   rc_ver_stringinfo *vs, **pp;
1772
1773   vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
1774   vs->next = NULL;
1775   vs->key = unichar_dup (key);
1776   vs->value = unichar_dup (value);
1777
1778   for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1779     ;
1780   *pp = vs;
1781
1782   return strings;
1783 }
1784
1785 /* Append version variable information to a list.  */
1786
1787 rc_ver_varinfo *
1788 append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
1789                  rc_uint_type charset)
1790 {
1791   rc_ver_varinfo *vv, **pp;
1792
1793   vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
1794   vv->next = NULL;
1795   vv->language = language;
1796   vv->charset = charset;
1797
1798   for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1799     ;
1800   *pp = vv;
1801
1802   return var;
1803 }
1804 \f
1805 /* Local functions used to write out an rc file.  */
1806
1807 static void indent (FILE *, int);
1808 static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
1809                                 const rc_res_id *, rc_uint_type *, int);
1810 static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
1811                              const rc_res_id *, rc_uint_type *, int);
1812 static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
1813                                const rc_res_resource *, rc_uint_type *);
1814 static void write_rc_accelerators (FILE *, const rc_accelerator *);
1815 static void write_rc_cursor (FILE *, const rc_cursor *);
1816 static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
1817 static void write_rc_dialog (FILE *, const rc_dialog *);
1818 static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
1819 static void write_rc_fontdir (FILE *, const rc_fontdir *);
1820 static void write_rc_group_icon (FILE *, const rc_group_icon *);
1821 static void write_rc_menu (FILE *, const rc_menu *, int);
1822 static void write_rc_toolbar (FILE *, const rc_toolbar *);
1823 static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
1824 static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
1825
1826 static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
1827 static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
1828 static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
1829 static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
1830
1831 /* Indent a given number of spaces.  */
1832
1833 static void
1834 indent (FILE *e, int c)
1835 {
1836   int i;
1837
1838   for (i = 0; i < c; i++)
1839     putc (' ', e);
1840 }
1841
1842 /* Dump the resources we have read in the format of an rc file.
1843
1844    Reasoned by the fact, that some resources need to be stored into file and
1845    refer to that file, we use the user-data model for that to express it binary
1846    without the need to store it somewhere externally.  */
1847
1848 void
1849 write_rc_file (const char *filename, const rc_res_directory *resources)
1850 {
1851   FILE *e;
1852   rc_uint_type language;
1853
1854   if (filename == NULL)
1855     e = stdout;
1856   else
1857     {
1858       e = fopen (filename, FOPEN_WT);
1859       if (e == NULL)
1860         fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1861     }
1862
1863   language = (rc_uint_type) ((bfd_signed_vma) -1);
1864   write_rc_directory (e, resources, (const rc_res_id *) NULL,
1865                       (const rc_res_id *) NULL, &language, 1);
1866 }
1867
1868 /* Write out a directory.  E is the file to write to.  RD is the
1869    directory.  TYPE is a pointer to the level 1 ID which serves as the
1870    resource type.  NAME is a pointer to the level 2 ID which serves as
1871    an individual resource name.  LANGUAGE is a pointer to the current
1872    language.  LEVEL is the level in the tree.  */
1873
1874 static void
1875 write_rc_directory (FILE *e, const rc_res_directory *rd,
1876                     const rc_res_id *type, const rc_res_id *name,
1877                     rc_uint_type *language, int level)
1878 {
1879   const rc_res_entry *re;
1880
1881   /* Print out some COFF information that rc files can't represent.  */
1882   if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
1883     {
1884       wr_printcomment (e, "COFF information not part of RC");
1885   if (rd->time != 0)
1886         wr_printcomment (e, "Time stamp: %u", rd->time);
1887   if (rd->characteristics != 0)
1888         wr_printcomment (e, "Characteristics: %u", rd->characteristics);
1889   if (rd->major != 0 || rd->minor != 0)
1890         wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
1891     }
1892
1893   for (re = rd->entries;  re != NULL; re = re->next)
1894     {
1895       switch (level)
1896         {
1897         case 1:
1898           /* If we're at level 1, the key of this resource is the
1899              type.  This normally duplicates the information we have
1900              stored with the resource itself, but we need to remember
1901              the type if this is a user define resource type.  */
1902           type = &re->id;
1903           break;
1904
1905         case 2:
1906           /* If we're at level 2, the key of this resource is the name
1907              we are going to use in the rc printout.  */
1908           name = &re->id;
1909           break;
1910
1911         case 3:
1912           /* If we're at level 3, then this key represents a language.
1913              Use it to update the current language.  */
1914           if (! re->id.named
1915               && re->id.u.id != (unsigned long) (unsigned int) *language
1916               && (re->id.u.id & 0xffff) == re->id.u.id)
1917             {
1918               wr_print (e, "LANGUAGE %u, %u\n",
1919                        re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
1920                        (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
1921               *language = re->id.u.id;
1922             }
1923           break;
1924
1925         default:
1926           break;
1927         }
1928
1929       if (re->subdir)
1930         write_rc_subdir (e, re, type, name, language, level);
1931       else
1932         {
1933           if (level == 3)
1934             {
1935               /* This is the normal case: the three levels are
1936                  TYPE/NAME/LANGUAGE.  NAME will have been set at level
1937                  2, and represents the name to use.  We probably just
1938                  set LANGUAGE, and it will probably match what the
1939                  resource itself records if anything.  */
1940               write_rc_resource (e, type, name, re->u.res, language);
1941             }
1942           else
1943             {
1944               wr_printcomment (e, "Resource at unexpected level %d", level);
1945               write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
1946                                  language);
1947             }
1948         }
1949     }
1950   if (rd->entries == NULL)
1951     {
1952       wr_print_flush (e);
1953     }
1954 }
1955
1956 /* Write out a subdirectory entry.  E is the file to write to.  RE is
1957    the subdirectory entry.  TYPE and NAME are pointers to higher level
1958    IDs, or NULL.  LANGUAGE is a pointer to the current language.
1959    LEVEL is the level in the tree.  */
1960
1961 static void
1962 write_rc_subdir (FILE *e, const rc_res_entry *re,
1963                  const rc_res_id *type, const rc_res_id *name,
1964                  rc_uint_type *language, int level)
1965 {
1966   fprintf (e, "\n");
1967   switch (level)
1968     {
1969     case 1:
1970       wr_printcomment (e, "Type: ");
1971       if (re->id.named)
1972         res_id_print (e, re->id, 1);
1973       else
1974         {
1975           const char *s;
1976
1977           switch (re->id.u.id)
1978             {
1979             case RT_CURSOR: s = "cursor"; break;
1980             case RT_BITMAP: s = "bitmap"; break;
1981             case RT_ICON: s = "icon"; break;
1982             case RT_MENU: s = "menu"; break;
1983             case RT_DIALOG: s = "dialog"; break;
1984             case RT_STRING: s = "stringtable"; break;
1985             case RT_FONTDIR: s = "fontdir"; break;
1986             case RT_FONT: s = "font"; break;
1987             case RT_ACCELERATOR: s = "accelerators"; break;
1988             case RT_RCDATA: s = "rcdata"; break;
1989             case RT_MESSAGETABLE: s = "messagetable"; break;
1990             case RT_GROUP_CURSOR: s = "group cursor"; break;
1991             case RT_GROUP_ICON: s = "group icon"; break;
1992             case RT_VERSION: s = "version"; break;
1993             case RT_DLGINCLUDE: s = "dlginclude"; break;
1994             case RT_PLUGPLAY: s = "plugplay"; break;
1995             case RT_VXD: s = "vxd"; break;
1996             case RT_ANICURSOR: s = "anicursor"; break;
1997             case RT_ANIICON: s = "aniicon"; break;
1998             case RT_TOOLBAR: s = "toolbar"; break;
1999             case RT_HTML: s = "html"; break;
2000             default: s = NULL; break;
2001             }
2002
2003           if (s != NULL)
2004             fprintf (e, "%s", s);
2005           else
2006             res_id_print (e, re->id, 1);
2007         }
2008       break;
2009
2010     case 2:
2011       wr_printcomment (e, "Name: ");
2012       res_id_print (e, re->id, 1);
2013       break;
2014
2015     case 3:
2016       wr_printcomment (e, "Language: ");
2017       res_id_print (e, re->id, 1);
2018       break;
2019
2020     default:
2021       wr_printcomment (e, "Level %d: ", level);
2022       res_id_print (e, re->id, 1);
2023     }
2024
2025   write_rc_directory (e, re->u.dir, type, name, language, level + 1);
2026 }
2027
2028 /* Write out a single resource.  E is the file to write to.  TYPE is a
2029    pointer to the type of the resource.  NAME is a pointer to the name
2030    of the resource; it will be NULL if there is a level mismatch.  RES
2031    is the resource data.  LANGUAGE is a pointer to the current
2032    language.  */
2033
2034 static void
2035 write_rc_resource (FILE *e, const rc_res_id *type,
2036                    const rc_res_id *name, const rc_res_resource *res,
2037                    rc_uint_type *language)
2038 {
2039   const char *s;
2040   int rt;
2041   int menuex = 0;
2042
2043   switch (res->type)
2044     {
2045     default:
2046       abort ();
2047
2048     case RES_TYPE_ACCELERATOR:
2049       s = "ACCELERATORS";
2050       rt = RT_ACCELERATOR;
2051       break;
2052
2053     case RES_TYPE_BITMAP:
2054       s = "2 /* RT_BITMAP */";
2055       rt = RT_BITMAP;
2056       break;
2057
2058     case RES_TYPE_CURSOR:
2059       s = "1 /* RT_CURSOR */";
2060       rt = RT_CURSOR;
2061       break;
2062
2063     case RES_TYPE_GROUP_CURSOR:
2064       s = "12 /* RT_GROUP_CURSOR */";
2065       rt = RT_GROUP_CURSOR;
2066       break;
2067
2068     case RES_TYPE_DIALOG:
2069       if (extended_dialog (res->u.dialog))
2070         s = "DIALOGEX";
2071       else
2072         s = "DIALOG";
2073       rt = RT_DIALOG;
2074       break;
2075
2076     case RES_TYPE_FONT:
2077       s = "8 /* RT_FONT */";
2078       rt = RT_FONT;
2079       break;
2080
2081     case RES_TYPE_FONTDIR:
2082       s = "7 /* RT_FONTDIR */";
2083       rt = RT_FONTDIR;
2084       break;
2085
2086     case RES_TYPE_ICON:
2087       s = "3 /* RT_ICON */";
2088       rt = RT_ICON;
2089       break;
2090
2091     case RES_TYPE_GROUP_ICON:
2092       s = "14 /* RT_GROUP_ICON */";
2093       rt = RT_GROUP_ICON;
2094       break;
2095
2096     case RES_TYPE_MENU:
2097       if (extended_menu (res->u.menu))
2098         {
2099           s = "MENUEX";
2100           menuex = 1;
2101         }
2102       else
2103         {
2104           s = "MENU";
2105           menuex = 0;
2106         }
2107       rt = RT_MENU;
2108       break;
2109
2110     case RES_TYPE_MESSAGETABLE:
2111       s = "11 /* RT_MESSAGETABLE */";
2112       rt = RT_MESSAGETABLE;
2113       break;
2114
2115     case RES_TYPE_RCDATA:
2116       s = "RCDATA";
2117       rt = RT_RCDATA;
2118       break;
2119
2120     case RES_TYPE_STRINGTABLE:
2121       s = "STRINGTABLE";
2122       rt = RT_STRING;
2123       break;
2124
2125     case RES_TYPE_USERDATA:
2126       s = NULL;
2127       rt = 0;
2128       break;
2129
2130     case RES_TYPE_VERSIONINFO:
2131       s = "VERSIONINFO";
2132       rt = RT_VERSION;
2133       break;
2134
2135     case RES_TYPE_TOOLBAR:
2136       s = "TOOLBAR";
2137       rt = RT_TOOLBAR;
2138       break;
2139     }
2140
2141   if (rt != 0
2142       && type != NULL
2143       && (type->named || type->u.id != (unsigned long) rt))
2144     {
2145       wr_printcomment (e, "Unexpected resource type mismatch: ");
2146       res_id_print (e, *type, 1);
2147       fprintf (e, " != %d", rt);
2148     }
2149
2150   if (res->coff_info.codepage != 0)
2151     wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
2152   if (res->coff_info.reserved != 0)
2153     wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
2154
2155   wr_print (e, "\n");
2156   if (rt == RT_STRING)
2157     ;
2158   else
2159     {
2160   if (name != NULL)
2161         res_id_print (e, *name, 1);
2162   else
2163     fprintf (e, "??Unknown-Name??");
2164   fprintf (e, " ");
2165     }
2166
2167   if (s != NULL)
2168     fprintf (e, "%s", s);
2169   else if (type != NULL)
2170     {
2171       if (type->named == 0)
2172         {
2173 #define PRINT_RT_NAME(NAME) case NAME: \
2174         fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2175         break
2176
2177           switch (type->u.id)
2178             {
2179             default:
2180     res_id_print (e, *type, 0);
2181               break;
2182         
2183             PRINT_RT_NAME(RT_MANIFEST);
2184             PRINT_RT_NAME(RT_ANICURSOR);
2185             PRINT_RT_NAME(RT_ANIICON);
2186             PRINT_RT_NAME(RT_RCDATA);
2187             PRINT_RT_NAME(RT_ICON);
2188             PRINT_RT_NAME(RT_CURSOR);
2189             PRINT_RT_NAME(RT_BITMAP);
2190             PRINT_RT_NAME(RT_PLUGPLAY);
2191             PRINT_RT_NAME(RT_VXD);
2192             PRINT_RT_NAME(RT_FONT);
2193             PRINT_RT_NAME(RT_FONTDIR);
2194             PRINT_RT_NAME(RT_HTML);
2195             PRINT_RT_NAME(RT_MESSAGETABLE);
2196             PRINT_RT_NAME(RT_DLGINCLUDE);
2197             PRINT_RT_NAME(RT_DLGINIT);
2198             }
2199 #undef PRINT_RT_NAME
2200         }
2201       else
2202         res_id_print (e, *type, 1);
2203     }
2204   else
2205     fprintf (e, "??Unknown-Type??");
2206
2207   if (res->res_info.memflags != 0)
2208     {
2209       if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
2210         fprintf (e, " MOVEABLE");
2211       if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
2212         fprintf (e, " PURE");
2213       if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
2214         fprintf (e, " PRELOAD");
2215       if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
2216         fprintf (e, " DISCARDABLE");
2217     }
2218
2219   if (res->type == RES_TYPE_DIALOG)
2220     {
2221       fprintf (e, " %d, %d, %d, %d",
2222                (int) res->u.dialog->x, (int) res->u.dialog->y,
2223                (int) res->u.dialog->width, (int) res->u.dialog->height);
2224       if (res->u.dialog->ex != NULL
2225           && res->u.dialog->ex->help != 0)
2226         fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
2227     }
2228   else if (res->type == RES_TYPE_TOOLBAR)
2229   {
2230     fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
2231              (int) res->u.toolbar->button_height);
2232     }
2233
2234   fprintf (e, "\n");
2235
2236   if ((res->res_info.language != 0 && res->res_info.language != *language)
2237       || res->res_info.characteristics != 0
2238       || res->res_info.version != 0)
2239     {
2240       int modifiers;
2241
2242       switch (res->type)
2243         {
2244         case RES_TYPE_ACCELERATOR:
2245         case RES_TYPE_DIALOG:
2246         case RES_TYPE_MENU:
2247         case RES_TYPE_RCDATA:
2248         case RES_TYPE_STRINGTABLE:
2249           modifiers = 1;
2250           break;
2251
2252         default:
2253           modifiers = 0;
2254           break;
2255         }
2256
2257       if (res->res_info.language != 0 && res->res_info.language != *language)
2258         fprintf (e, "%sLANGUAGE %d, %d\n",
2259                  modifiers ? "// " : "",
2260                  (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
2261                  (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
2262       if (res->res_info.characteristics != 0)
2263         fprintf (e, "%sCHARACTERISTICS %u\n",
2264                  modifiers ? "// " : "",
2265                  (unsigned int) res->res_info.characteristics);
2266       if (res->res_info.version != 0)
2267         fprintf (e, "%sVERSION %u\n",
2268                  modifiers ? "// " : "",
2269                  (unsigned int) res->res_info.version);
2270     }
2271
2272   switch (res->type)
2273     {
2274     default:
2275       abort ();
2276
2277     case RES_TYPE_ACCELERATOR:
2278       write_rc_accelerators (e, res->u.acc);
2279       break;
2280
2281     case RES_TYPE_CURSOR:
2282       write_rc_cursor (e, res->u.cursor);
2283       break;
2284
2285     case RES_TYPE_GROUP_CURSOR:
2286       write_rc_group_cursor (e, res->u.group_cursor);
2287       break;
2288
2289     case RES_TYPE_DIALOG:
2290       write_rc_dialog (e, res->u.dialog);
2291       break;
2292
2293     case RES_TYPE_FONTDIR:
2294       write_rc_fontdir (e, res->u.fontdir);
2295       break;
2296
2297     case RES_TYPE_GROUP_ICON:
2298       write_rc_group_icon (e, res->u.group_icon);
2299       break;
2300
2301     case RES_TYPE_MENU:
2302       write_rc_menu (e, res->u.menu, menuex);
2303       break;
2304
2305     case RES_TYPE_RCDATA:
2306       write_rc_rcdata (e, res->u.rcdata, 0);
2307       break;
2308
2309     case RES_TYPE_STRINGTABLE:
2310       write_rc_stringtable (e, name, res->u.stringtable);
2311       break;
2312
2313     case RES_TYPE_USERDATA:
2314       write_rc_rcdata (e, res->u.userdata, 0);
2315       break;
2316
2317     case RES_TYPE_TOOLBAR:
2318       write_rc_toolbar (e, res->u.toolbar);
2319       break;
2320
2321     case RES_TYPE_VERSIONINFO:
2322       write_rc_versioninfo (e, res->u.versioninfo);
2323       break;
2324
2325     case RES_TYPE_BITMAP:
2326     case RES_TYPE_FONT:
2327     case RES_TYPE_ICON:
2328       write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
2329       break;
2330     case RES_TYPE_MESSAGETABLE:
2331       write_rc_messagetable (e, res->u.data.length, res->u.data.data);
2332       break;
2333     }
2334 }
2335
2336 /* Write out accelerator information.  */
2337
2338 static void
2339 write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
2340 {
2341   const rc_accelerator *acc;
2342
2343   fprintf (e, "BEGIN\n");
2344   for (acc = accelerators; acc != NULL; acc = acc->next)
2345     {
2346       int printable;
2347
2348       fprintf (e, "  ");
2349
2350       if ((acc->key & 0x7f) == acc->key
2351           && ISPRINT (acc->key)
2352           && (acc->flags & ACC_VIRTKEY) == 0)
2353         {
2354           fprintf (e, "\"%c\"", (char) acc->key);
2355           printable = 1;
2356         }
2357       else
2358         {
2359           fprintf (e, "%d", (int) acc->key);
2360           printable = 0;
2361         }
2362
2363       fprintf (e, ", %d", (int) acc->id);
2364
2365       if (! printable)
2366         {
2367           if ((acc->flags & ACC_VIRTKEY) != 0)
2368             fprintf (e, ", VIRTKEY");
2369           else
2370             fprintf (e, ", ASCII");
2371         }
2372
2373       if ((acc->flags & ACC_SHIFT) != 0)
2374         fprintf (e, ", SHIFT");
2375       if ((acc->flags & ACC_CONTROL) != 0)
2376         fprintf (e, ", CONTROL");
2377       if ((acc->flags & ACC_ALT) != 0)
2378         fprintf (e, ", ALT");
2379
2380       fprintf (e, "\n");
2381     }
2382
2383   fprintf (e, "END\n");
2384 }
2385
2386 /* Write out cursor information.  This would normally be in a separate
2387    file, which the rc file would include.  */
2388
2389 static void
2390 write_rc_cursor (FILE *e, const rc_cursor *cursor)
2391 {
2392   fprintf (e, "BEGIN\n");
2393   indent (e, 2);
2394   fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d.  */\n",
2395            (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
2396            (int) cursor->xhotspot, (int) cursor->yhotspot);
2397   write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
2398                       0, 0, 0);
2399   fprintf (e, "END\n");
2400 }
2401
2402 /* Write out group cursor data.  This would normally be built from the
2403    cursor data.  */
2404
2405 static void
2406 write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
2407 {
2408   const rc_group_cursor *gc;
2409   int c;
2410
2411   for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2412     ;
2413   fprintf (e, "BEGIN\n");
2414
2415   indent (e, 2);
2416   fprintf (e, "0, 2, %d%s\t /* Having %d items.  */\n", c, (c != 0 ? "," : ""), c);
2417   indent (e, 4);
2418   fprintf (e, "/* width, height, planes, bits, bytes, index.  */\n");
2419
2420   for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2421     {
2422       indent (e, 4);
2423       fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2424         (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
2425         (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
2426       fprintf (e, "/* width: %d; height %d; planes %d; bits %d.  */\n",
2427              (int) gc->width, (int) gc->height, (int) gc->planes,
2428              (int) gc->bits);
2429     }
2430   fprintf (e, "END\n");
2431 }
2432
2433 /* Write dialog data.  */
2434
2435 static void
2436 write_rc_dialog (FILE *e, const rc_dialog *dialog)
2437 {
2438   const rc_dialog_control *control;
2439
2440   fprintf (e, "STYLE 0x%x\n", dialog->style);
2441
2442   if (dialog->exstyle != 0)
2443     fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
2444
2445   if ((dialog->class.named && dialog->class.u.n.length > 0)
2446       || dialog->class.u.id != 0)
2447     {
2448       fprintf (e, "CLASS ");
2449       res_id_print (e, dialog->class, 1);
2450       fprintf (e, "\n");
2451     }
2452
2453   if (dialog->caption != NULL)
2454     {
2455       fprintf (e, "CAPTION ");
2456       unicode_print_quoted (e, dialog->caption, -1);
2457       fprintf (e, "\n");
2458     }
2459
2460   if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2461       || dialog->menu.u.id != 0)
2462     {
2463       fprintf (e, "MENU ");
2464       res_id_print (e, dialog->menu, 0);
2465       fprintf (e, "\n");
2466     }
2467
2468   if (dialog->font != NULL)
2469     {
2470       fprintf (e, "FONT %d, ", (int) dialog->pointsize);
2471       unicode_print_quoted (e, dialog->font, -1);
2472       if (dialog->ex != NULL
2473           && (dialog->ex->weight != 0
2474               || dialog->ex->italic != 0
2475               || dialog->ex->charset != 1))
2476         fprintf (e, ", %d, %d, %d",
2477                  (int) dialog->ex->weight,
2478                  (int) dialog->ex->italic,
2479                  (int) dialog->ex->charset);
2480       fprintf (e, "\n");
2481     }
2482
2483   fprintf (e, "BEGIN\n");
2484
2485   for (control = dialog->controls; control != NULL; control = control->next)
2486     write_rc_dialog_control (e, control);
2487
2488   fprintf (e, "END\n");
2489 }
2490
2491 /* For each predefined control keyword, this table provides the class
2492    and the style.  */
2493
2494 struct control_info
2495 {
2496   const char *name;
2497   unsigned short class;
2498   unsigned long style;
2499 };
2500
2501 static const struct control_info control_info[] =
2502 {
2503   { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2504   { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2505   { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2506   { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2507   { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2508   { "CTEXT", CTL_STATIC, SS_CENTER },
2509   { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2510   { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2511   { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2512   { "ICON", CTL_STATIC, SS_ICON },
2513   { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2514   { "LTEXT", CTL_STATIC, SS_LEFT },
2515   { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2516   { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2517   { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2518   { "RTEXT", CTL_STATIC, SS_RIGHT },
2519   { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2520   { "STATE3", CTL_BUTTON, BS_3STATE },
2521   /* It's important that USERBUTTON come after all the other button
2522      types, so that it won't be matched too early.  */
2523   { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2524   { NULL, 0, 0 }
2525 };
2526
2527 /* Write a dialog control.  */
2528
2529 static void
2530 write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
2531 {
2532   const struct control_info *ci;
2533
2534   fprintf (e, "  ");
2535
2536   if (control->class.named)
2537     ci = NULL;
2538   else
2539     {
2540       for (ci = control_info; ci->name != NULL; ++ci)
2541         if (ci->class == control->class.u.id
2542             && (ci->style == (unsigned long) -1
2543                 || ci->style == (control->style & 0xff)))
2544           break;
2545     }
2546   if (ci == NULL)
2547     fprintf (e, "CONTROL");
2548   else if (ci->name != NULL)
2549     fprintf (e, "%s", ci->name);
2550   else
2551     {
2552     fprintf (e, "CONTROL");
2553       ci = NULL;
2554     }
2555
2556   if (control->text.named || control->text.u.id != 0)
2557     {
2558       fprintf (e, " ");
2559       res_id_print (e, control->text, 1);
2560       fprintf (e, ",");
2561     }
2562
2563   fprintf (e, " %d, ", (int) control->id);
2564
2565   if (ci == NULL)
2566     {
2567       if (control->class.named)
2568         fprintf (e, "\"");
2569       res_id_print (e, control->class, 0);
2570       if (control->class.named)
2571         fprintf (e, "\"");
2572       fprintf (e, ", 0x%x, ", (unsigned int) control->style);
2573     }
2574
2575   fprintf (e, "%d, %d", (int) control->x, (int) control->y);
2576
2577   if (control->style != SS_ICON
2578       || control->exstyle != 0
2579       || control->width != 0
2580       || control->height != 0
2581       || control->help != 0)
2582     {
2583       fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
2584
2585       /* FIXME: We don't need to print the style if it is the default.
2586          More importantly, in certain cases we actually need to turn
2587          off parts of the forced style, by using NOT.  */
2588       if (ci != NULL)
2589         fprintf (e, ", 0x%x", (unsigned int) control->style);
2590
2591       if (control->exstyle != 0 || control->help != 0)
2592         fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
2593                  (unsigned int) control->help);
2594     }
2595
2596   fprintf (e, "\n");
2597
2598   if (control->data != NULL)
2599     write_rc_rcdata (e, control->data, 2);
2600 }
2601
2602 /* Write out font directory data.  This would normally be built from
2603    the font data.  */
2604
2605 static void
2606 write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
2607 {
2608   const rc_fontdir *fc;
2609   int c;
2610
2611   for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
2612     ;
2613   fprintf (e, "BEGIN\n");
2614   indent (e, 2);
2615   fprintf (e, "%d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2616   for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
2617     {
2618       indent (e, 4);
2619       fprintf (e, "%d,\t/* Font no %d with index %d.  */\n",
2620         (int) fc->index, c, (int) fc->index);
2621       write_rc_datablock (e, (rc_uint_type) fc->length - 2,
2622                           (const bfd_byte *) fc->data + 4,fc->next != NULL,
2623                           0, 0);
2624     }
2625   fprintf (e, "END\n");
2626 }
2627
2628 /* Write out group icon data.  This would normally be built from the
2629    icon data.  */
2630
2631 static void
2632 write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
2633 {
2634   const rc_group_icon *gi;
2635   int c;
2636
2637   for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
2638     ;
2639
2640   fprintf (e, "BEGIN\n");
2641   indent (e, 2);
2642   fprintf (e, " 0, 1, %d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2643
2644   indent (e, 4);
2645   fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index.  */\n");
2646   for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
2647     {
2648       indent (e, 4);
2649       fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d.  */\n",
2650         gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
2651         (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
2652     }
2653   fprintf (e, "END\n");
2654 }
2655
2656 /* Write out a menu resource.  */
2657
2658 static void
2659 write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
2660 {
2661   if (menu->help != 0)
2662     fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
2663   write_rc_menuitems (e, menu->items, menuex, 0);
2664 }
2665
2666 static void
2667 write_rc_toolbar (FILE *e, const rc_toolbar *tb)
2668 {
2669   rc_toolbar_item *it;
2670   indent (e, 0);
2671   fprintf (e, "BEGIN\n");
2672   it = tb->items;
2673   while(it != NULL)
2674   {
2675     indent (e, 2);
2676     if (it->id.u.id == 0)
2677       fprintf (e, "SEPARATOR\n");
2678     else 
2679       fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
2680     it = it->next;
2681   }
2682   indent (e, 0);
2683   fprintf (e, "END\n");
2684 }
2685
2686 /* Write out menuitems.  */
2687
2688 static void
2689 write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
2690                     int ind)
2691 {
2692   const rc_menuitem *mi;
2693
2694   indent (e, ind);
2695   fprintf (e, "BEGIN\n");
2696
2697   for (mi = menuitems; mi != NULL; mi = mi->next)
2698     {
2699       indent (e, ind + 2);
2700
2701       if (mi->popup == NULL)
2702         fprintf (e, "MENUITEM");
2703       else
2704         fprintf (e, "POPUP");
2705
2706       if (! menuex
2707           && mi->popup == NULL
2708           && mi->text == NULL
2709           && mi->type == 0
2710           && mi->id == 0)
2711         {
2712           fprintf (e, " SEPARATOR\n");
2713           continue;
2714         }
2715
2716       if (mi->text == NULL)
2717         fprintf (e, " \"\"");
2718       else
2719         {
2720           fprintf (e, " ");
2721           unicode_print_quoted (e, mi->text, -1);
2722         }
2723
2724       if (! menuex)
2725         {
2726           if (mi->popup == NULL)
2727             fprintf (e, ", %d", (int) mi->id);
2728
2729           if ((mi->type & MENUITEM_CHECKED) != 0)
2730             fprintf (e, ", CHECKED");
2731           if ((mi->type & MENUITEM_GRAYED) != 0)
2732             fprintf (e, ", GRAYED");
2733           if ((mi->type & MENUITEM_HELP) != 0)
2734             fprintf (e, ", HELP");
2735           if ((mi->type & MENUITEM_INACTIVE) != 0)
2736             fprintf (e, ", INACTIVE");
2737           if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2738             fprintf (e, ", MENUBARBREAK");
2739           if ((mi->type & MENUITEM_MENUBREAK) != 0)
2740             fprintf (e, ", MENUBREAK");
2741         }
2742       else
2743         {
2744           if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2745             {
2746               fprintf (e, ", %d", (int) mi->id);
2747               if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2748                 {
2749                   fprintf (e, ", %u", (unsigned int) mi->type);
2750                   if (mi->state != 0 || mi->help != 0)
2751                     {
2752                       fprintf (e, ", %u", (unsigned int) mi->state);
2753                       if (mi->help != 0)
2754                         fprintf (e, ", %u", (unsigned int) mi->help);
2755                     }
2756                 }
2757             }
2758         }
2759
2760       fprintf (e, "\n");
2761
2762       if (mi->popup != NULL)
2763         write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2764     }
2765
2766   indent (e, ind);
2767   fprintf (e, "END\n");
2768 }
2769
2770 static int
2771 test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
2772 {
2773   rc_uint_type i;
2774   if ((length & 1) != 0)
2775     return 0;
2776
2777   for (i = 0; i < length; i += 2)
2778     {
2779       if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
2780         return 0;
2781       if (data[i] == 0xff && data[i + 1] == 0xff)
2782         return 0;
2783     }
2784   return 1;
2785 }
2786
2787 static int
2788 test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
2789 {
2790   int has_nl;
2791   rc_uint_type c;
2792   rc_uint_type i;
2793   
2794   if (length <= 1)
2795     return 0;
2796
2797   has_nl = 0;
2798   for (i = 0, c = 0; i < length; i++)
2799     {
2800       if (! ISPRINT (data[i]) && data[i] != '\n'
2801           && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
2802           && data[i] != '\t'
2803           && ! (data[i] == 0 && (i + 1) != length))
2804         {
2805           if (data[i] <= 7)
2806             return 0;
2807           c++;
2808         }
2809       else if (data[i] == '\n') has_nl++;
2810     }
2811   if (length > 80 && ! has_nl)
2812     return 0;
2813   c = (((c * 10000) + (i / 100) - 1)) / i;
2814   if (c >= 150)
2815     return 0;
2816   return 1;
2817 }
2818
2819 static void
2820 write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
2821 {
2822   int has_error = 0;
2823   const struct bin_messagetable *mt;
2824   fprintf (e, "BEGIN\n");
2825
2826   write_rc_datablock (e, length, data, 0, 0, 0);
2827
2828   fprintf (e, "\n");
2829   wr_printcomment (e, "MC syntax dump");
2830   if (length < BIN_MESSAGETABLE_SIZE)
2831     has_error = 1;
2832   else
2833     do {
2834       rc_uint_type m, i;
2835       mt = (const struct bin_messagetable *) data;
2836       m = windres_get_32 (&wrtarget, mt->cblocks, length);
2837       if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
2838         {
2839           has_error = 1;
2840           break;
2841         }
2842       for (i = 0; i < m; i++)
2843         {
2844           rc_uint_type low, high, offset;
2845           const struct bin_messagetable_item *mti;
2846
2847           low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
2848           high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
2849           offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
2850           while (low <= high)
2851             {
2852               rc_uint_type elen, flags;
2853               if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
2854                 {
2855                   has_error = 1;
2856           break;
2857                 }
2858               mti = (const struct bin_messagetable_item *) &data[offset];
2859               elen = windres_get_16 (&wrtarget, mti->length, 2);
2860               flags = windres_get_16 (&wrtarget, mti->flags, 2);
2861               if ((offset + elen) > length)
2862                 {
2863                   has_error = 1;
2864                   break;
2865                 }
2866               wr_printcomment (e, "MessageId = 0x%x", low);
2867               wr_printcomment (e, "");
2868               if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
2869                 unicode_print (e, (const unichar *) mti->data,
2870                                (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
2871               else
2872                 ascii_print (e, (const char *) mti->data,
2873                              (elen - BIN_MESSAGETABLE_ITEM_SIZE));
2874               wr_printcomment (e,"");
2875               ++low;
2876               offset += elen;
2877             }
2878         }
2879     } while (0);
2880   if (has_error)
2881     wr_printcomment (e, "Illegal data");
2882   wr_print_flush (e);
2883   fprintf (e, "END\n");
2884 }
2885
2886 static void
2887 write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
2888                     int hasblock, int show_comment)
2889 {
2890   int plen;
2891
2892   if (hasblock)
2893     fprintf (e, "BEGIN\n");
2894
2895   if (show_comment == -1)
2896           {
2897       if (test_rc_datablock_text(length, data))
2898         {
2899           rc_uint_type i, c;
2900           for (i = 0; i < length;)
2901             {
2902               indent (e, 2);
2903               fprintf (e, "\"");
2904
2905               for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
2906                 ;
2907               if (i < length && data[i] == '\n')
2908                 ++i, ++c;
2909               ascii_print (e, (const char *) &data[i - c], c);
2910             fprintf (e, "\"");
2911               if (i < length)
2912                 fprintf (e, "\n");
2913             }
2914           
2915           if (i == 0)
2916               {
2917               indent (e, 2);
2918               fprintf (e, "\"\"");
2919               }
2920           if (has_next)
2921             fprintf (e, ",");
2922           fprintf (e, "\n");
2923           if (hasblock)
2924             fprintf (e, "END\n");
2925           return;
2926           }
2927       if (test_rc_datablock_unicode (length, data))
2928         {
2929           rc_uint_type i, c;
2930           for (i = 0; i < length;)
2931             {
2932               const unichar *u;
2933
2934               u = (const unichar *) &data[i];
2935               indent (e, 2);
2936           fprintf (e, "L\"");
2937           
2938               for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
2939                 ;
2940               if (i < length && u[c] == '\n')
2941                 i += 2, ++c;
2942               unicode_print (e, u, c);
2943           fprintf (e, "\"");
2944               if (i < length)
2945                 fprintf (e, "\n");
2946             }
2947
2948           if (i == 0)
2949           {
2950               indent (e, 2);
2951               fprintf (e, "L\"\"");
2952             }
2953           if (has_next)
2954             fprintf (e, ",");
2955           fprintf (e, "\n");
2956           if (hasblock)
2957             fprintf (e, "END\n");
2958           return;
2959         }
2960
2961       show_comment = 0;
2962     }
2963
2964   if (length != 0)
2965               {
2966       rc_uint_type i, max_row;
2967       int first = 1;
2968
2969       max_row = (show_comment ? 4 : 8);
2970       indent (e, 2);
2971       for (i = 0; i + 3 < length;)
2972                   {
2973           rc_uint_type k;
2974           rc_uint_type comment_start;
2975           
2976           comment_start = i;
2977           
2978           if (! first)
2979             indent (e, 2);
2980
2981           for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
2982                       {
2983               if (k == 0)
2984                 plen  = fprintf (e, "0x%lxL",
2985                                  (long) windres_get_32 (&wrtarget, data + i, length - i));
2986                         else
2987                 plen = fprintf (e, " 0x%lxL",
2988                                 (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
2989               if (has_next || (i + 4) < length)
2990                           {
2991                   if (plen>0 && plen < 11)
2992                     indent (e, 11 - plen);
2993                   fprintf (e, ",");
2994                           }
2995                       }
2996           if (show_comment)
2997             {
2998               fprintf (e, "\t/* ");
2999               ascii_print (e, (const char *) &data[comment_start], i - comment_start);
3000               fprintf (e, ".  */");
3001                   }
3002                 fprintf (e, "\n");
3003                 first = 0;
3004               }
3005
3006       if (i + 1 < length)
3007               {
3008                 if (! first)
3009             indent (e, 2);
3010           plen = fprintf (e, "0x%x",
3011                           (int) windres_get_16 (&wrtarget, data + i, length - i));
3012           if (has_next || i + 2 < length)
3013                   {
3014               if (plen > 0 && plen < 11)
3015                 indent (e, 11 - plen);
3016               fprintf (e, ",");
3017                       }
3018           if (show_comment)
3019             {
3020               fprintf (e, "\t/* ");
3021               ascii_print (e, (const char *) &data[i], 2);
3022               fprintf (e, ".  */");
3023                   }
3024                 fprintf (e, "\n");
3025                 i += 2;
3026                 first = 0;
3027               }
3028
3029       if (i < length)
3030               {
3031                 if (! first)
3032             indent (e, 2);
3033           fprintf (e, "\"");
3034           ascii_print (e, (const char *) &data[i], 1);
3035           fprintf (e, "\"");
3036           if (has_next)
3037                   fprintf (e, ",");
3038                 fprintf (e, "\n");
3039                 first = 0;
3040               }
3041     }
3042   if (hasblock)
3043     fprintf (e, "END\n");
3044 }
3045
3046 /* Write out an rcdata resource.  This is also used for other types of
3047    resources that need to print arbitrary data.  */
3048
3049 static void
3050 write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
3051 {
3052   const rc_rcdata_item *ri;
3053
3054   indent (e, ind);
3055   fprintf (e, "BEGIN\n");
3056
3057   for (ri = rcdata; ri != NULL; ri = ri->next)
3058     {
3059       if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
3060         continue;
3061
3062       switch (ri->type)
3063         {
3064         default:
3065           abort ();
3066
3067         case RCDATA_WORD:
3068           indent (e, ind + 2);
3069           fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
3070           break;
3071
3072         case RCDATA_DWORD:
3073           indent (e, ind + 2);
3074           fprintf (e, "%luL", (unsigned long) ri->u.dword);
3075           break;
3076
3077         case RCDATA_STRING:
3078           indent (e, ind + 2);
3079           fprintf (e, "\"");
3080           ascii_print (e, ri->u.string.s, ri->u.string.length);
3081           fprintf (e, "\"");
3082           break;
3083
3084         case RCDATA_WSTRING:
3085           indent (e, ind + 2);
3086           fprintf (e, "L\"");
3087           unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
3088           fprintf (e, "\"");
3089           break;
3090
3091         case RCDATA_BUFFER:
3092           write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
3093                               (const bfd_byte *) ri->u.buffer.data,
3094                               ri->next != NULL, 0, -1);
3095             break;
3096         }
3097
3098       if (ri->type != RCDATA_BUFFER)
3099         {
3100           if (ri->next != NULL)
3101             fprintf (e, ",");
3102           fprintf (e, "\n");
3103         }
3104     }
3105
3106   indent (e, ind);
3107   fprintf (e, "END\n");
3108 }
3109
3110 /* Write out a stringtable resource.  */
3111
3112 static void
3113 write_rc_stringtable (FILE *e, const rc_res_id *name,
3114                       const rc_stringtable *stringtable)
3115 {
3116   rc_uint_type offset;
3117   int i;
3118
3119   if (name != NULL && ! name->named)
3120     offset = (name->u.id - 1) << 4;
3121   else
3122     {
3123       fprintf (e, "/* %s string table name.  */\n",
3124                name == NULL ? "Missing" : "Invalid");
3125       offset = 0;
3126     }
3127
3128   fprintf (e, "BEGIN\n");
3129
3130   for (i = 0; i < 16; i++)
3131     {
3132       if (stringtable->strings[i].length != 0)
3133         {
3134           fprintf (e, "  %lu, ", (long) offset + i);
3135           unicode_print_quoted (e, stringtable->strings[i].string,
3136                          stringtable->strings[i].length);
3137           fprintf (e, "\n");
3138         }
3139     }
3140
3141   fprintf (e, "END\n");
3142 }
3143
3144 /* Write out a versioninfo resource.  */
3145
3146 static void
3147 write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
3148 {
3149   const rc_fixed_versioninfo *f;
3150   const rc_ver_info *vi;
3151
3152   f = versioninfo->fixed;
3153   if (f->file_version_ms != 0 || f->file_version_ls != 0)
3154     fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
3155              (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
3156              (unsigned int) (f->file_version_ms & 0xffff),
3157              (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
3158              (unsigned int) (f->file_version_ls & 0xffff));
3159   if (f->product_version_ms != 0 || f->product_version_ls != 0)
3160     fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
3161              (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
3162              (unsigned int) (f->product_version_ms & 0xffff),
3163              (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
3164              (unsigned int) (f->product_version_ls & 0xffff));
3165   if (f->file_flags_mask != 0)
3166     fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
3167   if (f->file_flags != 0)
3168     fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
3169   if (f->file_os != 0)
3170     fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
3171   if (f->file_type != 0)
3172     fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
3173   if (f->file_subtype != 0)
3174     fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
3175   if (f->file_date_ms != 0 || f->file_date_ls != 0)
3176     fprintf (e, "/* Date: %u, %u.  */\n",
3177              (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
3178
3179   fprintf (e, "BEGIN\n");
3180
3181   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
3182     {
3183       switch (vi->type)
3184         {
3185         case VERINFO_STRING:
3186           {
3187             const rc_ver_stringinfo *vs;
3188
3189             fprintf (e, "  BLOCK \"StringFileInfo\"\n");
3190             fprintf (e, "  BEGIN\n");
3191             fprintf (e, "    BLOCK ");
3192             unicode_print_quoted (e, vi->u.string.language, -1);
3193             fprintf (e, "\n");
3194             fprintf (e, "    BEGIN\n");
3195
3196             for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
3197               {
3198                 fprintf (e, "      VALUE ");
3199                 unicode_print_quoted (e, vs->key, -1);
3200                 fprintf (e, ", ");
3201                 unicode_print_quoted (e, vs->value, -1);
3202                 fprintf (e, "\n");
3203               }
3204
3205             fprintf (e, "    END\n");
3206             fprintf (e, "  END\n");
3207             break;
3208           }
3209
3210         case VERINFO_VAR:
3211           {
3212             const rc_ver_varinfo *vv;
3213
3214             fprintf (e, "  BLOCK \"VarFileInfo\"\n");
3215             fprintf (e, "  BEGIN\n");
3216             fprintf (e, "    VALUE ");
3217             unicode_print_quoted (e, vi->u.var.key, -1);
3218
3219             for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
3220               fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
3221                        (int) vv->charset);
3222
3223             fprintf (e, "\n  END\n");
3224
3225             break;
3226           }
3227         }
3228     }
3229
3230   fprintf (e, "END\n");
3231 }
3232
3233 static rc_uint_type
3234 rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
3235 {
3236   if (! src)
3237     return 0;
3238   switch (src->type)
3239         {
3240     case RCDATA_WORD:
3241       if (dst)
3242         windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
3243       return 2;
3244     case RCDATA_DWORD:
3245       if (dst)
3246         windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
3247       return 4;
3248     case RCDATA_STRING:
3249       if (dst && src->u.string.length)
3250         memcpy (dst, src->u.string.s, src->u.string.length);
3251       return (rc_uint_type) src->u.string.length;
3252     case RCDATA_WSTRING:
3253       if (dst && src->u.wstring.length)
3254         memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
3255       return (rc_uint_type) (src->u.wstring.length  * sizeof (unichar));
3256     case RCDATA_BUFFER:
3257       if (dst && src->u.buffer.length)
3258         memcpy (dst, src->u.buffer.data, src->u.buffer.length);
3259       return (rc_uint_type) src->u.buffer.length;
3260     default:
3261       abort ();
3262     }
3263   /* Never reached.  */
3264   return 0;
3265 }