OSDN Git Service

Updated Russian translation.
[pf3gnuchains/pf3gnuchains3x.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 void
1061 set_endianess (bfd *abfd, const char *target)
1062 {
1063   const bfd_target *target_vec;
1064
1065   def_target_arch = NULL;
1066   target_vec = bfd_get_target_info (target, abfd, &target_is_bigendian, NULL,
1067                                    &def_target_arch);
1068   if (! target_vec)
1069     fatal ("Can't detect target endianess and architecture.");
1070   if (! def_target_arch)
1071     fatal ("Can't detect architecture.");
1072 }
1073
1074 bfd *
1075 windres_open_as_binary (const char *filename, int rdmode)
1076 {
1077   bfd *abfd;
1078
1079   abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary"));
1080   if (! abfd)
1081     fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output"));
1082
1083   if (rdmode && ! bfd_check_format (abfd, bfd_object))
1084     fatal ("can't open `%s' for input.", filename);
1085   
1086   return abfd;
1087 }
1088
1089 void
1090 set_windres_bfd_endianess (windres_bfd *wrbfd, int is_bigendian)
1091 {
1092   assert (!! wrbfd);
1093   switch (WR_KIND(wrbfd))
1094   {
1095   case WR_KIND_BFD_BIN_L:
1096     if (is_bigendian)
1097       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_B;
1098     break;
1099   case WR_KIND_BFD_BIN_B:
1100     if (! is_bigendian)
1101       WR_KIND(wrbfd) = WR_KIND_BFD_BIN_L;
1102     break;
1103   default:
1104     /* only binary bfd can be overriden. */
1105     abort ();
1106   }
1107 }
1108
1109 void
1110 set_windres_bfd (windres_bfd *wrbfd, bfd *abfd, asection *sec, rc_uint_type kind)
1111 {
1112   assert (!! wrbfd);
1113   switch (kind)
1114   {
1115   case WR_KIND_TARGET:
1116     abfd = NULL;
1117     sec = NULL;
1118     break;
1119   case WR_KIND_BFD:
1120   case WR_KIND_BFD_BIN_L:
1121   case WR_KIND_BFD_BIN_B:
1122     assert (!! abfd);
1123     assert (!!sec);
1124     break;
1125   default:
1126     abort ();
1127   }
1128   WR_KIND(wrbfd) = kind;
1129   WR_BFD(wrbfd) = abfd;
1130   WR_SECTION(wrbfd) = sec;
1131 }
1132
1133 void
1134 set_windres_bfd_content (windres_bfd *wrbfd, const void *data, rc_uint_type off,
1135                          rc_uint_type length)
1136 {
1137   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
1138     {
1139       if (! bfd_set_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
1140         bfd_fatal ("bfd_set_section_contents");
1141     }
1142   else
1143     abort ();
1144 }
1145
1146 void
1147 get_windres_bfd_content (windres_bfd *wrbfd, void *data, rc_uint_type off,
1148                          rc_uint_type length)
1149 {
1150   if (WR_KIND(wrbfd) != WR_KIND_TARGET)
1151     {
1152       if (! bfd_get_section_contents (WR_BFD(wrbfd), WR_SECTION(wrbfd), data, off, length))
1153         bfd_fatal ("bfd_get_section_contents");
1154     }
1155   else
1156     abort ();
1157 }
1158
1159 void
1160 windres_put_8 (windres_bfd *wrbfd, void *p, rc_uint_type value)
1161 {
1162   switch (WR_KIND(wrbfd))
1163     {
1164     case WR_KIND_TARGET:
1165       target_put_8 (p, value);
1166       break;
1167     case WR_KIND_BFD:
1168     case WR_KIND_BFD_BIN_L:
1169     case WR_KIND_BFD_BIN_B:
1170       bfd_put_8 (WR_BFD(wrbfd), value, p);
1171       break;
1172     default:
1173       abort ();
1174     }
1175 }
1176
1177 void
1178 windres_put_16 (windres_bfd *wrbfd, void *data, rc_uint_type value)
1179 {
1180   switch (WR_KIND(wrbfd))
1181     {
1182     case WR_KIND_TARGET:
1183       target_put_16 (data, value);
1184       break;
1185     case WR_KIND_BFD:
1186     case WR_KIND_BFD_BIN_B:
1187       bfd_put_16 (WR_BFD(wrbfd), value, data);
1188       break;
1189     case WR_KIND_BFD_BIN_L:
1190       bfd_putl16 (value, data);
1191       break;
1192     default:
1193       abort ();
1194     }
1195 }
1196
1197 void
1198 windres_put_32 (windres_bfd *wrbfd, void *data, rc_uint_type value)
1199 {
1200   switch (WR_KIND(wrbfd))
1201     {
1202     case WR_KIND_TARGET:
1203       target_put_32 (data, value);
1204       break;
1205     case WR_KIND_BFD:
1206     case WR_KIND_BFD_BIN_B:
1207       bfd_put_32 (WR_BFD(wrbfd), value, data);
1208       break;
1209     case WR_KIND_BFD_BIN_L:
1210       bfd_putl32 (value, data);
1211       break;
1212     default:
1213       abort ();
1214     }
1215 }
1216
1217 rc_uint_type
1218 windres_get_8 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1219 {
1220   if (length < 1)
1221     fatal ("windres_get_8: unexpected eob.");
1222   switch (WR_KIND(wrbfd))
1223     {
1224     case WR_KIND_TARGET:
1225       return target_get_8 (data, length);
1226     case WR_KIND_BFD:
1227     case WR_KIND_BFD_BIN_B:
1228     case WR_KIND_BFD_BIN_L:
1229       return bfd_get_8 (WR_BFD(wrbfd), data);
1230     default:
1231       abort ();
1232     }
1233   return 0;
1234 }
1235
1236 rc_uint_type
1237 windres_get_16 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1238 {
1239   if (length < 2)
1240     fatal ("windres_get_16: unexpected eob.");
1241   switch (WR_KIND(wrbfd))
1242     {
1243     case WR_KIND_TARGET:
1244       return target_get_16 (data, length);
1245     case WR_KIND_BFD:
1246     case WR_KIND_BFD_BIN_B:
1247       return bfd_get_16 (WR_BFD(wrbfd), data);
1248     case WR_KIND_BFD_BIN_L:
1249       return bfd_getl16 (data);
1250     default:
1251       abort ();
1252     }
1253   return 0;
1254 }
1255
1256 rc_uint_type
1257 windres_get_32 (windres_bfd *wrbfd, const void *data, rc_uint_type length)
1258 {
1259   if (length < 4)
1260     fatal ("windres_get_32: unexpected eob.");
1261   switch (WR_KIND(wrbfd))
1262     {
1263     case WR_KIND_TARGET:
1264       return target_get_32 (data, length);
1265     case WR_KIND_BFD:
1266     case WR_KIND_BFD_BIN_B:
1267       return bfd_get_32 (WR_BFD(wrbfd), data);
1268     case WR_KIND_BFD_BIN_L:
1269       return bfd_getl32 (data);
1270     default:
1271       abort ();
1272     }
1273   return 0;
1274 }
1275
1276 static rc_uint_type
1277 target_get_8 (const void *p, rc_uint_type length)
1278 {
1279   rc_uint_type ret;
1280   
1281   if (length < 1)
1282     fatal ("Resource too small for getting 8-bit value.");
1283
1284   ret = (rc_uint_type) *((const bfd_byte *) p);
1285   return ret & 0xff;
1286 }
1287
1288 static rc_uint_type
1289 target_get_16 (const void *p, rc_uint_type length)
1290 {
1291   if (length < 2)
1292     fatal ("Resource too small for getting 16-bit value.");
1293   
1294   if (target_is_bigendian)
1295     return bfd_getb16 (p);
1296   else
1297     return bfd_getl16 (p);
1298 }
1299
1300 static rc_uint_type
1301 target_get_32 (const void *p, rc_uint_type length)
1302 {
1303   if (length < 4)
1304     fatal ("Resource too small for getting 32-bit value.");
1305   
1306   if (target_is_bigendian)
1307     return bfd_getb32 (p);
1308   else
1309     return bfd_getl32 (p);
1310 }
1311
1312 static void
1313 target_put_8 (void *p, rc_uint_type value)
1314 {
1315   assert (!! p);
1316   *((bfd_byte *) p)=(bfd_byte) value;
1317 }
1318
1319 static void
1320 target_put_16 (void *p, rc_uint_type value)
1321 {
1322   assert (!! p);
1323   
1324   if (target_is_bigendian)
1325     bfd_putb16 (value, p);
1326   else
1327     bfd_putl16 (value, p);
1328 }
1329
1330 static void
1331 target_put_32 (void *p, rc_uint_type value)
1332 {
1333   assert (!! p);
1334   
1335   if (target_is_bigendian)
1336     bfd_putb32 (value, p);
1337   else
1338     bfd_putl32 (value, p);
1339 }
1340
1341 static int isInComment = 0;
1342
1343 int wr_printcomment (FILE *e, const char *fmt, ...)
1344 {
1345   va_list arg;
1346   int r = 0;
1347
1348   if (isInComment)
1349     r += fprintf (e, "\n   ");
1350   else
1351     fprintf (e, "/* ");
1352   isInComment = 1;
1353   if (fmt == NULL)
1354     return r;
1355   va_start (arg, fmt);
1356   r += vfprintf (e, fmt, arg);
1357   va_end (arg);
1358   return r;
1359 }
1360
1361 int wr_print (FILE *e, const char *fmt, ...)
1362 {
1363   va_list arg;
1364   int r = 0;
1365   if (isInComment)
1366     r += fprintf (e, ".  */\n");
1367   isInComment = 0;
1368   if (! fmt)
1369     return r;
1370   va_start (arg, fmt);
1371   r += vfprintf (e, fmt, arg);
1372   va_end (arg);
1373   return r;    
1374 }