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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [resbin.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
/* resbin.c -- manipulate the Windows binary resource format.
/* resbin.c -- manipulate the Windows binary resource format.
   Copyright 1997, 1998, 1999, 2002, 2003, 2007
   Copyright 1997, 1998, 1999, 2002, 2003, 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 to convert between the binary resource
/* This file contains functions to convert between the binary resource
   format and the internal structures that we want to use.  The same
   format and the internal structures that we want to use.  The same
   binary resource format is used in both res and COFF files.  */
   binary resource format is used in both res and COFF files.  */
 
 
#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 "windres.h"
#include "windres.h"
 
 
/* Local functions.  */
/* Local functions.  */
 
 
static void toosmall (const char *);
static void toosmall (const char *);
 
 
static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
                                            const bfd_byte *, rc_uint_type);
                                            const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
                                          rc_uint_type *);
                                          rc_uint_type *);
static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
                                            rc_uint_type *);
                                            rc_uint_type *);
static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
                                unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
                                unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
                                rc_uint_type *);
                                rc_uint_type *);
 
 
/* Given a resource type ID, a pointer to data, a length, return a
/* Given a resource type ID, a pointer to data, a length, return a
   rc_res_resource structure which represents that resource.  The caller
   rc_res_resource structure which represents that resource.  The caller
   is responsible for initializing the res_info and coff_info fields
   is responsible for initializing the res_info and coff_info fields
   of the returned structure.  */
   of the returned structure.  */
 
 
rc_res_resource *
rc_res_resource *
bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
            rc_uint_type length)
            rc_uint_type length)
{
{
  if (type.named)
  if (type.named)
    return bin_to_res_userdata (wrbfd, data, length);
    return bin_to_res_userdata (wrbfd, data, length);
  else
  else
    {
    {
      switch (type.u.id)
      switch (type.u.id)
        {
        {
        default:
        default:
          return bin_to_res_userdata (wrbfd, data, length);
          return bin_to_res_userdata (wrbfd, data, length);
        case RT_CURSOR:
        case RT_CURSOR:
          return bin_to_res_cursor (wrbfd, data, length);
          return bin_to_res_cursor (wrbfd, data, length);
        case RT_BITMAP:
        case RT_BITMAP:
          return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
          return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
        case RT_ICON:
        case RT_ICON:
          return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
          return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
        case RT_MENU:
        case RT_MENU:
          return bin_to_res_menu (wrbfd, data, length);
          return bin_to_res_menu (wrbfd, data, length);
        case RT_DIALOG:
        case RT_DIALOG:
          return bin_to_res_dialog (wrbfd, data, length);
          return bin_to_res_dialog (wrbfd, data, length);
        case RT_STRING:
        case RT_STRING:
          return bin_to_res_string (wrbfd, data, length);
          return bin_to_res_string (wrbfd, data, length);
        case RT_FONTDIR:
        case RT_FONTDIR:
          return bin_to_res_fontdir (wrbfd, data, length);
          return bin_to_res_fontdir (wrbfd, data, length);
        case RT_FONT:
        case RT_FONT:
          return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
          return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
        case RT_ACCELERATOR:
        case RT_ACCELERATOR:
          return bin_to_res_accelerators (wrbfd, data, length);
          return bin_to_res_accelerators (wrbfd, data, length);
        case RT_RCDATA:
        case RT_RCDATA:
          return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
          return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
        case RT_MESSAGETABLE:
        case RT_MESSAGETABLE:
          return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
          return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
        case RT_GROUP_CURSOR:
        case RT_GROUP_CURSOR:
          return bin_to_res_group_cursor (wrbfd, data, length);
          return bin_to_res_group_cursor (wrbfd, data, length);
        case RT_GROUP_ICON:
        case RT_GROUP_ICON:
          return bin_to_res_group_icon (wrbfd, data, length);
          return bin_to_res_group_icon (wrbfd, data, length);
        case RT_VERSION:
        case RT_VERSION:
          return bin_to_res_version (wrbfd, data, length);
          return bin_to_res_version (wrbfd, data, length);
        case RT_TOOLBAR:
        case RT_TOOLBAR:
          return  bin_to_res_toolbar (wrbfd, data, length);
          return  bin_to_res_toolbar (wrbfd, data, length);
 
 
        }
        }
    }
    }
}
}
 
 
/* Give an error if the binary data is too small.  */
/* Give an error if the binary data is too small.  */
 
 
static void
static void
toosmall (const char *msg)
toosmall (const char *msg)
{
{
  fatal (_("%s: not enough binary data"), msg);
  fatal (_("%s: not enough binary data"), msg);
}
}
 
 
/* Swap in a NULL terminated unicode string.  */
/* Swap in a NULL terminated unicode string.  */
 
 
static unichar *
static unichar *
get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
             rc_uint_type *retlen)
             rc_uint_type *retlen)
{
{
  rc_uint_type c, i;
  rc_uint_type c, i;
  unichar *ret;
  unichar *ret;
 
 
  c = 0;
  c = 0;
  while (1)
  while (1)
    {
    {
      if (length < c * 2 + 2)
      if (length < c * 2 + 2)
        toosmall (_("null terminated unicode string"));
        toosmall (_("null terminated unicode string"));
      if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
      if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
        break;
        break;
      ++c;
      ++c;
    }
    }
 
 
  ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
  ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
    ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
  ret[i] = 0;
  ret[i] = 0;
 
 
  if (retlen != NULL)
  if (retlen != NULL)
    *retlen = c;
    *retlen = c;
 
 
  return ret;
  return ret;
}
}
 
 
/* Get a resource identifier.  This returns the number of bytes used.  */
/* Get a resource identifier.  This returns the number of bytes used.  */
 
 
static int
static int
get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
           rc_uint_type length)
           rc_uint_type length)
{
{
  rc_uint_type first;
  rc_uint_type first;
 
 
  if (length < 2)
  if (length < 2)
    toosmall (_("resource ID"));
    toosmall (_("resource ID"));
 
 
  first = windres_get_16 (wrbfd, data, 2);
  first = windres_get_16 (wrbfd, data, 2);
  if (first == 0xffff)
  if (first == 0xffff)
    {
    {
      if (length < 4)
      if (length < 4)
        toosmall (_("resource ID"));
        toosmall (_("resource ID"));
      id->named = 0;
      id->named = 0;
      id->u.id = windres_get_16 (wrbfd, data + 2, 2);
      id->u.id = windres_get_16 (wrbfd, data + 2, 2);
      return 4;
      return 4;
    }
    }
  else
  else
    {
    {
      id->named = 1;
      id->named = 1;
      id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
      id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
      return id->u.n.length * 2 + 2;
      return id->u.n.length * 2 + 2;
    }
    }
}
}
 
 
/* Convert a resource which just stores uninterpreted data from
/* Convert a resource which just stores uninterpreted data from
   binary.  */
   binary.  */
 
 
rc_res_resource *
rc_res_resource *
bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
                    const bfd_byte *data, rc_uint_type length)
                    const bfd_byte *data, rc_uint_type length)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r->type = type;
  r->type = type;
  r->u.data.data = data;
  r->u.data.data = data;
  r->u.data.length = length;
  r->u.data.length = length;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a cursor resource from binary.  */
/* Convert a cursor resource from binary.  */
 
 
rc_res_resource *
rc_res_resource *
bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_cursor *c;
  rc_cursor *c;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  if (length < 4)
  if (length < 4)
    toosmall (_("cursor"));
    toosmall (_("cursor"));
 
 
  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  c->xhotspot = windres_get_16 (wrbfd, data, 2);
  c->xhotspot = windres_get_16 (wrbfd, data, 2);
  c->yhotspot = windres_get_16 (wrbfd, data + 2, 2);
  c->yhotspot = windres_get_16 (wrbfd, data + 2, 2);
  c->length = length - 4;
  c->length = length - 4;
  c->data = data + 4;
  c->data = data + 4;
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_CURSOR;
  r->type = RES_TYPE_CURSOR;
  r->u.cursor = c;
  r->u.cursor = c;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a menu resource from binary.  */
/* Convert a menu resource from binary.  */
 
 
rc_res_resource *
rc_res_resource *
bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_res_resource *r;
  rc_res_resource *r;
  rc_menu *m;
  rc_menu *m;
  rc_uint_type version, read;
  rc_uint_type version, read;
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_MENU;
  r->type = RES_TYPE_MENU;
 
 
  m = (rc_menu *) res_alloc (sizeof (rc_menu));
  m = (rc_menu *) res_alloc (sizeof (rc_menu));
  r->u.menu = m;
  r->u.menu = m;
 
 
  if (length < 2)
  if (length < 2)
    toosmall (_("menu header"));
    toosmall (_("menu header"));
 
 
  version = windres_get_16 (wrbfd, data, 2);
  version = windres_get_16 (wrbfd, data, 2);
 
 
  if (version == 0)
  if (version == 0)
    {
    {
      if (length < 4)
      if (length < 4)
        toosmall (_("menu header"));
        toosmall (_("menu header"));
      m->help = 0;
      m->help = 0;
      m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read);
      m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read);
    }
    }
  else if (version == 1)
  else if (version == 1)
    {
    {
      rc_uint_type offset;
      rc_uint_type offset;
 
 
      if (length < 8)
      if (length < 8)
        toosmall (_("menuex header"));
        toosmall (_("menuex header"));
      m->help = windres_get_32 (wrbfd, data + 4, 4);
      m->help = windres_get_32 (wrbfd, data + 4, 4);
      offset = windres_get_16 (wrbfd, data + 2, 2);
      offset = windres_get_16 (wrbfd, data + 2, 2);
      if (offset + 4 >= length)
      if (offset + 4 >= length)
        toosmall (_("menuex offset"));
        toosmall (_("menuex offset"));
      m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
      m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
                                         length - (4 + offset), &read);
                                         length - (4 + offset), &read);
    }
    }
  else
  else
    fatal (_("unsupported menu version %d"), (int) version);
    fatal (_("unsupported menu version %d"), (int) version);
 
 
  return r;
  return r;
}
}
 
 
/* Convert menu items from binary.  */
/* Convert menu items from binary.  */
 
 
static rc_menuitem *
static rc_menuitem *
bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
                      rc_uint_type *read)
                      rc_uint_type *read)
{
{
  rc_menuitem *first, **pp;
  rc_menuitem *first, **pp;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  *read = 0;
  *read = 0;
 
 
  while (length > 0)
  while (length > 0)
    {
    {
      rc_uint_type flags, slen, itemlen;
      rc_uint_type flags, slen, itemlen;
      rc_uint_type stroff;
      rc_uint_type stroff;
      rc_menuitem *mi;
      rc_menuitem *mi;
 
 
      if (length < 4)
      if (length < 4)
        toosmall (_("menuitem header"));
        toosmall (_("menuitem header"));
 
 
      mi = (rc_menuitem *) res_alloc (sizeof *mi);
      mi = (rc_menuitem *) res_alloc (sizeof *mi);
      mi->state = 0;
      mi->state = 0;
      mi->help = 0;
      mi->help = 0;
 
 
      flags = windres_get_16 (wrbfd, data, 2);
      flags = windres_get_16 (wrbfd, data, 2);
      mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
      mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
 
 
      if ((flags & MENUITEM_POPUP) == 0)
      if ((flags & MENUITEM_POPUP) == 0)
        stroff = 4;
        stroff = 4;
      else
      else
        stroff = 2;
        stroff = 2;
 
 
      if (length < stroff + 2)
      if (length < stroff + 2)
        toosmall (_("menuitem header"));
        toosmall (_("menuitem header"));
 
 
      if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
      if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
        {
        {
          slen = 0;
          slen = 0;
          mi->text = NULL;
          mi->text = NULL;
        }
        }
      else
      else
        mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
        mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
 
 
      itemlen = stroff + slen * 2 + 2;
      itemlen = stroff + slen * 2 + 2;
 
 
      if ((flags & MENUITEM_POPUP) == 0)
      if ((flags & MENUITEM_POPUP) == 0)
        {
        {
          mi->popup = NULL;
          mi->popup = NULL;
          mi->id = windres_get_16 (wrbfd, data + 2, 2);
          mi->id = windres_get_16 (wrbfd, data + 2, 2);
        }
        }
      else
      else
        {
        {
          rc_uint_type subread;
          rc_uint_type subread;
 
 
          mi->id = 0;
          mi->id = 0;
          mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
          mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
                                            &subread);
                                            &subread);
          itemlen += subread;
          itemlen += subread;
        }
        }
 
 
      mi->next = NULL;
      mi->next = NULL;
      *pp = mi;
      *pp = mi;
      pp = &mi->next;
      pp = &mi->next;
 
 
      data += itemlen;
      data += itemlen;
      length -= itemlen;
      length -= itemlen;
      *read += itemlen;
      *read += itemlen;
 
 
      if ((flags & MENUITEM_ENDMENU) != 0)
      if ((flags & MENUITEM_ENDMENU) != 0)
        return first;
        return first;
    }
    }
 
 
  return first;
  return first;
}
}
 
 
/* Convert menuex items from binary.  */
/* Convert menuex items from binary.  */
 
 
static rc_menuitem *
static rc_menuitem *
bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
                        rc_uint_type *read)
                        rc_uint_type *read)
{
{
  rc_menuitem *first, **pp;
  rc_menuitem *first, **pp;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  *read = 0;
  *read = 0;
 
 
  while (length > 0)
  while (length > 0)
    {
    {
      rc_uint_type flags, slen;
      rc_uint_type flags, slen;
      rc_uint_type itemlen;
      rc_uint_type itemlen;
      rc_menuitem *mi;
      rc_menuitem *mi;
 
 
      if (length < 16)
      if (length < 16)
        toosmall (_("menuitem header"));
        toosmall (_("menuitem header"));
 
 
      mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
      mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
      mi->type = windres_get_32 (wrbfd, data, 4);
      mi->type = windres_get_32 (wrbfd, data, 4);
      mi->state = windres_get_32 (wrbfd, data + 4, 4);
      mi->state = windres_get_32 (wrbfd, data + 4, 4);
      mi->id = windres_get_32 (wrbfd, data + 8, 4);
      mi->id = windres_get_32 (wrbfd, data + 8, 4);
 
 
      flags = windres_get_16 (wrbfd, data + 12, 2);
      flags = windres_get_16 (wrbfd, data + 12, 2);
 
 
      if (windres_get_16 (wrbfd, data + 14, 2) == 0)
      if (windres_get_16 (wrbfd, data + 14, 2) == 0)
        {
        {
          slen = 0;
          slen = 0;
          mi->text = NULL;
          mi->text = NULL;
        }
        }
      else
      else
        mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
        mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
 
 
      itemlen = 14 + slen * 2 + 2;
      itemlen = 14 + slen * 2 + 2;
      itemlen = (itemlen + 3) &~ 3;
      itemlen = (itemlen + 3) &~ 3;
 
 
      if ((flags & 1) == 0)
      if ((flags & 1) == 0)
        {
        {
          mi->popup = NULL;
          mi->popup = NULL;
          mi->help = 0;
          mi->help = 0;
        }
        }
      else
      else
        {
        {
          rc_uint_type subread;
          rc_uint_type subread;
 
 
          if (length < itemlen + 4)
          if (length < itemlen + 4)
            toosmall (_("menuitem"));
            toosmall (_("menuitem"));
          mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
          mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
          itemlen += 4;
          itemlen += 4;
 
 
          mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
          mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
                                              length - itemlen, &subread);
                                              length - itemlen, &subread);
          itemlen += subread;
          itemlen += subread;
        }
        }
 
 
      mi->next = NULL;
      mi->next = NULL;
      *pp = mi;
      *pp = mi;
      pp = &mi->next;
      pp = &mi->next;
 
 
      data += itemlen;
      data += itemlen;
      length -= itemlen;
      length -= itemlen;
      *read += itemlen;
      *read += itemlen;
 
 
      if ((flags & 0x80) != 0)
      if ((flags & 0x80) != 0)
        return first;
        return first;
    }
    }
 
 
  return first;
  return first;
}
}
 
 
/* Convert a dialog resource from binary.  */
/* Convert a dialog resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_uint_type signature;
  rc_uint_type signature;
  rc_dialog *d;
  rc_dialog *d;
  rc_uint_type c, sublen, i;
  rc_uint_type c, sublen, i;
  rc_uint_type off;
  rc_uint_type off;
  rc_dialog_control **pp;
  rc_dialog_control **pp;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  if (length < 18)
  if (length < 18)
    toosmall (_("dialog header"));
    toosmall (_("dialog header"));
 
 
  d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
  d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
 
 
  signature = windres_get_16 (wrbfd, data + 2, 2);
  signature = windres_get_16 (wrbfd, data + 2, 2);
  if (signature != 0xffff)
  if (signature != 0xffff)
    {
    {
      d->ex = NULL;
      d->ex = NULL;
      d->style = windres_get_32 (wrbfd, data, 4);
      d->style = windres_get_32 (wrbfd, data, 4);
      d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
      d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
      off = 8;
      off = 8;
    }
    }
  else
  else
    {
    {
      int version;
      int version;
 
 
      version = windres_get_16 (wrbfd, data, 2);
      version = windres_get_16 (wrbfd, data, 2);
      if (version != 1)
      if (version != 1)
        fatal (_("unexpected DIALOGEX version %d"), version);
        fatal (_("unexpected DIALOGEX version %d"), version);
 
 
      d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex));
      d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex));
      d->ex->help = windres_get_32 (wrbfd, data + 4, 4);
      d->ex->help = windres_get_32 (wrbfd, data + 4, 4);
      d->exstyle = windres_get_32 (wrbfd, data + 8, 4);
      d->exstyle = windres_get_32 (wrbfd, data + 8, 4);
      d->style = windres_get_32 (wrbfd, data + 12, 4);
      d->style = windres_get_32 (wrbfd, data + 12, 4);
      off = 16;
      off = 16;
    }
    }
 
 
  if (length < off + 10)
  if (length < off + 10)
    toosmall (_("dialog header"));
    toosmall (_("dialog header"));
 
 
  c = windres_get_16 (wrbfd, data + off, 2);
  c = windres_get_16 (wrbfd, data + off, 2);
  d->x = windres_get_16 (wrbfd, data + off + 2, 2);
  d->x = windres_get_16 (wrbfd, data + off + 2, 2);
  d->y = windres_get_16 (wrbfd, data + off + 4, 2);
  d->y = windres_get_16 (wrbfd, data + off + 4, 2);
  d->width = windres_get_16 (wrbfd, data + off + 6, 2);
  d->width = windres_get_16 (wrbfd, data + off + 6, 2);
  d->height = windres_get_16 (wrbfd, data + off + 8, 2);
  d->height = windres_get_16 (wrbfd, data + off + 8, 2);
 
 
  off += 10;
  off += 10;
 
 
  sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
  sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
  off += sublen;
  off += sublen;
 
 
  sublen = get_resid (wrbfd, &d->class, data + off, length - off);
  sublen = get_resid (wrbfd, &d->class, data + off, length - off);
  off += sublen;
  off += sublen;
 
 
  d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
  d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
  off += sublen * 2 + 2;
  off += sublen * 2 + 2;
  if (sublen == 0)
  if (sublen == 0)
    d->caption = NULL;
    d->caption = NULL;
 
 
  if ((d->style & DS_SETFONT) == 0)
  if ((d->style & DS_SETFONT) == 0)
    {
    {
      d->pointsize = 0;
      d->pointsize = 0;
      d->font = NULL;
      d->font = NULL;
      if (d->ex != NULL)
      if (d->ex != NULL)
        {
        {
          d->ex->weight = 0;
          d->ex->weight = 0;
          d->ex->italic = 0;
          d->ex->italic = 0;
          d->ex->charset = 1; /* Default charset.  */
          d->ex->charset = 1; /* Default charset.  */
        }
        }
    }
    }
  else
  else
    {
    {
      if (length < off + 2)
      if (length < off + 2)
        toosmall (_("dialog font point size"));
        toosmall (_("dialog font point size"));
 
 
      d->pointsize = windres_get_16 (wrbfd, data + off, 2);
      d->pointsize = windres_get_16 (wrbfd, data + off, 2);
      off += 2;
      off += 2;
 
 
      if (d->ex != NULL)
      if (d->ex != NULL)
        {
        {
          if (length < off + 4)
          if (length < off + 4)
            toosmall (_("dialogex font information"));
            toosmall (_("dialogex font information"));
          d->ex->weight = windres_get_16 (wrbfd, data + off, 2);
          d->ex->weight = windres_get_16 (wrbfd, data + off, 2);
          d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1);
          d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1);
          d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1);
          d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1);
          off += 4;
          off += 4;
        }
        }
 
 
      d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
      d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
      off += sublen * 2 + 2;
      off += sublen * 2 + 2;
    }
    }
 
 
  d->controls = NULL;
  d->controls = NULL;
  pp = &d->controls;
  pp = &d->controls;
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    {
    {
      rc_dialog_control *dc;
      rc_dialog_control *dc;
      int datalen;
      int datalen;
 
 
      off = (off + 3) &~ 3;
      off = (off + 3) &~ 3;
 
 
      dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
      dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
 
 
      if (d->ex == NULL)
      if (d->ex == NULL)
        {
        {
          if (length < off + 8)
          if (length < off + 8)
            toosmall (_("dialog control"));
            toosmall (_("dialog control"));
 
 
          dc->style = windres_get_32 (wrbfd, data + off, 4);
          dc->style = windres_get_32 (wrbfd, data + off, 4);
          dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
          dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
          dc->help = 0;
          dc->help = 0;
          off += 8;
          off += 8;
        }
        }
      else
      else
        {
        {
          if (length < off + 12)
          if (length < off + 12)
            toosmall (_("dialogex control"));
            toosmall (_("dialogex control"));
          dc->help = windres_get_32 (wrbfd, data + off, 4);
          dc->help = windres_get_32 (wrbfd, data + off, 4);
          dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
          dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
          dc->style = windres_get_32 (wrbfd, data + off + 8, 4);
          dc->style = windres_get_32 (wrbfd, data + off + 8, 4);
          off += 12;
          off += 12;
        }
        }
 
 
      if (length < off + (d->ex != NULL ? 2 : 0) + 10)
      if (length < off + (d->ex != NULL ? 2 : 0) + 10)
        toosmall (_("dialog control"));
        toosmall (_("dialog control"));
 
 
      dc->x = windres_get_16 (wrbfd, data + off, 2);
      dc->x = windres_get_16 (wrbfd, data + off, 2);
      dc->y = windres_get_16 (wrbfd, data + off + 2, 2);
      dc->y = windres_get_16 (wrbfd, data + off + 2, 2);
      dc->width = windres_get_16 (wrbfd, data + off + 4, 2);
      dc->width = windres_get_16 (wrbfd, data + off + 4, 2);
      dc->height = windres_get_16 (wrbfd, data + off + 6, 2);
      dc->height = windres_get_16 (wrbfd, data + off + 6, 2);
 
 
      if (d->ex != NULL)
      if (d->ex != NULL)
        dc->id = windres_get_32 (wrbfd, data + off + 8, 4);
        dc->id = windres_get_32 (wrbfd, data + off + 8, 4);
      else
      else
        dc->id = windres_get_16 (wrbfd, data + off + 8, 2);
        dc->id = windres_get_16 (wrbfd, data + off + 8, 2);
 
 
      off += 10 + (d->ex != NULL ? 2 : 0);
      off += 10 + (d->ex != NULL ? 2 : 0);
 
 
      sublen = get_resid (wrbfd, &dc->class, data + off, length - off);
      sublen = get_resid (wrbfd, &dc->class, data + off, length - off);
      off += sublen;
      off += sublen;
 
 
      sublen = get_resid (wrbfd, &dc->text, data + off, length - off);
      sublen = get_resid (wrbfd, &dc->text, data + off, length - off);
      off += sublen;
      off += sublen;
 
 
      if (length < off + 2)
      if (length < off + 2)
        toosmall (_("dialog control end"));
        toosmall (_("dialog control end"));
 
 
      datalen = windres_get_16 (wrbfd, data + off, 2);
      datalen = windres_get_16 (wrbfd, data + off, 2);
      off += 2;
      off += 2;
 
 
      if (datalen == 0)
      if (datalen == 0)
        dc->data = NULL;
        dc->data = NULL;
      else
      else
        {
        {
          off = (off + 3) &~ 3;
          off = (off + 3) &~ 3;
 
 
          if (length < off + datalen)
          if (length < off + datalen)
            toosmall (_("dialog control data"));
            toosmall (_("dialog control data"));
 
 
          dc->data = ((rc_rcdata_item *)
          dc->data = ((rc_rcdata_item *)
                      res_alloc (sizeof (rc_rcdata_item)));
                      res_alloc (sizeof (rc_rcdata_item)));
          dc->data->next = NULL;
          dc->data->next = NULL;
          dc->data->type = RCDATA_BUFFER;
          dc->data->type = RCDATA_BUFFER;
          dc->data->u.buffer.length = datalen;
          dc->data->u.buffer.length = datalen;
          dc->data->u.buffer.data = data + off;
          dc->data->u.buffer.data = data + off;
 
 
          off += datalen;
          off += datalen;
        }
        }
 
 
      dc->next = NULL;
      dc->next = NULL;
      *pp = dc;
      *pp = dc;
      pp = &dc->next;
      pp = &dc->next;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_DIALOG;
  r->type = RES_TYPE_DIALOG;
  r->u.dialog = d;
  r->u.dialog = d;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a stringtable resource from binary.  */
/* Convert a stringtable resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_stringtable *st;
  rc_stringtable *st;
  int i;
  int i;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable));
  st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable));
 
 
  for (i = 0; i < 16; i++)
  for (i = 0; i < 16; i++)
    {
    {
      unsigned int slen;
      unsigned int slen;
 
 
      if (length < 2)
      if (length < 2)
        toosmall (_("stringtable string length"));
        toosmall (_("stringtable string length"));
      slen = windres_get_16 (wrbfd, data, 2);
      slen = windres_get_16 (wrbfd, data, 2);
      st->strings[i].length = slen;
      st->strings[i].length = slen;
 
 
      if (slen > 0)
      if (slen > 0)
        {
        {
          unichar *s;
          unichar *s;
          unsigned int j;
          unsigned int j;
 
 
          if (length < 2 + 2 * slen)
          if (length < 2 + 2 * slen)
            toosmall (_("stringtable string"));
            toosmall (_("stringtable string"));
 
 
          s = (unichar *) res_alloc (slen * sizeof (unichar));
          s = (unichar *) res_alloc (slen * sizeof (unichar));
          st->strings[i].string = s;
          st->strings[i].string = s;
 
 
          for (j = 0; j < slen; j++)
          for (j = 0; j < slen; j++)
            s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2);
            s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2);
        }
        }
 
 
      data += 2 + 2 * slen;
      data += 2 + 2 * slen;
      length -= 2 + 2 * slen;
      length -= 2 + 2 * slen;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_STRINGTABLE;
  r->type = RES_TYPE_STRINGTABLE;
  r->u.stringtable = st;
  r->u.stringtable = st;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a fontdir resource from binary.  */
/* Convert a fontdir resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_uint_type c, i;
  rc_uint_type c, i;
  rc_fontdir *first, **pp;
  rc_fontdir *first, **pp;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  if (length < 2)
  if (length < 2)
    toosmall (_("fontdir header"));
    toosmall (_("fontdir header"));
 
 
  c = windres_get_16 (wrbfd, data, 2);
  c = windres_get_16 (wrbfd, data, 2);
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    {
    {
      const struct bin_fontdir_item *bfi;
      const struct bin_fontdir_item *bfi;
      rc_fontdir *fd;
      rc_fontdir *fd;
      unsigned int off;
      unsigned int off;
 
 
      if (length < 56)
      if (length < 56)
        toosmall (_("fontdir"));
        toosmall (_("fontdir"));
 
 
      bfi = (const struct bin_fontdir_item *) data;
      bfi = (const struct bin_fontdir_item *) data;
      fd = (rc_fontdir *) res_alloc (sizeof *fd);
      fd = (rc_fontdir *) res_alloc (sizeof *fd);
      fd->index = windres_get_16 (wrbfd, bfi->index, 2);
      fd->index = windres_get_16 (wrbfd, bfi->index, 2);
 
 
      /* To work out the length of the fontdir data, we must get the
      /* To work out the length of the fontdir data, we must get the
         length of the device name and face name strings, even though
         length of the device name and face name strings, even though
         we don't store them in the rc_fontdir.  The
         we don't store them in the rc_fontdir.  The
         documentation says that these are NULL terminated char
         documentation says that these are NULL terminated char
         strings, not Unicode strings.  */
         strings, not Unicode strings.  */
 
 
      off = 56;
      off = 56;
 
 
      while (off < length && data[off] != '\0')
      while (off < length && data[off] != '\0')
        ++off;
        ++off;
      if (off >= length)
      if (off >= length)
        toosmall (_("fontdir device name"));
        toosmall (_("fontdir device name"));
      ++off;
      ++off;
 
 
      while (off < length && data[off] != '\0')
      while (off < length && data[off] != '\0')
        ++off;
        ++off;
      if (off >= length)
      if (off >= length)
        toosmall (_("fontdir face name"));
        toosmall (_("fontdir face name"));
      ++off;
      ++off;
 
 
      fd->length = off;
      fd->length = off;
      fd->data = data;
      fd->data = data;
 
 
      fd->next = NULL;
      fd->next = NULL;
      *pp = fd;
      *pp = fd;
      pp = &fd->next;
      pp = &fd->next;
 
 
      /* The documentation does not indicate that any rounding is
      /* The documentation does not indicate that any rounding is
         required.  */
         required.  */
 
 
      data += off;
      data += off;
      length -= off;
      length -= off;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_FONTDIR;
  r->type = RES_TYPE_FONTDIR;
  r->u.fontdir = first;
  r->u.fontdir = first;
 
 
  return r;
  return r;
}
}
 
 
/* Convert an accelerators resource from binary.  */
/* Convert an accelerators resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_accelerator *first, **pp;
  rc_accelerator *first, **pp;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  while (1)
  while (1)
    {
    {
      rc_accelerator *a;
      rc_accelerator *a;
 
 
      if (length < 8)
      if (length < 8)
        toosmall (_("accelerator"));
        toosmall (_("accelerator"));
 
 
      a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator));
      a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator));
 
 
      a->flags = windres_get_16 (wrbfd, data, 2);
      a->flags = windres_get_16 (wrbfd, data, 2);
      a->key = windres_get_16 (wrbfd, data + 2, 2);
      a->key = windres_get_16 (wrbfd, data + 2, 2);
      a->id = windres_get_16 (wrbfd, data + 4, 2);
      a->id = windres_get_16 (wrbfd, data + 4, 2);
 
 
      a->next = NULL;
      a->next = NULL;
      *pp = a;
      *pp = a;
      pp = &a->next;
      pp = &a->next;
 
 
      if ((a->flags & ACC_LAST) != 0)
      if ((a->flags & ACC_LAST) != 0)
        break;
        break;
 
 
      data += 8;
      data += 8;
      length -= 8;
      length -= 8;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r->type = RES_TYPE_ACCELERATOR;
  r->type = RES_TYPE_ACCELERATOR;
  r->u.acc = first;
  r->u.acc = first;
 
 
  return r;
  return r;
}
}
 
 
/* Convert an rcdata resource from binary.  */
/* Convert an rcdata resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
                   rc_uint_type length, int rctyp)
                   rc_uint_type length, int rctyp)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  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 = length;
  ri->u.buffer.length = length;
  ri->u.buffer.data = data;
  ri->u.buffer.data = data;
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = rctyp;
  r->type = rctyp;
  r->u.rcdata = ri;
  r->u.rcdata = ri;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a group cursor resource from binary.  */
/* Convert a group cursor resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  int type, c, i;
  int type, c, i;
  rc_group_cursor *first, **pp;
  rc_group_cursor *first, **pp;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  if (length < 6)
  if (length < 6)
    toosmall (_("group cursor header"));
    toosmall (_("group cursor header"));
 
 
  type = windres_get_16 (wrbfd, data + 2, 2);
  type = windres_get_16 (wrbfd, data + 2, 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 (wrbfd, data + 4, 2);
  c = windres_get_16 (wrbfd, data + 4, 2);
 
 
  data += 6;
  data += 6;
  length -= 6;
  length -= 6;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    {
    {
      rc_group_cursor *gc;
      rc_group_cursor *gc;
 
 
      if (length < 14)
      if (length < 14)
        toosmall (_("group cursor"));
        toosmall (_("group cursor"));
 
 
      gc = (rc_group_cursor *) res_alloc (sizeof *gc);
      gc = (rc_group_cursor *) res_alloc (sizeof *gc);
 
 
      gc->width = windres_get_16 (wrbfd, data, 2);
      gc->width = windres_get_16 (wrbfd, data, 2);
      gc->height = windres_get_16 (wrbfd, data + 2, 2);
      gc->height = windres_get_16 (wrbfd, data + 2, 2);
      gc->planes = windres_get_16 (wrbfd, data + 4, 2);
      gc->planes = windres_get_16 (wrbfd, data + 4, 2);
      gc->bits = windres_get_16 (wrbfd, data + 6, 2);
      gc->bits = windres_get_16 (wrbfd, data + 6, 2);
      gc->bytes = windres_get_32 (wrbfd, data + 8, 4);
      gc->bytes = windres_get_32 (wrbfd, data + 8, 4);
      gc->index = windres_get_16 (wrbfd, data + 12, 2);
      gc->index = windres_get_16 (wrbfd, data + 12, 2);
 
 
      gc->next = NULL;
      gc->next = NULL;
      *pp = gc;
      *pp = gc;
      pp = &gc->next;
      pp = &gc->next;
 
 
      data += 14;
      data += 14;
      length -= 14;
      length -= 14;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
  r->type = RES_TYPE_GROUP_CURSOR;
  r->type = RES_TYPE_GROUP_CURSOR;
  r->u.group_cursor = first;
  r->u.group_cursor = first;
 
 
  return r;
  return r;
}
}
 
 
/* Convert a group icon resource from binary.  */
/* Convert a group icon resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  int type, c, i;
  int type, c, i;
  rc_group_icon *first, **pp;
  rc_group_icon *first, **pp;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  if (length < 6)
  if (length < 6)
    toosmall (_("group icon header"));
    toosmall (_("group icon header"));
 
 
  type = windres_get_16 (wrbfd, data + 2, 2);
  type = windres_get_16 (wrbfd, data + 2, 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 (wrbfd, data + 4, 2);
  c = windres_get_16 (wrbfd, data + 4, 2);
 
 
  data += 6;
  data += 6;
  length -= 6;
  length -= 6;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  for (i = 0; i < c; i++)
  for (i = 0; i < c; i++)
    {
    {
      rc_group_icon *gi;
      rc_group_icon *gi;
 
 
      if (length < 14)
      if (length < 14)
        toosmall (_("group icon"));
        toosmall (_("group icon"));
 
 
      gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
      gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
 
 
      gi->width = windres_get_8 (wrbfd, data, 1);
      gi->width = windres_get_8 (wrbfd, data, 1);
      gi->height = windres_get_8 (wrbfd, data + 1, 1);
      gi->height = windres_get_8 (wrbfd, data + 1, 1);
      gi->colors = windres_get_8 (wrbfd, data + 2, 1);
      gi->colors = windres_get_8 (wrbfd, data + 2, 1);
      gi->planes = windres_get_16 (wrbfd, data + 4, 2);
      gi->planes = windres_get_16 (wrbfd, data + 4, 2);
      gi->bits = windres_get_16 (wrbfd, data + 6, 2);
      gi->bits = windres_get_16 (wrbfd, data + 6, 2);
      gi->bytes = windres_get_32 (wrbfd, data + 8, 4);
      gi->bytes = windres_get_32 (wrbfd, data + 8, 4);
      gi->index = windres_get_16 (wrbfd, data + 12, 2);
      gi->index = windres_get_16 (wrbfd, data + 12, 2);
 
 
      gi->next = NULL;
      gi->next = NULL;
      *pp = gi;
      *pp = gi;
      pp = &gi->next;
      pp = &gi->next;
 
 
      data += 14;
      data += 14;
      length -= 14;
      length -= 14;
    }
    }
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_GROUP_ICON;
  r->type = RES_TYPE_GROUP_ICON;
  r->u.group_icon = first;
  r->u.group_icon = first;
 
 
  return r;
  return r;
}
}
 
 
/* Extract data from a version header.  If KEY is not NULL, then the
/* Extract data from a version header.  If KEY is not NULL, then the
   key must be KEY; otherwise, the key is returned in *PKEY.  This
   key must be KEY; otherwise, the key is returned in *PKEY.  This
   sets *LEN to the total length, *VALLEN to the value length, *TYPE
   sets *LEN to the total length, *VALLEN to the value length, *TYPE
   to the type, and *OFF to the offset to the children.  */
   to the type, and *OFF to the offset to the children.  */
 
 
static void
static void
get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
                    const char *key, unichar **pkey,
                    const char *key, unichar **pkey,
                    rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type,
                    rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type,
                    rc_uint_type *off)
                    rc_uint_type *off)
{
{
  if (length < 8)
  if (length < 8)
    toosmall (key);
    toosmall (key);
 
 
  *len = windres_get_16 (wrbfd, data, 2);
  *len = windres_get_16 (wrbfd, data, 2);
  *vallen = windres_get_16 (wrbfd, data + 2, 2);
  *vallen = windres_get_16 (wrbfd, data + 2, 2);
  *type = windres_get_16 (wrbfd, data + 4, 2);
  *type = windres_get_16 (wrbfd, data + 4, 2);
 
 
  *off = 6;
  *off = 6;
 
 
  length -= 6;
  length -= 6;
  data += 6;
  data += 6;
 
 
  if (key == NULL)
  if (key == NULL)
    {
    {
      rc_uint_type sublen;
      rc_uint_type sublen;
 
 
      *pkey = get_unicode (wrbfd, data, length, &sublen);
      *pkey = get_unicode (wrbfd, data, length, &sublen);
      *off += (sublen + 1) * sizeof (unichar);
      *off += (sublen + 1) * sizeof (unichar);
    }
    }
  else
  else
    {
    {
      while (1)
      while (1)
        {
        {
          if (length < 2)
          if (length < 2)
            toosmall (key);
            toosmall (key);
          if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key)
          if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key)
            fatal (_("unexpected version string"));
            fatal (_("unexpected version string"));
 
 
          *off += 2;
          *off += 2;
          length -= 2;
          length -= 2;
          data += 2;
          data += 2;
 
 
          if (*key == '\0')
          if (*key == '\0')
            break;
            break;
 
 
          ++key;
          ++key;
        }
        }
    }
    }
 
 
  *off = (*off + 3) &~ 3;
  *off = (*off + 3) &~ 3;
}
}
 
 
/* Convert a version resource from binary.  */
/* Convert a version resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_uint_type verlen, vallen, type, off;
  rc_uint_type verlen, vallen, type, off;
  rc_fixed_versioninfo *fi;
  rc_fixed_versioninfo *fi;
  rc_ver_info *first, **pp;
  rc_ver_info *first, **pp;
  rc_versioninfo *v;
  rc_versioninfo *v;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  get_version_header (wrbfd, data, length, "VS_VERSION_INFO",
  get_version_header (wrbfd, data, length, "VS_VERSION_INFO",
                      (unichar **) NULL, &verlen, &vallen, &type, &off);
                      (unichar **) NULL, &verlen, &vallen, &type, &off);
 
 
  if ((unsigned int) verlen != length)
  if ((unsigned int) verlen != length)
    fatal (_("version length %d does not match resource length %lu"),
    fatal (_("version length %d does not match resource length %lu"),
           (int) verlen, (unsigned long) length);
           (int) verlen, (unsigned long) length);
 
 
  if (type != 0)
  if (type != 0)
    fatal (_("unexpected version type %d"), (int) type);
    fatal (_("unexpected version type %d"), (int) type);
 
 
  data += off;
  data += off;
  length -= off;
  length -= off;
 
 
  if (vallen == 0)
  if (vallen == 0)
    fi = NULL;
    fi = NULL;
  else
  else
    {
    {
      unsigned long signature, fiv;
      unsigned long signature, fiv;
 
 
      if (vallen != 52)
      if (vallen != 52)
        fatal (_("unexpected fixed version information length %ld"), (long) vallen);
        fatal (_("unexpected fixed version information length %ld"), (long) vallen);
 
 
      if (length < 52)
      if (length < 52)
        toosmall (_("fixed version info"));
        toosmall (_("fixed version info"));
 
 
      signature = windres_get_32 (wrbfd, data, 4);
      signature = windres_get_32 (wrbfd, data, 4);
      if (signature != 0xfeef04bd)
      if (signature != 0xfeef04bd)
        fatal (_("unexpected fixed version signature %lu"), signature);
        fatal (_("unexpected fixed version signature %lu"), signature);
 
 
      fiv = windres_get_32 (wrbfd, data + 4, 4);
      fiv = windres_get_32 (wrbfd, data + 4, 4);
      if (fiv != 0 && fiv != 0x10000)
      if (fiv != 0 && fiv != 0x10000)
        fatal (_("unexpected fixed version info version %lu"), fiv);
        fatal (_("unexpected fixed version info version %lu"), fiv);
 
 
      fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo));
      fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo));
 
 
      fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4);
      fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4);
      fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4);
      fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4);
      fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4);
      fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4);
      fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4);
      fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4);
      fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4);
      fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4);
      fi->file_flags = windres_get_32 (wrbfd, data + 28, 4);
      fi->file_flags = windres_get_32 (wrbfd, data + 28, 4);
      fi->file_os = windres_get_32 (wrbfd, data + 32, 4);
      fi->file_os = windres_get_32 (wrbfd, data + 32, 4);
      fi->file_type = windres_get_32 (wrbfd, data + 36, 4);
      fi->file_type = windres_get_32 (wrbfd, data + 36, 4);
      fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4);
      fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4);
      fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4);
      fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4);
      fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4);
      fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4);
 
 
      data += 52;
      data += 52;
      length -= 52;
      length -= 52;
    }
    }
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  while (length > 0)
  while (length > 0)
    {
    {
      rc_ver_info *vi;
      rc_ver_info *vi;
      int ch;
      int ch;
 
 
      if (length < 8)
      if (length < 8)
        toosmall (_("version var info"));
        toosmall (_("version var info"));
 
 
      vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
      vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
 
 
      ch = windres_get_16 (wrbfd, data + 6, 2);
      ch = windres_get_16 (wrbfd, data + 6, 2);
 
 
      if (ch == 'S')
      if (ch == 'S')
        {
        {
          rc_ver_stringinfo **ppvs;
          rc_ver_stringinfo **ppvs;
 
 
          vi->type = VERINFO_STRING;
          vi->type = VERINFO_STRING;
 
 
          get_version_header (wrbfd, data, length, "StringFileInfo",
          get_version_header (wrbfd, data, length, "StringFileInfo",
                              (unichar **) NULL, &verlen, &vallen, &type,
                              (unichar **) NULL, &verlen, &vallen, &type,
                              &off);
                              &off);
 
 
          if (vallen != 0)
          if (vallen != 0)
            fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen);
            fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen);
 
 
          data += off;
          data += off;
          length -= off;
          length -= off;
 
 
          get_version_header (wrbfd, data, length, (const char *) NULL,
          get_version_header (wrbfd, data, length, (const char *) NULL,
                              &vi->u.string.language, &verlen, &vallen,
                              &vi->u.string.language, &verlen, &vallen,
                              &type, &off);
                              &type, &off);
 
 
          if (vallen != 0)
          if (vallen != 0)
            fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
            fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
 
 
          data += off;
          data += off;
          length -= off;
          length -= off;
          verlen -= off;
          verlen -= off;
 
 
          vi->u.string.strings = NULL;
          vi->u.string.strings = NULL;
          ppvs = &vi->u.string.strings;
          ppvs = &vi->u.string.strings;
 
 
          /* It's convenient to round verlen to a 4 byte alignment,
          /* It's convenient to round verlen to a 4 byte alignment,
             since we round the subvariables in the loop.  */
             since we round the subvariables in the loop.  */
          verlen = (verlen + 3) &~ 3;
          verlen = (verlen + 3) &~ 3;
 
 
          while (verlen > 0)
          while (verlen > 0)
            {
            {
              rc_ver_stringinfo *vs;
              rc_ver_stringinfo *vs;
              rc_uint_type subverlen, vslen, valoff;
              rc_uint_type subverlen, vslen, valoff;
 
 
              vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs);
              vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs);
 
 
              get_version_header (wrbfd, data, length,
              get_version_header (wrbfd, data, length,
                                  (const char *) NULL, &vs->key, &subverlen,
                                  (const char *) NULL, &vs->key, &subverlen,
                                  &vallen, &type, &off);
                                  &vallen, &type, &off);
 
 
              subverlen = (subverlen + 3) &~ 3;
              subverlen = (subverlen + 3) &~ 3;
 
 
              data += off;
              data += off;
              length -= off;
              length -= off;
 
 
              vs->value = get_unicode (wrbfd, data, length, &vslen);
              vs->value = get_unicode (wrbfd, data, length, &vslen);
              valoff = vslen * 2 + 2;
              valoff = vslen * 2 + 2;
              valoff = (valoff + 3) &~ 3;
              valoff = (valoff + 3) &~ 3;
 
 
              if (off + valoff != subverlen)
              if (off + valoff != subverlen)
                fatal (_("unexpected version string length %ld != %ld + %ld"),
                fatal (_("unexpected version string length %ld != %ld + %ld"),
                       (long) subverlen, (long) off, (long) valoff);
                       (long) subverlen, (long) off, (long) valoff);
 
 
              vs->next = NULL;
              vs->next = NULL;
              *ppvs = vs;
              *ppvs = vs;
              ppvs = &vs->next;
              ppvs = &vs->next;
 
 
              data += valoff;
              data += valoff;
              length -= valoff;
              length -= valoff;
 
 
              if (verlen < subverlen)
              if (verlen < subverlen)
                fatal (_("unexpected version string length %ld < %ld"),
                fatal (_("unexpected version string length %ld < %ld"),
                       (long) verlen, (long) subverlen);
                       (long) verlen, (long) subverlen);
 
 
              verlen -= subverlen;
              verlen -= subverlen;
            }
            }
        }
        }
      else if (ch == 'V')
      else if (ch == 'V')
        {
        {
          rc_ver_varinfo **ppvv;
          rc_ver_varinfo **ppvv;
 
 
          vi->type = VERINFO_VAR;
          vi->type = VERINFO_VAR;
 
 
          get_version_header (wrbfd, data, length, "VarFileInfo",
          get_version_header (wrbfd, data, length, "VarFileInfo",
                              (unichar **) NULL, &verlen, &vallen, &type,
                              (unichar **) NULL, &verlen, &vallen, &type,
                              &off);
                              &off);
 
 
          if (vallen != 0)
          if (vallen != 0)
            fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
            fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
 
 
          data += off;
          data += off;
          length -= off;
          length -= off;
 
 
          get_version_header (wrbfd, data, length, (const char *) NULL,
          get_version_header (wrbfd, data, length, (const char *) NULL,
                              &vi->u.var.key, &verlen, &vallen, &type, &off);
                              &vi->u.var.key, &verlen, &vallen, &type, &off);
 
 
          data += off;
          data += off;
          length -= off;
          length -= off;
 
 
          vi->u.var.var = NULL;
          vi->u.var.var = NULL;
          ppvv = &vi->u.var.var;
          ppvv = &vi->u.var.var;
 
 
          while (vallen > 0)
          while (vallen > 0)
            {
            {
              rc_ver_varinfo *vv;
              rc_ver_varinfo *vv;
 
 
              if (length < 4)
              if (length < 4)
                toosmall (_("version varfileinfo"));
                toosmall (_("version varfileinfo"));
 
 
              vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
              vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
 
 
              vv->language = windres_get_16 (wrbfd, data, 2);
              vv->language = windres_get_16 (wrbfd, data, 2);
              vv->charset = windres_get_16 (wrbfd, data + 2, 2);
              vv->charset = windres_get_16 (wrbfd, data + 2, 2);
 
 
              vv->next = NULL;
              vv->next = NULL;
              *ppvv = vv;
              *ppvv = vv;
              ppvv = &vv->next;
              ppvv = &vv->next;
 
 
              data += 4;
              data += 4;
              length -= 4;
              length -= 4;
 
 
              if (vallen < 4)
              if (vallen < 4)
                fatal (_("unexpected version value length %ld"), (long) vallen);
                fatal (_("unexpected version value length %ld"), (long) vallen);
 
 
              vallen -= 4;
              vallen -= 4;
            }
            }
        }
        }
      else
      else
        fatal (_("unexpected version string"));
        fatal (_("unexpected version string"));
 
 
      vi->next = NULL;
      vi->next = NULL;
      *pp = vi;
      *pp = vi;
      pp = &vi->next;
      pp = &vi->next;
    }
    }
 
 
  v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
  v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
  v->fixed = fi;
  v->fixed = fi;
  v->var = first;
  v->var = first;
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_VERSIONINFO;
  r->type = RES_TYPE_VERSIONINFO;
  r->u.versioninfo = v;
  r->u.versioninfo = v;
 
 
  return r;
  return r;
}
}
 
 
/* Convert an arbitrary user defined resource from binary.  */
/* Convert an arbitrary user defined resource from binary.  */
 
 
static rc_res_resource *
static rc_res_resource *
bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
                     rc_uint_type length)
                     rc_uint_type length)
{
{
  rc_rcdata_item *ri;
  rc_rcdata_item *ri;
  rc_res_resource *r;
  rc_res_resource *r;
 
 
  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 = length;
  ri->u.buffer.length = length;
  ri->u.buffer.data = data;
  ri->u.buffer.data = data;
 
 
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_USERDATA;
  r->type = RES_TYPE_USERDATA;
  r->u.rcdata = ri;
  r->u.rcdata = ri;
 
 
  return r;
  return r;
}
}


static rc_res_resource *
static rc_res_resource *
bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
{
{
  rc_toolbar *ri;
  rc_toolbar *ri;
  rc_res_resource *r;
  rc_res_resource *r;
  rc_uint_type i;
  rc_uint_type i;
 
 
  ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
  ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
  ri->button_width = windres_get_32 (wrbfd, data, 4);
  ri->button_width = windres_get_32 (wrbfd, data, 4);
  ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
  ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
  ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
  ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
  ri->items = NULL;
  ri->items = NULL;
 
 
  data += 12;
  data += 12;
  length -= 12;
  length -= 12;
  for (i=0 ; i < ri->nitems; i++)
  for (i=0 ; i < ri->nitems; i++)
  {
  {
    rc_toolbar_item *it;
    rc_toolbar_item *it;
    it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
    it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
    it->id.named = 0;
    it->id.named = 0;
    it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
    it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
    it->prev = it->next = NULL;
    it->prev = it->next = NULL;
    data += 4;
    data += 4;
    length -= 4;
    length -= 4;
    if(ri->items) {
    if(ri->items) {
      rc_toolbar_item *ii = ri->items;
      rc_toolbar_item *ii = ri->items;
      while (ii->next != NULL)
      while (ii->next != NULL)
        ii = ii->next;
        ii = ii->next;
      it->prev = ii;
      it->prev = ii;
      ii->next = it;
      ii->next = it;
    }
    }
    else
    else
      ri->items = it;
      ri->items = it;
  }
  }
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r = (rc_res_resource *) res_alloc (sizeof *r);
  r->type = RES_TYPE_TOOLBAR;
  r->type = RES_TYPE_TOOLBAR;
  r->u.toolbar = ri;
  r->u.toolbar = ri;
  return r;
  return r;
}
}
 
 
 
 
/* Local functions used to convert resources to binary format.  */
/* Local functions used to convert resources to binary format.  */
 
 
static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
                                        const bfd_byte *);
                                        const bfd_byte *);
 
 
/* Convert a resource to binary.  */
/* Convert a resource to binary.  */
 
 
rc_uint_type
rc_uint_type
res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
{
{
  switch (res->type)
  switch (res->type)
    {
    {
    case RES_TYPE_BITMAP:
    case RES_TYPE_BITMAP:
    case RES_TYPE_FONT:
    case RES_TYPE_FONT:
    case RES_TYPE_ICON:
    case RES_TYPE_ICON:
    case RES_TYPE_MESSAGETABLE:
    case RES_TYPE_MESSAGETABLE:
      return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
      return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
    case RES_TYPE_ACCELERATOR:
    case RES_TYPE_ACCELERATOR:
      return res_to_bin_accelerator (wrbfd, off, res->u.acc);
      return res_to_bin_accelerator (wrbfd, off, res->u.acc);
    case RES_TYPE_CURSOR:
    case RES_TYPE_CURSOR:
      return res_to_bin_cursor (wrbfd, off, res->u.cursor);
      return res_to_bin_cursor (wrbfd, off, res->u.cursor);
    case RES_TYPE_GROUP_CURSOR:
    case RES_TYPE_GROUP_CURSOR:
      return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
      return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
    case RES_TYPE_DIALOG:
    case RES_TYPE_DIALOG:
      return res_to_bin_dialog (wrbfd, off, res->u.dialog);
      return res_to_bin_dialog (wrbfd, off, res->u.dialog);
    case RES_TYPE_FONTDIR:
    case RES_TYPE_FONTDIR:
      return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
      return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
    case RES_TYPE_GROUP_ICON:
    case RES_TYPE_GROUP_ICON:
      return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
      return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
    case RES_TYPE_MENU:
    case RES_TYPE_MENU:
      return res_to_bin_menu (wrbfd, off, res->u.menu);
      return res_to_bin_menu (wrbfd, off, res->u.menu);
    case RES_TYPE_STRINGTABLE:
    case RES_TYPE_STRINGTABLE:
      return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
      return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
    case RES_TYPE_VERSIONINFO:
    case RES_TYPE_VERSIONINFO:
      return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
      return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
    case RES_TYPE_TOOLBAR:
    case RES_TYPE_TOOLBAR:
      return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
      return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
    case RES_TYPE_USERDATA:
    case RES_TYPE_USERDATA:
    case RES_TYPE_RCDATA:
    case RES_TYPE_RCDATA:
    default:
    default:
      return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
      return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
    }
    }
}
}
 
 
/* Convert a resource ID to binary.  This always returns exactly one
/* Convert a resource ID to binary.  This always returns exactly one
   bindata structure.  */
   bindata structure.  */
 
 
static rc_uint_type
static rc_uint_type
resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
{
{
  if (! id.named)
  if (! id.named)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          struct bin_res_id bri;
          struct bin_res_id bri;
 
 
          windres_put_16 (wrbfd, bri.sig, 0xffff);
          windres_put_16 (wrbfd, bri.sig, 0xffff);
          windres_put_16 (wrbfd, bri.id, id.u.id);
          windres_put_16 (wrbfd, bri.id, id.u.id);
          set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
          set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
        }
        }
      off += BIN_RES_ID;
      off += BIN_RES_ID;
    }
    }
  else
  else
    {
    {
      rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
      rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
      if (wrbfd)
      if (wrbfd)
        {
        {
          bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
          bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
          rc_uint_type i;
          rc_uint_type i;
          for (i = 0; i < len; i++)
          for (i = 0; i < len; i++)
            windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
            windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
          windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
          windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
          set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
          set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
    }
    }
      off += (rc_uint_type) ((len + 1) * sizeof (unichar));
      off += (rc_uint_type) ((len + 1) * sizeof (unichar));
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a null terminated unicode string to binary.  This always
/* Convert a null terminated unicode string to binary.  This always
   returns exactly one bindata structure.  */
   returns exactly one bindata structure.  */
 
 
static rc_uint_type
static rc_uint_type
unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
{
{
  rc_uint_type len = 0;
  rc_uint_type len = 0;
 
 
  if (str != NULL)
  if (str != NULL)
    len = unichar_len (str);
    len = unichar_len (str);
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      bfd_byte *d;
      bfd_byte *d;
      rc_uint_type i;
      rc_uint_type i;
      d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
      d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
      for (i = 0; i < len; i++)
      for (i = 0; i < len; i++)
        windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
        windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
      windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
      windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
      set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
      set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
    }
    }
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
 
 
  return off;
  return off;
}
}
 
 
/* Convert an accelerator resource to binary.  */
/* Convert an accelerator resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
                        const rc_accelerator *accelerators)
                        const rc_accelerator *accelerators)
{
{
  bindata *first, **pp;
  bindata *first, **pp;
  const rc_accelerator *a;
  const rc_accelerator *a;
 
 
  first = NULL;
  first = NULL;
  pp = &first;
  pp = &first;
 
 
  for (a = accelerators; a != NULL; a = a->next)
  for (a = accelerators; a != NULL; a = a->next)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          struct bin_accelerator ba;
          struct bin_accelerator ba;
 
 
          windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
          windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
          windres_put_16 (wrbfd, ba.key, a->key);
          windres_put_16 (wrbfd, ba.key, a->key);
          windres_put_16 (wrbfd, ba.id, a->id);
          windres_put_16 (wrbfd, ba.id, a->id);
          windres_put_16 (wrbfd, ba.pad, 0);
          windres_put_16 (wrbfd, ba.pad, 0);
          set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
          set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
    }
    }
      off += BIN_ACCELERATOR_SIZE;
      off += BIN_ACCELERATOR_SIZE;
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a cursor resource to binary.  */
/* Convert a cursor resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
{
{
  if (wrbfd)
  if (wrbfd)
    {
    {
      struct bin_cursor bc;
      struct bin_cursor bc;
 
 
      windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
      windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
      windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
      windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
      set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
      set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
      if (c->length)
      if (c->length)
        set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
        set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
    }
    }
  off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
  off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
  return off;
  return off;
}
}
 
 
/* Convert a group cursor resource to binary.  */
/* Convert a group cursor resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
                         const rc_group_cursor *group_cursors)
                         const rc_group_cursor *group_cursors)
{
{
  int c = 0;
  int c = 0;
  const rc_group_cursor *gc;
  const rc_group_cursor *gc;
  struct bin_group_cursor bgc;
  struct bin_group_cursor bgc;
  struct bin_group_cursor_item bgci;
  struct bin_group_cursor_item bgci;
  rc_uint_type start = off;
  rc_uint_type start = off;
 
 
  off += BIN_GROUP_CURSOR_SIZE;
  off += BIN_GROUP_CURSOR_SIZE;
 
 
  for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
  for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          windres_put_16 (wrbfd, bgci.width, gc->width);
          windres_put_16 (wrbfd, bgci.width, gc->width);
          windres_put_16 (wrbfd, bgci.height, gc->height);
          windres_put_16 (wrbfd, bgci.height, gc->height);
          windres_put_16 (wrbfd, bgci.planes, gc->planes);
          windres_put_16 (wrbfd, bgci.planes, gc->planes);
          windres_put_16 (wrbfd, bgci.bits, gc->bits);
          windres_put_16 (wrbfd, bgci.bits, gc->bits);
          windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
          windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
          windres_put_16 (wrbfd, bgci.index, gc->index);
          windres_put_16 (wrbfd, bgci.index, gc->index);
          set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
          set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
    }
    }
 
 
      off += BIN_GROUP_CURSOR_ITEM_SIZE;
      off += BIN_GROUP_CURSOR_ITEM_SIZE;
    }
    }
  if (wrbfd)
  if (wrbfd)
    {
    {
      windres_put_16 (wrbfd, bgc.sig1, 0);
      windres_put_16 (wrbfd, bgc.sig1, 0);
      windres_put_16 (wrbfd, bgc.sig2, 2);
      windres_put_16 (wrbfd, bgc.sig2, 2);
      windres_put_16 (wrbfd, bgc.nitems, c);
      windres_put_16 (wrbfd, bgc.nitems, c);
      set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
      set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a dialog resource to binary.  */
/* Convert a dialog resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
{
{
  rc_uint_type off_delta;
  rc_uint_type off_delta;
  rc_uint_type start, marker;
  rc_uint_type start, marker;
  int dialogex;
  int dialogex;
  int c;
  int c;
  rc_dialog_control *dc;
  rc_dialog_control *dc;
  struct bin_dialogex bdx;
  struct bin_dialogex bdx;
  struct bin_dialog bd;
  struct bin_dialog bd;
 
 
  off_delta = off;
  off_delta = off;
  start = off;
  start = off;
  dialogex = extended_dialog (dialog);
  dialogex = extended_dialog (dialog);
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
  if (! dialogex)
  if (! dialogex)
    {
    {
          windres_put_32 (wrbfd, bd.style, dialog->style);
          windres_put_32 (wrbfd, bd.style, dialog->style);
          windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
          windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
          windres_put_16 (wrbfd, bd.x, dialog->x);
          windres_put_16 (wrbfd, bd.x, dialog->x);
          windres_put_16 (wrbfd, bd.y, dialog->y);
          windres_put_16 (wrbfd, bd.y, dialog->y);
          windres_put_16 (wrbfd, bd.width, dialog->width);
          windres_put_16 (wrbfd, bd.width, dialog->width);
          windres_put_16 (wrbfd, bd.height, dialog->height);
          windres_put_16 (wrbfd, bd.height, dialog->height);
    }
    }
  else
  else
    {
    {
          windres_put_16 (wrbfd, bdx.sig1, 1);
          windres_put_16 (wrbfd, bdx.sig1, 1);
          windres_put_16 (wrbfd, bdx.sig2, 0xffff);
          windres_put_16 (wrbfd, bdx.sig2, 0xffff);
          windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
          windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
          windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
          windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
          windres_put_32 (wrbfd, bdx.style, dialog->style);
          windres_put_32 (wrbfd, bdx.style, dialog->style);
          windres_put_16 (wrbfd, bdx.x, dialog->x);
          windres_put_16 (wrbfd, bdx.x, dialog->x);
          windres_put_16 (wrbfd, bdx.y, dialog->y);
          windres_put_16 (wrbfd, bdx.y, dialog->y);
          windres_put_16 (wrbfd, bdx.width, dialog->width);
          windres_put_16 (wrbfd, bdx.width, dialog->width);
          windres_put_16 (wrbfd, bdx.height, dialog->height);
          windres_put_16 (wrbfd, bdx.height, dialog->height);
        }
        }
    }
    }
 
 
  off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
  off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
 
 
  off = resid_to_bin (wrbfd, off, dialog->menu);
  off = resid_to_bin (wrbfd, off, dialog->menu);
  off = resid_to_bin (wrbfd, off, dialog->class);
  off = resid_to_bin (wrbfd, off, dialog->class);
  off = unicode_to_bin (wrbfd, off, dialog->caption);
  off = unicode_to_bin (wrbfd, off, dialog->caption);
 
 
  if ((dialog->style & DS_SETFONT) != 0)
  if ((dialog->style & DS_SETFONT) != 0)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          if (! dialogex)
          if (! dialogex)
            {
            {
              struct bin_dialogfont bdf;
              struct bin_dialogfont bdf;
              windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
              windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
              set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
              set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
            }
            }
          else
          else
            {
            {
              struct bin_dialogexfont bdxf;
              struct bin_dialogexfont bdxf;
              windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
              windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
              windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
              windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
              windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
              windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
              windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
              windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
              set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
              set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
            }
            }
        }
        }
      off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
      off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
      off = unicode_to_bin (wrbfd, off, dialog->font);
      off = unicode_to_bin (wrbfd, off, dialog->font);
    }
    }
  for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
  for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
    {
    {
      bfd_byte dc_rclen[2];
      bfd_byte dc_rclen[2];
 
 
      off += (4 - ((off - off_delta) & 3)) & 3;
      off += (4 - ((off - off_delta) & 3)) & 3;
      if (wrbfd)
      if (wrbfd)
        {
        {
      if (! dialogex)
      if (! dialogex)
        {
        {
              struct bin_dialog_control bdc;
              struct bin_dialog_control bdc;
 
 
              windres_put_32 (wrbfd, bdc.style, dc->style);
              windres_put_32 (wrbfd, bdc.style, dc->style);
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
              windres_put_16 (wrbfd, bdc.x, dc->x);
              windres_put_16 (wrbfd, bdc.x, dc->x);
              windres_put_16 (wrbfd, bdc.y, dc->y);
              windres_put_16 (wrbfd, bdc.y, dc->y);
              windres_put_16 (wrbfd, bdc.width, dc->width);
              windres_put_16 (wrbfd, bdc.width, dc->width);
              windres_put_16 (wrbfd, bdc.height, dc->height);
              windres_put_16 (wrbfd, bdc.height, dc->height);
              windres_put_16 (wrbfd, bdc.id, dc->id);
              windres_put_16 (wrbfd, bdc.id, dc->id);
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
        }
        }
      else
      else
        {
        {
              struct bin_dialogex_control bdc;
              struct bin_dialogex_control bdc;
 
 
              windres_put_32 (wrbfd, bdc.help, dc->help);
              windres_put_32 (wrbfd, bdc.help, dc->help);
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
              windres_put_32 (wrbfd, bdc.style, dc->style);
              windres_put_32 (wrbfd, bdc.style, dc->style);
              windres_put_16 (wrbfd, bdc.x, dc->x);
              windres_put_16 (wrbfd, bdc.x, dc->x);
              windres_put_16 (wrbfd, bdc.y, dc->y);
              windres_put_16 (wrbfd, bdc.y, dc->y);
              windres_put_16 (wrbfd, bdc.width, dc->width);
              windres_put_16 (wrbfd, bdc.width, dc->width);
              windres_put_16 (wrbfd, bdc.height, dc->height);
              windres_put_16 (wrbfd, bdc.height, dc->height);
              windres_put_32 (wrbfd, bdc.id, dc->id);
              windres_put_32 (wrbfd, bdc.id, dc->id);
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
            }
            }
        }
        }
      off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
      off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
 
 
      off = resid_to_bin (wrbfd, off, dc->class);
      off = resid_to_bin (wrbfd, off, dc->class);
      off = resid_to_bin (wrbfd, off, dc->text);
      off = resid_to_bin (wrbfd, off, dc->text);
 
 
      marker = off; /* Save two bytes for size of optional data.  */
      marker = off; /* Save two bytes for size of optional data.  */
      off += 2;
      off += 2;
 
 
      if (dc->data == NULL)
      if (dc->data == NULL)
        {
        {
          if (wrbfd)
          if (wrbfd)
            windres_put_16 (wrbfd, dc_rclen, 0);
            windres_put_16 (wrbfd, dc_rclen, 0);
        }
        }
      else
      else
        {
        {
          rc_uint_type saved_off = off;
          rc_uint_type saved_off = off;
          rc_uint_type old_off;
          rc_uint_type old_off;
          off += (4 - ((off - off_delta) & 3)) & 3;
          off += (4 - ((off - off_delta) & 3)) & 3;
 
 
          old_off = off;
          old_off = off;
          off = res_to_bin_rcdata (wrbfd, off, dc->data);
          off = res_to_bin_rcdata (wrbfd, off, dc->data);
          if ((off - old_off) == 0)
          if ((off - old_off) == 0)
            old_off = off = saved_off;
            old_off = off = saved_off;
          if (wrbfd)
          if (wrbfd)
            windres_put_16 (wrbfd, dc_rclen, off - old_off);
            windres_put_16 (wrbfd, dc_rclen, off - old_off);
            }
            }
      if (wrbfd)
      if (wrbfd)
        set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
        set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
        }
        }
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
      windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
      if (! dialogex)
      if (! dialogex)
        set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
        set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
      else
      else
        set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
        set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
    }
    }
 
 
  return off;
  return off;
}
}
 
 
/* Convert a fontdir resource to binary.  */
/* Convert a fontdir resource to binary.  */
static rc_uint_type
static rc_uint_type
res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
{
{
  rc_uint_type start;
  rc_uint_type start;
  int c;
  int c;
  const rc_fontdir *fd;
  const rc_fontdir *fd;
 
 
  start = off;
  start = off;
  off += 2;
  off += 2;
 
 
  for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
  for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          bfd_byte d[2];
          bfd_byte d[2];
          windres_put_16 (wrbfd, d, fd->index);
          windres_put_16 (wrbfd, d, fd->index);
          set_windres_bfd_content (wrbfd, d, off, 2);
          set_windres_bfd_content (wrbfd, d, off, 2);
          if (fd->length)
          if (fd->length)
            set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
            set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
        }
        }
      off += (rc_uint_type) fd->length + 2;
      off += (rc_uint_type) fd->length + 2;
    }
    }
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      bfd_byte d[2];
      bfd_byte d[2];
      windres_put_16 (wrbfd, d, c);
      windres_put_16 (wrbfd, d, c);
      set_windres_bfd_content (wrbfd, d, start, 2);
      set_windres_bfd_content (wrbfd, d, start, 2);
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a group icon resource to binary.  */
/* Convert a group icon resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
{
{
  rc_uint_type start;
  rc_uint_type start;
  struct bin_group_icon bgi;
  struct bin_group_icon bgi;
  int c;
  int c;
  const rc_group_icon *gi;
  const rc_group_icon *gi;
 
 
  start = off;
  start = off;
  off += BIN_GROUP_ICON_SIZE;
  off += BIN_GROUP_ICON_SIZE;
 
 
  for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
  for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
    {
    {
      struct bin_group_icon_item bgii;
      struct bin_group_icon_item bgii;
 
 
      if (wrbfd)
      if (wrbfd)
        {
        {
          windres_put_8 (wrbfd, bgii.width, gi->width);
          windres_put_8 (wrbfd, bgii.width, gi->width);
          windres_put_8 (wrbfd, bgii.height, gi->height);
          windres_put_8 (wrbfd, bgii.height, gi->height);
          windres_put_8 (wrbfd, bgii.colors, gi->colors);
          windres_put_8 (wrbfd, bgii.colors, gi->colors);
          windres_put_8 (wrbfd, bgii.pad, 0);
          windres_put_8 (wrbfd, bgii.pad, 0);
          windres_put_16 (wrbfd, bgii.planes, gi->planes);
          windres_put_16 (wrbfd, bgii.planes, gi->planes);
          windres_put_16 (wrbfd, bgii.bits, gi->bits);
          windres_put_16 (wrbfd, bgii.bits, gi->bits);
          windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
          windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
          windres_put_16 (wrbfd, bgii.index, gi->index);
          windres_put_16 (wrbfd, bgii.index, gi->index);
          set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
          set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
        }
        }
      off += BIN_GROUP_ICON_ITEM_SIZE;
      off += BIN_GROUP_ICON_ITEM_SIZE;
    }
    }
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      windres_put_16 (wrbfd, bgi.sig1, 0);
      windres_put_16 (wrbfd, bgi.sig1, 0);
      windres_put_16 (wrbfd, bgi.sig2, 1);
      windres_put_16 (wrbfd, bgi.sig2, 1);
      windres_put_16 (wrbfd, bgi.count, c);
      windres_put_16 (wrbfd, bgi.count, c);
      set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
      set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a menu resource to binary.  */
/* Convert a menu resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
{
{
  int menuex;
  int menuex;
 
 
  menuex = extended_menu (menu);
  menuex = extended_menu (menu);
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
  if (! menuex)
  if (! menuex)
    {
    {
          struct bin_menu bm;
          struct bin_menu bm;
          windres_put_16 (wrbfd, bm.sig1, 0);
          windres_put_16 (wrbfd, bm.sig1, 0);
          windres_put_16 (wrbfd, bm.sig2, 0);
          windres_put_16 (wrbfd, bm.sig2, 0);
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
    }
    }
  else
  else
    {
    {
          struct bin_menuex bm;
          struct bin_menuex bm;
          windres_put_16 (wrbfd, bm.sig1, 1);
          windres_put_16 (wrbfd, bm.sig1, 1);
          windres_put_16 (wrbfd, bm.sig2, 4);
          windres_put_16 (wrbfd, bm.sig2, 4);
          windres_put_32 (wrbfd, bm.help, menu->help);
          windres_put_32 (wrbfd, bm.help, menu->help);
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
    }
    }
    }
    }
  off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
  off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
  if (! menuex)
  if (! menuex)
    {
    {
      off = res_to_bin_menuitems (wrbfd, off, menu->items);
      off = res_to_bin_menuitems (wrbfd, off, menu->items);
    }
    }
  else
  else
    {
    {
      off = res_to_bin_menuexitems (wrbfd, off, menu->items);
      off = res_to_bin_menuexitems (wrbfd, off, menu->items);
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert menu items to binary.  */
/* Convert menu items to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
{
{
  const rc_menuitem *mi;
  const rc_menuitem *mi;
 
 
  for (mi = items; mi != NULL; mi = mi->next)
  for (mi = items; mi != NULL; mi = mi->next)
    {
    {
      struct bin_menuitem bmi;
      struct bin_menuitem bmi;
      int flags;
      int flags;
 
 
      flags = mi->type;
      flags = mi->type;
      if (mi->next == NULL)
      if (mi->next == NULL)
        flags |= MENUITEM_ENDMENU;
        flags |= MENUITEM_ENDMENU;
      if (mi->popup != NULL)
      if (mi->popup != NULL)
        flags |= MENUITEM_POPUP;
        flags |= MENUITEM_POPUP;
 
 
      if (wrbfd)
      if (wrbfd)
        {
        {
          windres_put_16 (wrbfd, bmi.flags, flags);
          windres_put_16 (wrbfd, bmi.flags, flags);
      if (mi->popup == NULL)
      if (mi->popup == NULL)
            windres_put_16 (wrbfd, bmi.id, mi->id);
            windres_put_16 (wrbfd, bmi.id, mi->id);
          set_windres_bfd_content (wrbfd, &bmi, off,
          set_windres_bfd_content (wrbfd, &bmi, off,
                                   mi->popup == NULL ? BIN_MENUITEM_SIZE
                                   mi->popup == NULL ? BIN_MENUITEM_SIZE
                                                     : BIN_MENUITEM_POPUP_SIZE);
                                                     : BIN_MENUITEM_POPUP_SIZE);
        }
        }
      off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
      off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
 
 
      off = unicode_to_bin (wrbfd, off, mi->text);
      off = unicode_to_bin (wrbfd, off, mi->text);
 
 
      if (mi->popup != NULL)
      if (mi->popup != NULL)
        {
        {
          off = res_to_bin_menuitems (wrbfd, off, mi->popup);
          off = res_to_bin_menuitems (wrbfd, off, mi->popup);
        }
        }
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert menuex items to binary.  */
/* Convert menuex items to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
{
{
  rc_uint_type off_delta = off;
  rc_uint_type off_delta = off;
  const rc_menuitem *mi;
  const rc_menuitem *mi;
 
 
  for (mi = items; mi != NULL; mi = mi->next)
  for (mi = items; mi != NULL; mi = mi->next)
    {
    {
      struct bin_menuitemex bmi;
      struct bin_menuitemex bmi;
      int flags;
      int flags;
 
 
      off += (4 - ((off - off_delta) & 3)) & 3;
      off += (4 - ((off - off_delta) & 3)) & 3;
 
 
      flags = 0;
      flags = 0;
      if (mi->next == NULL)
      if (mi->next == NULL)
        flags |= 0x80;
        flags |= 0x80;
      if (mi->popup != NULL)
      if (mi->popup != NULL)
        flags |= 1;
        flags |= 1;
 
 
      if (wrbfd)
      if (wrbfd)
        {
        {
          windres_put_32 (wrbfd, bmi.type, mi->type);
          windres_put_32 (wrbfd, bmi.type, mi->type);
          windres_put_32 (wrbfd, bmi.state, mi->state);
          windres_put_32 (wrbfd, bmi.state, mi->state);
          windres_put_32 (wrbfd, bmi.id, mi->id);
          windres_put_32 (wrbfd, bmi.id, mi->id);
          windres_put_16 (wrbfd, bmi.flags, flags);
          windres_put_16 (wrbfd, bmi.flags, flags);
          set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
          set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
        }
        }
      off += BIN_MENUITEMEX_SIZE;
      off += BIN_MENUITEMEX_SIZE;
 
 
      off = unicode_to_bin (wrbfd, off, mi->text);
      off = unicode_to_bin (wrbfd, off, mi->text);
 
 
      if (mi->popup != NULL)
      if (mi->popup != NULL)
        {
        {
          bfd_byte help[4];
          bfd_byte help[4];
 
 
          off += (4 - ((off - off_delta) & 3)) & 3;
          off += (4 - ((off - off_delta) & 3)) & 3;
 
 
          if (wrbfd)
          if (wrbfd)
            {
            {
              windres_put_32 (wrbfd, help, mi->help);
              windres_put_32 (wrbfd, help, mi->help);
              set_windres_bfd_content (wrbfd, help, off, 4);
              set_windres_bfd_content (wrbfd, help, off, 4);
            }
            }
          off += 4;
          off += 4;
          off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
          off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
        }
        }
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert an rcdata resource to binary.  This is also used to convert
/* Convert an rcdata resource to binary.  This is also used to convert
   other information which happens to be stored in rc_rcdata_item lists
   other information which happens to be stored in rc_rcdata_item lists
   to binary.  */
   to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
{
{
  const rc_rcdata_item *ri;
  const rc_rcdata_item *ri;
 
 
  for (ri = items; ri != NULL; ri = ri->next)
  for (ri = items; ri != NULL; ri = ri->next)
    {
    {
      rc_uint_type len;
      rc_uint_type len;
      switch (ri->type)
      switch (ri->type)
        {
        {
        default:
        default:
          abort ();
          abort ();
        case RCDATA_WORD:
        case RCDATA_WORD:
          len = 2;
          len = 2;
          break;
          break;
        case RCDATA_DWORD:
        case RCDATA_DWORD:
          len = 4;
          len = 4;
          break;
          break;
        case RCDATA_STRING:
        case RCDATA_STRING:
          len = ri->u.string.length;
          len = ri->u.string.length;
          break;
          break;
        case RCDATA_WSTRING:
        case RCDATA_WSTRING:
          len = ri->u.wstring.length * sizeof (unichar);
          len = ri->u.wstring.length * sizeof (unichar);
          break;
          break;
        case RCDATA_BUFFER:
        case RCDATA_BUFFER:
          len = ri->u.buffer.length;
          len = ri->u.buffer.length;
          break;
          break;
        }
        }
      if (wrbfd)
      if (wrbfd)
        {
        {
          bfd_byte h[4];
          bfd_byte h[4];
          bfd_byte *hp = &h[0];
          bfd_byte *hp = &h[0];
          switch (ri->type)
          switch (ri->type)
            {
            {
            case RCDATA_WORD:
            case RCDATA_WORD:
              windres_put_16 (wrbfd, hp, ri->u.word);
              windres_put_16 (wrbfd, hp, ri->u.word);
              break;
              break;
            case RCDATA_DWORD:
            case RCDATA_DWORD:
              windres_put_32 (wrbfd, hp, ri->u.dword);
              windres_put_32 (wrbfd, hp, ri->u.dword);
              break;
              break;
            case RCDATA_STRING:
            case RCDATA_STRING:
              hp = (bfd_byte *) ri->u.string.s;
              hp = (bfd_byte *) ri->u.string.s;
          break;
          break;
        case RCDATA_WSTRING:
        case RCDATA_WSTRING:
          {
          {
                rc_uint_type i;
                rc_uint_type i;
 
 
                hp = (bfd_byte *) reswr_alloc (len);
                hp = (bfd_byte *) reswr_alloc (len);
            for (i = 0; i < ri->u.wstring.length; i++)
            for (i = 0; i < ri->u.wstring.length; i++)
                  windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
                  windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
          }
          }
              break;
              break;
        case RCDATA_BUFFER:
        case RCDATA_BUFFER:
              hp = (bfd_byte *) ri->u.buffer.data;
              hp = (bfd_byte *) ri->u.buffer.data;
          break;
          break;
        }
        }
          set_windres_bfd_content (wrbfd, hp, off, len);
          set_windres_bfd_content (wrbfd, hp, off, len);
    }
    }
      off += len;
      off += len;
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a stringtable resource to binary.  */
/* Convert a stringtable resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
                        const rc_stringtable *st)
                        const rc_stringtable *st)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < 16; i++)
  for (i = 0; i < 16; i++)
    {
    {
      rc_uint_type slen, length;
      rc_uint_type slen, length;
      unichar *s;
      unichar *s;
 
 
      slen = (rc_uint_type) st->strings[i].length;
      slen = (rc_uint_type) st->strings[i].length;
      s = st->strings[i].string;
      s = st->strings[i].string;
 
 
      length = 2 + slen * 2;
      length = 2 + slen * 2;
      if (wrbfd)
      if (wrbfd)
        {
        {
          bfd_byte *hp;
          bfd_byte *hp;
          rc_uint_type j;
          rc_uint_type j;
 
 
          hp = (bfd_byte *) reswr_alloc (length);
          hp = (bfd_byte *) reswr_alloc (length);
          windres_put_16 (wrbfd, hp, slen);
          windres_put_16 (wrbfd, hp, slen);
 
 
      for (j = 0; j < slen; j++)
      for (j = 0; j < slen; j++)
            windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
            windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
          set_windres_bfd_content (wrbfd, hp, off, length);
          set_windres_bfd_content (wrbfd, hp, off, length);
    }
    }
      off += length;
      off += length;
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert an ASCII string to a unicode binary string.  This always
/* Convert an ASCII string to a unicode binary string.  This always
   returns exactly one bindata structure.  */
   returns exactly one bindata structure.  */
 
 
static rc_uint_type
static rc_uint_type
string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
{
{
  rc_uint_type len;
  rc_uint_type len;
 
 
  len = (rc_uint_type) strlen (s);
  len = (rc_uint_type) strlen (s);
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      rc_uint_type i;
      rc_uint_type i;
      bfd_byte *hp;
      bfd_byte *hp;
 
 
      hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
      hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
 
 
      for (i = 0; i < len; i++)
      for (i = 0; i < len; i++)
        windres_put_16 (wrbfd, hp + i * 2, s[i]);
        windres_put_16 (wrbfd, hp + i * 2, s[i]);
      windres_put_16 (wrbfd, hp + i * 2, 0);
      windres_put_16 (wrbfd, hp + i * 2, 0);
      set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
      set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
    }
    }
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
  return off;
  return off;
}
}
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
{
{
  if (wrbfd)
  if (wrbfd)
    {
    {
      struct bin_toolbar bt;
      struct bin_toolbar bt;
      windres_put_32 (wrbfd, bt.button_width, tb->button_width);
      windres_put_32 (wrbfd, bt.button_width, tb->button_width);
      windres_put_32 (wrbfd, bt.button_height, tb->button_height);
      windres_put_32 (wrbfd, bt.button_height, tb->button_height);
      windres_put_32 (wrbfd, bt.nitems, tb->nitems);
      windres_put_32 (wrbfd, bt.nitems, tb->nitems);
      set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
      set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
      if (tb->nitems > 0)
      if (tb->nitems > 0)
        {
        {
          rc_toolbar_item *it;
          rc_toolbar_item *it;
          bfd_byte *ids;
          bfd_byte *ids;
          rc_uint_type i = 0;
          rc_uint_type i = 0;
 
 
          ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
          ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
          it=tb->items;
          it=tb->items;
          while(it != NULL)
          while(it != NULL)
            {
            {
              windres_put_32 (wrbfd, ids + i, it->id.u.id);
              windres_put_32 (wrbfd, ids + i, it->id.u.id);
              i += 4;
              i += 4;
              it = it->next;
              it = it->next;
            }
            }
          set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
          set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
        }
        }
    }
    }
  off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
  off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
 
 
  return off;
  return off;
}
}
 
 
/* Convert a versioninfo resource to binary.  */
/* Convert a versioninfo resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
                        const rc_versioninfo *versioninfo)
                        const rc_versioninfo *versioninfo)
{
{
  rc_uint_type off_delta = off;
  rc_uint_type off_delta = off;
  rc_uint_type start;
  rc_uint_type start;
  struct bin_versioninfo bvi;
  struct bin_versioninfo bvi;
  rc_ver_info *vi;
  rc_ver_info *vi;
 
 
  start = off;
  start = off;
  off += BIN_VERSIONINFO_SIZE;
  off += BIN_VERSIONINFO_SIZE;
  off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
  off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
  off += (4 - ((off - off_delta) & 3)) & 3;
  off += (4 - ((off - off_delta) & 3)) & 3;
 
 
  if (versioninfo->fixed != NULL)
  if (versioninfo->fixed != NULL)
    {
    {
      if (wrbfd)
      if (wrbfd)
        {
        {
          struct bin_fixed_versioninfo bfv;
          struct bin_fixed_versioninfo bfv;
          const rc_fixed_versioninfo *fi;
          const rc_fixed_versioninfo *fi;
 
 
      fi = versioninfo->fixed;
      fi = versioninfo->fixed;
          windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
          windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
          windres_put_32 (wrbfd, bfv.sig2, 0x10000);
          windres_put_32 (wrbfd, bfv.sig2, 0x10000);
          windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
          windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
          windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
          windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
          windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
          windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
          windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
          windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
          windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
          windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
          windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
          windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
          windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
          windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
          windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
          windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
          windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
          windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
          windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
          windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
          windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
          windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
          set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
          set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
        }
        }
      off += BIN_FIXED_VERSIONINFO_SIZE;
      off += BIN_FIXED_VERSIONINFO_SIZE;
    }
    }
 
 
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
    {
    {
      struct bin_ver_info bv;
      struct bin_ver_info bv;
      rc_uint_type bv_off;
      rc_uint_type bv_off;
 
 
      off += (4 - ((off - off_delta) & 3)) & 3;
      off += (4 - ((off - off_delta) & 3)) & 3;
 
 
      bv_off = off;
      bv_off = off;
 
 
      off += BIN_VER_INFO_SIZE;
      off += BIN_VER_INFO_SIZE;
 
 
      switch (vi->type)
      switch (vi->type)
        {
        {
        default:
        default:
          abort ();
          abort ();
        case VERINFO_STRING:
        case VERINFO_STRING:
          {
          {
            struct bin_ver_info bvsd;
            struct bin_ver_info bvsd;
            rc_uint_type vs_off;
            rc_uint_type vs_off;
            const rc_ver_stringinfo *vs;
            const rc_ver_stringinfo *vs;
 
 
            off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
            off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
            off += (4 - ((off - off_delta) & 3)) & 3;
            off += (4 - ((off - off_delta) & 3)) & 3;
 
 
            vs_off = off;
            vs_off = off;
 
 
            off += BIN_VER_INFO_SIZE;
            off += BIN_VER_INFO_SIZE;
 
 
            off = unicode_to_bin (wrbfd, off, vi->u.string.language);
            off = unicode_to_bin (wrbfd, off, vi->u.string.language);
 
 
            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
              {
              {
                struct bin_ver_info bvss;
                struct bin_ver_info bvss;
                rc_uint_type vss_off,str_off;
                rc_uint_type vss_off,str_off;
 
 
                off += (4 - ((off - off_delta) & 3)) & 3;
                off += (4 - ((off - off_delta) & 3)) & 3;
 
 
                vss_off = off;
                vss_off = off;
                off += BIN_VER_INFO_SIZE;
                off += BIN_VER_INFO_SIZE;
 
 
                off = unicode_to_bin (wrbfd, off, vs->key);
                off = unicode_to_bin (wrbfd, off, vs->key);
 
 
                off += (4 - ((off - off_delta) & 3)) & 3;
                off += (4 - ((off - off_delta) & 3)) & 3;
 
 
                str_off = off;
                str_off = off;
                off = unicode_to_bin (wrbfd, off, vs->value);
                off = unicode_to_bin (wrbfd, off, vs->value);
                if (wrbfd)
                if (wrbfd)
                  {
                  {
                    windres_put_16 (wrbfd, bvss.size, off - vss_off);
                    windres_put_16 (wrbfd, bvss.size, off - vss_off);
                    windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2);
                    windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2);
                    windres_put_16 (wrbfd, bvss.sig2, 1);
                    windres_put_16 (wrbfd, bvss.sig2, 1);
                    set_windres_bfd_content (wrbfd, &bvss, vss_off,
                    set_windres_bfd_content (wrbfd, &bvss, vss_off,
                                             BIN_VER_INFO_SIZE);
                                             BIN_VER_INFO_SIZE);
                  }
                  }
              }
              }
            if (wrbfd)
            if (wrbfd)
              {
              {
                windres_put_16 (wrbfd, bvsd.size, off - vs_off);
                windres_put_16 (wrbfd, bvsd.size, off - vs_off);
                windres_put_16 (wrbfd, bvsd.sig1, 0);
                windres_put_16 (wrbfd, bvsd.sig1, 0);
                windres_put_16 (wrbfd, bvsd.sig2, 0);
                windres_put_16 (wrbfd, bvsd.sig2, 0);
                set_windres_bfd_content (wrbfd, &bvsd, vs_off,
                set_windres_bfd_content (wrbfd, &bvsd, vs_off,
                                         BIN_VER_INFO_SIZE);
                                         BIN_VER_INFO_SIZE);
              }
              }
            break;
            break;
          }
          }
 
 
        case VERINFO_VAR:
        case VERINFO_VAR:
          {
          {
            rc_uint_type vvd_off, vvvd_off;
            rc_uint_type vvd_off, vvvd_off;
            struct bin_ver_info bvvd;
            struct bin_ver_info bvvd;
            const rc_ver_varinfo *vv;
            const rc_ver_varinfo *vv;
 
 
            off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
            off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
 
 
            off += (4 - ((off - off_delta) & 3)) & 3;
            off += (4 - ((off - off_delta) & 3)) & 3;
 
 
            vvd_off = off;
            vvd_off = off;
            off += BIN_VER_INFO_SIZE;
            off += BIN_VER_INFO_SIZE;
 
 
            off = unicode_to_bin (wrbfd, off, vi->u.var.key);
            off = unicode_to_bin (wrbfd, off, vi->u.var.key);
 
 
            off += (4 - ((off - off_delta) & 3)) & 3;
            off += (4 - ((off - off_delta) & 3)) & 3;
 
 
            vvvd_off = off;
            vvvd_off = off;
 
 
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
              {
              {
                if (wrbfd)
                if (wrbfd)
                  {
                  {
                    bfd_byte vvsd[4];
                    bfd_byte vvsd[4];
 
 
                    windres_put_16 (wrbfd, &vvsd[0], vv->language);
                    windres_put_16 (wrbfd, &vvsd[0], vv->language);
                    windres_put_16 (wrbfd, &vvsd[2], vv->charset);
                    windres_put_16 (wrbfd, &vvsd[2], vv->charset);
                    set_windres_bfd_content (wrbfd, vvsd, off, 4);
                    set_windres_bfd_content (wrbfd, vvsd, off, 4);
                  }
                  }
                off += 4;
                off += 4;
              }
              }
            if (wrbfd)
            if (wrbfd)
            {
            {
                windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
                windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
                windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
                windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
                windres_put_16 (wrbfd, bvvd.sig2, 0);
                windres_put_16 (wrbfd, bvvd.sig2, 0);
                set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
                set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
                                         BIN_VER_INFO_SIZE);
                                         BIN_VER_INFO_SIZE);
            }
            }
 
 
            break;
            break;
          }
          }
        }
        }
 
 
      if (wrbfd)
      if (wrbfd)
        {
        {
          windres_put_16 (wrbfd, bv.size, off-bv_off);
          windres_put_16 (wrbfd, bv.size, off-bv_off);
          windres_put_16 (wrbfd, bv.sig1, 0);
          windres_put_16 (wrbfd, bv.sig1, 0);
          windres_put_16 (wrbfd, bv.sig2, 0);
          windres_put_16 (wrbfd, bv.sig2, 0);
          set_windres_bfd_content (wrbfd, &bv, bv_off,
          set_windres_bfd_content (wrbfd, &bv, bv_off,
                                   BIN_VER_INFO_SIZE);
                                   BIN_VER_INFO_SIZE);
        }
        }
    }
    }
 
 
  if (wrbfd)
  if (wrbfd)
    {
    {
      windres_put_16 (wrbfd, bvi.size, off - start);
      windres_put_16 (wrbfd, bvi.size, off - start);
      windres_put_16 (wrbfd, bvi.fixed_size,
      windres_put_16 (wrbfd, bvi.fixed_size,
                      versioninfo->fixed == NULL ? 0
                      versioninfo->fixed == NULL ? 0
                                                 : BIN_FIXED_VERSIONINFO_SIZE);
                                                 : BIN_FIXED_VERSIONINFO_SIZE);
      windres_put_16 (wrbfd, bvi.sig2, 0);
      windres_put_16 (wrbfd, bvi.sig2, 0);
      set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
      set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
    }
    }
  return off;
  return off;
}
}
 
 
/* Convert a generic resource to binary.  */
/* Convert a generic resource to binary.  */
 
 
static rc_uint_type
static rc_uint_type
res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
                    const bfd_byte *data)
                    const bfd_byte *data)
{
{
  if (wrbfd && length != 0)
  if (wrbfd && length != 0)
    set_windres_bfd_content (wrbfd, data, off, length);
    set_windres_bfd_content (wrbfd, data, off, length);
  return off + (rc_uint_type) length;
  return off + (rc_uint_type) length;
}
}
 
 

powered by: WebSVN 2.1.0

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