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