OSDN Git Service

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