Home | History | Annotate | Download | only in binutils
      1 /* windres.c -- a program to manipulate Windows resources
      2    Copyright (C) 1997-2014 Free Software Foundation, Inc.
      3    Written by Ian Lance Taylor, Cygnus Support.
      4    Rewritten by Kai Tietz, Onevision.
      5 
      6    This file is part of GNU Binutils.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
     21    02110-1301, USA.  */
     22 
     23 /* This program can read and write Windows resources in various
     24    formats.  In particular, it can act like the rc resource compiler
     25    program, and it can act like the cvtres res to COFF conversion
     26    program.
     27 
     28    It is based on information taken from the following sources:
     29 
     30    * Microsoft documentation.
     31 
     32    * The rcl program, written by Gunther Ebert
     33      <gunther.ebert (at) ixos-leipzig.de>.
     34 
     35    * The res2coff program, written by Pedro A. Aranda <paag (at) tid.es>.  */
     36 
     37 #include "sysdep.h"
     38 #include <assert.h>
     39 #include "bfd.h"
     40 #include "getopt.h"
     41 #include "bucomm.h"
     42 #include "libiberty.h"
     43 #include "safe-ctype.h"
     44 #include "obstack.h"
     45 #include "windres.h"
     46 
     47 /* Used by resrc.c at least.  */
     48 
     49 int verbose = 0;
     50 
     51 int target_is_bigendian = 0;
     52 const char *def_target_arch;
     53 
     54 static void set_endianness (bfd *, const char *);
     55 
     56 /* An enumeration of format types.  */
     57 
     58 enum res_format
     59 {
     60   /* Unknown format.  */
     61   RES_FORMAT_UNKNOWN,
     62   /* Textual RC file.  */
     63   RES_FORMAT_RC,
     64   /* Binary RES file.  */
     65   RES_FORMAT_RES,
     66   /* COFF file.  */
     67   RES_FORMAT_COFF
     68 };
     69 
     70 /* A structure used to map between format types and strings.  */
     71 
     72 struct format_map
     73 {
     74   const char *name;
     75   enum res_format format;
     76 };
     77 
     78 /* A mapping between names and format types.  */
     79 
     80 static const struct format_map format_names[] =
     81 {
     82   { "rc", RES_FORMAT_RC },
     83   { "res", RES_FORMAT_RES },
     84   { "coff", RES_FORMAT_COFF },
     85   { NULL, RES_FORMAT_UNKNOWN }
     86 };
     87 
     88 /* A mapping from file extensions to format types.  */
     89 
     90 static const struct format_map format_fileexts[] =
     91 {
     92   { "rc", RES_FORMAT_RC },
     93   { "res", RES_FORMAT_RES },
     94   { "exe", RES_FORMAT_COFF },
     95   { "obj", RES_FORMAT_COFF },
     96   { "o", RES_FORMAT_COFF },
     97   { NULL, RES_FORMAT_UNKNOWN }
     98 };
     99 
    100 /* A list of include directories.  */
    101 
    102 struct include_dir
    103 {
    104   struct include_dir *next;
    105   char *dir;
    106 };
    107 
    108 static struct include_dir *include_dirs;
    109 
    110 /* Static functions.  */
    111 
    112 static void res_init (void);
    113 static int extended_menuitems (const rc_menuitem *);
    114 static enum res_format format_from_name (const char *, int);
    115 static enum res_format format_from_filename (const char *, int);
    116 static void usage (FILE *, int);
    117 static int cmp_res_entry (const void *, const void *);
    118 static rc_res_directory *sort_resources (rc_res_directory *);
    119 static void reswr_init (void);
    120 static const char * quot (const char *);
    121 
    122 static rc_uint_type target_get_8 (const void *, rc_uint_type);
    124 static void target_put_8 (void *, rc_uint_type);
    125 static rc_uint_type target_get_16 (const void *, rc_uint_type);
    126 static void target_put_16 (void *, rc_uint_type);
    127 static rc_uint_type target_get_32 (const void *, rc_uint_type);
    128 static void target_put_32 (void *, rc_uint_type);
    129 
    130 
    131 /* When we are building a resource tree, we allocate everything onto
    133    an obstack, so that we can free it all at once if we want.  */
    134 
    135 #define obstack_chunk_alloc xmalloc
    136 #define obstack_chunk_free free
    137 
    138 /* The resource building obstack.  */
    139 
    140 static struct obstack res_obstack;
    141 
    142 /* Initialize the resource building obstack.  */
    143 
    144 static void
    145 res_init (void)
    146 {
    147   obstack_init (&res_obstack);
    148 }
    149 
    150 /* Allocate space on the resource building obstack.  */
    151 
    152 void *
    153 res_alloc (rc_uint_type bytes)
    154 {
    155   return obstack_alloc (&res_obstack, (size_t) bytes);
    156 }
    157 
    158 /* We also use an obstack to save memory used while writing out a set
    159    of resources.  */
    160 
    161 static struct obstack reswr_obstack;
    162 
    163 /* Initialize the resource writing obstack.  */
    164 
    165 static void
    166 reswr_init (void)
    167 {
    168   obstack_init (&reswr_obstack);
    169 }
    170 
    171 /* Allocate space on the resource writing obstack.  */
    172 
    173 void *
    174 reswr_alloc (rc_uint_type bytes)
    175 {
    176   return obstack_alloc (&reswr_obstack, (size_t) bytes);
    177 }
    178 
    179 /* Open a file using the include directory search list.  */
    181 
    182 FILE *
    183 open_file_search (const char *filename, const char *mode, const char *errmsg,
    184 		  char **real_filename)
    185 {
    186   FILE *e;
    187   struct include_dir *d;
    188 
    189   e = fopen (filename, mode);
    190   if (e != NULL)
    191     {
    192       *real_filename = xstrdup (filename);
    193       return e;
    194     }
    195 
    196   if (errno == ENOENT)
    197     {
    198       for (d = include_dirs; d != NULL; d = d->next)
    199 	{
    200 	  char *n;
    201 
    202 	  n = (char *) xmalloc (strlen (d->dir) + strlen (filename) + 2);
    203 	  sprintf (n, "%s/%s", d->dir, filename);
    204 	  e = fopen (n, mode);
    205 	  if (e != NULL)
    206 	    {
    207 	      *real_filename = n;
    208 	      return e;
    209 	    }
    210 
    211 	  if (errno != ENOENT)
    212 	    break;
    213 	}
    214     }
    215 
    216   fatal (_("can't open %s `%s': %s"), errmsg, filename, strerror (errno));
    217 
    218   /* Return a value to avoid a compiler warning.  */
    219   return NULL;
    220 }
    221 
    222 /* Compare two resource ID's.  We consider name entries to come before
    224    numeric entries, because that is how they appear in the COFF .rsrc
    225    section.  */
    226 
    227 int
    228 res_id_cmp (rc_res_id a, rc_res_id b)
    229 {
    230   if (! a.named)
    231     {
    232       if (b.named)
    233 	return 1;
    234       if (a.u.id > b.u.id)
    235 	return 1;
    236       else if (a.u.id < b.u.id)
    237 	return -1;
    238       else
    239 	return 0;
    240     }
    241   else
    242     {
    243       unichar *as, *ase, *bs, *bse;
    244 
    245       if (! b.named)
    246 	return -1;
    247 
    248       as = a.u.n.name;
    249       ase = as + a.u.n.length;
    250       bs = b.u.n.name;
    251       bse = bs + b.u.n.length;
    252 
    253       while (as < ase)
    254 	{
    255 	  int i;
    256 
    257 	  if (bs >= bse)
    258 	    return 1;
    259 	  i = (int) *as - (int) *bs;
    260 	  if (i != 0)
    261 	    return i;
    262 	  ++as;
    263 	  ++bs;
    264 	}
    265 
    266       if (bs < bse)
    267 	return -1;
    268 
    269       return 0;
    270     }
    271 }
    272 
    273 /* Print a resource ID.  */
    274 
    275 void
    276 res_id_print (FILE *stream, rc_res_id id, int quote)
    277 {
    278   if (! id.named)
    279     fprintf (stream, "%u", (int) id.u.id);
    280   else
    281     {
    282       if (quote)
    283 	unicode_print_quoted (stream, id.u.n.name, id.u.n.length);
    284       else
    285       unicode_print (stream, id.u.n.name, id.u.n.length);
    286     }
    287 }
    288 
    289 /* Print a list of resource ID's.  */
    290 
    291 void
    292 res_ids_print (FILE *stream, int cids, const rc_res_id *ids)
    293 {
    294   int i;
    295 
    296   for (i = 0; i < cids; i++)
    297     {
    298       res_id_print (stream, ids[i], 1);
    299       if (i + 1 < cids)
    300 	fprintf (stream, ": ");
    301     }
    302 }
    303 
    304 /* Convert an ASCII string to a resource ID.  */
    305 
    306 void
    307 res_string_to_id (rc_res_id *res_id, const char *string)
    308 {
    309   res_id->named = 1;
    310   unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string);
    311 }
    312 
    313 /* Convert an unicode string to a resource ID.  */
    314 void
    315 res_unistring_to_id (rc_res_id *res_id, const unichar *u)
    316 {
    317   res_id->named = 1;
    318   res_id->u.n.length = unichar_len (u);
    319   res_id->u.n.name = unichar_dup_uppercase (u);
    320 }
    321 
    322 /* Define a resource.  The arguments are the resource tree, RESOURCES,
    323    and the location at which to put it in the tree, CIDS and IDS.
    324    This returns a newly allocated rc_res_resource structure, which the
    325    caller is expected to initialize.  If DUPOK is non-zero, then if a
    326    resource with this ID exists, it is returned.  Otherwise, a warning
    327    is issued, and a new resource is created replacing the existing
    328    one.  */
    329 
    330 rc_res_resource *
    331 define_resource (rc_res_directory **resources, int cids,
    332 		 const rc_res_id *ids, int dupok)
    333 {
    334   rc_res_entry *re = NULL;
    335   int i;
    336 
    337   assert (cids > 0);
    338   for (i = 0; i < cids; i++)
    339     {
    340       rc_res_entry **pp;
    341 
    342       if (*resources == NULL)
    343 	{
    344 	  *resources = ((rc_res_directory *)
    345 			res_alloc (sizeof (rc_res_directory)));
    346 	  (*resources)->characteristics = 0;
    347 	  /* Using a real timestamp only serves to create non-deterministic
    348 	     results.  Use zero instead.  */
    349 	  (*resources)->time = 0;
    350 	  (*resources)->major = 0;
    351 	  (*resources)->minor = 0;
    352 	  (*resources)->entries = NULL;
    353 	}
    354 
    355       for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
    356 	if (res_id_cmp ((*pp)->id, ids[i]) == 0)
    357 	  break;
    358 
    359       if (*pp != NULL)
    360 	re = *pp;
    361       else
    362 	{
    363 	  re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
    364 	  re->next = NULL;
    365 	  re->id = ids[i];
    366 	  if ((i + 1) < cids)
    367 	    {
    368 	      re->subdir = 1;
    369 	      re->u.dir = NULL;
    370 	    }
    371 	  else
    372 	    {
    373 	      re->subdir = 0;
    374 	      re->u.res = NULL;
    375 	    }
    376 
    377 	  *pp = re;
    378 	}
    379 
    380       if ((i + 1) < cids)
    381 	{
    382 	  if (! re->subdir)
    383 	    {
    384 	      fprintf (stderr, "%s: ", program_name);
    385 	      res_ids_print (stderr, i, ids);
    386 	      fprintf (stderr, _(": expected to be a directory\n"));
    387 	      xexit (1);
    388 	    }
    389 
    390 	  resources = &re->u.dir;
    391 	}
    392     }
    393 
    394   if (re->subdir)
    395     {
    396       fprintf (stderr, "%s: ", program_name);
    397       res_ids_print (stderr, cids, ids);
    398       fprintf (stderr, _(": expected to be a leaf\n"));
    399       xexit (1);
    400     }
    401 
    402   if (re->u.res != NULL)
    403     {
    404       if (dupok)
    405 	return re->u.res;
    406 
    407       fprintf (stderr, _("%s: warning: "), program_name);
    408       res_ids_print (stderr, cids, ids);
    409       fprintf (stderr, _(": duplicate value\n"));
    410     }
    411 
    412   re->u.res = ((rc_res_resource *)
    413 	       res_alloc (sizeof (rc_res_resource)));
    414   memset (re->u.res, 0, sizeof (rc_res_resource));
    415 
    416   re->u.res->type = RES_TYPE_UNINITIALIZED;
    417   return re->u.res;
    418 }
    419 
    420 /* Define a standard resource.  This is a version of define_resource
    421    that just takes type, name, and language arguments.  */
    422 
    423 rc_res_resource *
    424 define_standard_resource (rc_res_directory **resources, int type,
    425 			  rc_res_id name, rc_uint_type language, int dupok)
    426 {
    427   rc_res_id a[3];
    428 
    429   a[0].named = 0;
    430   a[0].u.id = type;
    431   a[1] = name;
    432   a[2].named = 0;
    433   a[2].u.id = language;
    434   return define_resource (resources, 3, a, dupok);
    435 }
    436 
    437 /* Comparison routine for resource sorting.  */
    438 
    439 static int
    440 cmp_res_entry (const void *p1, const void *p2)
    441 {
    442   const rc_res_entry **re1, **re2;
    443 
    444   re1 = (const rc_res_entry **) p1;
    445   re2 = (const rc_res_entry **) p2;
    446   return res_id_cmp ((*re1)->id, (*re2)->id);
    447 }
    448 
    449 /* Sort the resources.  */
    450 
    451 static rc_res_directory *
    452 sort_resources (rc_res_directory *resdir)
    453 {
    454   int c, i;
    455   rc_res_entry *re;
    456   rc_res_entry **a;
    457 
    458   if (resdir->entries == NULL)
    459     return resdir;
    460 
    461   c = 0;
    462   for (re = resdir->entries; re != NULL; re = re->next)
    463     ++c;
    464 
    465   /* This is a recursive routine, so using xmalloc is probably better
    466      than alloca.  */
    467   a = (rc_res_entry **) xmalloc (c * sizeof (rc_res_entry *));
    468 
    469   for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++)
    470     a[i] = re;
    471 
    472   qsort (a, c, sizeof (rc_res_entry *), cmp_res_entry);
    473 
    474   resdir->entries = a[0];
    475   for (i = 0; i < c - 1; i++)
    476     a[i]->next = a[i + 1];
    477   a[i]->next = NULL;
    478 
    479   free (a);
    480 
    481   /* Now sort the subdirectories.  */
    482 
    483   for (re = resdir->entries; re != NULL; re = re->next)
    484     if (re->subdir)
    485       re->u.dir = sort_resources (re->u.dir);
    486 
    487   return resdir;
    488 }
    489 
    490 /* Return whether the dialog resource DIALOG is a DIALOG or a
    492    DIALOGEX.  */
    493 
    494 int
    495 extended_dialog (const rc_dialog *dialog)
    496 {
    497   const rc_dialog_control *c;
    498 
    499   if (dialog->ex != NULL)
    500     return 1;
    501 
    502   for (c = dialog->controls; c != NULL; c = c->next)
    503     if (c->data != NULL || c->help != 0)
    504       return 1;
    505 
    506   return 0;
    507 }
    508 
    509 /* Return whether MENUITEMS are a MENU or a MENUEX.  */
    510 
    511 int
    512 extended_menu (const rc_menu *menu)
    513 {
    514   return extended_menuitems (menu->items);
    515 }
    516 
    517 static int
    518 extended_menuitems (const rc_menuitem *menuitems)
    519 {
    520   const rc_menuitem *mi;
    521 
    522   for (mi = menuitems; mi != NULL; mi = mi->next)
    523     {
    524       if (mi->help != 0 || mi->state != 0)
    525 	return 1;
    526       if (mi->popup != NULL && mi->id != 0)
    527 	return 1;
    528       if ((mi->type
    529 	   & ~ (MENUITEM_CHECKED
    530 		| MENUITEM_GRAYED
    531 		| MENUITEM_HELP
    532 		| MENUITEM_INACTIVE
    533 		| MENUITEM_MENUBARBREAK
    534 		| MENUITEM_MENUBREAK))
    535 	  != 0)
    536 	return 1;
    537       if (mi->popup != NULL)
    538 	{
    539 	  if (extended_menuitems (mi->popup))
    540 	    return 1;
    541 	}
    542     }
    543 
    544   return 0;
    545 }
    546 
    547 /* Convert a string to a format type, or exit if it can't be done.  */
    549 
    550 static enum res_format
    551 format_from_name (const char *name, int exit_on_error)
    552 {
    553   const struct format_map *m;
    554 
    555   for (m = format_names; m->name != NULL; m++)
    556     if (strcasecmp (m->name, name) == 0)
    557       break;
    558 
    559   if (m->name == NULL && exit_on_error)
    560     {
    561       non_fatal (_("unknown format type `%s'"), name);
    562       fprintf (stderr, _("%s: supported formats:"), program_name);
    563       for (m = format_names; m->name != NULL; m++)
    564 	fprintf (stderr, " %s", m->name);
    565       fprintf (stderr, "\n");
    566       xexit (1);
    567     }
    568 
    569   return m->format;
    570 }
    571 
    572 /* Work out a format type given a file name.  If INPUT is non-zero,
    573    it's OK to look at the file itself.  */
    574 
    575 static enum res_format
    576 format_from_filename (const char *filename, int input)
    577 {
    578   const char *ext;
    579   FILE *e;
    580   bfd_byte b1, b2, b3, b4, b5;
    581   int magic;
    582 
    583   /* If we have an extension, see if we recognize it as implying a
    584      particular format.  */
    585   ext = strrchr (filename, '.');
    586   if (ext != NULL)
    587     {
    588       const struct format_map *m;
    589 
    590       ++ext;
    591       for (m = format_fileexts; m->name != NULL; m++)
    592 	if (strcasecmp (m->name, ext) == 0)
    593 	  return m->format;
    594     }
    595 
    596   /* If we don't recognize the name of an output file, assume it's a
    597      COFF file.  */
    598   if (! input)
    599     return RES_FORMAT_COFF;
    600 
    601   /* Read the first few bytes of the file to see if we can guess what
    602      it is.  */
    603   e = fopen (filename, FOPEN_RB);
    604   if (e == NULL)
    605     fatal ("%s: %s", filename, strerror (errno));
    606 
    607   b1 = getc (e);
    608   b2 = getc (e);
    609   b3 = getc (e);
    610   b4 = getc (e);
    611   b5 = getc (e);
    612 
    613   fclose (e);
    614 
    615   /* A PE executable starts with 0x4d 0x5a.  */
    616   if (b1 == 0x4d && b2 == 0x5a)
    617     return RES_FORMAT_COFF;
    618 
    619   /* A COFF .o file starts with a COFF magic number.  */
    620   magic = (b2 << 8) | b1;
    621   switch (magic)
    622     {
    623     case 0x14c: /* i386 */
    624     case 0x166: /* MIPS */
    625     case 0x184: /* Alpha */
    626     case 0x268: /* 68k */
    627     case 0x1f0: /* PowerPC */
    628     case 0x290: /* PA */
    629       return RES_FORMAT_COFF;
    630     }
    631 
    632   /* A RES file starts with 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0.  */
    633   if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 && b5 == 0x20)
    634     return RES_FORMAT_RES;
    635 
    636   /* If every character is printable or space, assume it's an RC file.  */
    637   if ((ISPRINT (b1) || ISSPACE (b1))
    638       && (ISPRINT (b2) || ISSPACE (b2))
    639       && (ISPRINT (b3) || ISSPACE (b3))
    640       && (ISPRINT (b4) || ISSPACE (b4))
    641       && (ISPRINT (b5) || ISSPACE (b5)))
    642     return RES_FORMAT_RC;
    643 
    644   /* Otherwise, we give up.  */
    645   fatal (_("can not determine type of file `%s'; use the -J option"),
    646 	 filename);
    647 
    648   /* Return something to silence the compiler warning.  */
    649   return RES_FORMAT_UNKNOWN;
    650 }
    651 
    652 /* Print a usage message and exit.  */
    653 
    654 static void
    655 usage (FILE *stream, int status)
    656 {
    657   fprintf (stream, _("Usage: %s [option(s)] [input-file] [output-file]\n"),
    658 	   program_name);
    659   fprintf (stream, _(" The options are:\n\
    660   -i --input=<file>            Name input file\n\
    661   -o --output=<file>           Name output file\n\
    662   -J --input-format=<format>   Specify input format\n\
    663   -O --output-format=<format>  Specify output format\n\
    664   -F --target=<target>         Specify COFF target\n\
    665      --preprocessor=<program>  Program to use to preprocess rc file\n\
    666      --preprocessor-arg=<arg>  Additional preprocessor argument\n\
    667   -I --include-dir=<dir>       Include directory when preprocessing rc file\n\
    668   -D --define <sym>[=<val>]    Define SYM when preprocessing rc file\n\
    669   -U --undefine <sym>          Undefine SYM when preprocessing rc file\n\
    670   -v --verbose                 Verbose - tells you what it's doing\n\
    671   -c --codepage=<codepage>     Specify default codepage\n\
    672   -l --language=<val>          Set language when reading rc file\n\
    673      --use-temp-file           Use a temporary file instead of popen to read\n\
    674                                the preprocessor output\n\
    675      --no-use-temp-file        Use popen (default)\n"));
    676 #ifdef YYDEBUG
    677   fprintf (stream, _("\
    678      --yydebug                 Turn on parser debugging\n"));
    679 #endif
    680   fprintf (stream, _("\
    681   -r                           Ignored for compatibility with rc\n\
    682   @<file>                      Read options from <file>\n\
    683   -h --help                    Print this help message\n\
    684   -V --version                 Print version information\n"));
    685   fprintf (stream, _("\
    686 FORMAT is one of rc, res, or coff, and is deduced from the file name\n\
    687 extension if not specified.  A single file name is an input file.\n\
    688 No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"));
    689 
    690   list_supported_targets (program_name, stream);
    691 
    692   if (REPORT_BUGS_TO[0] && status == 0)
    693     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
    694 
    695   exit (status);
    696 }
    697 
    698 /* Quote characters that will confuse the shell when we run the preprocessor.  */
    699 
    700 static const char *
    701 quot (const char *string)
    702 {
    703   static char *buf = 0;
    704   static int buflen = 0;
    705   int slen = strlen (string);
    706   const char *src;
    707   char *dest;
    708 
    709   if ((buflen < slen * 2 + 2) || ! buf)
    710     {
    711       buflen = slen * 2 + 2;
    712       if (buf)
    713 	free (buf);
    714       buf = (char *) xmalloc (buflen);
    715     }
    716 
    717   for (src=string, dest=buf; *src; src++, dest++)
    718     {
    719       if (*src == '(' || *src == ')' || *src == ' ')
    720 	*dest++ = '\\';
    721       *dest = *src;
    722     }
    723   *dest = 0;
    724   return buf;
    725 }
    726 
    727 /* Long options.  */
    728 
    729 enum option_values
    730 {
    731   /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
    732   OPTION_PREPROCESSOR	= 150,
    733   OPTION_USE_TEMP_FILE,
    734   OPTION_NO_USE_TEMP_FILE,
    735   OPTION_YYDEBUG,
    736   OPTION_INCLUDE_DIR,
    737   OPTION_PREPROCESSOR_ARG
    738 };
    739 
    740 static const struct option long_options[] =
    741 {
    742   {"input", required_argument, 0, 'i'},
    743   {"output", required_argument, 0, 'o'},
    744   {"input-format", required_argument, 0, 'J'},
    745   {"output-format", required_argument, 0, 'O'},
    746   {"target", required_argument, 0, 'F'},
    747   {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
    748   {"preprocessor-arg", required_argument, 0, OPTION_PREPROCESSOR_ARG},
    749   {"include-dir", required_argument, 0, OPTION_INCLUDE_DIR},
    750   {"define", required_argument, 0, 'D'},
    751   {"undefine", required_argument, 0, 'U'},
    752   {"verbose", no_argument, 0, 'v'},
    753   {"codepage", required_argument, 0, 'c'},
    754   {"language", required_argument, 0, 'l'},
    755   {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
    756   {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
    757   {"yydebug", no_argument, 0, OPTION_YYDEBUG},
    758   {"version", no_argument, 0, 'V'},
    759   {"help", no_argument, 0, 'h'},
    760   {0, no_argument, 0, 0}
    761 };
    762 
    763 void
    764 windres_add_include_dir (const char *p)
    765 {
    766   struct include_dir *n, **pp;
    767 
    768   /* Computing paths is often complicated and error prone.
    769      The easiest way to check for mistakes is at the time
    770      we add them to include_dirs.  */
    771   assert (p != NULL);
    772   assert (*p != '\0');
    773 
    774   n = xmalloc (sizeof *n);
    775   n->next = NULL;
    776   n->dir = (char * ) p;
    777 
    778   for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
    779     ;
    780   *pp = n;
    781 }
    782 
    783 /* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes.  */
    784 int main (int, char **);
    785 
    786 /* The main function.  */
    787 
    788 int
    789 main (int argc, char **argv)
    790 {
    791   int c;
    792   char *input_filename;
    793   char *output_filename;
    794   enum res_format input_format;
    795   enum res_format input_format_tmp;
    796   enum res_format output_format;
    797   char *target;
    798   char *preprocessor;
    799   char *preprocargs;
    800   const char *quotedarg;
    801   int language;
    802   rc_res_directory *resources;
    803   int use_temp_file;
    804 
    805 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
    806   setlocale (LC_MESSAGES, "");
    807 #endif
    808 #if defined (HAVE_SETLOCALE)
    809   setlocale (LC_CTYPE, "");
    810 #endif
    811   bindtextdomain (PACKAGE, LOCALEDIR);
    812   textdomain (PACKAGE);
    813 
    814   program_name = argv[0];
    815   xmalloc_set_program_name (program_name);
    816 
    817   expandargv (&argc, &argv);
    818 
    819   bfd_init ();
    820   set_default_bfd_target ();
    821 
    822   res_init ();
    823 
    824   input_filename = NULL;
    825   output_filename = NULL;
    826   input_format = RES_FORMAT_UNKNOWN;
    827   output_format = RES_FORMAT_UNKNOWN;
    828   target = NULL;
    829   preprocessor = NULL;
    830   preprocargs = NULL;
    831   language = 0x409;   /* LANG_ENGLISH, SUBLANG_ENGLISH_US.  */
    832   use_temp_file = 0;
    833 
    834   while ((c = getopt_long (argc, argv, "c:f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
    835 			   (int *) 0)) != EOF)
    836     {
    837       switch (c)
    838 	{
    839 	case 'c':
    840 	  {
    841 	    rc_uint_type ncp;
    842 
    843 	    if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X'))
    844 	      ncp = (rc_uint_type) strtol (optarg + 2, NULL, 16);
    845 	    else
    846 	      ncp = (rc_uint_type) strtol (optarg, NULL, 10);
    847 	    if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
    848 	      fatal (_("invalid codepage specified.\n"));
    849 	    wind_default_codepage = wind_current_codepage = ncp;
    850 	  }
    851 	  break;
    852 
    853 	case 'i':
    854 	  input_filename = optarg;
    855 	  break;
    856 
    857 	case 'f':
    858 	  /* For compatibility with rc we accept "-fo <name>" as being the
    859 	     equivalent of "-o <name>".  We do not advertise this fact
    860 	     though, as we do not want users to use non-GNU like command
    861 	     line switches.  */
    862 	  if (*optarg != 'o')
    863 	    fatal (_("invalid option -f\n"));
    864 	  optarg++;
    865 	  if (* optarg == 0)
    866 	    {
    867 	      if (optind == argc)
    868 		fatal (_("No filename following the -fo option.\n"));
    869 	      optarg = argv [optind++];
    870 	    }
    871 	  /* Fall through.  */
    872 
    873 	case 'o':
    874 	  output_filename = optarg;
    875 	  break;
    876 
    877 	case 'J':
    878 	  input_format = format_from_name (optarg, 1);
    879 	  break;
    880 
    881 	case 'O':
    882 	  output_format = format_from_name (optarg, 1);
    883 	  break;
    884 
    885 	case 'F':
    886 	  target = optarg;
    887 	  break;
    888 
    889 	case OPTION_PREPROCESSOR:
    890 	  preprocessor = optarg;
    891 	  break;
    892 
    893 	case OPTION_PREPROCESSOR_ARG:
    894 	  if (preprocargs == NULL)
    895 	    {
    896 	      quotedarg = quot (optarg);
    897 	      preprocargs = xstrdup (quotedarg);
    898 	    }
    899 	  else
    900 	    {
    901 	      char *n;
    902 
    903 	      quotedarg = quot (optarg);
    904 	      n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 2);
    905 	      sprintf (n, "%s %s", preprocargs, quotedarg);
    906 	      free (preprocargs);
    907 	      preprocargs = n;
    908 	    }
    909 	  break;
    910 
    911 	case 'D':
    912 	case 'U':
    913 	  if (preprocargs == NULL)
    914 	    {
    915 	      quotedarg = quot (optarg);
    916 	      preprocargs = xmalloc (strlen (quotedarg) + 3);
    917 	      sprintf (preprocargs, "-%c%s", c, quotedarg);
    918 	    }
    919 	  else
    920 	    {
    921 	      char *n;
    922 
    923 	      quotedarg = quot (optarg);
    924 	      n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
    925 	      sprintf (n, "%s -%c%s", preprocargs, c, quotedarg);
    926 	      free (preprocargs);
    927 	      preprocargs = n;
    928 	    }
    929 	  break;
    930 
    931 	case 'r':
    932 	  /* Ignored for compatibility with rc.  */
    933 	  break;
    934 
    935 	case 'v':
    936 	  verbose ++;
    937 	  break;
    938 
    939 	case 'I':
    940 	  /* For backward compatibility, should be removed in the future.  */
    941 	  input_format_tmp = format_from_name (optarg, 0);
    942 	  if (input_format_tmp != RES_FORMAT_UNKNOWN)
    943 	    {
    944 	      struct stat statbuf;
    945 	      char modebuf[11];
    946 
    947 	      if (stat (optarg, & statbuf) == 0
    948 		  /* Coded this way to avoid importing knowledge of S_ISDIR into this file.  */
    949 		  && (mode_string (statbuf.st_mode, modebuf), modebuf[0] == 'd'))
    950 		/* We have a -I option with a directory name that just happens
    951 		   to match a format name as well.  eg: -I res  Assume that the
    952 		   user knows what they are doing and do not complain.  */
    953 		;
    954 	      else
    955 		{
    956 		  fprintf (stderr,
    957 			   _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
    958 		  input_format = input_format_tmp;
    959 		  break;
    960 		}
    961 	    }
    962 	  /* Fall through.  */
    963 
    964 	case OPTION_INCLUDE_DIR:
    965 	  if (preprocargs == NULL)
    966 	    {
    967 	      quotedarg = quot (optarg);
    968 	      preprocargs = xmalloc (strlen (quotedarg) + 3);
    969 	      sprintf (preprocargs, "-I%s", quotedarg);
    970 	    }
    971 	  else
    972 	    {
    973 	      char *n;
    974 
    975 	      quotedarg = quot (optarg);
    976 	      n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
    977 	      sprintf (n, "%s -I%s", preprocargs, quotedarg);
    978 	      free (preprocargs);
    979 	      preprocargs = n;
    980 	    }
    981 
    982 	  windres_add_include_dir (optarg);
    983 
    984 	  break;
    985 
    986 	case 'l':
    987 	  language = strtol (optarg, (char **) NULL, 16);
    988 	  break;
    989 
    990 	case OPTION_USE_TEMP_FILE:
    991 	  use_temp_file = 1;
    992 	  break;
    993 
    994 	case OPTION_NO_USE_TEMP_FILE:
    995 	  use_temp_file = 0;
    996 	  break;
    997 
    998 #ifdef YYDEBUG
    999 	case OPTION_YYDEBUG:
   1000 	  yydebug = 1;
   1001 	  break;
   1002 #endif
   1003 
   1004 	case 'h':
   1005 	case 'H':
   1006 	  usage (stdout, 0);
   1007 	  break;
   1008 
   1009 	case 'V':
   1010 	  print_version ("windres");
   1011 	  break;
   1012 
   1013 	default:
   1014 	  usage (stderr, 1);
   1015 	  break;
   1016 	}
   1017     }
   1018 
   1019   if (input_filename == NULL && optind < argc)
   1020     {
   1021       input_filename = argv[optind];
   1022       ++optind;
   1023     }
   1024 
   1025   if (output_filename == NULL && optind < argc)
   1026     {
   1027       output_filename = argv[optind];
   1028       ++optind;
   1029     }
   1030 
   1031   if (argc != optind)
   1032     usage (stderr, 1);
   1033 
   1034   if (input_format == RES_FORMAT_UNKNOWN)
   1035     {
   1036       if (input_filename == NULL)
   1037 	input_format = RES_FORMAT_RC;
   1038       else
   1039 	input_format = format_from_filename (input_filename, 1);
   1040     }
   1041 
   1042   if (output_format == RES_FORMAT_UNKNOWN)
   1043     {
   1044       if (output_filename == NULL)
   1045 	output_format = RES_FORMAT_RC;
   1046       else
   1047 	output_format = format_from_filename (output_filename, 0);
   1048     }
   1049 
   1050   set_endianness (NULL, target);
   1051 
   1052   /* Read the input file.  */
   1053   switch (input_format)
   1054     {
   1055     default:
   1056       abort ();
   1057     case RES_FORMAT_RC:
   1058       resources = read_rc_file (input_filename, preprocessor, preprocargs,
   1059 				language, use_temp_file);
   1060       break;
   1061     case RES_FORMAT_RES:
   1062       resources = read_res_file (input_filename);
   1063       break;
   1064     case RES_FORMAT_COFF:
   1065       resources = read_coff_rsrc (input_filename, target);
   1066       break;
   1067     }
   1068 
   1069   if (resources == NULL)
   1070     fatal (_("no resources"));
   1071 
   1072   /* Sort the resources.  This is required for COFF, convenient for
   1073      rc, and unimportant for res.  */
   1074   resources = sort_resources (resources);
   1075 
   1076   /* Write the output file.  */
   1077   reswr_init ();
   1078 
   1079   switch (output_format)
   1080     {
   1081     default:
   1082       abort ();
   1083     case RES_FORMAT_RC:
   1084       write_rc_file (output_filename, resources);
   1085       break;
   1086     case RES_FORMAT_RES:
   1087       write_res_file (output_filename, resources);
   1088       break;
   1089     case RES_FORMAT_COFF:
   1090       write_coff_file (output_filename, target, resources);
   1091       break;
   1092     }
   1093 
   1094   xexit (0);
   1095   return 0;
   1096 }
   1097 
   1098 static void
   1099 set_endianness (bfd *abfd, const char *target)
   1100 {
   1101   const bfd_target *target_vec;
   1102 
   1103   def_target_arch = NULL;
   1104   target_vec = bfd_get_target_info (target, abfd, &target_is_bigendian, NULL,
   1105                                    &def_target_arch);
   1106   if (! target_vec)
   1107     fatal ("Can't detect target endianness and architecture.");
   1108   if (! def_target_arch)
   1109     fatal ("Can't detect architecture.");
   1110 }
   1111 
   1112 bfd *
   1113 windres_open_as_binary (const char *filename, int rdmode)
   1114 {
   1115   bfd *abfd;
   1116 
   1117   abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary"));
   1118   if (! abfd)
   1119     fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output"));
   1120 
   1121   if (rdmode && ! bfd_check_format (abfd, bfd_object))
   1122     fatal ("can't open `%s' for input.", filename);
   1123 
   1124   return abfd;
   1125 }
   1126 
   1127 void
   1128 set_windres_bfd_endianness (windres_bfd *wrbfd, int is_bigendian)
   1129 {
   1130   assert (!! wrbfd);
   1131   switch (WR_KIND(wrbfd))
   1132   {
   1133   case WR_KIND_BFD_BIN_L:
   1134     if (is_bigendian)
   1135       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_B;
   1136     break;
   1137   case WR_KIND_BFD_BIN_B:
   1138     if (! is_bigendian)
   1139       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_L;
   1140     break;
   1141   default:
   1142     /* only binary bfd can be overriden. */
   1143     abort ();
   1144   }
   1145 }
   1146 
   1147 void
   1148 set_windres_bfd (windres_bfd *wrbfd, bfd *abfd, asection *sec, rc_uint_type kind)
   1149 {
   1150   assert (!! wrbfd);
   1151   switch (kind)
   1152   {
   1153   case WR_KIND_TARGET:
   1154     abfd = NULL;
   1155     sec = NULL;
   1156     break;
   1157   case WR_KIND_BFD:
   1158   case WR_KIND_BFD_BIN_L:
   1159   case WR_KIND_BFD_BIN_B:
   1160     assert (!! abfd);
   1161     assert (!!sec);
   1162     break;
   1163   default:
   1164     abort ();
   1165   }
   1166   WR_KIND(wrbfd) = kind;
   1167   WR_BFD(wrbfd) = abfd;
   1168   WR_SECTION(wrbfd) = sec;
   1169 }
   1170 
   1171 void
   1172 set_windres_bfd_content (windres_bfd *wrbfd, const void *data, rc_uint_type off,
   1173 			 rc_uint_type length)
   1174 {
   1175   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
   1176     {
   1177       if (! bfd_set_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
   1178 	bfd_fatal ("bfd_set_section_contents");
   1179     }
   1180   else
   1181     abort ();
   1182 }
   1183 
   1184 void
   1185 get_windres_bfd_content (windres_bfd *wrbfd, void *data, rc_uint_type off,
   1186 			 rc_uint_type length)
   1187 {
   1188   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
   1189     {
   1190       if (! bfd_get_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
   1191 	bfd_fatal ("bfd_get_section_contents");
   1192     }
   1193   else
   1194     abort ();
   1195 }
   1196 
   1197 void
   1198 windres_put_8 (windres_bfd *wrbfd, void *p, rc_uint_type value)
   1199 {
   1200   switch (WR_KIND(wrbfd))
   1201     {
   1202     case WR_KIND_TARGET:
   1203       target_put_8 (p, value);
   1204       break;
   1205     case WR_KIND_BFD:
   1206     case WR_KIND_BFD_BIN_L:
   1207     case WR_KIND_BFD_BIN_B:
   1208       bfd_put_8 (WR_BFD(wrbfd), value, p);
   1209       break;
   1210     default:
   1211       abort ();
   1212     }
   1213 }
   1214 
   1215 void
   1216 windres_put_16 (windres_bfd *wrbfd, void *data, rc_uint_type value)
   1217 {
   1218   switch (WR_KIND(wrbfd))
   1219     {
   1220     case WR_KIND_TARGET:
   1221       target_put_16 (data, value);
   1222       break;
   1223     case WR_KIND_BFD:
   1224     case WR_KIND_BFD_BIN_B:
   1225       bfd_put_16 (WR_BFD(wrbfd), value, data);
   1226       break;
   1227     case WR_KIND_BFD_BIN_L:
   1228       bfd_putl16 (value, data);
   1229       break;
   1230     default:
   1231       abort ();
   1232     }
   1233 }
   1234 
   1235 void
   1236 windres_put_32 (windres_bfd *wrbfd, void *data, rc_uint_type value)
   1237 {
   1238   switch (WR_KIND(wrbfd))
   1239     {
   1240     case WR_KIND_TARGET:
   1241       target_put_32 (data, value);
   1242       break;
   1243     case WR_KIND_BFD:
   1244     case WR_KIND_BFD_BIN_B:
   1245       bfd_put_32 (WR_BFD(wrbfd), value, data);
   1246       break;
   1247     case WR_KIND_BFD_BIN_L:
   1248       bfd_putl32 (value, data);
   1249       break;
   1250     default:
   1251       abort ();
   1252     }
   1253 }
   1254 
   1255 rc_uint_type
   1256 windres_get_8 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
   1257 {
   1258   if (length < 1)
   1259     fatal ("windres_get_8: unexpected eob.");
   1260   switch (WR_KIND(wrbfd))
   1261     {
   1262     case WR_KIND_TARGET:
   1263       return target_get_8 (data, length);
   1264     case WR_KIND_BFD:
   1265     case WR_KIND_BFD_BIN_B:
   1266     case WR_KIND_BFD_BIN_L:
   1267       return bfd_get_8 (WR_BFD(wrbfd), data);
   1268     default:
   1269       abort ();
   1270     }
   1271   return 0;
   1272 }
   1273 
   1274 rc_uint_type
   1275 windres_get_16 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
   1276 {
   1277   if (length < 2)
   1278     fatal ("windres_get_16: unexpected eob.");
   1279   switch (WR_KIND(wrbfd))
   1280     {
   1281     case WR_KIND_TARGET:
   1282       return target_get_16 (data, length);
   1283     case WR_KIND_BFD:
   1284     case WR_KIND_BFD_BIN_B:
   1285       return bfd_get_16 (WR_BFD(wrbfd), data);
   1286     case WR_KIND_BFD_BIN_L:
   1287       return bfd_getl16 (data);
   1288     default:
   1289       abort ();
   1290     }
   1291   return 0;
   1292 }
   1293 
   1294 rc_uint_type
   1295 windres_get_32 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
   1296 {
   1297   if (length < 4)
   1298     fatal ("windres_get_32: unexpected eob.");
   1299   switch (WR_KIND(wrbfd))
   1300     {
   1301     case WR_KIND_TARGET:
   1302       return target_get_32 (data, length);
   1303     case WR_KIND_BFD:
   1304     case WR_KIND_BFD_BIN_B:
   1305       return bfd_get_32 (WR_BFD(wrbfd), data);
   1306     case WR_KIND_BFD_BIN_L:
   1307       return bfd_getl32 (data);
   1308     default:
   1309       abort ();
   1310     }
   1311   return 0;
   1312 }
   1313 
   1314 static rc_uint_type
   1315 target_get_8 (const void *p, rc_uint_type length)
   1316 {
   1317   rc_uint_type ret;
   1318 
   1319   if (length < 1)
   1320     fatal ("Resource too small for getting 8-bit value.");
   1321 
   1322   ret = (rc_uint_type) *((const bfd_byte *) p);
   1323   return ret & 0xff;
   1324 }
   1325 
   1326 static rc_uint_type
   1327 target_get_16 (const void *p, rc_uint_type length)
   1328 {
   1329   if (length < 2)
   1330     fatal ("Resource too small for getting 16-bit value.");
   1331 
   1332   if (target_is_bigendian)
   1333     return bfd_getb16 (p);
   1334   else
   1335     return bfd_getl16 (p);
   1336 }
   1337 
   1338 static rc_uint_type
   1339 target_get_32 (const void *p, rc_uint_type length)
   1340 {
   1341   if (length < 4)
   1342     fatal ("Resource too small for getting 32-bit value.");
   1343 
   1344   if (target_is_bigendian)
   1345     return bfd_getb32 (p);
   1346   else
   1347     return bfd_getl32 (p);
   1348 }
   1349 
   1350 static void
   1351 target_put_8 (void *p, rc_uint_type value)
   1352 {
   1353   assert (!! p);
   1354   *((bfd_byte *) p)=(bfd_byte) value;
   1355 }
   1356 
   1357 static void
   1358 target_put_16 (void *p, rc_uint_type value)
   1359 {
   1360   assert (!! p);
   1361 
   1362   if (target_is_bigendian)
   1363     bfd_putb16 (value, p);
   1364   else
   1365     bfd_putl16 (value, p);
   1366 }
   1367 
   1368 static void
   1369 target_put_32 (void *p, rc_uint_type value)
   1370 {
   1371   assert (!! p);
   1372 
   1373   if (target_is_bigendian)
   1374     bfd_putb32 (value, p);
   1375   else
   1376     bfd_putl32 (value, p);
   1377 }
   1378 
   1379 static int isInComment = 0;
   1380 
   1381 int wr_printcomment (FILE *e, const char *fmt, ...)
   1382 {
   1383   va_list arg;
   1384   int r = 0;
   1385 
   1386   if (isInComment)
   1387     r += fprintf (e, "\n   ");
   1388   else
   1389     fprintf (e, "/* ");
   1390   isInComment = 1;
   1391   if (fmt == NULL)
   1392     return r;
   1393   va_start (arg, fmt);
   1394   r += vfprintf (e, fmt, arg);
   1395   va_end (arg);
   1396   return r;
   1397 }
   1398 
   1399 int wr_print (FILE *e, const char *fmt, ...)
   1400 {
   1401   va_list arg;
   1402   int r = 0;
   1403   if (isInComment)
   1404     r += fprintf (e, ".  */\n");
   1405   isInComment = 0;
   1406   if (! fmt)
   1407     return r;
   1408   va_start (arg, fmt);
   1409   r += vfprintf (e, fmt, arg);
   1410   va_end (arg);
   1411   return r;
   1412 }
   1413