* obcopy.c (copy_object): New parameter `input_arch', architecture
[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 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_endianess (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   -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 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
730
731 #define OPTION_PREPROCESSOR     150
732 #define OPTION_USE_TEMP_FILE    (OPTION_PREPROCESSOR + 1)
733 #define OPTION_NO_USE_TEMP_FILE (OPTION_USE_TEMP_FILE + 1)
734 #define OPTION_YYDEBUG          (OPTION_NO_USE_TEMP_FILE + 1)
735
736 static const struct option long_options[] =
737 {
738   {"input", required_argument, 0, 'i'},
739   {"output", required_argument, 0, 'o'},
740   {"input-format", required_argument, 0, 'J'},
741   {"output-format", required_argument, 0, 'O'},
742   {"target", required_argument, 0, 'F'},
743   {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
744   {"include-dir", required_argument, 0, 'I'},
745   {"define", required_argument, 0, 'D'},
746   {"undefine", required_argument, 0, 'U'},
747   {"verbose", no_argument, 0, 'v'},
748   {"codepage", required_argument, 0, 'c'},
749   {"language", required_argument, 0, 'l'},
750   {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
751   {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
752   {"yydebug", no_argument, 0, OPTION_YYDEBUG},
753   {"version", no_argument, 0, 'V'},
754   {"help", no_argument, 0, 'h'},
755   {0, no_argument, 0, 0}
756 };
757
758 void
759 windres_add_include_dir (const char *p)
760 {
761   struct include_dir *n, **pp;
762
763   /* Computing paths is often complicated and error prone.
764      The easiest way to check for mistakes is at the time
765      we add them to include_dirs.  */
766   assert (p != NULL);
767   assert (*p != '\0');
768
769   n = xmalloc (sizeof *n);
770   n->next = NULL;
771   n->dir = (char * ) p;
772
773   for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
774     ;
775   *pp = n;
776 }
777
778 /* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes.  */
779 int main (int, char **);
780
781 /* The main function.  */
782
783 int
784 main (int argc, char **argv)
785 {
786   int c;
787   char *input_filename;
788   char *output_filename;
789   enum res_format input_format;
790   enum res_format input_format_tmp;
791   enum res_format output_format;
792   char *target;
793   char *preprocessor;
794   char *preprocargs;
795   const char *quotedarg;
796   int language;
797   rc_res_directory *resources;
798   int use_temp_file;
799
800 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
801   setlocale (LC_MESSAGES, "");
802 #endif
803 #if defined (HAVE_SETLOCALE)
804   setlocale (LC_CTYPE, "");
805 #endif
806   bindtextdomain (PACKAGE, LOCALEDIR);
807   textdomain (PACKAGE);
808
809   program_name = argv[0];
810   xmalloc_set_program_name (program_name);
811
812   expandargv (&argc, &argv);
813
814   bfd_init ();
815   set_default_bfd_target ();
816
817   res_init ();
818
819   input_filename = NULL;
820   output_filename = NULL;
821   input_format = RES_FORMAT_UNKNOWN;
822   output_format = RES_FORMAT_UNKNOWN;
823   target = NULL;
824   preprocessor = NULL;
825   preprocargs = NULL;
826   language = 0x409;   /* LANG_ENGLISH, SUBLANG_ENGLISH_US.  */
827   use_temp_file = 0;
828
829   while ((c = getopt_long (argc, argv, "c:f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
830                            (int *) 0)) != EOF)
831     {
832       switch (c)
833         {
834         case 'c':
835           {
836             rc_uint_type ncp;
837
838             if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X'))
839               ncp = (rc_uint_type) strtol (optarg + 2, NULL, 16);
840             else
841               ncp = (rc_uint_type) strtol (optarg, NULL, 10);
842             if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
843               fatal (_("invalid codepage specified.\n"));
844             wind_default_codepage = wind_current_codepage = ncp;
845           }
846           break;
847
848         case 'i':
849           input_filename = optarg;
850           break;
851
852         case 'f':
853           /* For compatibility with rc we accept "-fo <name>" as being the
854              equivalent of "-o <name>".  We do not advertise this fact
855              though, as we do not want users to use non-GNU like command
856              line switches.  */
857           if (*optarg != 'o')
858             fatal (_("invalid option -f\n"));
859           optarg++;
860           if (* optarg == 0)
861             {
862               if (optind == argc)
863                 fatal (_("No filename following the -fo option.\n"));
864               optarg = argv [optind++];
865             }
866           /* Fall through.  */
867
868         case 'o':
869           output_filename = optarg;
870           break;
871
872         case 'J':
873           input_format = format_from_name (optarg, 1);
874           break;
875
876         case 'O':
877           output_format = format_from_name (optarg, 1);
878           break;
879
880         case 'F':
881           target = optarg;
882           break;
883
884         case OPTION_PREPROCESSOR:
885           preprocessor = optarg;
886           break;
887
888         case 'D':
889         case 'U':
890           if (preprocargs == NULL)
891             {
892               quotedarg = quot (optarg);
893               preprocargs = xmalloc (strlen (quotedarg) + 3);
894               sprintf (preprocargs, "-%c%s", c, quotedarg);
895             }
896           else
897             {
898               char *n;
899
900               quotedarg = quot (optarg);
901               n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
902               sprintf (n, "%s -%c%s", preprocargs, c, quotedarg);
903               free (preprocargs);
904               preprocargs = n;
905             }
906           break;
907
908         case 'r':
909           /* Ignored for compatibility with rc.  */
910           break;
911
912         case 'v':
913           verbose ++;
914           break;
915
916         case 'I':
917           /* For backward compatibility, should be removed in the future.  */
918           input_format_tmp = format_from_name (optarg, 0);
919           if (input_format_tmp != RES_FORMAT_UNKNOWN)
920             {
921               fprintf (stderr,
922                        _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
923               input_format = input_format_tmp;
924               break;
925             }
926
927           if (preprocargs == NULL)
928             {
929               quotedarg = quot (optarg);
930               preprocargs = xmalloc (strlen (quotedarg) + 3);
931               sprintf (preprocargs, "-I%s", quotedarg);
932             }
933           else
934             {
935               char *n;
936
937               quotedarg = quot (optarg);
938               n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
939               sprintf (n, "%s -I%s", preprocargs, quotedarg);
940               free (preprocargs);
941               preprocargs = n;
942             }
943
944           windres_add_include_dir (optarg);
945
946           break;
947
948         case 'l':
949           language = strtol (optarg, (char **) NULL, 16);
950           break;
951
952         case OPTION_USE_TEMP_FILE:
953           use_temp_file = 1;
954           break;
955
956         case OPTION_NO_USE_TEMP_FILE:
957           use_temp_file = 0;
958           break;
959
960 #ifdef YYDEBUG
961         case OPTION_YYDEBUG:
962           yydebug = 1;
963           break;
964 #endif
965
966         case 'h':
967         case 'H':
968           usage (stdout, 0);
969           break;
970
971         case 'V':
972           print_version ("windres");
973           break;
974
975         default:
976           usage (stderr, 1);
977           break;
978         }
979     }
980
981   if (input_filename == NULL && optind < argc)
982     {
983       input_filename = argv[optind];
984       ++optind;
985     }
986
987   if (output_filename == NULL && optind < argc)
988     {
989       output_filename = argv[optind];
990       ++optind;
991     }
992
993   if (argc != optind)
994     usage (stderr, 1);
995
996   if (input_format == RES_FORMAT_UNKNOWN)
997     {
998       if (input_filename == NULL)
999         input_format = RES_FORMAT_RC;
1000       else
1001         input_format = format_from_filename (input_filename, 1);
1002     }
1003
1004   if (output_format == RES_FORMAT_UNKNOWN)
1005     {
1006       if (output_filename == NULL)
1007         output_format = RES_FORMAT_RC;
1008       else
1009         output_format = format_from_filename (output_filename, 0);
1010     }
1011
1012   set_endianess (NULL, target);
1013
1014   /* Read the input file.  */
1015   switch (input_format)
1016     {
1017     default:
1018       abort ();
1019     case RES_FORMAT_RC:
1020       resources = read_rc_file (input_filename, preprocessor, preprocargs,
1021                                 language, use_temp_file);
1022       break;
1023     case RES_FORMAT_RES:
1024       resources = read_res_file (input_filename);
1025       break;
1026     case RES_FORMAT_COFF:
1027       resources = read_coff_rsrc (input_filename, target);
1028       break;
1029     }
1030
1031   if (resources == NULL)
1032     fatal (_("no resources"));
1033
1034   /* Sort the resources.  This is required for COFF, convenient for
1035      rc, and unimportant for res.  */
1036   resources = sort_resources (resources);
1037
1038   /* Write the output file.  */
1039   reswr_init ();
1040
1041   switch (output_format)
1042     {
1043     default:
1044       abort ();
1045     case RES_FORMAT_RC:
1046       write_rc_file (output_filename, resources);
1047       break;
1048     case RES_FORMAT_RES:
1049       write_res_file (output_filename, resources);
1050       break;
1051     case RES_FORMAT_COFF:
1052       write_coff_file (output_filename, target, resources);
1053       break;
1054     }
1055
1056   xexit (0);
1057   return 0;
1058 }
1059
1060 static int
1061 find_arch_match(const char *tname,const char **arch)
1062 {
1063   while (*arch != NULL)
1064     {
1065       const char *in_a = strstr (*arch, tname);
1066       char end_ch = (in_a ? in_a[strlen(tname)] : 0);
1067
1068       if (in_a && (in_a == *arch || in_a[-1] == ':')
1069           && end_ch == 0)
1070         {
1071           def_target_arch = *arch;
1072           return 1;
1073         }
1074       arch++;
1075     }
1076   return 0;
1077 }
1078
1079 static void
1080 set_endianess (bfd *abfd, const char *target)
1081 {
1082   const bfd_target *target_vec;
1083
1084   def_target_arch = NULL;
1085   target_vec = bfd_find_target (target, abfd);
1086   if (! target_vec)
1087     fatal ("Can't detect target endianess and architecture.");
1088   target_is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? 1 : 0);
1089
1090   {
1091     const char *  tname = target_vec->name;
1092     const char ** arches = bfd_arch_list();
1093
1094     if (arches && tname)
1095       {
1096         char *hyp = strchr (tname, '-');
1097
1098         if (hyp != NULL)
1099           {
1100             tname = ++hyp;
1101
1102             /* Make sure we dectect architecture names
1103                for triplets like "pe-arm-wince-little".  */
1104             if (!find_arch_match (tname, arches))
1105               {
1106                 char *new_tname = (char *) alloca (strlen (hyp) + 1);
1107                 strcpy (new_tname, hyp);
1108                 while ((hyp = strrchr (new_tname, '-')) != NULL)
1109                   {
1110                     *hyp = 0;
1111                     if (find_arch_match (new_tname, arches))
1112                       break;
1113                   }
1114               }
1115           }
1116         else
1117           find_arch_match (tname, arches);
1118       }
1119
1120     free (arches);
1121
1122     if (! def_target_arch)
1123       fatal ("Can't detect architecture.");
1124   }
1125 }
1126
1127 bfd *
1128 windres_open_as_binary (const char *filename, int rdmode)
1129 {
1130   bfd *abfd;
1131
1132   abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary"));
1133   if (! abfd)
1134     fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output"));
1135
1136   if (rdmode && ! bfd_check_format (abfd, bfd_object))
1137     fatal ("can't open `%s' for input.", filename);
1138   
1139   return abfd;
1140 }
1141
1142 void
1143 set_windres_bfd_endianess (windres_bfd *wrbfd, int is_bigendian)
1144 {
1145   assert (!! wrbfd);
1146   switch (WR_KIND(wrbfd))
1147   {
1148   case WR_KIND_BFD_BIN_L:
1149     if (is_bigendian)
1150       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_B;
1151     break;
1152   case WR_KIND_BFD_BIN_B:
1153     if (! is_bigendian)
1154       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_L;
1155     break;
1156   default:
1157     /* only binary bfd can be overriden. */
1158     abort ();
1159   }
1160 }
1161
1162 void
1163 set_windres_bfd (windres_bfd *wrbfd, bfd *abfd, asection *sec, rc_uint_type kind)
1164 {
1165   assert (!! wrbfd);
1166   switch (kind)
1167   {
1168   case WR_KIND_TARGET:
1169     abfd = NULL;
1170     sec = NULL;
1171     break;
1172   case WR_KIND_BFD:
1173   case WR_KIND_BFD_BIN_L:
1174   case WR_KIND_BFD_BIN_B:
1175     assert (!! abfd);
1176     assert (!!sec);
1177     break;
1178   default:
1179     abort ();
1180   }
1181   WR_KIND(wrbfd) = kind;
1182   WR_BFD(wrbfd) = abfd;
1183   WR_SECTION(wrbfd) = sec;
1184 }
1185
1186 void
1187 set_windres_bfd_content (windres_bfd *wrbfd, const void *data, rc_uint_type off,
1188                          rc_uint_type length)
1189 {
1190   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
1191     {
1192       if (! bfd_set_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
1193         bfd_fatal ("bfd_set_section_contents");
1194     }
1195   else
1196     abort ();
1197 }
1198
1199 void
1200 get_windres_bfd_content (windres_bfd *wrbfd, void *data, rc_uint_type off,
1201                          rc_uint_type length)
1202 {
1203   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
1204     {
1205       if (! bfd_get_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
1206         bfd_fatal ("bfd_get_section_contents");
1207     }
1208   else
1209     abort ();
1210 }
1211
1212 void
1213 windres_put_8 (windres_bfd *wrbfd, void *p, rc_uint_type value)
1214 {
1215   switch (WR_KIND(wrbfd))
1216     {
1217     case WR_KIND_TARGET:
1218       target_put_8 (p, value);
1219       break;
1220     case WR_KIND_BFD:
1221     case WR_KIND_BFD_BIN_L:
1222     case WR_KIND_BFD_BIN_B:
1223       bfd_put_8 (WR_BFD(wrbfd), value, p);
1224       break;
1225     default:
1226       abort ();
1227     }
1228 }
1229
1230 void
1231 windres_put_16 (windres_bfd *wrbfd, void *data, rc_uint_type value)
1232 {
1233   switch (WR_KIND(wrbfd))
1234     {
1235     case WR_KIND_TARGET:
1236       target_put_16 (data, value);
1237       break;
1238     case WR_KIND_BFD:
1239     case WR_KIND_BFD_BIN_B:
1240       bfd_put_16 (WR_BFD(wrbfd), value, data);
1241       break;
1242     case WR_KIND_BFD_BIN_L:
1243       bfd_putl16 (value, data);
1244       break;
1245     default:
1246       abort ();
1247     }
1248 }
1249
1250 void
1251 windres_put_32 (windres_bfd *wrbfd, void *data, rc_uint_type value)
1252 {
1253   switch (WR_KIND(wrbfd))
1254     {
1255     case WR_KIND_TARGET:
1256       target_put_32 (data, value);
1257       break;
1258     case WR_KIND_BFD:
1259     case WR_KIND_BFD_BIN_B:
1260       bfd_put_32 (WR_BFD(wrbfd), value, data);
1261       break;
1262     case WR_KIND_BFD_BIN_L:
1263       bfd_putl32 (value, data);
1264       break;
1265     default:
1266       abort ();
1267     }
1268 }
1269
1270 rc_uint_type
1271 windres_get_8 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1272 {
1273   if (length < 1)
1274     fatal ("windres_get_8: unexpected eob.");
1275   switch (WR_KIND(wrbfd))
1276     {
1277     case WR_KIND_TARGET:
1278       return target_get_8 (data, length);
1279     case WR_KIND_BFD:
1280     case WR_KIND_BFD_BIN_B:
1281     case WR_KIND_BFD_BIN_L:
1282       return bfd_get_8 (WR_BFD(wrbfd), data);
1283     default:
1284       abort ();
1285     }
1286   return 0;
1287 }
1288
1289 rc_uint_type
1290 windres_get_16 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1291 {
1292   if (length < 2)
1293     fatal ("windres_get_16: unexpected eob.");
1294   switch (WR_KIND(wrbfd))
1295     {
1296     case WR_KIND_TARGET:
1297       return target_get_16 (data, length);
1298     case WR_KIND_BFD:
1299     case WR_KIND_BFD_BIN_B:
1300       return bfd_get_16 (WR_BFD(wrbfd), data);
1301     case WR_KIND_BFD_BIN_L:
1302       return bfd_getl16 (data);
1303     default:
1304       abort ();
1305     }
1306   return 0;
1307 }
1308
1309 rc_uint_type
1310 windres_get_32 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1311 {
1312   if (length < 4)
1313     fatal ("windres_get_32: unexpected eob.");
1314   switch (WR_KIND(wrbfd))
1315     {
1316     case WR_KIND_TARGET:
1317       return target_get_32 (data, length);
1318     case WR_KIND_BFD:
1319     case WR_KIND_BFD_BIN_B:
1320       return bfd_get_32 (WR_BFD(wrbfd), data);
1321     case WR_KIND_BFD_BIN_L:
1322       return bfd_getl32 (data);
1323     default:
1324       abort ();
1325     }
1326   return 0;
1327 }
1328
1329 static rc_uint_type
1330 target_get_8 (const void *p, rc_uint_type length)
1331 {
1332   rc_uint_type ret;
1333   
1334   if (length < 1)
1335     fatal ("Resource too small for getting 8-bit value.");
1336
1337   ret = (rc_uint_type) *((const bfd_byte *) p);
1338   return ret & 0xff;
1339 }
1340
1341 static rc_uint_type
1342 target_get_16 (const void *p, rc_uint_type length)
1343 {
1344   if (length < 2)
1345     fatal ("Resource too small for getting 16-bit value.");
1346   
1347   if (target_is_bigendian)
1348     return bfd_getb16 (p);
1349   else
1350     return bfd_getl16 (p);
1351 }
1352
1353 static rc_uint_type
1354 target_get_32 (const void *p, rc_uint_type length)
1355 {
1356   if (length < 4)
1357     fatal ("Resource too small for getting 32-bit value.");
1358   
1359   if (target_is_bigendian)
1360     return bfd_getb32 (p);
1361   else
1362     return bfd_getl32 (p);
1363 }
1364
1365 static void
1366 target_put_8 (void *p, rc_uint_type value)
1367 {
1368   assert (!! p);
1369   *((bfd_byte *) p)=(bfd_byte) value;
1370 }
1371
1372 static void
1373 target_put_16 (void *p, rc_uint_type value)
1374 {
1375   assert (!! p);
1376   
1377   if (target_is_bigendian)
1378     bfd_putb16 (value, p);
1379   else
1380     bfd_putl16 (value, p);
1381 }
1382
1383 static void
1384 target_put_32 (void *p, rc_uint_type value)
1385 {
1386   assert (!! p);
1387   
1388   if (target_is_bigendian)
1389     bfd_putb32 (value, p);
1390   else
1391     bfd_putl32 (value, p);
1392 }
1393
1394 static int isInComment = 0;
1395
1396 int wr_printcomment (FILE *e, const char *fmt, ...)
1397 {
1398   va_list arg;
1399   int r = 0;
1400
1401   if (isInComment)
1402     r += fprintf (e, "\n   ");
1403   else
1404     fprintf (e, "/* ");
1405   isInComment = 1;
1406   if (fmt == NULL)
1407     return r;
1408   va_start (arg, fmt);
1409   r += vfprintf (e, fmt, arg);
1410   va_end (arg);
1411   return r;
1412 }
1413
1414 int wr_print (FILE *e, const char *fmt, ...)
1415 {
1416   va_list arg;
1417   int r = 0;
1418   if (isInComment)
1419     r += fprintf (e, ".  */\n");
1420   isInComment = 0;
1421   if (! fmt)
1422     return r;
1423   va_start (arg, fmt);
1424   r += vfprintf (e, fmt, arg);
1425   va_end (arg);
1426   return r;    
1427 }