OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [resrc.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* resrc.c -- read and write Windows rc files.
/* resrc.c -- read and write Windows rc files.
   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Ian Lance Taylor, Cygnus Support.
   Written by Ian Lance Taylor, Cygnus Support.
   Rewritten by Kai Tietz, Onevision.
   Rewritten by Kai Tietz, Onevision.
 
 
   This file is part of GNU Binutils.
   This file is part of GNU Binutils.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
/* This file contains functions that read and write Windows rc files.
/* This file contains functions that read and write Windows rc files.
   These are text files that represent resources.  */
   These are text files that represent resources.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "bucomm.h"
#include "bucomm.h"
#include "libiberty.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "windres.h"
#include "windres.h"
 
 
#include <assert.h>
#include <assert.h>
#include <errno.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
 
 
#ifdef HAVE_SYS_WAIT_H
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#include <sys/wait.h>
#else /* ! HAVE_SYS_WAIT_H */
#else /* ! HAVE_SYS_WAIT_H */
#if ! defined (_WIN32) || defined (__CYGWIN__)
#if ! defined (_WIN32) || defined (__CYGWIN__)
#ifndef WIFEXITED
#ifndef WIFEXITED
#define WIFEXITED(w)    (((w)&0377) == 0)
#define WIFEXITED(w)    (((w)&0377) == 0)
#endif
#endif
#ifndef WIFSIGNALED
#ifndef WIFSIGNALED
#define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
#define WIFSIGNALED(w)  (((w)&0377) != 0177 && ((w)&~0377) == 0)
#endif
#endif
#ifndef WTERMSIG
#ifndef WTERMSIG
#define WTERMSIG(w)     ((w) & 0177)
#define WTERMSIG(w)     ((w) & 0177)
#endif
#endif
#ifndef WEXITSTATUS
#ifndef WEXITSTATUS
#define WEXITSTATUS(w)  (((w) >> 8) & 0377)
#define WEXITSTATUS(w)  (((w) >> 8) & 0377)
#endif
#endif
#else /* defined (_WIN32) && ! defined (__CYGWIN__) */
#else /* defined (_WIN32) && ! defined (__CYGWIN__) */
#ifndef WIFEXITED
#ifndef WIFEXITED
#define WIFEXITED(w)    (((w) & 0xff) == 0)
#define WIFEXITED(w)    (((w) & 0xff) == 0)
#endif
#endif
#ifndef WIFSIGNALED
#ifndef WIFSIGNALED
#define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
#define WIFSIGNALED(w)  (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
#endif
#endif
#ifndef WTERMSIG
#ifndef WTERMSIG
#define WTERMSIG(w)     ((w) & 0x7f)
#define WTERMSIG(w)     ((w) & 0x7f)
#endif
#endif
#ifndef WEXITSTATUS
#ifndef WEXITSTATUS
#define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
#define WEXITSTATUS(w)  (((w) & 0xff00) >> 8)
#endif
#endif
#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
#endif /* ! HAVE_SYS_WAIT_H */
#endif /* ! HAVE_SYS_WAIT_H */
 
 
#ifndef STDOUT_FILENO
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#define STDOUT_FILENO 1
#endif
#endif
 
 
#if defined (_WIN32) && ! defined (__CYGWIN__)
#if defined (_WIN32) && ! defined (__CYGWIN__)
#define popen _popen
#define popen _popen
#define pclose _pclose
#define pclose _pclose
#endif
#endif
 
 
/* The default preprocessor.  */
/* The default preprocessor.  */
 
 
#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
 
 
/* We read the directory entries in a cursor or icon file into
/* We read the directory entries in a cursor or icon file into
   instances of this structure.  */
   instances of this structure.  */
 
 
struct icondir
struct icondir
{
{
  /* Width of image.  */
  /* Width of image.  */
  bfd_byte width;
  bfd_byte width;
  /* Height of image.  */
  /* Height of image.  */
  bfd_byte height;
  bfd_byte height;
  /* Number of colors in image.  */
  /* Number of colors in image.  */
  bfd_byte colorcount;
  bfd_byte colorcount;
  union
  union
  {
  {
    struct
    struct
    {
    {
      /* Color planes.  */
      /* Color planes.  */
      unsigned short planes;
      unsigned short planes;
      /* Bits per pixel.  */
      /* Bits per pixel.  */
      unsigned short bits;
      unsigned short bits;
    } icon;
    } icon;
    struct
    struct
    {
    {
      /* X coordinate of hotspot.  */
      /* X coordinate of hotspot.  */
      unsigned short xhotspot;
      unsigned short xhotspot;
      /* Y coordinate of hotspot.  */
      /* Y coordinate of hotspot.  */
      unsigned short yhotspot;
      unsigned short yhotspot;
    } cursor;
    } cursor;
  } u;
  } u;
  /* Bytes in image.  */
  /* Bytes in image.  */
  unsigned long bytes;
  unsigned long bytes;
  /* File offset of image.  */
  /* File offset of image.  */
  unsigned long offset;
  unsigned long offset;
};
};
 
 
/* The name of the rc file we are reading.  */
/* The name of the rc file we are reading.  */
 
 
char *rc_filename;
char *rc_filename;
 
 
/* The line number in the rc file.  */
/* The line number in the rc file.  */
 
 
int rc_lineno;
int rc_lineno;
 
 
/* The pipe we are reading from, so that we can close it if we exit.  */
/* The pipe we are reading from, so that we can close it if we exit.  */
 
 
FILE *cpp_pipe;
FILE *cpp_pipe;
 
 
/* The temporary file used if we're not using popen, so we can delete it
/* The temporary file used if we're not using popen, so we can delete it
   if we exit.  */
   if we exit.  */
 
 
static char *cpp_temp_file;
static char *cpp_temp_file;
 
 
/* Input stream is either a file or a pipe.  */
/* Input stream is either a file or a pipe.  */
 
 
static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
 
 
/* As we read the rc file, we attach information to this structure.  */
/* As we read the rc file, we attach information to this structure.  */
 
 
static rc_res_directory *resources;
static rc_res_directory *resources;
 
 
/* The number of cursor resources we have written out.  */
/* The number of cursor resources we have written out.  */
 
 
static int cursors;
static int cursors;
 
 
/* The number of font resources we have written out.  */
/* The number of font resources we have written out.  */
 
 
static int fonts;
static int fonts;
 
 
/* Font directory information.  */
/* Font directory information.  */
 
 
rc_fontdir *fontdirs;
rc_fontdir *fontdirs;
 
 
/* Resource info to use for fontdirs.  */
/* Resource info to use for fontdirs.  */
 
 
rc_res_res_info fontdirs_resinfo;
rc_res_res_info fontdirs_resinfo;
 
 
/* The number of icon resources we have written out.  */
/* The number of icon resources we have written out.  */
 
 
static int icons;
static int icons;
 
 
/* The windres target bfd .  */
/* The windres target bfd .  */
 
 
static windres_bfd wrtarget =
static windres_bfd wrtarget =
{
{
  (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
  (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
};
};
 
 
/* Local functions for rcdata based resource definitions.  */
/* Local functions for rcdata based resource definitions.  */
 
 
static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
                                rc_rcdata_item *);
                                rc_rcdata_item *);
static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
                                rc_rcdata_item *);
                                rc_rcdata_item *);
static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
                                  rc_rcdata_item *);
                                  rc_rcdata_item *);
static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
                                  rc_rcdata_item *);
                                  rc_rcdata_item *);
static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
                                   rc_rcdata_item *);
                                   rc_rcdata_item *);
static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
                                        rc_rcdata_item *);
                                        rc_rcdata_item *);
static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
 
 
static int run_cmd (char *, const char *);
static int run_cmd (char *, const char *);
static FILE *open_input_stream (char *);
static FILE *open_input_stream (char *);
static FILE *look_for_default
static FILE *look_for_default
  (char *, const char *, int, const char *, const char *);
  (char *, const char *, int, const char *, const char *);
static void close_input_stream (void);
static void close_input_stream (void);
static void unexpected_eof (const char *);
static void unexpected_eof (const char *);
static int get_word (FILE *, const char *);
static int get_word (FILE *, const char *);
static unsigned long get_long (FILE *, const char *);
static unsigned long get_long (FILE *, const char *);
static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
static void define_fontdirs (void);
static void define_fontdirs (void);


/* Run `cmd' and redirect the output to `redir'.  */
/* Run `cmd' and redirect the output to `redir'.  */
 
 
static int
static int
run_cmd (char *cmd, const char *redir)
run_cmd (char *cmd, const char *redir)
{
{
  char *s;
  char *s;
  int pid, wait_status, retcode;
  int pid, wait_status, retcode;
  int i;
  int i;
  const char **argv;
  const char **argv;
  char *errmsg_fmt, *errmsg_arg;
  char *errmsg_fmt, *errmsg_arg;
  char *temp_base = choose_temp_base ();
  char *temp_base = choose_temp_base ();
  int in_quote;
  int in_quote;
  char sep;
  char sep;
  int redir_handle = -1;
  int redir_handle = -1;
  int stdout_save = -1;
  int stdout_save = -1;
 
 
  /* Count the args.  */
  /* Count the args.  */
  i = 0;
  i = 0;
 
 
  for (s = cmd; *s; s++)
  for (s = cmd; *s; s++)
    if (*s == ' ')
    if (*s == ' ')
      i++;
      i++;
 
 
  i++;
  i++;
  argv = alloca (sizeof (char *) * (i + 3));
  argv = alloca (sizeof (char *) * (i + 3));
  i = 0;
  i = 0;
  s = cmd;
  s = cmd;
 
 
  while (1)
  while (1)
    {
    {
      while (*s == ' ' && *s != 0)
      while (*s == ' ' && *s != 0)
        s++;
        s++;
 
 
      if (*s == 0)
      if (*s == 0)
        break;
        break;
 
 
      in_quote = (*s == '\'' || *s == '"');
      in_quote = (*s == '\'' || *s == '"');
      sep = (in_quote) ? *s++ : ' ';
      sep = (in_quote) ? *s++ : ' ';
      argv[i++] = s;
      argv[i++] = s;
 
 
      while (*s != sep && *s != 0)
      while (*s != sep && *s != 0)
        s++;
        s++;
 
 
      if (*s == 0)
      if (*s == 0)
        break;
        break;
 
 
      *s++ = 0;
      *s++ = 0;
 
 
      if (in_quote)
      if (in_quote)
        s++;
        s++;
    }
    }
  argv[i++] = NULL;
  argv[i++] = NULL;
 
 
  /* Setup the redirection.  We can't use the usual fork/exec and redirect
  /* Setup the redirection.  We can't use the usual fork/exec and redirect
     since we may be running on non-POSIX Windows host.  */
     since we may be running on non-POSIX Windows host.  */
 
 
  fflush (stdout);
  fflush (stdout);
  fflush (stderr);
  fflush (stderr);
 
 
  /* Open temporary output file.  */
  /* Open temporary output file.  */
  redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
  redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
  if (redir_handle == -1)
  if (redir_handle == -1)
    fatal (_("can't open temporary file `%s': %s"), redir,
    fatal (_("can't open temporary file `%s': %s"), redir,
           strerror (errno));
           strerror (errno));
 
 
  /* Duplicate the stdout file handle so it can be restored later.  */
  /* Duplicate the stdout file handle so it can be restored later.  */
  stdout_save = dup (STDOUT_FILENO);
  stdout_save = dup (STDOUT_FILENO);
  if (stdout_save == -1)
  if (stdout_save == -1)
    fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
    fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
 
 
  /* Redirect stdout to our output file.  */
  /* Redirect stdout to our output file.  */
  dup2 (redir_handle, STDOUT_FILENO);
  dup2 (redir_handle, STDOUT_FILENO);
 
 
  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
                  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
                  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
 
 
  /* Restore stdout to its previous setting.  */
  /* Restore stdout to its previous setting.  */
  dup2 (stdout_save, STDOUT_FILENO);
  dup2 (stdout_save, STDOUT_FILENO);
 
 
  /* Close response file.  */
  /* Close response file.  */
  close (redir_handle);
  close (redir_handle);
 
 
  if (pid == -1)
  if (pid == -1)
    {
    {
      fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
      fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
      return 1;
      return 1;
    }
    }
 
 
  retcode = 0;
  retcode = 0;
  pid = pwait (pid, &wait_status, 0);
  pid = pwait (pid, &wait_status, 0);
 
 
  if (pid == -1)
  if (pid == -1)
    {
    {
      fatal (_("wait: %s"), strerror (errno));
      fatal (_("wait: %s"), strerror (errno));
      retcode = 1;
      retcode = 1;
    }
    }
  else if (WIFSIGNALED (wait_status))
  else if (WIFSIGNALED (wait_status))
    {
    {
      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
      retcode = 1;
      retcode = 1;
    }
    }
  else if (WIFEXITED (wait_status))
  else if (WIFEXITED (wait_status))
    {
    {
      if (WEXITSTATUS (wait_status) != 0)
      if (WEXITSTATUS (wait_status) != 0)
        {
        {
          fatal (_("%s exited with status %d"), cmd,
          fatal (_("%s exited with status %d"), cmd,
                 WEXITSTATUS (wait_status));
                 WEXITSTATUS (wait_status));
          retcode = 1;
          retcode = 1;
        }
        }
    }
    }
  else
  else
    retcode = 1;
    retcode = 1;
 
 
  return retcode;
  return retcode;
}
}
 
 
static FILE *
static FILE *
open_input_stream (char *cmd)
open_input_stream (char *cmd)
{
{
  if (istream_type == ISTREAM_FILE)
  if (istream_type == ISTREAM_FILE)
    {
    {
      char *fileprefix;
      char *fileprefix;
 
 
      fileprefix = choose_temp_base ();
      fileprefix = choose_temp_base ();
      cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
      cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
      sprintf (cpp_temp_file, "%s.irc", fileprefix);
      sprintf (cpp_temp_file, "%s.irc", fileprefix);
      free (fileprefix);
      free (fileprefix);
 
 
      if (run_cmd (cmd, cpp_temp_file))
      if (run_cmd (cmd, cpp_temp_file))
        fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
        fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
 
 
      cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
      cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
      if (cpp_pipe == NULL)
      if (cpp_pipe == NULL)
        fatal (_("can't open temporary file `%s': %s"),
        fatal (_("can't open temporary file `%s': %s"),
               cpp_temp_file, strerror (errno));
               cpp_temp_file, strerror (errno));
 
 
      if (verbose)
      if (verbose)
        fprintf (stderr,
        fprintf (stderr,
                 _("Using temporary file `%s' to read preprocessor output\n"),
                 _("Using temporary file `%s' to read preprocessor output\n"),
                 cpp_temp_file);
                 cpp_temp_file);
    }
    }
  else
  else
    {
    {
      cpp_pipe = popen (cmd, FOPEN_RT);
      cpp_pipe = popen (cmd, FOPEN_RT);
      if (cpp_pipe == NULL)
      if (cpp_pipe == NULL)
        fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
        fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
      if (verbose)
      if (verbose)
        fprintf (stderr, _("Using popen to read preprocessor output\n"));
        fprintf (stderr, _("Using popen to read preprocessor output\n"));
    }
    }
 
 
  xatexit (close_input_stream);
  xatexit (close_input_stream);
  return cpp_pipe;
  return cpp_pipe;
}
}
 
 
/* Determine if FILENAME contains special characters that
/* Determine if FILENAME contains special characters that
   can cause problems unless the entire filename is quoted.  */
   can cause problems unless the entire filename is quoted.  */
 
 
static int
static int
filename_need_quotes (const char *filename)
filename_need_quotes (const char *filename)
{
{
  if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
  if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
    return 0;
    return 0;
 
 
  while (*filename != 0)
  while (*filename != 0)
    {
    {
      switch (*filename)
      switch (*filename)
        {
        {
        case '&':
        case '&':
        case ' ':
        case ' ':
        case '<':
        case '<':
        case '>':
        case '>':
        case '|':
        case '|':
        case '%':
        case '%':
          return 1;
          return 1;
        }
        }
      ++filename;
      ++filename;
    }
    }
  return 0;
  return 0;
}
}
 
 
/* Look for the preprocessor program.  */
/* Look for the preprocessor program.  */
 
 
static FILE *
static FILE *
look_for_default (char *cmd, const char *prefix, int end_prefix,
look_for_default (char *cmd, const char *prefix, int end_prefix,
                  const char *preprocargs, const char *filename)
                  const char *preprocargs, const char *filename)
{
{
  char *space;
  char *space;
  int found;
  int found;
  struct stat s;
  struct stat s;
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
 
 
  strcpy (cmd, prefix);
  strcpy (cmd, prefix);
 
 
  sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
  sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
  space = strchr (cmd + end_prefix, ' ');
  space = strchr (cmd + end_prefix, ' ');
  if (space)
  if (space)
    *space = 0;
    *space = 0;
 
 
  if (
  if (
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
      strchr (cmd, '\\') ||
      strchr (cmd, '\\') ||
#endif
#endif
      strchr (cmd, '/'))
      strchr (cmd, '/'))
    {
    {
      found = (stat (cmd, &s) == 0
      found = (stat (cmd, &s) == 0
#ifdef HAVE_EXECUTABLE_SUFFIX
#ifdef HAVE_EXECUTABLE_SUFFIX
               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
               || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
#endif
#endif
               );
               );
 
 
      if (! found)
      if (! found)
        {
        {
          if (verbose)
          if (verbose)
            fprintf (stderr, _("Tried `%s'\n"), cmd);
            fprintf (stderr, _("Tried `%s'\n"), cmd);
          return NULL;
          return NULL;
        }
        }
    }
    }
 
 
  strcpy (cmd, prefix);
  strcpy (cmd, prefix);
 
 
  sprintf (cmd + end_prefix, "%s %s %s%s%s",
  sprintf (cmd + end_prefix, "%s %s %s%s%s",
           DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
           DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
 
 
  if (verbose)
  if (verbose)
    fprintf (stderr, _("Using `%s'\n"), cmd);
    fprintf (stderr, _("Using `%s'\n"), cmd);
 
 
  cpp_pipe = open_input_stream (cmd);
  cpp_pipe = open_input_stream (cmd);
  return cpp_pipe;
  return cpp_pipe;
}
}
 
 
/* Read an rc file.  */
/* Read an rc file.  */
 
 
rc_res_directory *
rc_res_directory *
read_rc_file (const char *filename, const char *preprocessor,
read_rc_file (const char *filename, const char *preprocessor,
              const char *preprocargs, int language, int use_temp_file)
              const char *preprocargs, int language, int use_temp_file)
{
{
  char *cmd;
  char *cmd;
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
 
 
  if (filename == NULL)
  if (filename == NULL)
    filename = "-";
    filename = "-";
  /* Setup the default resource import path taken from input file.  */
  /* Setup the default resource import path taken from input file.  */
  else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
  else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
    {
    {
      char *edit, *dir;
      char *edit, *dir;
 
 
      if (filename[0] == '/'
      if (filename[0] == '/'
          || filename[0] == '\\'
          || filename[0] == '\\'
          || filename[1] == ':')
          || filename[1] == ':')
        /* Absolute path.  */
        /* Absolute path.  */
        edit = dir = xstrdup (filename);
        edit = dir = xstrdup (filename);
      else
      else
        {
        {
          /* Relative path.  */
          /* Relative path.  */
          edit = dir = xmalloc (strlen (filename) + 3);
          edit = dir = xmalloc (strlen (filename) + 3);
          sprintf (dir, "./%s", filename);
          sprintf (dir, "./%s", filename);
        }
        }
 
 
      /* Walk dir backwards stopping at the first directory separator.  */
      /* Walk dir backwards stopping at the first directory separator.  */
      edit += strlen (dir);
      edit += strlen (dir);
      while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
      while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
        {
        {
          --edit;
          --edit;
          edit[0] = 0;
          edit[0] = 0;
        }
        }
 
 
      /* Cut off trailing slash.  */
      /* Cut off trailing slash.  */
      --edit;
      --edit;
      edit[0] = 0;
      edit[0] = 0;
 
 
      /* Convert all back slashes to forward slashes.  */
      /* Convert all back slashes to forward slashes.  */
      while ((edit = strchr (dir, '\\')) != NULL)
      while ((edit = strchr (dir, '\\')) != NULL)
        *edit = '/';
        *edit = '/';
 
 
      windres_add_include_dir (dir);
      windres_add_include_dir (dir);
    }
    }
 
 
  istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
  istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
 
 
  if (preprocargs == NULL)
  if (preprocargs == NULL)
    preprocargs = "";
    preprocargs = "";
 
 
  if (preprocessor)
  if (preprocessor)
    {
    {
      cmd = xmalloc (strlen (preprocessor)
      cmd = xmalloc (strlen (preprocessor)
                     + strlen (preprocargs)
                     + strlen (preprocargs)
                     + strlen (filename)
                     + strlen (filename)
                     + strlen (fnquotes) * 2
                     + strlen (fnquotes) * 2
                     + 10);
                     + 10);
      sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
      sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
               fnquotes, filename, fnquotes);
               fnquotes, filename, fnquotes);
 
 
      cpp_pipe = open_input_stream (cmd);
      cpp_pipe = open_input_stream (cmd);
    }
    }
  else
  else
    {
    {
      char *dash, *slash, *cp;
      char *dash, *slash, *cp;
 
 
      preprocessor = DEFAULT_PREPROCESSOR;
      preprocessor = DEFAULT_PREPROCESSOR;
 
 
      cmd = xmalloc (strlen (program_name)
      cmd = xmalloc (strlen (program_name)
                     + strlen (preprocessor)
                     + strlen (preprocessor)
                     + strlen (preprocargs)
                     + strlen (preprocargs)
                     + strlen (filename)
                     + strlen (filename)
                     + strlen (fnquotes) * 2
                     + strlen (fnquotes) * 2
#ifdef HAVE_EXECUTABLE_SUFFIX
#ifdef HAVE_EXECUTABLE_SUFFIX
                     + strlen (EXECUTABLE_SUFFIX)
                     + strlen (EXECUTABLE_SUFFIX)
#endif
#endif
                     + 10);
                     + 10);
 
 
 
 
      dash = slash = 0;
      dash = slash = 0;
      for (cp = program_name; *cp; cp++)
      for (cp = program_name; *cp; cp++)
        {
        {
          if (*cp == '-')
          if (*cp == '-')
            dash = cp;
            dash = cp;
          if (
          if (
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
              *cp == ':' || *cp == '\\' ||
              *cp == ':' || *cp == '\\' ||
#endif
#endif
              *cp == '/')
              *cp == '/')
            {
            {
              slash = cp;
              slash = cp;
              dash = 0;
              dash = 0;
            }
            }
        }
        }
 
 
      cpp_pipe = 0;
      cpp_pipe = 0;
 
 
      if (dash)
      if (dash)
        {
        {
          /* First, try looking for a prefixed gcc in the windres
          /* First, try looking for a prefixed gcc in the windres
             directory, with the same prefix as windres */
             directory, with the same prefix as windres */
 
 
          cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
          cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
                                       preprocargs, filename);
                                       preprocargs, filename);
        }
        }
 
 
      if (slash && ! cpp_pipe)
      if (slash && ! cpp_pipe)
        {
        {
          /* Next, try looking for a gcc in the same directory as
          /* Next, try looking for a gcc in the same directory as
             that windres */
             that windres */
 
 
          cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
          cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
                                       preprocargs, filename);
                                       preprocargs, filename);
        }
        }
 
 
      if (! cpp_pipe)
      if (! cpp_pipe)
        {
        {
          /* Sigh, try the default */
          /* Sigh, try the default */
 
 
          cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
          cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
        }
        }
 
 
    }
    }
 
 
  free (cmd);
  free (cmd);
 
 
  rc_filename = xstrdup (filename);
  rc_filename = xstrdup (filename);
  rc_lineno = 1;
  rc_lineno = 1;
  if (language != -1)
  if (language != -1)
    rcparse_set_language (language);
    rcparse_set_language (language);
  yyparse ();
  yyparse ();
  rcparse_discard_strings ();
  rcparse_discard_strings ();
 
 
  close_input_stream ();
  close_input_stream ();
 
 
  if (fontdirs != NULL)
  if (fontdirs != NULL)
    define_fontdirs ();
    define_fontdirs ();
 
 
  free (rc_filename);
  free (rc_filename);
  rc_filename = NULL;
  rc_filename = NULL;
 
 
  return resources;
  return resources;
}
}
 
 
/* Close the input stream if it is open.  */
/* Close the input stream if it is open.  */
 
 
static void
static void
close_input_stream (void)
close_input_stream (void)
{
{
  if (istream_type == ISTREAM_FILE)
  if (istream_type == ISTREAM_FILE)
    {
    {
      if (cpp_pipe != NULL)
      if (cpp_pipe != NULL)
        fclose (cpp_pipe);
        fclose (cpp_pipe);
 
 
      if (cpp_temp_file != NULL)
      if (cpp_temp_file != NULL)
        {
        {
          int errno_save = errno;
          int errno_save = errno;
 
 
          unlink (cpp_temp_file);
          unlink (cpp_temp_file);
          errno = errno_save;
          errno = errno_save;
          free (cpp_temp_file);
          free (cpp_temp_file);
        }
        }
    }
    }
  else
  else
    {
    {
      if (cpp_pipe != NULL)
      if (cpp_pipe != NULL)
        {
        {
          int err;
          int err;
          err = pclose (cpp_pipe);
          err = pclose (cpp_pipe);
          /* We are reading from a pipe, therefore we don't
          /* We are reading from a pipe, therefore we don't
             know if cpp failed or succeeded until pclose.  */
             know if cpp failed or succeeded until pclose.  */
          if (err != 0 || errno == ECHILD)
          if (err != 0 || errno == ECHILD)
            {
            {
              /* Since this is also run via xatexit, safeguard.  */
              /* Since this is also run via xatexit, safeguard.  */
              cpp_pipe = NULL;
              cpp_pipe = NULL;
              cpp_temp_file = NULL;
              cpp_temp_file = NULL;
              fatal (_("preprocessing failed."));
              fatal (_("preprocessing failed."));
            }
            }
        }
        }
    }
    }
 
 
  /* Since this is also run via xatexit, safeguard.  */
  /* Since this is also run via xatexit, safeguard.  */
  cpp_pipe = NULL;
  cpp_pipe = NULL;
  cpp_temp_file = NULL;
  cpp_temp_file = NULL;
}
}
 
 
/* Report an error while reading an rc file.  */
/* Report an error while reading an rc file.  */
 
 
void
void
yyerror (const char *msg)
yyerror (const char *msg)
{
{
  fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
  fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
}
}
 
 
/* Issue a warning while reading an rc file.  */
/* Issue a warning while reading an rc file.  */
 
 
void
void
rcparse_warning (const char *msg)
rcparse_warning (const char *msg)
{
{
  fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
  fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
}
}
 
 
/* Die if we get an unexpected end of file.  */
/* Die if we get an unexpected end of file.  */
 
 
static void
static void
unexpected_eof (const char *msg)
unexpected_eof (const char *msg)
{
{
  fatal (_("%s: unexpected EOF"), msg);
  fatal (_("%s: unexpected EOF"), msg);
}
}
 
 
/* Read a 16 bit word from a file.  The data is assumed to be little
/* Read a 16 bit word from a file.  The data is assumed to be little
   endian.  */
   endian.  */
 
 
static int
static int
get_word (FILE *e, const char *msg)
get_word (FILE *e, const char *msg)
{
{
  int b1, b2;
  int b1, b2;
 
 
  b1 = getc (e);
  b1 = getc (e);
  b2 = getc (e);
  b2 = getc (e);
  if (feof (e))
  if (feof (e))
    unexpected_eof (msg);
    unexpected_eof (msg);
  return ((b2 & 0xff) << 8) | (b1 & 0xff);
  return ((b2 & 0xff) << 8) | (b1 & 0xff);
}
}
 
 
/* Read a 32 bit word from a file.  The data is assumed to be little
/* Read a 32 bit word from a file.  The data is assumed to be little
   endian.  */
   endian.  */
 
 
static unsigned long
static unsigned long
get_long (FILE *e, const char *msg)
get_long (FILE *e, const char *msg)
{
{
  int b1, b2, b3, b4;
  int b1, b2, b3, b4;
 
 
  b1 = getc (e);
  b1 = getc (e);
  b2 = getc (e);
  b2 = getc (e);
  b3 = getc (e);
  b3 = getc (e);
  b4 = getc (e);
  b4 = getc (e);
  if (feof (e))
  if (feof (e))
    unexpected_eof (msg);
    unexpected_eof (msg);
  return (((((((b4 & 0xff) << 8)
  return (((((((b4 & 0xff) << 8)
              | (b3 & 0xff)) << 8)
              | (b3 & 0xff)) << 8)
            | (b2 & 0xff)) << 8)
            | (b2 & 0xff)) << 8)
          | (b1 & 0xff));
          | (b1 & 0xff));
}
}
 
 
/* Read data from a file.  This is a wrapper to do error checking.  */
/* Read data from a file.  This is a wrapper to do error checking.  */
 
 
static void
static void
get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
{
{
  rc_uint_type got; // $$$d
  rc_uint_type got; // $$$d
 
 
  got = (rc_uint_type) fread (p, 1, c, e);
  got = (rc_uint_type) fread (p, 1, c, e);
  if (got == c)
  if (got == c)
    return;
    return;
 
 
  fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got);
  fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got);
}
}


/* Define an accelerator resource.  */
/* Define an accelerator resource.  */
 
 
void
void
define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
                    rc_accelerator *data)
                    rc_accelerator *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  r = define_standard_resource (&resources, RT_ACCELERATOR, id,
  r = define_standard_resource (&resources, RT_ACCELERATOR, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_ACCELERATOR;
  r->type = RES_TYPE_ACCELERATOR;
  r->u.acc = data;
  r->u.acc = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a bitmap resource.  Bitmap data is stored in a file.  The
/* Define a bitmap resource.  Bitmap data is stored in a file.  The
   first 14 bytes of the file are a standard header, which is not
   first 14 bytes of the file are a standard header, which is not
   included in the resource data.  */
   included in the resource data.  */
 
 
#define BITMAP_SKIP (14)
#define BITMAP_SKIP (14)
 
 
void
void
define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
               const char *filename)
               const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  struct stat s;
  struct stat s;
  bfd_byte *data;
  bfd_byte *data;
  rc_uint_type i;
  rc_uint_type i;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
 
 
  if (stat (real_filename, &s) < 0)
  if (stat (real_filename, &s) < 0)
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
           strerror (errno));
           strerror (errno));
 
 
  data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
  data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
 
 
  for (i = 0; i < BITMAP_SKIP; i++)
  for (i = 0; i < BITMAP_SKIP; i++)
    getc (e);
    getc (e);
 
 
  get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
  get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  r = define_standard_resource (&resources, RT_BITMAP, id,
  r = define_standard_resource (&resources, RT_BITMAP, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
 
 
  r->type = RES_TYPE_BITMAP;
  r->type = RES_TYPE_BITMAP;
  r->u.data.length = s.st_size - BITMAP_SKIP;
  r->u.data.length = s.st_size - BITMAP_SKIP;
  r->u.data.data = data;
  r->u.data.data = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a cursor resource.  A cursor file may contain a set of
/* Define a cursor resource.  A cursor file may contain a set of
   bitmaps, each representing the same cursor at various different
   bitmaps, each representing the same cursor at various different
   resolutions.  They each get written out with a different ID.  The
   resolutions.  They each get written out with a different ID.  The
   real cursor resource is then a group resource which can be used to
   real cursor resource is then a group resource which can be used to
   select one of the actual cursors.  */
   select one of the actual cursors.  */
 
 
void
void
define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
               const char *filename)
               const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  int type, count, i;
  int type, count, i;
  struct icondir *icondirs;
  struct icondir *icondirs;
  int first_cursor;
  int first_cursor;
  rc_res_resource *r;
  rc_res_resource *r;
  rc_group_cursor *first, **pp;
  rc_group_cursor *first, **pp;
 
 
  e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
 
 
  /* A cursor file is basically an icon file.  The start of the file
  /* A cursor file is basically an icon file.  The start of the file
     is a three word structure.  The first word is ignored.  The
     is a three word structure.  The first word is ignored.  The
     second word is the type of data.  The third word is the number of
     second word is the type of data.  The third word is the number of
     entries.  */
     entries.  */
 
 
  get_word (e, real_filename);
  get_word (e, real_filename);
  type = get_word (e, real_filename);
  type = get_word (e, real_filename);
  count = get_word (e, real_filename);
  count = get_word (e, real_filename);
  if (type != 2)
  if (type != 2)
    fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
    fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
 
 
  /* Read in the icon directory entries.  */
  /* Read in the icon directory entries.  */
 
 
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
 
 
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      icondirs[i].width = getc (e);
      icondirs[i].width = getc (e);
      icondirs[i].height = getc (e);
      icondirs[i].height = getc (e);
      icondirs[i].colorcount = getc (e);
      icondirs[i].colorcount = getc (e);
      getc (e);
      getc (e);
      icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
      icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
      icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
      icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
      icondirs[i].bytes = get_long (e, real_filename);
      icondirs[i].bytes = get_long (e, real_filename);
      icondirs[i].offset = get_long (e, real_filename);
      icondirs[i].offset = get_long (e, real_filename);
 
 
      if (feof (e))
      if (feof (e))
        unexpected_eof (real_filename);
        unexpected_eof (real_filename);
    }
    }
 
 
  /* Define each cursor as a unique resource.  */
  /* Define each cursor as a unique resource.  */
 
 
  first_cursor = cursors;
  first_cursor = cursors;
 
 
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      bfd_byte *data;
      bfd_byte *data;
      rc_res_id name;
      rc_res_id name;
      rc_cursor *c;
      rc_cursor *c;
 
 
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
               icondirs[i].offset, strerror (errno));
               icondirs[i].offset, strerror (errno));
 
 
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
 
 
      get_data (e, data, icondirs[i].bytes, real_filename);
      get_data (e, data, icondirs[i].bytes, real_filename);
 
 
      c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
      c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
      c->xhotspot = icondirs[i].u.cursor.xhotspot;
      c->xhotspot = icondirs[i].u.cursor.xhotspot;
      c->yhotspot = icondirs[i].u.cursor.yhotspot;
      c->yhotspot = icondirs[i].u.cursor.yhotspot;
      c->length = icondirs[i].bytes;
      c->length = icondirs[i].bytes;
      c->data = data;
      c->data = data;
 
 
      ++cursors;
      ++cursors;
 
 
      name.named = 0;
      name.named = 0;
      name.u.id = cursors;
      name.u.id = cursors;
 
 
      r = define_standard_resource (&resources, RT_CURSOR, name,
      r = define_standard_resource (&resources, RT_CURSOR, name,
                                    resinfo->language, 0);
                                    resinfo->language, 0);
      r->type = RES_TYPE_CURSOR;
      r->type = RES_TYPE_CURSOR;
      r->u.cursor = c;
      r->u.cursor = c;
      r->res_info = *resinfo;
      r->res_info = *resinfo;
    }
    }
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  /* Define a cursor group resource.  */
  /* Define a cursor group resource.  */
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      rc_group_cursor *cg;
      rc_group_cursor *cg;
 
 
      cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
      cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
      cg->next = NULL;
      cg->next = NULL;
      cg->width = icondirs[i].width;
      cg->width = icondirs[i].width;
      cg->height = 2 * icondirs[i].height;
      cg->height = 2 * icondirs[i].height;
 
 
      /* FIXME: What should these be set to?  */
      /* FIXME: What should these be set to?  */
      cg->planes = 1;
      cg->planes = 1;
      cg->bits = 1;
      cg->bits = 1;
 
 
      cg->bytes = icondirs[i].bytes + 4;
      cg->bytes = icondirs[i].bytes + 4;
      cg->index = first_cursor + i + 1;
      cg->index = first_cursor + i + 1;
 
 
      *pp = cg;
      *pp = cg;
      pp = &(*pp)->next;
      pp = &(*pp)->next;
    }
    }
 
 
  free (icondirs);
  free (icondirs);
 
 
  r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
  r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_GROUP_CURSOR;
  r->type = RES_TYPE_GROUP_CURSOR;
  r->u.group_cursor = first;
  r->u.group_cursor = first;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a dialog resource.  */
/* Define a dialog resource.  */
 
 
void
void
define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
               const rc_dialog *dialog)
               const rc_dialog *dialog)
{
{
  rc_dialog *copy;
  rc_dialog *copy;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  copy = (rc_dialog *) res_alloc (sizeof *copy);
  copy = (rc_dialog *) res_alloc (sizeof *copy);
  *copy = *dialog;
  *copy = *dialog;
 
 
  r = define_standard_resource (&resources, RT_DIALOG, id,
  r = define_standard_resource (&resources, RT_DIALOG, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_DIALOG;
  r->type = RES_TYPE_DIALOG;
  r->u.dialog = copy;
  r->u.dialog = copy;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a dialog control.  This does not define a resource, but
/* Define a dialog control.  This does not define a resource, but
   merely allocates and fills in a structure.  */
   merely allocates and fills in a structure.  */
 
 
rc_dialog_control *
rc_dialog_control *
define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
                rc_uint_type y, rc_uint_type width, rc_uint_type height,
                rc_uint_type y, rc_uint_type width, rc_uint_type height,
                const rc_res_id class, rc_uint_type style,
                const rc_res_id class, rc_uint_type style,
                rc_uint_type exstyle)
                rc_uint_type exstyle)
{
{
  rc_dialog_control *n;
  rc_dialog_control *n;
 
 
  n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
  n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
  n->next = NULL;
  n->next = NULL;
  n->id = id;
  n->id = id;
  n->style = style;
  n->style = style;
  n->exstyle = exstyle;
  n->exstyle = exstyle;
  n->x = x;
  n->x = x;
  n->y = y;
  n->y = y;
  n->width = width;
  n->width = width;
  n->height = height;
  n->height = height;
  n->class = class;
  n->class = class;
  n->text = iid;
  n->text = iid;
  n->data = NULL;
  n->data = NULL;
  n->help = 0;
  n->help = 0;
 
 
  return n;
  return n;
}
}
 
 
rc_dialog_control *
rc_dialog_control *
define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
                     rc_uint_type y, rc_uint_type style,
                     rc_uint_type y, rc_uint_type style,
                     rc_uint_type exstyle, rc_uint_type help,
                     rc_uint_type exstyle, rc_uint_type help,
                     rc_rcdata_item *data, rc_dialog_ex *ex)
                     rc_rcdata_item *data, rc_dialog_ex *ex)
{
{
  rc_dialog_control *n;
  rc_dialog_control *n;
  rc_res_id tid;
  rc_res_id tid;
  rc_res_id cid;
  rc_res_id cid;
 
 
  if (style == 0)
  if (style == 0)
    style = SS_ICON | WS_CHILD | WS_VISIBLE;
    style = SS_ICON | WS_CHILD | WS_VISIBLE;
  res_string_to_id (&tid, "");
  res_string_to_id (&tid, "");
  cid.named = 0;
  cid.named = 0;
  cid.u.id = CTL_STATIC;
  cid.u.id = CTL_STATIC;
  n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
  n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
  n->text = iid;
  n->text = iid;
  if (help && ! ex)
  if (help && ! ex)
    rcparse_warning (_("help ID requires DIALOGEX"));
    rcparse_warning (_("help ID requires DIALOGEX"));
  if (data && ! ex)
  if (data && ! ex)
    rcparse_warning (_("control data requires DIALOGEX"));
    rcparse_warning (_("control data requires DIALOGEX"));
  n->help = help;
  n->help = help;
  n->data = data;
  n->data = data;
 
 
  return n;
  return n;
}
}
 
 
/* Define a font resource.  */
/* Define a font resource.  */
 
 
void
void
define_font (rc_res_id id, const rc_res_res_info *resinfo,
define_font (rc_res_id id, const rc_res_res_info *resinfo,
             const char *filename)
             const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  struct stat s;
  struct stat s;
  bfd_byte *data;
  bfd_byte *data;
  rc_res_resource *r;
  rc_res_resource *r;
  long offset;
  long offset;
  long fontdatalength;
  long fontdatalength;
  bfd_byte *fontdata;
  bfd_byte *fontdata;
  rc_fontdir *fd;
  rc_fontdir *fd;
  const char *device, *face;
  const char *device, *face;
  rc_fontdir **pp;
  rc_fontdir **pp;
 
 
  e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
 
 
  if (stat (real_filename, &s) < 0)
  if (stat (real_filename, &s) < 0)
    fatal (_("stat failed on font file `%s': %s"), real_filename,
    fatal (_("stat failed on font file `%s': %s"), real_filename,
           strerror (errno));
           strerror (errno));
 
 
  data = (bfd_byte *) res_alloc (s.st_size);
  data = (bfd_byte *) res_alloc (s.st_size);
 
 
  get_data (e, data, s.st_size, real_filename);
  get_data (e, data, s.st_size, real_filename);
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  r = define_standard_resource (&resources, RT_FONT, id,
  r = define_standard_resource (&resources, RT_FONT, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
 
 
  r->type = RES_TYPE_FONT;
  r->type = RES_TYPE_FONT;
  r->u.data.length = s.st_size;
  r->u.data.length = s.st_size;
  r->u.data.data = data;
  r->u.data.data = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
 
 
  /* For each font resource, we must add an entry in the FONTDIR
  /* For each font resource, we must add an entry in the FONTDIR
     resource.  The FONTDIR resource includes some strings in the font
     resource.  The FONTDIR resource includes some strings in the font
     file.  To find them, we have to do some magic on the data we have
     file.  To find them, we have to do some magic on the data we have
     read.  */
     read.  */
 
 
  offset = ((((((data[47] << 8)
  offset = ((((((data[47] << 8)
                | data[46]) << 8)
                | data[46]) << 8)
              | data[45]) << 8)
              | data[45]) << 8)
            | data[44]);
            | data[44]);
  if (offset > 0 && offset < s.st_size)
  if (offset > 0 && offset < s.st_size)
    device = (char *) data + offset;
    device = (char *) data + offset;
  else
  else
    device = "";
    device = "";
 
 
  offset = ((((((data[51] << 8)
  offset = ((((((data[51] << 8)
                | data[50]) << 8)
                | data[50]) << 8)
              | data[49]) << 8)
              | data[49]) << 8)
            | data[48]);
            | data[48]);
  if (offset > 0 && offset < s.st_size)
  if (offset > 0 && offset < s.st_size)
    face = (char *) data + offset;
    face = (char *) data + offset;
  else
  else
    face = "";
    face = "";
 
 
  ++fonts;
  ++fonts;
 
 
  fontdatalength = 58 + strlen (device) + strlen (face);
  fontdatalength = 58 + strlen (device) + strlen (face);
  fontdata = (bfd_byte *) res_alloc (fontdatalength);
  fontdata = (bfd_byte *) res_alloc (fontdatalength);
  memcpy (fontdata, data, 56);
  memcpy (fontdata, data, 56);
  strcpy ((char *) fontdata + 56, device);
  strcpy ((char *) fontdata + 56, device);
  strcpy ((char *) fontdata + 57 + strlen (device), face);
  strcpy ((char *) fontdata + 57 + strlen (device), face);
 
 
  fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
  fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
  fd->next = NULL;
  fd->next = NULL;
  fd->index = fonts;
  fd->index = fonts;
  fd->length = fontdatalength;
  fd->length = fontdatalength;
  fd->data = fontdata;
  fd->data = fontdata;
 
 
  for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
  for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
    ;
    ;
  *pp = fd;
  *pp = fd;
 
 
  /* For the single fontdirs resource, we always use the resource
  /* For the single fontdirs resource, we always use the resource
     information of the last font.  I don't know what else to do.  */
     information of the last font.  I don't know what else to do.  */
  fontdirs_resinfo = *resinfo;
  fontdirs_resinfo = *resinfo;
}
}
 
 
static void
static void
define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
                    rc_rcdata_item *data)
                    rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  r = define_standard_resource (&resources, RT_FONT, id,
  r = define_standard_resource (&resources, RT_FONT, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  r->type = RES_TYPE_FONT;
  r->type = RES_TYPE_FONT;
  r->u.data.length = len_data;
  r->u.data.length = len_data;
  r->u.data.data = pb_data;
  r->u.data.data = pb_data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define the fontdirs resource.  This is called after the entire rc
/* Define the fontdirs resource.  This is called after the entire rc
   file has been parsed, if any font resources were seen.  */
   file has been parsed, if any font resources were seen.  */
 
 
static void
static void
define_fontdirs (void)
define_fontdirs (void)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_res_id id;
  rc_res_id id;
 
 
  id.named = 0;
  id.named = 0;
  id.u.id = 1;
  id.u.id = 1;
 
 
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
 
 
  r->type = RES_TYPE_FONTDIR;
  r->type = RES_TYPE_FONTDIR;
  r->u.fontdir = fontdirs;
  r->u.fontdir = fontdirs;
  r->res_info = fontdirs_resinfo;
  r->res_info = fontdirs_resinfo;
}
}
 
 
static bfd_byte *
static bfd_byte *
rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
{
{
  const rc_rcdata_item *d;
  const rc_rcdata_item *d;
  bfd_byte *ret = NULL, *pret;
  bfd_byte *ret = NULL, *pret;
  rc_uint_type len = 0;
  rc_uint_type len = 0;
 
 
  for (d = data; d != NULL; d = d->next)
  for (d = data; d != NULL; d = d->next)
    len += rcdata_copy (d, NULL);
    len += rcdata_copy (d, NULL);
  if (len != 0)
  if (len != 0)
    {
    {
      ret = pret = (bfd_byte *) res_alloc (len);
      ret = pret = (bfd_byte *) res_alloc (len);
      for (d = data; d != NULL; d = d->next)
      for (d = data; d != NULL; d = d->next)
        pret += rcdata_copy (d, pret);
        pret += rcdata_copy (d, pret);
    }
    }
  if (plen)
  if (plen)
    *plen = len;
    *plen = len;
  return ret;
  return ret;
}
}
 
 
static void
static void
define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
                       rc_rcdata_item *data)
                       rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_fontdir *fd, *fd_first, *fd_cur;
  rc_fontdir *fd, *fd_first, *fd_cur;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
  rc_uint_type c;
  rc_uint_type c;
 
 
  fd_cur = fd_first = NULL;
  fd_cur = fd_first = NULL;
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  if (pb_data)
  if (pb_data)
    {
    {
      rc_uint_type off = 2;
      rc_uint_type off = 2;
      c = windres_get_16 (&wrtarget, pb_data, len_data);
      c = windres_get_16 (&wrtarget, pb_data, len_data);
      for (; c > 0; c--)
      for (; c > 0; c--)
        {
        {
          size_t len;
          size_t len;
          rc_uint_type safe_pos = off;
          rc_uint_type safe_pos = off;
          const struct bin_fontdir_item *bfi;
          const struct bin_fontdir_item *bfi;
 
 
          bfi = (const struct bin_fontdir_item *) pb_data + off;
          bfi = (const struct bin_fontdir_item *) pb_data + off;
          fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
          fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
          fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
          fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
          fd->data = pb_data + off;
          fd->data = pb_data + off;
          off += 56;
          off += 56;
          len = strlen ((char *) bfi->device_name) + 1;
          len = strlen ((char *) bfi->device_name) + 1;
          off += (rc_uint_type) len;
          off += (rc_uint_type) len;
          off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
          off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
          fd->length = (off - safe_pos);
          fd->length = (off - safe_pos);
          fd->next = NULL;
          fd->next = NULL;
          if (fd_first == NULL)
          if (fd_first == NULL)
            fd_first = fd;
            fd_first = fd;
          else
          else
            fd_cur->next = fd;
            fd_cur->next = fd;
          fd_cur = fd;
          fd_cur = fd;
        }
        }
    }
    }
  r->type = RES_TYPE_FONTDIR;
  r->type = RES_TYPE_FONTDIR;
  r->u.fontdir = fd_first;
  r->u.fontdir = fd_first;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                                        rc_rcdata_item *data)
                                        rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
  r->type = RES_TYPE_MESSAGETABLE;
  r->type = RES_TYPE_MESSAGETABLE;
  r->u.data.length = len_data;
  r->u.data.length = len_data;
  r->u.data.data = pb_data;
  r->u.data.data = pb_data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define an icon resource.  An icon file may contain a set of
/* Define an icon resource.  An icon file may contain a set of
   bitmaps, each representing the same icon at various different
   bitmaps, each representing the same icon at various different
   resolutions.  They each get written out with a different ID.  The
   resolutions.  They each get written out with a different ID.  The
   real icon resource is then a group resource which can be used to
   real icon resource is then a group resource which can be used to
   select one of the actual icon bitmaps.  */
   select one of the actual icon bitmaps.  */
 
 
void
void
define_icon (rc_res_id id, const rc_res_res_info *resinfo,
define_icon (rc_res_id id, const rc_res_res_info *resinfo,
             const char *filename)
             const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  int type, count, i;
  int type, count, i;
  struct icondir *icondirs;
  struct icondir *icondirs;
  int first_icon;
  int first_icon;
  rc_res_resource *r;
  rc_res_resource *r;
  rc_group_icon *first, **pp;
  rc_group_icon *first, **pp;
 
 
  e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
 
 
  /* The start of an icon file is a three word structure.  The first
  /* The start of an icon file is a three word structure.  The first
     word is ignored.  The second word is the type of data.  The third
     word is ignored.  The second word is the type of data.  The third
     word is the number of entries.  */
     word is the number of entries.  */
 
 
  get_word (e, real_filename);
  get_word (e, real_filename);
  type = get_word (e, real_filename);
  type = get_word (e, real_filename);
  count = get_word (e, real_filename);
  count = get_word (e, real_filename);
  if (type != 1)
  if (type != 1)
    fatal (_("icon file `%s' does not contain icon data"), real_filename);
    fatal (_("icon file `%s' does not contain icon data"), real_filename);
 
 
  /* Read in the icon directory entries.  */
  /* Read in the icon directory entries.  */
 
 
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
 
 
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      icondirs[i].width = getc (e);
      icondirs[i].width = getc (e);
      icondirs[i].height = getc (e);
      icondirs[i].height = getc (e);
      icondirs[i].colorcount = getc (e);
      icondirs[i].colorcount = getc (e);
      getc (e);
      getc (e);
      icondirs[i].u.icon.planes = get_word (e, real_filename);
      icondirs[i].u.icon.planes = get_word (e, real_filename);
      icondirs[i].u.icon.bits = get_word (e, real_filename);
      icondirs[i].u.icon.bits = get_word (e, real_filename);
      icondirs[i].bytes = get_long (e, real_filename);
      icondirs[i].bytes = get_long (e, real_filename);
      icondirs[i].offset = get_long (e, real_filename);
      icondirs[i].offset = get_long (e, real_filename);
 
 
      if (feof (e))
      if (feof (e))
        unexpected_eof (real_filename);
        unexpected_eof (real_filename);
    }
    }
 
 
  /* Define each icon as a unique resource.  */
  /* Define each icon as a unique resource.  */
 
 
  first_icon = icons;
  first_icon = icons;
 
 
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      bfd_byte *data;
      bfd_byte *data;
      rc_res_id name;
      rc_res_id name;
 
 
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
        fatal (_("%s: fseek to %lu failed: %s"), real_filename,
               icondirs[i].offset, strerror (errno));
               icondirs[i].offset, strerror (errno));
 
 
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
      data = (bfd_byte *) res_alloc (icondirs[i].bytes);
 
 
      get_data (e, data, icondirs[i].bytes, real_filename);
      get_data (e, data, icondirs[i].bytes, real_filename);
 
 
      ++icons;
      ++icons;
 
 
      name.named = 0;
      name.named = 0;
      name.u.id = icons;
      name.u.id = icons;
 
 
      r = define_standard_resource (&resources, RT_ICON, name,
      r = define_standard_resource (&resources, RT_ICON, name,
                                    resinfo->language, 0);
                                    resinfo->language, 0);
      r->type = RES_TYPE_ICON;
      r->type = RES_TYPE_ICON;
      r->u.data.length = icondirs[i].bytes;
      r->u.data.length = icondirs[i].bytes;
      r->u.data.data = data;
      r->u.data.data = data;
      r->res_info = *resinfo;
      r->res_info = *resinfo;
    }
    }
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  /* Define an icon group resource.  */
  /* Define an icon group resource.  */
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    {
    {
      rc_group_icon *cg;
      rc_group_icon *cg;
 
 
      /* For some reason, at least in some files the planes and bits
      /* For some reason, at least in some files the planes and bits
         are zero.  We instead set them from the color.  This is
         are zero.  We instead set them from the color.  This is
         copied from rcl.  */
         copied from rcl.  */
 
 
      cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
      cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
      cg->next = NULL;
      cg->next = NULL;
      cg->width = icondirs[i].width;
      cg->width = icondirs[i].width;
      cg->height = icondirs[i].height;
      cg->height = icondirs[i].height;
      cg->colors = icondirs[i].colorcount;
      cg->colors = icondirs[i].colorcount;
 
 
      if (icondirs[i].u.icon.planes)
      if (icondirs[i].u.icon.planes)
        cg->planes = icondirs[i].u.icon.planes;
        cg->planes = icondirs[i].u.icon.planes;
      else
      else
        cg->planes = 1;
        cg->planes = 1;
 
 
      if (icondirs[i].u.icon.bits)
      if (icondirs[i].u.icon.bits)
        cg->bits = icondirs[i].u.icon.bits;
        cg->bits = icondirs[i].u.icon.bits;
      else
      else
        {
        {
          cg->bits = 0;
          cg->bits = 0;
 
 
          while ((1L << cg->bits) < cg->colors)
          while ((1L << cg->bits) < cg->colors)
            ++cg->bits;
            ++cg->bits;
        }
        }
 
 
      cg->bytes = icondirs[i].bytes;
      cg->bytes = icondirs[i].bytes;
      cg->index = first_icon + i + 1;
      cg->index = first_icon + i + 1;
 
 
      *pp = cg;
      *pp = cg;
      pp = &(*pp)->next;
      pp = &(*pp)->next;
    }
    }
 
 
  free (icondirs);
  free (icondirs);
 
 
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_GROUP_ICON;
  r->type = RES_TYPE_GROUP_ICON;
  r->u.group_icon = first;
  r->u.group_icon = first;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void
static void
define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                          rc_rcdata_item *data)
                          rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_group_icon *cg, *first, *cur;
  rc_group_icon *cg, *first, *cur;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  cur = NULL;
  cur = NULL;
  first = NULL;
  first = NULL;
 
 
  while (len_data >= 6)
  while (len_data >= 6)
    {
    {
      int c, i;
      int c, i;
      unsigned short type;
      unsigned short type;
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
      if (type != 1)
      if (type != 1)
        fatal (_("unexpected group icon type %d"), type);
        fatal (_("unexpected group icon type %d"), type);
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
      len_data -= 6;
      len_data -= 6;
      pb_data += 6;
      pb_data += 6;
 
 
      for (i = 0; i < c; i++)
      for (i = 0; i < c; i++)
        {
        {
          if (len_data < 14)
          if (len_data < 14)
            fatal ("too small group icon rcdata");
            fatal ("too small group icon rcdata");
          cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
          cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
          cg->next = NULL;
          cg->next = NULL;
          cg->width = pb_data[0];
          cg->width = pb_data[0];
          cg->height = pb_data[1];
          cg->height = pb_data[1];
          cg->colors = pb_data[2];
          cg->colors = pb_data[2];
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
          if (! first)
          if (! first)
            first = cg;
            first = cg;
          else
          else
            cur->next = cg;
            cur->next = cg;
          cur = cg;
          cur = cg;
          pb_data += 14;
          pb_data += 14;
          len_data -= 14;
          len_data -= 14;
        }
        }
    }
    }
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_GROUP_ICON;
  r->type = RES_TYPE_GROUP_ICON;
  r->u.group_icon = first;
  r->u.group_icon = first;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void
static void
define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                            rc_rcdata_item *data)
                            rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_group_cursor *cg, *first, *cur;
  rc_group_cursor *cg, *first, *cur;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  first = cur = NULL;
  first = cur = NULL;
 
 
  while (len_data >= 6)
  while (len_data >= 6)
    {
    {
      int c, i;
      int c, i;
      unsigned short type;
      unsigned short type;
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
      type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
      if (type != 2)
      if (type != 2)
        fatal (_("unexpected group cursor type %d"), type);
        fatal (_("unexpected group cursor type %d"), type);
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
      c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
      len_data -= 6;
      len_data -= 6;
      pb_data += 6;
      pb_data += 6;
 
 
      for (i = 0; i < c; i++)
      for (i = 0; i < c; i++)
        {
        {
          if (len_data < 14)
          if (len_data < 14)
            fatal ("too small group icon rcdata");
            fatal ("too small group icon rcdata");
          cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
          cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
          cg->next = NULL;
          cg->next = NULL;
          cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
          cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
          cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
          cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
          cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
          cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
          cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
          cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
          if (! first)
          if (! first)
            first = cg;
            first = cg;
          else
          else
            cur->next = cg;
            cur->next = cg;
          cur = cg;
          cur = cg;
          pb_data += 14;
          pb_data += 14;
          len_data -= 14;
          len_data -= 14;
        }
        }
    }
    }
 
 
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_GROUP_CURSOR;
  r->type = RES_TYPE_GROUP_CURSOR;
  r->u.group_cursor = first;
  r->u.group_cursor = first;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void
static void
define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                      rc_rcdata_item *data)
                      rc_rcdata_item *data)
{
{
  rc_cursor *c;
  rc_cursor *c;
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
  c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
  c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  c->length = len_data - BIN_CURSOR_SIZE;
  c->length = len_data - BIN_CURSOR_SIZE;
  c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
  c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
 
 
  r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
  r->type = RES_TYPE_CURSOR;
  r->type = RES_TYPE_CURSOR;
  r->u.cursor = c;
  r->u.cursor = c;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void
static void
define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                      rc_rcdata_item *data)
                      rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
  r->type = RES_TYPE_BITMAP;
  r->type = RES_TYPE_BITMAP;
  r->u.data.length = len_data;
  r->u.data.length = len_data;
  r->u.data.data = pb_data;
  r->u.data.data = pb_data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
static void
static void
define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
                    rc_rcdata_item *data)
                    rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type len_data;
  rc_uint_type len_data;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
 
 
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
 
 
  r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
  r->type = RES_TYPE_ICON;
  r->type = RES_TYPE_ICON;
  r->u.data.length = len_data;
  r->u.data.length = len_data;
  r->u.data.data = pb_data;
  r->u.data.data = pb_data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a menu resource.  */
/* Define a menu resource.  */
 
 
void
void
define_menu (rc_res_id id, const rc_res_res_info *resinfo,
define_menu (rc_res_id id, const rc_res_res_info *resinfo,
             rc_menuitem *menuitems)
             rc_menuitem *menuitems)
{
{
  rc_menu *m;
  rc_menu *m;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  m = (rc_menu *) res_alloc (sizeof (rc_menu));
  m = (rc_menu *) res_alloc (sizeof (rc_menu));
  m->items = menuitems;
  m->items = menuitems;
  m->help = 0;
  m->help = 0;
 
 
  r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
  r->type = RES_TYPE_MENU;
  r->type = RES_TYPE_MENU;
  r->u.menu = m;
  r->u.menu = m;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a menu item.  This does not define a resource, but merely
/* Define a menu item.  This does not define a resource, but merely
   allocates and fills in a structure.  */
   allocates and fills in a structure.  */
 
 
rc_menuitem *
rc_menuitem *
define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
                 rc_uint_type state, rc_uint_type help,
                 rc_uint_type state, rc_uint_type help,
                 rc_menuitem *menuitems)
                 rc_menuitem *menuitems)
{
{
  rc_menuitem *mi;
  rc_menuitem *mi;
 
 
  mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
  mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
  mi->next = NULL;
  mi->next = NULL;
  mi->type = type;
  mi->type = type;
  mi->state = state;
  mi->state = state;
  mi->id = menuid;
  mi->id = menuid;
  mi->text = unichar_dup (text);
  mi->text = unichar_dup (text);
  mi->help = help;
  mi->help = help;
  mi->popup = menuitems;
  mi->popup = menuitems;
  return mi;
  return mi;
}
}
 
 
/* Define a messagetable resource.  */
/* Define a messagetable resource.  */
 
 
void
void
define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
                     const char *filename)
                     const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  struct stat s;
  struct stat s;
  bfd_byte *data;
  bfd_byte *data;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  e = open_file_search (filename, FOPEN_RB, "messagetable file",
  e = open_file_search (filename, FOPEN_RB, "messagetable file",
                        &real_filename);
                        &real_filename);
 
 
  if (stat (real_filename, &s) < 0)
  if (stat (real_filename, &s) < 0)
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
           strerror (errno));
           strerror (errno));
 
 
  data = (bfd_byte *) res_alloc (s.st_size);
  data = (bfd_byte *) res_alloc (s.st_size);
 
 
  get_data (e, data, s.st_size, real_filename);
  get_data (e, data, s.st_size, real_filename);
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
  r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
 
 
  r->type = RES_TYPE_MESSAGETABLE;
  r->type = RES_TYPE_MESSAGETABLE;
  r->u.data.length = s.st_size;
  r->u.data.length = s.st_size;
  r->u.data.data = data;
  r->u.data.data = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define an rcdata resource.  */
/* Define an rcdata resource.  */
 
 
void
void
define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
               rc_rcdata_item *data)
               rc_rcdata_item *data)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  r = define_standard_resource (&resources, RT_RCDATA, id,
  r = define_standard_resource (&resources, RT_RCDATA, id,
                                resinfo->language, 0);
                                resinfo->language, 0);
  r->type = RES_TYPE_RCDATA;
  r->type = RES_TYPE_RCDATA;
  r->u.rcdata = data;
  r->u.rcdata = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Create an rcdata item holding a string.  */
/* Create an rcdata item holding a string.  */
 
 
rc_rcdata_item *
rc_rcdata_item *
define_rcdata_string (const char *string, rc_uint_type len)
define_rcdata_string (const char *string, rc_uint_type len)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
  char *s;
  char *s;
 
 
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri->next = NULL;
  ri->next = NULL;
  ri->type = RCDATA_STRING;
  ri->type = RCDATA_STRING;
  ri->u.string.length = len;
  ri->u.string.length = len;
  s = (char *) res_alloc (len);
  s = (char *) res_alloc (len);
  memcpy (s, string, len);
  memcpy (s, string, len);
  ri->u.string.s = s;
  ri->u.string.s = s;
 
 
  return ri;
  return ri;
}
}
 
 
/* Create an rcdata item holding a unicode string.  */
/* Create an rcdata item holding a unicode string.  */
 
 
rc_rcdata_item *
rc_rcdata_item *
define_rcdata_unistring (const unichar *string, rc_uint_type len)
define_rcdata_unistring (const unichar *string, rc_uint_type len)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
  unichar *s;
  unichar *s;
 
 
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri->next = NULL;
  ri->next = NULL;
  ri->type = RCDATA_WSTRING;
  ri->type = RCDATA_WSTRING;
  ri->u.wstring.length = len;
  ri->u.wstring.length = len;
  s = (unichar *) res_alloc (len * sizeof (unichar));
  s = (unichar *) res_alloc (len * sizeof (unichar));
  memcpy (s, string, len * sizeof (unichar));
  memcpy (s, string, len * sizeof (unichar));
  ri->u.wstring.w = s;
  ri->u.wstring.w = s;
 
 
  return ri;
  return ri;
}
}
 
 
/* Create an rcdata item holding a number.  */
/* Create an rcdata item holding a number.  */
 
 
rc_rcdata_item *
rc_rcdata_item *
define_rcdata_number (rc_uint_type val, int dword)
define_rcdata_number (rc_uint_type val, int dword)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
 
 
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri->next = NULL;
  ri->next = NULL;
  ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
  ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
  ri->u.word = val;
  ri->u.word = val;
 
 
  return ri;
  return ri;
}
}
 
 
/* Define a stringtable resource.  This is called for each string
/* Define a stringtable resource.  This is called for each string
   which appears in a STRINGTABLE statement.  */
   which appears in a STRINGTABLE statement.  */
 
 
void
void
define_stringtable (const rc_res_res_info *resinfo,
define_stringtable (const rc_res_res_info *resinfo,
                    rc_uint_type stringid, const unichar *string)
                    rc_uint_type stringid, const unichar *string)
{
{
  rc_res_id id;
  rc_res_id id;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  id.named = 0;
  id.named = 0;
  id.u.id = (stringid >> 4) + 1;
  id.u.id = (stringid >> 4) + 1;
  r = define_standard_resource (&resources, RT_STRING, id,
  r = define_standard_resource (&resources, RT_STRING, id,
                                resinfo->language, 1);
                                resinfo->language, 1);
 
 
  if (r->type == RES_TYPE_UNINITIALIZED)
  if (r->type == RES_TYPE_UNINITIALIZED)
    {
    {
      int i;
      int i;
 
 
      r->type = RES_TYPE_STRINGTABLE;
      r->type = RES_TYPE_STRINGTABLE;
      r->u.stringtable = ((rc_stringtable *)
      r->u.stringtable = ((rc_stringtable *)
                          res_alloc (sizeof (rc_stringtable)));
                          res_alloc (sizeof (rc_stringtable)));
      for (i = 0; i < 16; i++)
      for (i = 0; i < 16; i++)
        {
        {
          r->u.stringtable->strings[i].length = 0;
          r->u.stringtable->strings[i].length = 0;
          r->u.stringtable->strings[i].string = NULL;
          r->u.stringtable->strings[i].string = NULL;
        }
        }
 
 
      r->res_info = *resinfo;
      r->res_info = *resinfo;
    }
    }
 
 
  r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string);
  r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string);
  r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string);
  r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string);
}
}
 
 
void
void
define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
                rc_toolbar_item *items)
                rc_toolbar_item *items)
{
{
  rc_toolbar *t;
  rc_toolbar *t;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
  t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
  t->button_width = width;
  t->button_width = width;
  t->button_height = height;
  t->button_height = height;
  t->nitems = 0;
  t->nitems = 0;
  t->items = items;
  t->items = items;
  while (items != NULL)
  while (items != NULL)
  {
  {
    t->nitems+=1;
    t->nitems+=1;
    items = items->next;
    items = items->next;
  }
  }
  r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
  r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
  r->type = RES_TYPE_TOOLBAR;
  r->type = RES_TYPE_TOOLBAR;
  r->u.toolbar = t;
  r->u.toolbar = t;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a user data resource where the data is in the rc file.  */
/* Define a user data resource where the data is in the rc file.  */
 
 
void
void
define_user_data (rc_res_id id, rc_res_id type,
define_user_data (rc_res_id id, rc_res_id type,
                  const rc_res_res_info *resinfo,
                  const rc_res_res_info *resinfo,
                  rc_rcdata_item *data)
                  rc_rcdata_item *data)
{
{
  rc_res_id ids[3];
  rc_res_id ids[3];
  rc_res_resource *r;
  rc_res_resource *r;
  bfd_byte *pb_data;
  bfd_byte *pb_data;
  rc_uint_type len_data;
  rc_uint_type len_data;
 
 
  /* We have to check if the binary data is parsed specially.  */
  /* We have to check if the binary data is parsed specially.  */
  if (type.named == 0)
  if (type.named == 0)
    {
    {
      switch (type.u.id)
      switch (type.u.id)
      {
      {
      case RT_FONTDIR:
      case RT_FONTDIR:
        define_fontdir_rcdata (id, resinfo, data);
        define_fontdir_rcdata (id, resinfo, data);
        return;
        return;
      case RT_FONT:
      case RT_FONT:
        define_font_rcdata (id, resinfo, data);
        define_font_rcdata (id, resinfo, data);
        return;
        return;
      case RT_ICON:
      case RT_ICON:
        define_icon_rcdata (id, resinfo, data);
        define_icon_rcdata (id, resinfo, data);
        return;
        return;
      case RT_BITMAP:
      case RT_BITMAP:
        define_bitmap_rcdata (id, resinfo, data);
        define_bitmap_rcdata (id, resinfo, data);
        return;
        return;
      case RT_CURSOR:
      case RT_CURSOR:
        define_cursor_rcdata (id, resinfo, data);
        define_cursor_rcdata (id, resinfo, data);
        return;
        return;
      case RT_GROUP_ICON:
      case RT_GROUP_ICON:
        define_group_icon_rcdata (id, resinfo, data);
        define_group_icon_rcdata (id, resinfo, data);
        return;
        return;
      case RT_GROUP_CURSOR:
      case RT_GROUP_CURSOR:
        define_group_cursor_rcdata (id, resinfo, data);
        define_group_cursor_rcdata (id, resinfo, data);
        return;
        return;
      case RT_MESSAGETABLE:
      case RT_MESSAGETABLE:
        define_messagetable_rcdata (id, resinfo, data);
        define_messagetable_rcdata (id, resinfo, data);
        return;
        return;
      default:
      default:
        /* Treat as normal user-data.  */
        /* Treat as normal user-data.  */
        break;
        break;
      }
      }
    }
    }
  ids[0] = type;
  ids[0] = type;
  ids[1] = id;
  ids[1] = id;
  ids[2].named = 0;
  ids[2].named = 0;
  ids[2].u.id = resinfo->language;
  ids[2].u.id = resinfo->language;
 
 
  r = define_resource (& resources, 3, ids, 0);
  r = define_resource (& resources, 3, ids, 0);
  r->type = RES_TYPE_USERDATA;
  r->type = RES_TYPE_USERDATA;
  r->u.userdata = ((rc_rcdata_item *)
  r->u.userdata = ((rc_rcdata_item *)
                   res_alloc (sizeof (rc_rcdata_item)));
                   res_alloc (sizeof (rc_rcdata_item)));
  r->u.userdata->next = NULL;
  r->u.userdata->next = NULL;
  r->u.userdata->type = RCDATA_BUFFER;
  r->u.userdata->type = RCDATA_BUFFER;
  pb_data = rcdata_render_as_buffer (data, &len_data);
  pb_data = rcdata_render_as_buffer (data, &len_data);
  r->u.userdata->u.buffer.length = len_data;
  r->u.userdata->u.buffer.length = len_data;
  r->u.userdata->u.buffer.data = pb_data;
  r->u.userdata->u.buffer.data = pb_data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
void
void
define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
                    const char *filename)
                    const char *filename)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  struct stat s;
  struct stat s;
  bfd_byte *data;
  bfd_byte *data;
 
 
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
 
 
 
 
  if (stat (real_filename, &s) < 0)
  if (stat (real_filename, &s) < 0)
    fatal (_("stat failed on file `%s': %s"), real_filename,
    fatal (_("stat failed on file `%s': %s"), real_filename,
           strerror (errno));
           strerror (errno));
 
 
  data = (bfd_byte *) res_alloc (s.st_size);
  data = (bfd_byte *) res_alloc (s.st_size);
 
 
  get_data (e, data, s.st_size, real_filename);
  get_data (e, data, s.st_size, real_filename);
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  ri->next = NULL;
  ri->next = NULL;
  ri->type = RCDATA_BUFFER;
  ri->type = RCDATA_BUFFER;
  ri->u.buffer.length = s.st_size;
  ri->u.buffer.length = s.st_size;
  ri->u.buffer.data = data;
  ri->u.buffer.data = data;
 
 
  define_rcdata (id, resinfo, ri);
  define_rcdata (id, resinfo, ri);
}
}
 
 
/* Define a user data resource where the data is in a file.  */
/* Define a user data resource where the data is in a file.  */
 
 
void
void
define_user_file (rc_res_id id, rc_res_id type,
define_user_file (rc_res_id id, rc_res_id type,
                  const rc_res_res_info *resinfo, const char *filename)
                  const rc_res_res_info *resinfo, const char *filename)
{
{
  FILE *e;
  FILE *e;
  char *real_filename;
  char *real_filename;
  struct stat s;
  struct stat s;
  bfd_byte *data;
  bfd_byte *data;
  rc_res_id ids[3];
  rc_res_id ids[3];
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
  e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
 
 
  if (stat (real_filename, &s) < 0)
  if (stat (real_filename, &s) < 0)
    fatal (_("stat failed on file `%s': %s"), real_filename,
    fatal (_("stat failed on file `%s': %s"), real_filename,
           strerror (errno));
           strerror (errno));
 
 
  data = (bfd_byte *) res_alloc (s.st_size);
  data = (bfd_byte *) res_alloc (s.st_size);
 
 
  get_data (e, data, s.st_size, real_filename);
  get_data (e, data, s.st_size, real_filename);
 
 
  fclose (e);
  fclose (e);
  free (real_filename);
  free (real_filename);
 
 
  ids[0] = type;
  ids[0] = type;
  ids[1] = id;
  ids[1] = id;
  ids[2].named = 0;
  ids[2].named = 0;
  ids[2].u.id = resinfo->language;
  ids[2].u.id = resinfo->language;
 
 
  r = define_resource (&resources, 3, ids, 0);
  r = define_resource (&resources, 3, ids, 0);
  r->type = RES_TYPE_USERDATA;
  r->type = RES_TYPE_USERDATA;
  r->u.userdata = ((rc_rcdata_item *)
  r->u.userdata = ((rc_rcdata_item *)
                   res_alloc (sizeof (rc_rcdata_item)));
                   res_alloc (sizeof (rc_rcdata_item)));
  r->u.userdata->next = NULL;
  r->u.userdata->next = NULL;
  r->u.userdata->type = RCDATA_BUFFER;
  r->u.userdata->type = RCDATA_BUFFER;
  r->u.userdata->u.buffer.length = s.st_size;
  r->u.userdata->u.buffer.length = s.st_size;
  r->u.userdata->u.buffer.data = data;
  r->u.userdata->u.buffer.data = data;
  r->res_info = *resinfo;
  r->res_info = *resinfo;
}
}
 
 
/* Define a versioninfo resource.  */
/* Define a versioninfo resource.  */
 
 
void
void
define_versioninfo (rc_res_id id, rc_uint_type language,
define_versioninfo (rc_res_id id, rc_uint_type language,
                    rc_fixed_versioninfo *fixedverinfo,
                    rc_fixed_versioninfo *fixedverinfo,
                    rc_ver_info *verinfo)
                    rc_ver_info *verinfo)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
  r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
  r->type = RES_TYPE_VERSIONINFO;
  r->type = RES_TYPE_VERSIONINFO;
  r->u.versioninfo = ((rc_versioninfo *)
  r->u.versioninfo = ((rc_versioninfo *)
                      res_alloc (sizeof (rc_versioninfo)));
                      res_alloc (sizeof (rc_versioninfo)));
  r->u.versioninfo->fixed = fixedverinfo;
  r->u.versioninfo->fixed = fixedverinfo;
  r->u.versioninfo->var = verinfo;
  r->u.versioninfo->var = verinfo;
  r->res_info.language = language;
  r->res_info.language = language;
}
}
 
 
/* Add string version info to a list of version information.  */
/* Add string version info to a list of version information.  */
 
 
rc_ver_info *
rc_ver_info *
append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language,
append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language,
                           rc_ver_stringinfo *strings)
                           rc_ver_stringinfo *strings)
{
{
  rc_ver_info *vi, **pp;
  rc_ver_info *vi, **pp;
 
 
  vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
  vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
  vi->next = NULL;
  vi->next = NULL;
  vi->type = VERINFO_STRING;
  vi->type = VERINFO_STRING;
  unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language);
  unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language);
  vi->u.string.strings = strings;
  vi->u.string.strings = strings;
 
 
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
    ;
    ;
  *pp = vi;
  *pp = vi;
 
 
  return verinfo;
  return verinfo;
}
}
 
 
/* Add variable version info to a list of version information.  */
/* Add variable version info to a list of version information.  */
 
 
rc_ver_info *
rc_ver_info *
append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
                        rc_ver_varinfo *var)
                        rc_ver_varinfo *var)
{
{
  rc_ver_info *vi, **pp;
  rc_ver_info *vi, **pp;
 
 
  vi = (rc_ver_info *) res_alloc (sizeof *vi);
  vi = (rc_ver_info *) res_alloc (sizeof *vi);
  vi->next = NULL;
  vi->next = NULL;
  vi->type = VERINFO_VAR;
  vi->type = VERINFO_VAR;
  vi->u.var.key = unichar_dup (key);
  vi->u.var.key = unichar_dup (key);
  vi->u.var.var = var;
  vi->u.var.var = var;
 
 
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
    ;
    ;
  *pp = vi;
  *pp = vi;
 
 
  return verinfo;
  return verinfo;
}
}
 
 
/* Append version string information to a list.  */
/* Append version string information to a list.  */
 
 
rc_ver_stringinfo *
rc_ver_stringinfo *
append_verval (rc_ver_stringinfo *strings, const unichar *key,
append_verval (rc_ver_stringinfo *strings, const unichar *key,
               const unichar *value)
               const unichar *value)
{
{
  rc_ver_stringinfo *vs, **pp;
  rc_ver_stringinfo *vs, **pp;
 
 
  vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
  vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
  vs->next = NULL;
  vs->next = NULL;
  vs->key = unichar_dup (key);
  vs->key = unichar_dup (key);
  vs->value = unichar_dup (value);
  vs->value = unichar_dup (value);
 
 
  for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
  for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
    ;
    ;
  *pp = vs;
  *pp = vs;
 
 
  return strings;
  return strings;
}
}
 
 
/* Append version variable information to a list.  */
/* Append version variable information to a list.  */
 
 
rc_ver_varinfo *
rc_ver_varinfo *
append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
                 rc_uint_type charset)
                 rc_uint_type charset)
{
{
  rc_ver_varinfo *vv, **pp;
  rc_ver_varinfo *vv, **pp;
 
 
  vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
  vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
  vv->next = NULL;
  vv->next = NULL;
  vv->language = language;
  vv->language = language;
  vv->charset = charset;
  vv->charset = charset;
 
 
  for (pp = &var; *pp != NULL; pp = &(*pp)->next)
  for (pp = &var; *pp != NULL; pp = &(*pp)->next)
    ;
    ;
  *pp = vv;
  *pp = vv;
 
 
  return var;
  return var;
}
}


/* Local functions used to write out an rc file.  */
/* Local functions used to write out an rc file.  */
 
 
static void indent (FILE *, int);
static void indent (FILE *, int);
static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
                                const rc_res_id *, rc_uint_type *, int);
                                const rc_res_id *, rc_uint_type *, int);
static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
                             const rc_res_id *, rc_uint_type *, int);
                             const rc_res_id *, rc_uint_type *, int);
static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
                               const rc_res_resource *, rc_uint_type *);
                               const rc_res_resource *, rc_uint_type *);
static void write_rc_accelerators (FILE *, const rc_accelerator *);
static void write_rc_accelerators (FILE *, const rc_accelerator *);
static void write_rc_cursor (FILE *, const rc_cursor *);
static void write_rc_cursor (FILE *, const rc_cursor *);
static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
static void write_rc_dialog (FILE *, const rc_dialog *);
static void write_rc_dialog (FILE *, const rc_dialog *);
static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
static void write_rc_fontdir (FILE *, const rc_fontdir *);
static void write_rc_fontdir (FILE *, const rc_fontdir *);
static void write_rc_group_icon (FILE *, const rc_group_icon *);
static void write_rc_group_icon (FILE *, const rc_group_icon *);
static void write_rc_menu (FILE *, const rc_menu *, int);
static void write_rc_menu (FILE *, const rc_menu *, int);
static void write_rc_toolbar (FILE *, const rc_toolbar *);
static void write_rc_toolbar (FILE *, const rc_toolbar *);
static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
 
 
static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
 
 
/* Indent a given number of spaces.  */
/* Indent a given number of spaces.  */
 
 
static void
static void
indent (FILE *e, int c)
indent (FILE *e, int c)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    putc (' ', e);
    putc (' ', e);
}
}
 
 
/* Dump the resources we have read in the format of an rc file.
/* Dump the resources we have read in the format of an rc file.
 
 
   Reasoned by the fact, that some resources need to be stored into file and
   Reasoned by the fact, that some resources need to be stored into file and
   refer to that file, we use the user-data model for that to express it binary
   refer to that file, we use the user-data model for that to express it binary
   without the need to store it somewhere externally.  */
   without the need to store it somewhere externally.  */
 
 
void
void
write_rc_file (const char *filename, const rc_res_directory *resources)
write_rc_file (const char *filename, const rc_res_directory *resources)
{
{
  FILE *e;
  FILE *e;
  rc_uint_type language;
  rc_uint_type language;
 
 
  if (filename == NULL)
  if (filename == NULL)
    e = stdout;
    e = stdout;
  else
  else
    {
    {
      e = fopen (filename, FOPEN_WT);
      e = fopen (filename, FOPEN_WT);
      if (e == NULL)
      if (e == NULL)
        fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
        fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
    }
    }
 
 
  language = (rc_uint_type) ((bfd_signed_vma) -1);
  language = (rc_uint_type) ((bfd_signed_vma) -1);
  write_rc_directory (e, resources, (const rc_res_id *) NULL,
  write_rc_directory (e, resources, (const rc_res_id *) NULL,
                      (const rc_res_id *) NULL, &language, 1);
                      (const rc_res_id *) NULL, &language, 1);
}
}
 
 
/* Write out a directory.  E is the file to write to.  RD is the
/* Write out a directory.  E is the file to write to.  RD is the
   directory.  TYPE is a pointer to the level 1 ID which serves as the
   directory.  TYPE is a pointer to the level 1 ID which serves as the
   resource type.  NAME is a pointer to the level 2 ID which serves as
   resource type.  NAME is a pointer to the level 2 ID which serves as
   an individual resource name.  LANGUAGE is a pointer to the current
   an individual resource name.  LANGUAGE is a pointer to the current
   language.  LEVEL is the level in the tree.  */
   language.  LEVEL is the level in the tree.  */
 
 
static void
static void
write_rc_directory (FILE *e, const rc_res_directory *rd,
write_rc_directory (FILE *e, const rc_res_directory *rd,
                    const rc_res_id *type, const rc_res_id *name,
                    const rc_res_id *type, const rc_res_id *name,
                    rc_uint_type *language, int level)
                    rc_uint_type *language, int level)
{
{
  const rc_res_entry *re;
  const rc_res_entry *re;
 
 
  /* Print out some COFF information that rc files can't represent.  */
  /* Print out some COFF information that rc files can't represent.  */
  if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
  if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
    {
    {
      wr_printcomment (e, "COFF information not part of RC");
      wr_printcomment (e, "COFF information not part of RC");
  if (rd->time != 0)
  if (rd->time != 0)
        wr_printcomment (e, "Time stamp: %u", rd->time);
        wr_printcomment (e, "Time stamp: %u", rd->time);
  if (rd->characteristics != 0)
  if (rd->characteristics != 0)
        wr_printcomment (e, "Characteristics: %u", rd->characteristics);
        wr_printcomment (e, "Characteristics: %u", rd->characteristics);
  if (rd->major != 0 || rd->minor != 0)
  if (rd->major != 0 || rd->minor != 0)
        wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
        wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
    }
    }
 
 
  for (re = rd->entries;  re != NULL; re = re->next)
  for (re = rd->entries;  re != NULL; re = re->next)
    {
    {
      switch (level)
      switch (level)
        {
        {
        case 1:
        case 1:
          /* If we're at level 1, the key of this resource is the
          /* If we're at level 1, the key of this resource is the
             type.  This normally duplicates the information we have
             type.  This normally duplicates the information we have
             stored with the resource itself, but we need to remember
             stored with the resource itself, but we need to remember
             the type if this is a user define resource type.  */
             the type if this is a user define resource type.  */
          type = &re->id;
          type = &re->id;
          break;
          break;
 
 
        case 2:
        case 2:
          /* If we're at level 2, the key of this resource is the name
          /* If we're at level 2, the key of this resource is the name
             we are going to use in the rc printout.  */
             we are going to use in the rc printout.  */
          name = &re->id;
          name = &re->id;
          break;
          break;
 
 
        case 3:
        case 3:
          /* If we're at level 3, then this key represents a language.
          /* If we're at level 3, then this key represents a language.
             Use it to update the current language.  */
             Use it to update the current language.  */
          if (! re->id.named
          if (! re->id.named
              && re->id.u.id != (unsigned long) (unsigned int) *language
              && re->id.u.id != (unsigned long) (unsigned int) *language
              && (re->id.u.id & 0xffff) == re->id.u.id)
              && (re->id.u.id & 0xffff) == re->id.u.id)
            {
            {
              wr_print (e, "LANGUAGE %u, %u\n",
              wr_print (e, "LANGUAGE %u, %u\n",
                       re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
                       re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
                       (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
                       (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
              *language = re->id.u.id;
              *language = re->id.u.id;
            }
            }
          break;
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
 
 
      if (re->subdir)
      if (re->subdir)
        write_rc_subdir (e, re, type, name, language, level);
        write_rc_subdir (e, re, type, name, language, level);
      else
      else
        {
        {
          if (level == 3)
          if (level == 3)
            {
            {
              /* This is the normal case: the three levels are
              /* This is the normal case: the three levels are
                 TYPE/NAME/LANGUAGE.  NAME will have been set at level
                 TYPE/NAME/LANGUAGE.  NAME will have been set at level
                 2, and represents the name to use.  We probably just
                 2, and represents the name to use.  We probably just
                 set LANGUAGE, and it will probably match what the
                 set LANGUAGE, and it will probably match what the
                 resource itself records if anything.  */
                 resource itself records if anything.  */
              write_rc_resource (e, type, name, re->u.res, language);
              write_rc_resource (e, type, name, re->u.res, language);
            }
            }
          else
          else
            {
            {
              wr_printcomment (e, "Resource at unexpected level %d", level);
              wr_printcomment (e, "Resource at unexpected level %d", level);
              write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
              write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
                                 language);
                                 language);
            }
            }
        }
        }
    }
    }
  if (rd->entries == NULL)
  if (rd->entries == NULL)
    {
    {
      wr_print_flush (e);
      wr_print_flush (e);
    }
    }
}
}
 
 
/* Write out a subdirectory entry.  E is the file to write to.  RE is
/* Write out a subdirectory entry.  E is the file to write to.  RE is
   the subdirectory entry.  TYPE and NAME are pointers to higher level
   the subdirectory entry.  TYPE and NAME are pointers to higher level
   IDs, or NULL.  LANGUAGE is a pointer to the current language.
   IDs, or NULL.  LANGUAGE is a pointer to the current language.
   LEVEL is the level in the tree.  */
   LEVEL is the level in the tree.  */
 
 
static void
static void
write_rc_subdir (FILE *e, const rc_res_entry *re,
write_rc_subdir (FILE *e, const rc_res_entry *re,
                 const rc_res_id *type, const rc_res_id *name,
                 const rc_res_id *type, const rc_res_id *name,
                 rc_uint_type *language, int level)
                 rc_uint_type *language, int level)
{
{
  fprintf (e, "\n");
  fprintf (e, "\n");
  switch (level)
  switch (level)
    {
    {
    case 1:
    case 1:
      wr_printcomment (e, "Type: ");
      wr_printcomment (e, "Type: ");
      if (re->id.named)
      if (re->id.named)
        res_id_print (e, re->id, 1);
        res_id_print (e, re->id, 1);
      else
      else
        {
        {
          const char *s;
          const char *s;
 
 
          switch (re->id.u.id)
          switch (re->id.u.id)
            {
            {
            case RT_CURSOR: s = "cursor"; break;
            case RT_CURSOR: s = "cursor"; break;
            case RT_BITMAP: s = "bitmap"; break;
            case RT_BITMAP: s = "bitmap"; break;
            case RT_ICON: s = "icon"; break;
            case RT_ICON: s = "icon"; break;
            case RT_MENU: s = "menu"; break;
            case RT_MENU: s = "menu"; break;
            case RT_DIALOG: s = "dialog"; break;
            case RT_DIALOG: s = "dialog"; break;
            case RT_STRING: s = "stringtable"; break;
            case RT_STRING: s = "stringtable"; break;
            case RT_FONTDIR: s = "fontdir"; break;
            case RT_FONTDIR: s = "fontdir"; break;
            case RT_FONT: s = "font"; break;
            case RT_FONT: s = "font"; break;
            case RT_ACCELERATOR: s = "accelerators"; break;
            case RT_ACCELERATOR: s = "accelerators"; break;
            case RT_RCDATA: s = "rcdata"; break;
            case RT_RCDATA: s = "rcdata"; break;
            case RT_MESSAGETABLE: s = "messagetable"; break;
            case RT_MESSAGETABLE: s = "messagetable"; break;
            case RT_GROUP_CURSOR: s = "group cursor"; break;
            case RT_GROUP_CURSOR: s = "group cursor"; break;
            case RT_GROUP_ICON: s = "group icon"; break;
            case RT_GROUP_ICON: s = "group icon"; break;
            case RT_VERSION: s = "version"; break;
            case RT_VERSION: s = "version"; break;
            case RT_DLGINCLUDE: s = "dlginclude"; break;
            case RT_DLGINCLUDE: s = "dlginclude"; break;
            case RT_PLUGPLAY: s = "plugplay"; break;
            case RT_PLUGPLAY: s = "plugplay"; break;
            case RT_VXD: s = "vxd"; break;
            case RT_VXD: s = "vxd"; break;
            case RT_ANICURSOR: s = "anicursor"; break;
            case RT_ANICURSOR: s = "anicursor"; break;
            case RT_ANIICON: s = "aniicon"; break;
            case RT_ANIICON: s = "aniicon"; break;
            case RT_TOOLBAR: s = "toolbar"; break;
            case RT_TOOLBAR: s = "toolbar"; break;
            case RT_HTML: s = "html"; break;
            case RT_HTML: s = "html"; break;
            default: s = NULL; break;
            default: s = NULL; break;
            }
            }
 
 
          if (s != NULL)
          if (s != NULL)
            fprintf (e, "%s", s);
            fprintf (e, "%s", s);
          else
          else
            res_id_print (e, re->id, 1);
            res_id_print (e, re->id, 1);
        }
        }
      break;
      break;
 
 
    case 2:
    case 2:
      wr_printcomment (e, "Name: ");
      wr_printcomment (e, "Name: ");
      res_id_print (e, re->id, 1);
      res_id_print (e, re->id, 1);
      break;
      break;
 
 
    case 3:
    case 3:
      wr_printcomment (e, "Language: ");
      wr_printcomment (e, "Language: ");
      res_id_print (e, re->id, 1);
      res_id_print (e, re->id, 1);
      break;
      break;
 
 
    default:
    default:
      wr_printcomment (e, "Level %d: ", level);
      wr_printcomment (e, "Level %d: ", level);
      res_id_print (e, re->id, 1);
      res_id_print (e, re->id, 1);
    }
    }
 
 
  write_rc_directory (e, re->u.dir, type, name, language, level + 1);
  write_rc_directory (e, re->u.dir, type, name, language, level + 1);
}
}
 
 
/* Write out a single resource.  E is the file to write to.  TYPE is a
/* Write out a single resource.  E is the file to write to.  TYPE is a
   pointer to the type of the resource.  NAME is a pointer to the name
   pointer to the type of the resource.  NAME is a pointer to the name
   of the resource; it will be NULL if there is a level mismatch.  RES
   of the resource; it will be NULL if there is a level mismatch.  RES
   is the resource data.  LANGUAGE is a pointer to the current
   is the resource data.  LANGUAGE is a pointer to the current
   language.  */
   language.  */
 
 
static void
static void
write_rc_resource (FILE *e, const rc_res_id *type,
write_rc_resource (FILE *e, const rc_res_id *type,
                   const rc_res_id *name, const rc_res_resource *res,
                   const rc_res_id *name, const rc_res_resource *res,
                   rc_uint_type *language)
                   rc_uint_type *language)
{
{
  const char *s;
  const char *s;
  int rt;
  int rt;
  int menuex = 0;
  int menuex = 0;
 
 
  switch (res->type)
  switch (res->type)
    {
    {
    default:
    default:
      abort ();
      abort ();
 
 
    case RES_TYPE_ACCELERATOR:
    case RES_TYPE_ACCELERATOR:
      s = "ACCELERATORS";
      s = "ACCELERATORS";
      rt = RT_ACCELERATOR;
      rt = RT_ACCELERATOR;
      break;
      break;
 
 
    case RES_TYPE_BITMAP:
    case RES_TYPE_BITMAP:
      s = "2 /* RT_BITMAP */";
      s = "2 /* RT_BITMAP */";
      rt = RT_BITMAP;
      rt = RT_BITMAP;
      break;
      break;
 
 
    case RES_TYPE_CURSOR:
    case RES_TYPE_CURSOR:
      s = "1 /* RT_CURSOR */";
      s = "1 /* RT_CURSOR */";
      rt = RT_CURSOR;
      rt = RT_CURSOR;
      break;
      break;
 
 
    case RES_TYPE_GROUP_CURSOR:
    case RES_TYPE_GROUP_CURSOR:
      s = "12 /* RT_GROUP_CURSOR */";
      s = "12 /* RT_GROUP_CURSOR */";
      rt = RT_GROUP_CURSOR;
      rt = RT_GROUP_CURSOR;
      break;
      break;
 
 
    case RES_TYPE_DIALOG:
    case RES_TYPE_DIALOG:
      if (extended_dialog (res->u.dialog))
      if (extended_dialog (res->u.dialog))
        s = "DIALOGEX";
        s = "DIALOGEX";
      else
      else
        s = "DIALOG";
        s = "DIALOG";
      rt = RT_DIALOG;
      rt = RT_DIALOG;
      break;
      break;
 
 
    case RES_TYPE_FONT:
    case RES_TYPE_FONT:
      s = "8 /* RT_FONT */";
      s = "8 /* RT_FONT */";
      rt = RT_FONT;
      rt = RT_FONT;
      break;
      break;
 
 
    case RES_TYPE_FONTDIR:
    case RES_TYPE_FONTDIR:
      s = "7 /* RT_FONTDIR */";
      s = "7 /* RT_FONTDIR */";
      rt = RT_FONTDIR;
      rt = RT_FONTDIR;
      break;
      break;
 
 
    case RES_TYPE_ICON:
    case RES_TYPE_ICON:
      s = "3 /* RT_ICON */";
      s = "3 /* RT_ICON */";
      rt = RT_ICON;
      rt = RT_ICON;
      break;
      break;
 
 
    case RES_TYPE_GROUP_ICON:
    case RES_TYPE_GROUP_ICON:
      s = "14 /* RT_GROUP_ICON */";
      s = "14 /* RT_GROUP_ICON */";
      rt = RT_GROUP_ICON;
      rt = RT_GROUP_ICON;
      break;
      break;
 
 
    case RES_TYPE_MENU:
    case RES_TYPE_MENU:
      if (extended_menu (res->u.menu))
      if (extended_menu (res->u.menu))
        {
        {
          s = "MENUEX";
          s = "MENUEX";
          menuex = 1;
          menuex = 1;
        }
        }
      else
      else
        {
        {
          s = "MENU";
          s = "MENU";
          menuex = 0;
          menuex = 0;
        }
        }
      rt = RT_MENU;
      rt = RT_MENU;
      break;
      break;
 
 
    case RES_TYPE_MESSAGETABLE:
    case RES_TYPE_MESSAGETABLE:
      s = "11 /* RT_MESSAGETABLE */";
      s = "11 /* RT_MESSAGETABLE */";
      rt = RT_MESSAGETABLE;
      rt = RT_MESSAGETABLE;
      break;
      break;
 
 
    case RES_TYPE_RCDATA:
    case RES_TYPE_RCDATA:
      s = "RCDATA";
      s = "RCDATA";
      rt = RT_RCDATA;
      rt = RT_RCDATA;
      break;
      break;
 
 
    case RES_TYPE_STRINGTABLE:
    case RES_TYPE_STRINGTABLE:
      s = "STRINGTABLE";
      s = "STRINGTABLE";
      rt = RT_STRING;
      rt = RT_STRING;
      break;
      break;
 
 
    case RES_TYPE_USERDATA:
    case RES_TYPE_USERDATA:
      s = NULL;
      s = NULL;
      rt = 0;
      rt = 0;
      break;
      break;
 
 
    case RES_TYPE_VERSIONINFO:
    case RES_TYPE_VERSIONINFO:
      s = "VERSIONINFO";
      s = "VERSIONINFO";
      rt = RT_VERSION;
      rt = RT_VERSION;
      break;
      break;
 
 
    case RES_TYPE_TOOLBAR:
    case RES_TYPE_TOOLBAR:
      s = "TOOLBAR";
      s = "TOOLBAR";
      rt = RT_TOOLBAR;
      rt = RT_TOOLBAR;
      break;
      break;
    }
    }
 
 
  if (rt != 0
  if (rt != 0
      && type != NULL
      && type != NULL
      && (type->named || type->u.id != (unsigned long) rt))
      && (type->named || type->u.id != (unsigned long) rt))
    {
    {
      wr_printcomment (e, "Unexpected resource type mismatch: ");
      wr_printcomment (e, "Unexpected resource type mismatch: ");
      res_id_print (e, *type, 1);
      res_id_print (e, *type, 1);
      fprintf (e, " != %d", rt);
      fprintf (e, " != %d", rt);
    }
    }
 
 
  if (res->coff_info.codepage != 0)
  if (res->coff_info.codepage != 0)
    wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
    wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
  if (res->coff_info.reserved != 0)
  if (res->coff_info.reserved != 0)
    wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
    wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
 
 
  wr_print (e, "\n");
  wr_print (e, "\n");
  if (rt == RT_STRING)
  if (rt == RT_STRING)
    ;
    ;
  else
  else
    {
    {
  if (name != NULL)
  if (name != NULL)
        res_id_print (e, *name, 1);
        res_id_print (e, *name, 1);
  else
  else
    fprintf (e, "??Unknown-Name??");
    fprintf (e, "??Unknown-Name??");
  fprintf (e, " ");
  fprintf (e, " ");
    }
    }
 
 
  if (s != NULL)
  if (s != NULL)
    fprintf (e, "%s", s);
    fprintf (e, "%s", s);
  else if (type != NULL)
  else if (type != NULL)
    {
    {
      if (type->named == 0)
      if (type->named == 0)
        {
        {
#define PRINT_RT_NAME(NAME) case NAME: \
#define PRINT_RT_NAME(NAME) case NAME: \
        fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
        fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
        break
        break
 
 
          switch (type->u.id)
          switch (type->u.id)
            {
            {
            default:
            default:
    res_id_print (e, *type, 0);
    res_id_print (e, *type, 0);
              break;
              break;
 
 
            PRINT_RT_NAME(RT_MANIFEST);
            PRINT_RT_NAME(RT_MANIFEST);
            PRINT_RT_NAME(RT_ANICURSOR);
            PRINT_RT_NAME(RT_ANICURSOR);
            PRINT_RT_NAME(RT_ANIICON);
            PRINT_RT_NAME(RT_ANIICON);
            PRINT_RT_NAME(RT_RCDATA);
            PRINT_RT_NAME(RT_RCDATA);
            PRINT_RT_NAME(RT_ICON);
            PRINT_RT_NAME(RT_ICON);
            PRINT_RT_NAME(RT_CURSOR);
            PRINT_RT_NAME(RT_CURSOR);
            PRINT_RT_NAME(RT_BITMAP);
            PRINT_RT_NAME(RT_BITMAP);
            PRINT_RT_NAME(RT_PLUGPLAY);
            PRINT_RT_NAME(RT_PLUGPLAY);
            PRINT_RT_NAME(RT_VXD);
            PRINT_RT_NAME(RT_VXD);
            PRINT_RT_NAME(RT_FONT);
            PRINT_RT_NAME(RT_FONT);
            PRINT_RT_NAME(RT_FONTDIR);
            PRINT_RT_NAME(RT_FONTDIR);
            PRINT_RT_NAME(RT_HTML);
            PRINT_RT_NAME(RT_HTML);
            PRINT_RT_NAME(RT_MESSAGETABLE);
            PRINT_RT_NAME(RT_MESSAGETABLE);
            PRINT_RT_NAME(RT_DLGINCLUDE);
            PRINT_RT_NAME(RT_DLGINCLUDE);
            PRINT_RT_NAME(RT_DLGINIT);
            PRINT_RT_NAME(RT_DLGINIT);
            }
            }
#undef PRINT_RT_NAME
#undef PRINT_RT_NAME
        }
        }
      else
      else
        res_id_print (e, *type, 1);
        res_id_print (e, *type, 1);
    }
    }
  else
  else
    fprintf (e, "??Unknown-Type??");
    fprintf (e, "??Unknown-Type??");
 
 
  if (res->res_info.memflags != 0)
  if (res->res_info.memflags != 0)
    {
    {
      if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
      if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
        fprintf (e, " MOVEABLE");
        fprintf (e, " MOVEABLE");
      if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
      if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
        fprintf (e, " PURE");
        fprintf (e, " PURE");
      if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
      if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
        fprintf (e, " PRELOAD");
        fprintf (e, " PRELOAD");
      if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
      if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
        fprintf (e, " DISCARDABLE");
        fprintf (e, " DISCARDABLE");
    }
    }
 
 
  if (res->type == RES_TYPE_DIALOG)
  if (res->type == RES_TYPE_DIALOG)
    {
    {
      fprintf (e, " %d, %d, %d, %d",
      fprintf (e, " %d, %d, %d, %d",
               (int) res->u.dialog->x, (int) res->u.dialog->y,
               (int) res->u.dialog->x, (int) res->u.dialog->y,
               (int) res->u.dialog->width, (int) res->u.dialog->height);
               (int) res->u.dialog->width, (int) res->u.dialog->height);
      if (res->u.dialog->ex != NULL
      if (res->u.dialog->ex != NULL
          && res->u.dialog->ex->help != 0)
          && res->u.dialog->ex->help != 0)
        fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
        fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
    }
    }
  else if (res->type == RES_TYPE_TOOLBAR)
  else if (res->type == RES_TYPE_TOOLBAR)
  {
  {
    fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
    fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
             (int) res->u.toolbar->button_height);
             (int) res->u.toolbar->button_height);
    }
    }
 
 
  fprintf (e, "\n");
  fprintf (e, "\n");
 
 
  if ((res->res_info.language != 0 && res->res_info.language != *language)
  if ((res->res_info.language != 0 && res->res_info.language != *language)
      || res->res_info.characteristics != 0
      || res->res_info.characteristics != 0
      || res->res_info.version != 0)
      || res->res_info.version != 0)
    {
    {
      int modifiers;
      int modifiers;
 
 
      switch (res->type)
      switch (res->type)
        {
        {
        case RES_TYPE_ACCELERATOR:
        case RES_TYPE_ACCELERATOR:
        case RES_TYPE_DIALOG:
        case RES_TYPE_DIALOG:
        case RES_TYPE_MENU:
        case RES_TYPE_MENU:
        case RES_TYPE_RCDATA:
        case RES_TYPE_RCDATA:
        case RES_TYPE_STRINGTABLE:
        case RES_TYPE_STRINGTABLE:
          modifiers = 1;
          modifiers = 1;
          break;
          break;
 
 
        default:
        default:
          modifiers = 0;
          modifiers = 0;
          break;
          break;
        }
        }
 
 
      if (res->res_info.language != 0 && res->res_info.language != *language)
      if (res->res_info.language != 0 && res->res_info.language != *language)
        fprintf (e, "%sLANGUAGE %d, %d\n",
        fprintf (e, "%sLANGUAGE %d, %d\n",
                 modifiers ? "// " : "",
                 modifiers ? "// " : "",
                 (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
                 (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
                 (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
                 (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
      if (res->res_info.characteristics != 0)
      if (res->res_info.characteristics != 0)
        fprintf (e, "%sCHARACTERISTICS %u\n",
        fprintf (e, "%sCHARACTERISTICS %u\n",
                 modifiers ? "// " : "",
                 modifiers ? "// " : "",
                 (unsigned int) res->res_info.characteristics);
                 (unsigned int) res->res_info.characteristics);
      if (res->res_info.version != 0)
      if (res->res_info.version != 0)
        fprintf (e, "%sVERSION %u\n",
        fprintf (e, "%sVERSION %u\n",
                 modifiers ? "// " : "",
                 modifiers ? "// " : "",
                 (unsigned int) res->res_info.version);
                 (unsigned int) res->res_info.version);
    }
    }
 
 
  switch (res->type)
  switch (res->type)
    {
    {
    default:
    default:
      abort ();
      abort ();
 
 
    case RES_TYPE_ACCELERATOR:
    case RES_TYPE_ACCELERATOR:
      write_rc_accelerators (e, res->u.acc);
      write_rc_accelerators (e, res->u.acc);
      break;
      break;
 
 
    case RES_TYPE_CURSOR:
    case RES_TYPE_CURSOR:
      write_rc_cursor (e, res->u.cursor);
      write_rc_cursor (e, res->u.cursor);
      break;
      break;
 
 
    case RES_TYPE_GROUP_CURSOR:
    case RES_TYPE_GROUP_CURSOR:
      write_rc_group_cursor (e, res->u.group_cursor);
      write_rc_group_cursor (e, res->u.group_cursor);
      break;
      break;
 
 
    case RES_TYPE_DIALOG:
    case RES_TYPE_DIALOG:
      write_rc_dialog (e, res->u.dialog);
      write_rc_dialog (e, res->u.dialog);
      break;
      break;
 
 
    case RES_TYPE_FONTDIR:
    case RES_TYPE_FONTDIR:
      write_rc_fontdir (e, res->u.fontdir);
      write_rc_fontdir (e, res->u.fontdir);
      break;
      break;
 
 
    case RES_TYPE_GROUP_ICON:
    case RES_TYPE_GROUP_ICON:
      write_rc_group_icon (e, res->u.group_icon);
      write_rc_group_icon (e, res->u.group_icon);
      break;
      break;
 
 
    case RES_TYPE_MENU:
    case RES_TYPE_MENU:
      write_rc_menu (e, res->u.menu, menuex);
      write_rc_menu (e, res->u.menu, menuex);
      break;
      break;
 
 
    case RES_TYPE_RCDATA:
    case RES_TYPE_RCDATA:
      write_rc_rcdata (e, res->u.rcdata, 0);
      write_rc_rcdata (e, res->u.rcdata, 0);
      break;
      break;
 
 
    case RES_TYPE_STRINGTABLE:
    case RES_TYPE_STRINGTABLE:
      write_rc_stringtable (e, name, res->u.stringtable);
      write_rc_stringtable (e, name, res->u.stringtable);
      break;
      break;
 
 
    case RES_TYPE_USERDATA:
    case RES_TYPE_USERDATA:
      write_rc_rcdata (e, res->u.userdata, 0);
      write_rc_rcdata (e, res->u.userdata, 0);
      break;
      break;
 
 
    case RES_TYPE_TOOLBAR:
    case RES_TYPE_TOOLBAR:
      write_rc_toolbar (e, res->u.toolbar);
      write_rc_toolbar (e, res->u.toolbar);
      break;
      break;
 
 
    case RES_TYPE_VERSIONINFO:
    case RES_TYPE_VERSIONINFO:
      write_rc_versioninfo (e, res->u.versioninfo);
      write_rc_versioninfo (e, res->u.versioninfo);
      break;
      break;
 
 
    case RES_TYPE_BITMAP:
    case RES_TYPE_BITMAP:
    case RES_TYPE_FONT:
    case RES_TYPE_FONT:
    case RES_TYPE_ICON:
    case RES_TYPE_ICON:
      write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
      write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
      break;
      break;
    case RES_TYPE_MESSAGETABLE:
    case RES_TYPE_MESSAGETABLE:
      write_rc_messagetable (e, res->u.data.length, res->u.data.data);
      write_rc_messagetable (e, res->u.data.length, res->u.data.data);
      break;
      break;
    }
    }
}
}
 
 
/* Write out accelerator information.  */
/* Write out accelerator information.  */
 
 
static void
static void
write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
{
{
  const rc_accelerator *acc;
  const rc_accelerator *acc;
 
 
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
  for (acc = accelerators; acc != NULL; acc = acc->next)
  for (acc = accelerators; acc != NULL; acc = acc->next)
    {
    {
      int printable;
      int printable;
 
 
      fprintf (e, "  ");
      fprintf (e, "  ");
 
 
      if ((acc->key & 0x7f) == acc->key
      if ((acc->key & 0x7f) == acc->key
          && ISPRINT (acc->key)
          && ISPRINT (acc->key)
          && (acc->flags & ACC_VIRTKEY) == 0)
          && (acc->flags & ACC_VIRTKEY) == 0)
        {
        {
          fprintf (e, "\"%c\"", (char) acc->key);
          fprintf (e, "\"%c\"", (char) acc->key);
          printable = 1;
          printable = 1;
        }
        }
      else
      else
        {
        {
          fprintf (e, "%d", (int) acc->key);
          fprintf (e, "%d", (int) acc->key);
          printable = 0;
          printable = 0;
        }
        }
 
 
      fprintf (e, ", %d", (int) acc->id);
      fprintf (e, ", %d", (int) acc->id);
 
 
      if (! printable)
      if (! printable)
        {
        {
          if ((acc->flags & ACC_VIRTKEY) != 0)
          if ((acc->flags & ACC_VIRTKEY) != 0)
            fprintf (e, ", VIRTKEY");
            fprintf (e, ", VIRTKEY");
          else
          else
            fprintf (e, ", ASCII");
            fprintf (e, ", ASCII");
        }
        }
 
 
      if ((acc->flags & ACC_SHIFT) != 0)
      if ((acc->flags & ACC_SHIFT) != 0)
        fprintf (e, ", SHIFT");
        fprintf (e, ", SHIFT");
      if ((acc->flags & ACC_CONTROL) != 0)
      if ((acc->flags & ACC_CONTROL) != 0)
        fprintf (e, ", CONTROL");
        fprintf (e, ", CONTROL");
      if ((acc->flags & ACC_ALT) != 0)
      if ((acc->flags & ACC_ALT) != 0)
        fprintf (e, ", ALT");
        fprintf (e, ", ALT");
 
 
      fprintf (e, "\n");
      fprintf (e, "\n");
    }
    }
 
 
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out cursor information.  This would normally be in a separate
/* Write out cursor information.  This would normally be in a separate
   file, which the rc file would include.  */
   file, which the rc file would include.  */
 
 
static void
static void
write_rc_cursor (FILE *e, const rc_cursor *cursor)
write_rc_cursor (FILE *e, const rc_cursor *cursor)
{
{
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
  indent (e, 2);
  indent (e, 2);
  fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d.  */\n",
  fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d.  */\n",
           (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
           (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
           (int) cursor->xhotspot, (int) cursor->yhotspot);
           (int) cursor->xhotspot, (int) cursor->yhotspot);
  write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
  write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
                      0, 0, 0);
                      0, 0, 0);
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out group cursor data.  This would normally be built from the
/* Write out group cursor data.  This would normally be built from the
   cursor data.  */
   cursor data.  */
 
 
static void
static void
write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
{
{
  const rc_group_cursor *gc;
  const rc_group_cursor *gc;
  int c;
  int c;
 
 
  for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
  for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
    ;
    ;
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  indent (e, 2);
  indent (e, 2);
  fprintf (e, "0, 2, %d%s\t /* Having %d items.  */\n", c, (c != 0 ? "," : ""), c);
  fprintf (e, "0, 2, %d%s\t /* Having %d items.  */\n", c, (c != 0 ? "," : ""), c);
  indent (e, 4);
  indent (e, 4);
  fprintf (e, "/* width, height, planes, bits, bytes, index.  */\n");
  fprintf (e, "/* width, height, planes, bits, bytes, index.  */\n");
 
 
  for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
  for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
    {
    {
      indent (e, 4);
      indent (e, 4);
      fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
      fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
        (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
        (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
        (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
        (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
      fprintf (e, "/* width: %d; height %d; planes %d; bits %d.  */\n",
      fprintf (e, "/* width: %d; height %d; planes %d; bits %d.  */\n",
             (int) gc->width, (int) gc->height, (int) gc->planes,
             (int) gc->width, (int) gc->height, (int) gc->planes,
             (int) gc->bits);
             (int) gc->bits);
    }
    }
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write dialog data.  */
/* Write dialog data.  */
 
 
static void
static void
write_rc_dialog (FILE *e, const rc_dialog *dialog)
write_rc_dialog (FILE *e, const rc_dialog *dialog)
{
{
  const rc_dialog_control *control;
  const rc_dialog_control *control;
 
 
  fprintf (e, "STYLE 0x%x\n", dialog->style);
  fprintf (e, "STYLE 0x%x\n", dialog->style);
 
 
  if (dialog->exstyle != 0)
  if (dialog->exstyle != 0)
    fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
    fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
 
 
  if ((dialog->class.named && dialog->class.u.n.length > 0)
  if ((dialog->class.named && dialog->class.u.n.length > 0)
      || dialog->class.u.id != 0)
      || dialog->class.u.id != 0)
    {
    {
      fprintf (e, "CLASS ");
      fprintf (e, "CLASS ");
      res_id_print (e, dialog->class, 1);
      res_id_print (e, dialog->class, 1);
      fprintf (e, "\n");
      fprintf (e, "\n");
    }
    }
 
 
  if (dialog->caption != NULL)
  if (dialog->caption != NULL)
    {
    {
      fprintf (e, "CAPTION ");
      fprintf (e, "CAPTION ");
      unicode_print_quoted (e, dialog->caption, -1);
      unicode_print_quoted (e, dialog->caption, -1);
      fprintf (e, "\n");
      fprintf (e, "\n");
    }
    }
 
 
  if ((dialog->menu.named && dialog->menu.u.n.length > 0)
  if ((dialog->menu.named && dialog->menu.u.n.length > 0)
      || dialog->menu.u.id != 0)
      || dialog->menu.u.id != 0)
    {
    {
      fprintf (e, "MENU ");
      fprintf (e, "MENU ");
      res_id_print (e, dialog->menu, 0);
      res_id_print (e, dialog->menu, 0);
      fprintf (e, "\n");
      fprintf (e, "\n");
    }
    }
 
 
  if (dialog->font != NULL)
  if (dialog->font != NULL)
    {
    {
      fprintf (e, "FONT %d, ", (int) dialog->pointsize);
      fprintf (e, "FONT %d, ", (int) dialog->pointsize);
      unicode_print_quoted (e, dialog->font, -1);
      unicode_print_quoted (e, dialog->font, -1);
      if (dialog->ex != NULL
      if (dialog->ex != NULL
          && (dialog->ex->weight != 0
          && (dialog->ex->weight != 0
              || dialog->ex->italic != 0
              || dialog->ex->italic != 0
              || dialog->ex->charset != 1))
              || dialog->ex->charset != 1))
        fprintf (e, ", %d, %d, %d",
        fprintf (e, ", %d, %d, %d",
                 (int) dialog->ex->weight,
                 (int) dialog->ex->weight,
                 (int) dialog->ex->italic,
                 (int) dialog->ex->italic,
                 (int) dialog->ex->charset);
                 (int) dialog->ex->charset);
      fprintf (e, "\n");
      fprintf (e, "\n");
    }
    }
 
 
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  for (control = dialog->controls; control != NULL; control = control->next)
  for (control = dialog->controls; control != NULL; control = control->next)
    write_rc_dialog_control (e, control);
    write_rc_dialog_control (e, control);
 
 
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* For each predefined control keyword, this table provides the class
/* For each predefined control keyword, this table provides the class
   and the style.  */
   and the style.  */
 
 
struct control_info
struct control_info
{
{
  const char *name;
  const char *name;
  unsigned short class;
  unsigned short class;
  unsigned long style;
  unsigned long style;
};
};
 
 
static const struct control_info control_info[] =
static const struct control_info control_info[] =
{
{
  { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
  { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
  { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
  { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
  { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
  { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
  { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
  { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
  { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
  { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
  { "CTEXT", CTL_STATIC, SS_CENTER },
  { "CTEXT", CTL_STATIC, SS_CENTER },
  { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
  { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
  { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
  { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
  { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
  { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
  { "ICON", CTL_STATIC, SS_ICON },
  { "ICON", CTL_STATIC, SS_ICON },
  { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
  { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
  { "LTEXT", CTL_STATIC, SS_LEFT },
  { "LTEXT", CTL_STATIC, SS_LEFT },
  { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
  { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
  { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
  { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
  { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
  { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
  { "RTEXT", CTL_STATIC, SS_RIGHT },
  { "RTEXT", CTL_STATIC, SS_RIGHT },
  { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
  { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
  { "STATE3", CTL_BUTTON, BS_3STATE },
  { "STATE3", CTL_BUTTON, BS_3STATE },
  /* It's important that USERBUTTON come after all the other button
  /* It's important that USERBUTTON come after all the other button
     types, so that it won't be matched too early.  */
     types, so that it won't be matched too early.  */
  { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
  { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
  { NULL, 0, 0 }
  { NULL, 0, 0 }
};
};
 
 
/* Write a dialog control.  */
/* Write a dialog control.  */
 
 
static void
static void
write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
{
{
  const struct control_info *ci;
  const struct control_info *ci;
 
 
  fprintf (e, "  ");
  fprintf (e, "  ");
 
 
  if (control->class.named)
  if (control->class.named)
    ci = NULL;
    ci = NULL;
  else
  else
    {
    {
      for (ci = control_info; ci->name != NULL; ++ci)
      for (ci = control_info; ci->name != NULL; ++ci)
        if (ci->class == control->class.u.id
        if (ci->class == control->class.u.id
            && (ci->style == (unsigned long) -1
            && (ci->style == (unsigned long) -1
                || ci->style == (control->style & 0xff)))
                || ci->style == (control->style & 0xff)))
          break;
          break;
    }
    }
  if (ci == NULL)
  if (ci == NULL)
    fprintf (e, "CONTROL");
    fprintf (e, "CONTROL");
  else if (ci->name != NULL)
  else if (ci->name != NULL)
    fprintf (e, "%s", ci->name);
    fprintf (e, "%s", ci->name);
  else
  else
    {
    {
    fprintf (e, "CONTROL");
    fprintf (e, "CONTROL");
      ci = NULL;
      ci = NULL;
    }
    }
 
 
  if (control->text.named || control->text.u.id != 0)
  if (control->text.named || control->text.u.id != 0)
    {
    {
      fprintf (e, " ");
      fprintf (e, " ");
      res_id_print (e, control->text, 1);
      res_id_print (e, control->text, 1);
      fprintf (e, ",");
      fprintf (e, ",");
    }
    }
 
 
  fprintf (e, " %d, ", (int) control->id);
  fprintf (e, " %d, ", (int) control->id);
 
 
  if (ci == NULL)
  if (ci == NULL)
    {
    {
      if (control->class.named)
      if (control->class.named)
        fprintf (e, "\"");
        fprintf (e, "\"");
      res_id_print (e, control->class, 0);
      res_id_print (e, control->class, 0);
      if (control->class.named)
      if (control->class.named)
        fprintf (e, "\"");
        fprintf (e, "\"");
      fprintf (e, ", 0x%x, ", (unsigned int) control->style);
      fprintf (e, ", 0x%x, ", (unsigned int) control->style);
    }
    }
 
 
  fprintf (e, "%d, %d", (int) control->x, (int) control->y);
  fprintf (e, "%d, %d", (int) control->x, (int) control->y);
 
 
  if (control->style != SS_ICON
  if (control->style != SS_ICON
      || control->exstyle != 0
      || control->exstyle != 0
      || control->width != 0
      || control->width != 0
      || control->height != 0
      || control->height != 0
      || control->help != 0)
      || control->help != 0)
    {
    {
      fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
      fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
 
 
      /* FIXME: We don't need to print the style if it is the default.
      /* FIXME: We don't need to print the style if it is the default.
         More importantly, in certain cases we actually need to turn
         More importantly, in certain cases we actually need to turn
         off parts of the forced style, by using NOT.  */
         off parts of the forced style, by using NOT.  */
      if (ci != NULL)
      if (ci != NULL)
        fprintf (e, ", 0x%x", (unsigned int) control->style);
        fprintf (e, ", 0x%x", (unsigned int) control->style);
 
 
      if (control->exstyle != 0 || control->help != 0)
      if (control->exstyle != 0 || control->help != 0)
        fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
        fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
                 (unsigned int) control->help);
                 (unsigned int) control->help);
    }
    }
 
 
  fprintf (e, "\n");
  fprintf (e, "\n");
 
 
  if (control->data != NULL)
  if (control->data != NULL)
    write_rc_rcdata (e, control->data, 2);
    write_rc_rcdata (e, control->data, 2);
}
}
 
 
/* Write out font directory data.  This would normally be built from
/* Write out font directory data.  This would normally be built from
   the font data.  */
   the font data.  */
 
 
static void
static void
write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
{
{
  const rc_fontdir *fc;
  const rc_fontdir *fc;
  int c;
  int c;
 
 
  for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
  for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
    ;
    ;
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
  indent (e, 2);
  indent (e, 2);
  fprintf (e, "%d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
  fprintf (e, "%d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
  for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
  for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
    {
    {
      indent (e, 4);
      indent (e, 4);
      fprintf (e, "%d,\t/* Font no %d with index %d.  */\n",
      fprintf (e, "%d,\t/* Font no %d with index %d.  */\n",
        (int) fc->index, c, (int) fc->index);
        (int) fc->index, c, (int) fc->index);
      write_rc_datablock (e, (rc_uint_type) fc->length - 2,
      write_rc_datablock (e, (rc_uint_type) fc->length - 2,
                          (const bfd_byte *) fc->data + 4,fc->next != NULL,
                          (const bfd_byte *) fc->data + 4,fc->next != NULL,
                          0, 0);
                          0, 0);
    }
    }
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out group icon data.  This would normally be built from the
/* Write out group icon data.  This would normally be built from the
   icon data.  */
   icon data.  */
 
 
static void
static void
write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
{
{
  const rc_group_icon *gi;
  const rc_group_icon *gi;
  int c;
  int c;
 
 
  for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
  for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
    ;
    ;
 
 
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
  indent (e, 2);
  indent (e, 2);
  fprintf (e, " 0, 1, %d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
  fprintf (e, " 0, 1, %d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
 
 
  indent (e, 4);
  indent (e, 4);
  fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index.  */\n");
  fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index.  */\n");
  for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
  for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
    {
    {
      indent (e, 4);
      indent (e, 4);
      fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d.  */\n",
      fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d.  */\n",
        gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
        gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
        (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
        (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
    }
    }
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out a menu resource.  */
/* Write out a menu resource.  */
 
 
static void
static void
write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
{
{
  if (menu->help != 0)
  if (menu->help != 0)
    fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
    fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
  write_rc_menuitems (e, menu->items, menuex, 0);
  write_rc_menuitems (e, menu->items, menuex, 0);
}
}
 
 
static void
static void
write_rc_toolbar (FILE *e, const rc_toolbar *tb)
write_rc_toolbar (FILE *e, const rc_toolbar *tb)
{
{
  rc_toolbar_item *it;
  rc_toolbar_item *it;
  indent (e, 0);
  indent (e, 0);
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
  it = tb->items;
  it = tb->items;
  while(it != NULL)
  while(it != NULL)
  {
  {
    indent (e, 2);
    indent (e, 2);
    if (it->id.u.id == 0)
    if (it->id.u.id == 0)
      fprintf (e, "SEPARATOR\n");
      fprintf (e, "SEPARATOR\n");
    else
    else
      fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
      fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
    it = it->next;
    it = it->next;
  }
  }
  indent (e, 0);
  indent (e, 0);
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out menuitems.  */
/* Write out menuitems.  */
 
 
static void
static void
write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
                    int ind)
                    int ind)
{
{
  const rc_menuitem *mi;
  const rc_menuitem *mi;
 
 
  indent (e, ind);
  indent (e, ind);
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  for (mi = menuitems; mi != NULL; mi = mi->next)
  for (mi = menuitems; mi != NULL; mi = mi->next)
    {
    {
      indent (e, ind + 2);
      indent (e, ind + 2);
 
 
      if (mi->popup == NULL)
      if (mi->popup == NULL)
        fprintf (e, "MENUITEM");
        fprintf (e, "MENUITEM");
      else
      else
        fprintf (e, "POPUP");
        fprintf (e, "POPUP");
 
 
      if (! menuex
      if (! menuex
          && mi->popup == NULL
          && mi->popup == NULL
          && mi->text == NULL
          && mi->text == NULL
          && mi->type == 0
          && mi->type == 0
          && mi->id == 0)
          && mi->id == 0)
        {
        {
          fprintf (e, " SEPARATOR\n");
          fprintf (e, " SEPARATOR\n");
          continue;
          continue;
        }
        }
 
 
      if (mi->text == NULL)
      if (mi->text == NULL)
        fprintf (e, " \"\"");
        fprintf (e, " \"\"");
      else
      else
        {
        {
          fprintf (e, " ");
          fprintf (e, " ");
          unicode_print_quoted (e, mi->text, -1);
          unicode_print_quoted (e, mi->text, -1);
        }
        }
 
 
      if (! menuex)
      if (! menuex)
        {
        {
          if (mi->popup == NULL)
          if (mi->popup == NULL)
            fprintf (e, ", %d", (int) mi->id);
            fprintf (e, ", %d", (int) mi->id);
 
 
          if ((mi->type & MENUITEM_CHECKED) != 0)
          if ((mi->type & MENUITEM_CHECKED) != 0)
            fprintf (e, ", CHECKED");
            fprintf (e, ", CHECKED");
          if ((mi->type & MENUITEM_GRAYED) != 0)
          if ((mi->type & MENUITEM_GRAYED) != 0)
            fprintf (e, ", GRAYED");
            fprintf (e, ", GRAYED");
          if ((mi->type & MENUITEM_HELP) != 0)
          if ((mi->type & MENUITEM_HELP) != 0)
            fprintf (e, ", HELP");
            fprintf (e, ", HELP");
          if ((mi->type & MENUITEM_INACTIVE) != 0)
          if ((mi->type & MENUITEM_INACTIVE) != 0)
            fprintf (e, ", INACTIVE");
            fprintf (e, ", INACTIVE");
          if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
          if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
            fprintf (e, ", MENUBARBREAK");
            fprintf (e, ", MENUBARBREAK");
          if ((mi->type & MENUITEM_MENUBREAK) != 0)
          if ((mi->type & MENUITEM_MENUBREAK) != 0)
            fprintf (e, ", MENUBREAK");
            fprintf (e, ", MENUBREAK");
        }
        }
      else
      else
        {
        {
          if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
          if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
            {
            {
              fprintf (e, ", %d", (int) mi->id);
              fprintf (e, ", %d", (int) mi->id);
              if (mi->type != 0 || mi->state != 0 || mi->help != 0)
              if (mi->type != 0 || mi->state != 0 || mi->help != 0)
                {
                {
                  fprintf (e, ", %u", (unsigned int) mi->type);
                  fprintf (e, ", %u", (unsigned int) mi->type);
                  if (mi->state != 0 || mi->help != 0)
                  if (mi->state != 0 || mi->help != 0)
                    {
                    {
                      fprintf (e, ", %u", (unsigned int) mi->state);
                      fprintf (e, ", %u", (unsigned int) mi->state);
                      if (mi->help != 0)
                      if (mi->help != 0)
                        fprintf (e, ", %u", (unsigned int) mi->help);
                        fprintf (e, ", %u", (unsigned int) mi->help);
                    }
                    }
                }
                }
            }
            }
        }
        }
 
 
      fprintf (e, "\n");
      fprintf (e, "\n");
 
 
      if (mi->popup != NULL)
      if (mi->popup != NULL)
        write_rc_menuitems (e, mi->popup, menuex, ind + 2);
        write_rc_menuitems (e, mi->popup, menuex, ind + 2);
    }
    }
 
 
  indent (e, ind);
  indent (e, ind);
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
static int
static int
test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
{
{
  rc_uint_type i;
  rc_uint_type i;
  if ((length & 1) != 0)
  if ((length & 1) != 0)
    return 0;
    return 0;
 
 
  for (i = 0; i < length; i += 2)
  for (i = 0; i < length; i += 2)
    {
    {
      if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
      if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
        return 0;
        return 0;
      if (data[i] == 0xff && data[i + 1] == 0xff)
      if (data[i] == 0xff && data[i + 1] == 0xff)
        return 0;
        return 0;
    }
    }
  return 1;
  return 1;
}
}
 
 
static int
static int
test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
{
{
  int has_nl;
  int has_nl;
  rc_uint_type c;
  rc_uint_type c;
  rc_uint_type i;
  rc_uint_type i;
 
 
  if (length <= 1)
  if (length <= 1)
    return 0;
    return 0;
 
 
  has_nl = 0;
  has_nl = 0;
  for (i = 0, c = 0; i < length; i++)
  for (i = 0, c = 0; i < length; i++)
    {
    {
      if (! ISPRINT (data[i]) && data[i] != '\n'
      if (! ISPRINT (data[i]) && data[i] != '\n'
          && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
          && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
          && data[i] != '\t'
          && data[i] != '\t'
          && ! (data[i] == 0 && (i + 1) != length))
          && ! (data[i] == 0 && (i + 1) != length))
        {
        {
          if (data[i] <= 7)
          if (data[i] <= 7)
            return 0;
            return 0;
          c++;
          c++;
        }
        }
      else if (data[i] == '\n') has_nl++;
      else if (data[i] == '\n') has_nl++;
    }
    }
  if (length > 80 && ! has_nl)
  if (length > 80 && ! has_nl)
    return 0;
    return 0;
  c = (((c * 10000) + (i / 100) - 1)) / i;
  c = (((c * 10000) + (i / 100) - 1)) / i;
  if (c >= 150)
  if (c >= 150)
    return 0;
    return 0;
  return 1;
  return 1;
}
}
 
 
static void
static void
write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
{
{
  int has_error = 0;
  int has_error = 0;
  const struct bin_messagetable *mt;
  const struct bin_messagetable *mt;
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  write_rc_datablock (e, length, data, 0, 0, 0);
  write_rc_datablock (e, length, data, 0, 0, 0);
 
 
  fprintf (e, "\n");
  fprintf (e, "\n");
  wr_printcomment (e, "MC syntax dump");
  wr_printcomment (e, "MC syntax dump");
  if (length < BIN_MESSAGETABLE_SIZE)
  if (length < BIN_MESSAGETABLE_SIZE)
    has_error = 1;
    has_error = 1;
  else
  else
    do {
    do {
      rc_uint_type m, i;
      rc_uint_type m, i;
      mt = (const struct bin_messagetable *) data;
      mt = (const struct bin_messagetable *) data;
      m = windres_get_32 (&wrtarget, mt->cblocks, length);
      m = windres_get_32 (&wrtarget, mt->cblocks, length);
      if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
      if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
        {
        {
          has_error = 1;
          has_error = 1;
          break;
          break;
        }
        }
      for (i = 0; i < m; i++)
      for (i = 0; i < m; i++)
        {
        {
          rc_uint_type low, high, offset;
          rc_uint_type low, high, offset;
          const struct bin_messagetable_item *mti;
          const struct bin_messagetable_item *mti;
 
 
          low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
          low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
          high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
          high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
          offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
          offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
          while (low <= high)
          while (low <= high)
            {
            {
              rc_uint_type elen, flags;
              rc_uint_type elen, flags;
              if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
              if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
                {
                {
                  has_error = 1;
                  has_error = 1;
          break;
          break;
                }
                }
              mti = (const struct bin_messagetable_item *) &data[offset];
              mti = (const struct bin_messagetable_item *) &data[offset];
              elen = windres_get_16 (&wrtarget, mti->length, 2);
              elen = windres_get_16 (&wrtarget, mti->length, 2);
              flags = windres_get_16 (&wrtarget, mti->flags, 2);
              flags = windres_get_16 (&wrtarget, mti->flags, 2);
              if ((offset + elen) > length)
              if ((offset + elen) > length)
                {
                {
                  has_error = 1;
                  has_error = 1;
                  break;
                  break;
                }
                }
              wr_printcomment (e, "MessageId = 0x%x", low);
              wr_printcomment (e, "MessageId = 0x%x", low);
              wr_printcomment (e, "");
              wr_printcomment (e, "");
              if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
              if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
                unicode_print (e, (const unichar *) mti->data,
                unicode_print (e, (const unichar *) mti->data,
                               (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
                               (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
              else
              else
                ascii_print (e, (const char *) mti->data,
                ascii_print (e, (const char *) mti->data,
                             (elen - BIN_MESSAGETABLE_ITEM_SIZE));
                             (elen - BIN_MESSAGETABLE_ITEM_SIZE));
              wr_printcomment (e,"");
              wr_printcomment (e,"");
              ++low;
              ++low;
              offset += elen;
              offset += elen;
            }
            }
        }
        }
    } while (0);
    } while (0);
  if (has_error)
  if (has_error)
    wr_printcomment (e, "Illegal data");
    wr_printcomment (e, "Illegal data");
  wr_print_flush (e);
  wr_print_flush (e);
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
static void
static void
write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
                    int hasblock, int show_comment)
                    int hasblock, int show_comment)
{
{
  int plen;
  int plen;
 
 
  if (hasblock)
  if (hasblock)
    fprintf (e, "BEGIN\n");
    fprintf (e, "BEGIN\n");
 
 
  if (show_comment == -1)
  if (show_comment == -1)
          {
          {
      if (test_rc_datablock_text(length, data))
      if (test_rc_datablock_text(length, data))
        {
        {
          rc_uint_type i, c;
          rc_uint_type i, c;
          for (i = 0; i < length;)
          for (i = 0; i < length;)
            {
            {
              indent (e, 2);
              indent (e, 2);
              fprintf (e, "\"");
              fprintf (e, "\"");
 
 
              for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
              for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
                ;
                ;
              if (i < length && data[i] == '\n')
              if (i < length && data[i] == '\n')
                ++i, ++c;
                ++i, ++c;
              ascii_print (e, (const char *) &data[i - c], c);
              ascii_print (e, (const char *) &data[i - c], c);
            fprintf (e, "\"");
            fprintf (e, "\"");
              if (i < length)
              if (i < length)
                fprintf (e, "\n");
                fprintf (e, "\n");
            }
            }
 
 
          if (i == 0)
          if (i == 0)
              {
              {
              indent (e, 2);
              indent (e, 2);
              fprintf (e, "\"\"");
              fprintf (e, "\"\"");
              }
              }
          if (has_next)
          if (has_next)
            fprintf (e, ",");
            fprintf (e, ",");
          fprintf (e, "\n");
          fprintf (e, "\n");
          if (hasblock)
          if (hasblock)
            fprintf (e, "END\n");
            fprintf (e, "END\n");
          return;
          return;
          }
          }
      if (test_rc_datablock_unicode (length, data))
      if (test_rc_datablock_unicode (length, data))
        {
        {
          rc_uint_type i, c;
          rc_uint_type i, c;
          for (i = 0; i < length;)
          for (i = 0; i < length;)
            {
            {
              const unichar *u;
              const unichar *u;
 
 
              u = (const unichar *) &data[i];
              u = (const unichar *) &data[i];
              indent (e, 2);
              indent (e, 2);
          fprintf (e, "L\"");
          fprintf (e, "L\"");
 
 
              for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
              for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
                ;
                ;
              if (i < length && u[c] == '\n')
              if (i < length && u[c] == '\n')
                i += 2, ++c;
                i += 2, ++c;
              unicode_print (e, u, c);
              unicode_print (e, u, c);
          fprintf (e, "\"");
          fprintf (e, "\"");
              if (i < length)
              if (i < length)
                fprintf (e, "\n");
                fprintf (e, "\n");
            }
            }
 
 
          if (i == 0)
          if (i == 0)
          {
          {
              indent (e, 2);
              indent (e, 2);
              fprintf (e, "L\"\"");
              fprintf (e, "L\"\"");
            }
            }
          if (has_next)
          if (has_next)
            fprintf (e, ",");
            fprintf (e, ",");
          fprintf (e, "\n");
          fprintf (e, "\n");
          if (hasblock)
          if (hasblock)
            fprintf (e, "END\n");
            fprintf (e, "END\n");
          return;
          return;
        }
        }
 
 
      show_comment = 0;
      show_comment = 0;
    }
    }
 
 
  if (length != 0)
  if (length != 0)
              {
              {
      rc_uint_type i, max_row;
      rc_uint_type i, max_row;
      int first = 1;
      int first = 1;
 
 
      max_row = (show_comment ? 4 : 8);
      max_row = (show_comment ? 4 : 8);
      indent (e, 2);
      indent (e, 2);
      for (i = 0; i + 3 < length;)
      for (i = 0; i + 3 < length;)
                  {
                  {
          rc_uint_type k;
          rc_uint_type k;
          rc_uint_type comment_start;
          rc_uint_type comment_start;
 
 
          comment_start = i;
          comment_start = i;
 
 
          if (! first)
          if (! first)
            indent (e, 2);
            indent (e, 2);
 
 
          for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
          for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
                      {
                      {
              if (k == 0)
              if (k == 0)
                plen  = fprintf (e, "0x%lxL",
                plen  = fprintf (e, "0x%lxL",
                                 (long) windres_get_32 (&wrtarget, data + i, length - i));
                                 (long) windres_get_32 (&wrtarget, data + i, length - i));
                        else
                        else
                plen = fprintf (e, " 0x%lxL",
                plen = fprintf (e, " 0x%lxL",
                                (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
                                (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
              if (has_next || (i + 4) < length)
              if (has_next || (i + 4) < length)
                          {
                          {
                  if (plen>0 && plen < 11)
                  if (plen>0 && plen < 11)
                    indent (e, 11 - plen);
                    indent (e, 11 - plen);
                  fprintf (e, ",");
                  fprintf (e, ",");
                          }
                          }
                      }
                      }
          if (show_comment)
          if (show_comment)
            {
            {
              fprintf (e, "\t/* ");
              fprintf (e, "\t/* ");
              ascii_print (e, (const char *) &data[comment_start], i - comment_start);
              ascii_print (e, (const char *) &data[comment_start], i - comment_start);
              fprintf (e, ".  */");
              fprintf (e, ".  */");
                  }
                  }
                fprintf (e, "\n");
                fprintf (e, "\n");
                first = 0;
                first = 0;
              }
              }
 
 
      if (i + 1 < length)
      if (i + 1 < length)
              {
              {
                if (! first)
                if (! first)
            indent (e, 2);
            indent (e, 2);
          plen = fprintf (e, "0x%x",
          plen = fprintf (e, "0x%x",
                          (int) windres_get_16 (&wrtarget, data + i, length - i));
                          (int) windres_get_16 (&wrtarget, data + i, length - i));
          if (has_next || i + 2 < length)
          if (has_next || i + 2 < length)
                  {
                  {
              if (plen > 0 && plen < 11)
              if (plen > 0 && plen < 11)
                indent (e, 11 - plen);
                indent (e, 11 - plen);
              fprintf (e, ",");
              fprintf (e, ",");
                      }
                      }
          if (show_comment)
          if (show_comment)
            {
            {
              fprintf (e, "\t/* ");
              fprintf (e, "\t/* ");
              ascii_print (e, (const char *) &data[i], 2);
              ascii_print (e, (const char *) &data[i], 2);
              fprintf (e, ".  */");
              fprintf (e, ".  */");
                  }
                  }
                fprintf (e, "\n");
                fprintf (e, "\n");
                i += 2;
                i += 2;
                first = 0;
                first = 0;
              }
              }
 
 
      if (i < length)
      if (i < length)
              {
              {
                if (! first)
                if (! first)
            indent (e, 2);
            indent (e, 2);
          fprintf (e, "\"");
          fprintf (e, "\"");
          ascii_print (e, (const char *) &data[i], 1);
          ascii_print (e, (const char *) &data[i], 1);
          fprintf (e, "\"");
          fprintf (e, "\"");
          if (has_next)
          if (has_next)
                  fprintf (e, ",");
                  fprintf (e, ",");
                fprintf (e, "\n");
                fprintf (e, "\n");
                first = 0;
                first = 0;
              }
              }
    }
    }
  if (hasblock)
  if (hasblock)
    fprintf (e, "END\n");
    fprintf (e, "END\n");
}
}
 
 
/* Write out an rcdata resource.  This is also used for other types of
/* Write out an rcdata resource.  This is also used for other types of
   resources that need to print arbitrary data.  */
   resources that need to print arbitrary data.  */
 
 
static void
static void
write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
{
{
  const rc_rcdata_item *ri;
  const rc_rcdata_item *ri;
 
 
  indent (e, ind);
  indent (e, ind);
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  for (ri = rcdata; ri != NULL; ri = ri->next)
  for (ri = rcdata; ri != NULL; ri = ri->next)
    {
    {
      if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
      if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
        continue;
        continue;
 
 
      switch (ri->type)
      switch (ri->type)
        {
        {
        default:
        default:
          abort ();
          abort ();
 
 
        case RCDATA_WORD:
        case RCDATA_WORD:
          indent (e, ind + 2);
          indent (e, ind + 2);
          fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
          fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
          break;
          break;
 
 
        case RCDATA_DWORD:
        case RCDATA_DWORD:
          indent (e, ind + 2);
          indent (e, ind + 2);
          fprintf (e, "%luL", (unsigned long) ri->u.dword);
          fprintf (e, "%luL", (unsigned long) ri->u.dword);
          break;
          break;
 
 
        case RCDATA_STRING:
        case RCDATA_STRING:
          indent (e, ind + 2);
          indent (e, ind + 2);
          fprintf (e, "\"");
          fprintf (e, "\"");
          ascii_print (e, ri->u.string.s, ri->u.string.length);
          ascii_print (e, ri->u.string.s, ri->u.string.length);
          fprintf (e, "\"");
          fprintf (e, "\"");
          break;
          break;
 
 
        case RCDATA_WSTRING:
        case RCDATA_WSTRING:
          indent (e, ind + 2);
          indent (e, ind + 2);
          fprintf (e, "L\"");
          fprintf (e, "L\"");
          unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
          unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
          fprintf (e, "\"");
          fprintf (e, "\"");
          break;
          break;
 
 
        case RCDATA_BUFFER:
        case RCDATA_BUFFER:
          write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
          write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
                              (const bfd_byte *) ri->u.buffer.data,
                              (const bfd_byte *) ri->u.buffer.data,
                              ri->next != NULL, 0, -1);
                              ri->next != NULL, 0, -1);
            break;
            break;
        }
        }
 
 
      if (ri->type != RCDATA_BUFFER)
      if (ri->type != RCDATA_BUFFER)
        {
        {
          if (ri->next != NULL)
          if (ri->next != NULL)
            fprintf (e, ",");
            fprintf (e, ",");
          fprintf (e, "\n");
          fprintf (e, "\n");
        }
        }
    }
    }
 
 
  indent (e, ind);
  indent (e, ind);
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out a stringtable resource.  */
/* Write out a stringtable resource.  */
 
 
static void
static void
write_rc_stringtable (FILE *e, const rc_res_id *name,
write_rc_stringtable (FILE *e, const rc_res_id *name,
                      const rc_stringtable *stringtable)
                      const rc_stringtable *stringtable)
{
{
  rc_uint_type offset;
  rc_uint_type offset;
  int i;
  int i;
 
 
  if (name != NULL && ! name->named)
  if (name != NULL && ! name->named)
    offset = (name->u.id - 1) << 4;
    offset = (name->u.id - 1) << 4;
  else
  else
    {
    {
      fprintf (e, "/* %s string table name.  */\n",
      fprintf (e, "/* %s string table name.  */\n",
               name == NULL ? "Missing" : "Invalid");
               name == NULL ? "Missing" : "Invalid");
      offset = 0;
      offset = 0;
    }
    }
 
 
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  for (i = 0; i < 16; i++)
  for (i = 0; i < 16; i++)
    {
    {
      if (stringtable->strings[i].length != 0)
      if (stringtable->strings[i].length != 0)
        {
        {
          fprintf (e, "  %lu, ", (long) offset + i);
          fprintf (e, "  %lu, ", (long) offset + i);
          unicode_print_quoted (e, stringtable->strings[i].string,
          unicode_print_quoted (e, stringtable->strings[i].string,
                         stringtable->strings[i].length);
                         stringtable->strings[i].length);
          fprintf (e, "\n");
          fprintf (e, "\n");
        }
        }
    }
    }
 
 
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
/* Write out a versioninfo resource.  */
/* Write out a versioninfo resource.  */
 
 
static void
static void
write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
{
{
  const rc_fixed_versioninfo *f;
  const rc_fixed_versioninfo *f;
  const rc_ver_info *vi;
  const rc_ver_info *vi;
 
 
  f = versioninfo->fixed;
  f = versioninfo->fixed;
  if (f->file_version_ms != 0 || f->file_version_ls != 0)
  if (f->file_version_ms != 0 || f->file_version_ls != 0)
    fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
    fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
             (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
             (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
             (unsigned int) (f->file_version_ms & 0xffff),
             (unsigned int) (f->file_version_ms & 0xffff),
             (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
             (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
             (unsigned int) (f->file_version_ls & 0xffff));
             (unsigned int) (f->file_version_ls & 0xffff));
  if (f->product_version_ms != 0 || f->product_version_ls != 0)
  if (f->product_version_ms != 0 || f->product_version_ls != 0)
    fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
    fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
             (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
             (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
             (unsigned int) (f->product_version_ms & 0xffff),
             (unsigned int) (f->product_version_ms & 0xffff),
             (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
             (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
             (unsigned int) (f->product_version_ls & 0xffff));
             (unsigned int) (f->product_version_ls & 0xffff));
  if (f->file_flags_mask != 0)
  if (f->file_flags_mask != 0)
    fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
    fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
  if (f->file_flags != 0)
  if (f->file_flags != 0)
    fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
    fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
  if (f->file_os != 0)
  if (f->file_os != 0)
    fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
    fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
  if (f->file_type != 0)
  if (f->file_type != 0)
    fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
    fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
  if (f->file_subtype != 0)
  if (f->file_subtype != 0)
    fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
    fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
  if (f->file_date_ms != 0 || f->file_date_ls != 0)
  if (f->file_date_ms != 0 || f->file_date_ls != 0)
    fprintf (e, "/* Date: %u, %u.  */\n",
    fprintf (e, "/* Date: %u, %u.  */\n",
             (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
             (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
 
 
  fprintf (e, "BEGIN\n");
  fprintf (e, "BEGIN\n");
 
 
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
    {
    {
      switch (vi->type)
      switch (vi->type)
        {
        {
        case VERINFO_STRING:
        case VERINFO_STRING:
          {
          {
            const rc_ver_stringinfo *vs;
            const rc_ver_stringinfo *vs;
 
 
            fprintf (e, "  BLOCK \"StringFileInfo\"\n");
            fprintf (e, "  BLOCK \"StringFileInfo\"\n");
            fprintf (e, "  BEGIN\n");
            fprintf (e, "  BEGIN\n");
            fprintf (e, "    BLOCK ");
            fprintf (e, "    BLOCK ");
            unicode_print_quoted (e, vi->u.string.language, -1);
            unicode_print_quoted (e, vi->u.string.language, -1);
            fprintf (e, "\n");
            fprintf (e, "\n");
            fprintf (e, "    BEGIN\n");
            fprintf (e, "    BEGIN\n");
 
 
            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
              {
              {
                fprintf (e, "      VALUE ");
                fprintf (e, "      VALUE ");
                unicode_print_quoted (e, vs->key, -1);
                unicode_print_quoted (e, vs->key, -1);
                fprintf (e, ", ");
                fprintf (e, ", ");
                unicode_print_quoted (e, vs->value, -1);
                unicode_print_quoted (e, vs->value, -1);
                fprintf (e, "\n");
                fprintf (e, "\n");
              }
              }
 
 
            fprintf (e, "    END\n");
            fprintf (e, "    END\n");
            fprintf (e, "  END\n");
            fprintf (e, "  END\n");
            break;
            break;
          }
          }
 
 
        case VERINFO_VAR:
        case VERINFO_VAR:
          {
          {
            const rc_ver_varinfo *vv;
            const rc_ver_varinfo *vv;
 
 
            fprintf (e, "  BLOCK \"VarFileInfo\"\n");
            fprintf (e, "  BLOCK \"VarFileInfo\"\n");
            fprintf (e, "  BEGIN\n");
            fprintf (e, "  BEGIN\n");
            fprintf (e, "    VALUE ");
            fprintf (e, "    VALUE ");
            unicode_print_quoted (e, vi->u.var.key, -1);
            unicode_print_quoted (e, vi->u.var.key, -1);
 
 
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
              fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
              fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
                       (int) vv->charset);
                       (int) vv->charset);
 
 
            fprintf (e, "\n  END\n");
            fprintf (e, "\n  END\n");
 
 
            break;
            break;
          }
          }
        }
        }
    }
    }
 
 
  fprintf (e, "END\n");
  fprintf (e, "END\n");
}
}
 
 
static rc_uint_type
static rc_uint_type
rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
{
{
  if (! src)
  if (! src)
    return 0;
    return 0;
  switch (src->type)
  switch (src->type)
        {
        {
    case RCDATA_WORD:
    case RCDATA_WORD:
      if (dst)
      if (dst)
        windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
        windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
      return 2;
      return 2;
    case RCDATA_DWORD:
    case RCDATA_DWORD:
      if (dst)
      if (dst)
        windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
        windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
      return 4;
      return 4;
    case RCDATA_STRING:
    case RCDATA_STRING:
      if (dst && src->u.string.length)
      if (dst && src->u.string.length)
        memcpy (dst, src->u.string.s, src->u.string.length);
        memcpy (dst, src->u.string.s, src->u.string.length);
      return (rc_uint_type) src->u.string.length;
      return (rc_uint_type) src->u.string.length;
    case RCDATA_WSTRING:
    case RCDATA_WSTRING:
      if (dst && src->u.wstring.length)
      if (dst && src->u.wstring.length)
        memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
        memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
      return (rc_uint_type) (src->u.wstring.length  * sizeof (unichar));
      return (rc_uint_type) (src->u.wstring.length  * sizeof (unichar));
    case RCDATA_BUFFER:
    case RCDATA_BUFFER:
      if (dst && src->u.buffer.length)
      if (dst && src->u.buffer.length)
        memcpy (dst, src->u.buffer.data, src->u.buffer.length);
        memcpy (dst, src->u.buffer.data, src->u.buffer.length);
      return (rc_uint_type) src->u.buffer.length;
      return (rc_uint_type) src->u.buffer.length;
    default:
    default:
      abort ();
      abort ();
    }
    }
  /* Never reached.  */
  /* Never reached.  */
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.