xref: /netbsd-src/external/gpl3/binutils/dist/binutils/windres.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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 
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 
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 
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 
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 
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 
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 }
1414