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