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