1 /* windres.c -- a program to manipulate Windows resources
2    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5 
6    This file is part of GNU Binutils.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22 
23 /* This program can read and write Windows resources in various
24    formats.  In particular, it can act like the rc resource compiler
25    program, and it can act like the cvtres res to COFF conversion
26    program.
27 
28    It is based on information taken from the following sources:
29 
30    * Microsoft documentation.
31 
32    * The rcl program, written by Gunther Ebert
33      <gunther.ebert@ixos-leipzig.de>.
34 
35    * The res2coff program, written by Pedro A. Aranda <paag@tid.es>.  */
36 
37 #include "config.h"
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41 #include <assert.h>
42 #include <time.h>
43 #include "bfd.h"
44 #include "getopt.h"
45 #include "bucomm.h"
46 #include "libiberty.h"
47 #include "safe-ctype.h"
48 #include "obstack.h"
49 #include "windres.h"
50 
51 /* Used by resrc.c at least.  */
52 
53 int verbose = 0;
54 
55 /* An enumeration of format types.  */
56 
57 enum res_format
58 {
59   /* Unknown format.  */
60   RES_FORMAT_UNKNOWN,
61   /* Textual RC file.  */
62   RES_FORMAT_RC,
63   /* Binary RES file.  */
64   RES_FORMAT_RES,
65   /* COFF file.  */
66   RES_FORMAT_COFF
67 };
68 
69 /* A structure used to map between format types and strings.  */
70 
71 struct format_map
72 {
73   const char *name;
74   enum res_format format;
75 };
76 
77 /* A mapping between names and format types.  */
78 
79 static const struct format_map format_names[] =
80 {
81   { "rc", RES_FORMAT_RC },
82   { "res", RES_FORMAT_RES },
83   { "coff", RES_FORMAT_COFF },
84   { NULL, RES_FORMAT_UNKNOWN }
85 };
86 
87 /* A mapping from file extensions to format types.  */
88 
89 static const struct format_map format_fileexts[] =
90 {
91   { "rc", RES_FORMAT_RC },
92   { "res", RES_FORMAT_RES },
93   { "exe", RES_FORMAT_COFF },
94   { "obj", RES_FORMAT_COFF },
95   { "o", RES_FORMAT_COFF },
96   { NULL, RES_FORMAT_UNKNOWN }
97 };
98 
99 /* A list of include directories.  */
100 
101 struct include_dir
102 {
103   struct include_dir *next;
104   char *dir;
105 };
106 
107 static struct include_dir *include_dirs;
108 
109 /* Static functions.  */
110 
111 static void res_init (void);
112 static int extended_menuitems (const struct menuitem *);
113 static enum res_format format_from_name (const char *, int);
114 static enum res_format format_from_filename (const char *, int);
115 static void usage (FILE *, int);
116 static int cmp_res_entry (const void *, const void *);
117 static struct res_directory *sort_resources (struct res_directory *);
118 static void reswr_init (void);
119 static const char * quot (const char *);
120 
121 /* When we are building a resource tree, we allocate everything onto
122    an obstack, so that we can free it all at once if we want.  */
123 
124 #define obstack_chunk_alloc xmalloc
125 #define obstack_chunk_free free
126 
127 /* The resource building obstack.  */
128 
129 static struct obstack res_obstack;
130 
131 /* Initialize the resource building obstack.  */
132 
133 static void
res_init(void)134 res_init (void)
135 {
136   obstack_init (&res_obstack);
137 }
138 
139 /* Allocate space on the resource building obstack.  */
140 
141 void *
res_alloc(size_t bytes)142 res_alloc (size_t bytes)
143 {
144   return (void *) obstack_alloc (&res_obstack, bytes);
145 }
146 
147 /* We also use an obstack to save memory used while writing out a set
148    of resources.  */
149 
150 static struct obstack reswr_obstack;
151 
152 /* Initialize the resource writing obstack.  */
153 
154 static void
reswr_init(void)155 reswr_init (void)
156 {
157   obstack_init (&reswr_obstack);
158 }
159 
160 /* Allocate space on the resource writing obstack.  */
161 
162 void *
reswr_alloc(size_t bytes)163 reswr_alloc (size_t bytes)
164 {
165   return (void *) obstack_alloc (&reswr_obstack, bytes);
166 }
167 
168 /* Open a file using the include directory search list.  */
169 
170 FILE *
open_file_search(const char * filename,const char * mode,const char * errmsg,char ** real_filename)171 open_file_search (const char *filename, const char *mode, const char *errmsg,
172 		  char **real_filename)
173 {
174   FILE *e;
175   struct include_dir *d;
176 
177   e = fopen (filename, mode);
178   if (e != NULL)
179     {
180       *real_filename = xstrdup (filename);
181       return e;
182     }
183 
184   if (errno == ENOENT)
185     {
186       for (d = include_dirs; d != NULL; d = d->next)
187 	{
188 	  char *n;
189 
190 	  n = (char *) xmalloc (strlen (d->dir) + strlen (filename) + 2);
191 	  sprintf (n, "%s/%s", d->dir, filename);
192 	  e = fopen (n, mode);
193 	  if (e != NULL)
194 	    {
195 	      *real_filename = n;
196 	      return e;
197 	    }
198 
199 	  if (errno != ENOENT)
200 	    break;
201 	}
202     }
203 
204   fatal (_("can't open %s `%s': %s"), errmsg, filename, strerror (errno));
205 
206   /* Return a value to avoid a compiler warning.  */
207   return NULL;
208 }
209 
210 /* Compare two resource ID's.  We consider name entries to come before
211    numeric entries, because that is how they appear in the COFF .rsrc
212    section.  */
213 
214 int
res_id_cmp(struct res_id a,struct res_id b)215 res_id_cmp (struct res_id a, struct res_id b)
216 {
217   if (! a.named)
218     {
219       if (b.named)
220 	return 1;
221       if (a.u.id > b.u.id)
222 	return 1;
223       else if (a.u.id < b.u.id)
224 	return -1;
225       else
226 	return 0;
227     }
228   else
229     {
230       unichar *as, *ase, *bs, *bse;
231 
232       if (! b.named)
233 	return -1;
234 
235       as = a.u.n.name;
236       ase = as + a.u.n.length;
237       bs = b.u.n.name;
238       bse = bs + b.u.n.length;
239 
240       while (as < ase)
241 	{
242 	  int i;
243 
244 	  if (bs >= bse)
245 	    return 1;
246 	  i = (int) *as - (int) *bs;
247 	  if (i != 0)
248 	    return i;
249 	  ++as;
250 	  ++bs;
251 	}
252 
253       if (bs < bse)
254 	return -1;
255 
256       return 0;
257     }
258 }
259 
260 /* Print a resource ID.  */
261 
262 void
res_id_print(FILE * stream,struct res_id id,int quote)263 res_id_print (FILE *stream, struct res_id id, int quote)
264 {
265   if (! id.named)
266     fprintf (stream, "%lu", id.u.id);
267   else
268     {
269       if (quote)
270 	putc ('"', stream);
271       unicode_print (stream, id.u.n.name, id.u.n.length);
272       if (quote)
273 	putc ('"', stream);
274     }
275 }
276 
277 /* Print a list of resource ID's.  */
278 
279 void
res_ids_print(FILE * stream,int cids,const struct res_id * ids)280 res_ids_print (FILE *stream, int cids, const struct res_id *ids)
281 {
282   int i;
283 
284   for (i = 0; i < cids; i++)
285     {
286       res_id_print (stream, ids[i], 1);
287       if (i + 1 < cids)
288 	fprintf (stream, ": ");
289     }
290 }
291 
292 /* Convert an ASCII string to a resource ID.  */
293 
294 void
res_string_to_id(struct res_id * res_id,const char * string)295 res_string_to_id (struct res_id *res_id, const char *string)
296 {
297   res_id->named = 1;
298   unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string);
299 }
300 
301 /* Define a resource.  The arguments are the resource tree, RESOURCES,
302    and the location at which to put it in the tree, CIDS and IDS.
303    This returns a newly allocated res_resource structure, which the
304    caller is expected to initialize.  If DUPOK is non-zero, then if a
305    resource with this ID exists, it is returned.  Otherwise, a warning
306    is issued, and a new resource is created replacing the existing
307    one.  */
308 
309 struct res_resource *
define_resource(struct res_directory ** resources,int cids,const struct res_id * ids,int dupok)310 define_resource (struct res_directory **resources, int cids,
311 		 const struct res_id *ids, int dupok)
312 {
313   struct res_entry *re = NULL;
314   int i;
315 
316   assert (cids > 0);
317   for (i = 0; i < cids; i++)
318     {
319       struct res_entry **pp;
320 
321       if (*resources == NULL)
322 	{
323 	  static unsigned long timeval;
324 
325 	  /* Use the same timestamp for every resource created in a
326              single run.  */
327 	  if (timeval == 0)
328 	    timeval = time (NULL);
329 
330 	  *resources = ((struct res_directory *)
331 			res_alloc (sizeof **resources));
332 	  (*resources)->characteristics = 0;
333 	  (*resources)->time = timeval;
334 	  (*resources)->major = 0;
335 	  (*resources)->minor = 0;
336 	  (*resources)->entries = NULL;
337 	}
338 
339       for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
340 	if (res_id_cmp ((*pp)->id, ids[i]) == 0)
341 	  break;
342 
343       if (*pp != NULL)
344 	re = *pp;
345       else
346 	{
347 	  re = (struct res_entry *) res_alloc (sizeof *re);
348 	  re->next = NULL;
349 	  re->id = ids[i];
350 	  if ((i + 1) < cids)
351 	    {
352 	      re->subdir = 1;
353 	      re->u.dir = NULL;
354 	    }
355 	  else
356 	    {
357 	      re->subdir = 0;
358 	      re->u.res = NULL;
359 	    }
360 
361 	  *pp = re;
362 	}
363 
364       if ((i + 1) < cids)
365 	{
366 	  if (! re->subdir)
367 	    {
368 	      fprintf (stderr, "%s: ", program_name);
369 	      res_ids_print (stderr, i, ids);
370 	      fprintf (stderr, _(": expected to be a directory\n"));
371 	      xexit (1);
372 	    }
373 
374 	  resources = &re->u.dir;
375 	}
376     }
377 
378   if (re->subdir)
379     {
380       fprintf (stderr, "%s: ", program_name);
381       res_ids_print (stderr, cids, ids);
382       fprintf (stderr, _(": expected to be a leaf\n"));
383       xexit (1);
384     }
385 
386   if (re->u.res != NULL)
387     {
388       if (dupok)
389 	return re->u.res;
390 
391       fprintf (stderr, _("%s: warning: "), program_name);
392       res_ids_print (stderr, cids, ids);
393       fprintf (stderr, _(": duplicate value\n"));
394     }
395 
396   re->u.res = ((struct res_resource *)
397 	       res_alloc (sizeof (struct res_resource)));
398   memset (re->u.res, 0, sizeof (struct res_resource));
399 
400   re->u.res->type = RES_TYPE_UNINITIALIZED;
401   return re->u.res;
402 }
403 
404 /* Define a standard resource.  This is a version of define_resource
405    that just takes type, name, and language arguments.  */
406 
407 struct res_resource *
define_standard_resource(struct res_directory ** resources,int type,struct res_id name,int language,int dupok)408 define_standard_resource (struct res_directory **resources, int type,
409 			  struct res_id name, int language, int dupok)
410 {
411   struct res_id a[3];
412 
413   a[0].named = 0;
414   a[0].u.id = type;
415   a[1] = name;
416   a[2].named = 0;
417   a[2].u.id = language;
418   return define_resource (resources, 3, a, dupok);
419 }
420 
421 /* Comparison routine for resource sorting.  */
422 
423 static int
cmp_res_entry(const void * p1,const void * p2)424 cmp_res_entry (const void *p1, const void *p2)
425 {
426   const struct res_entry **re1, **re2;
427 
428   re1 = (const struct res_entry **) p1;
429   re2 = (const struct res_entry **) p2;
430   return res_id_cmp ((*re1)->id, (*re2)->id);
431 }
432 
433 /* Sort the resources.  */
434 
435 static struct res_directory *
sort_resources(struct res_directory * resdir)436 sort_resources (struct res_directory *resdir)
437 {
438   int c, i;
439   struct res_entry *re;
440   struct res_entry **a;
441 
442   if (resdir->entries == NULL)
443     return resdir;
444 
445   c = 0;
446   for (re = resdir->entries; re != NULL; re = re->next)
447     ++c;
448 
449   /* This is a recursive routine, so using xmalloc is probably better
450      than alloca.  */
451   a = (struct res_entry **) xmalloc (c * sizeof (struct res_entry *));
452 
453   for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++)
454     a[i] = re;
455 
456   qsort (a, c, sizeof (struct res_entry *), cmp_res_entry);
457 
458   resdir->entries = a[0];
459   for (i = 0; i < c - 1; i++)
460     a[i]->next = a[i + 1];
461   a[i]->next = NULL;
462 
463   free (a);
464 
465   /* Now sort the subdirectories.  */
466 
467   for (re = resdir->entries; re != NULL; re = re->next)
468     if (re->subdir)
469       re->u.dir = sort_resources (re->u.dir);
470 
471   return resdir;
472 }
473 
474 /* Return whether the dialog resource DIALOG is a DIALOG or a
475    DIALOGEX.  */
476 
477 int
extended_dialog(const struct dialog * dialog)478 extended_dialog (const struct dialog *dialog)
479 {
480   const struct dialog_control *c;
481 
482   if (dialog->ex != NULL)
483     return 1;
484 
485   for (c = dialog->controls; c != NULL; c = c->next)
486     if (c->data != NULL || c->help != 0)
487       return 1;
488 
489   return 0;
490 }
491 
492 /* Return whether MENUITEMS are a MENU or a MENUEX.  */
493 
494 int
extended_menu(const struct menu * menu)495 extended_menu (const struct menu *menu)
496 {
497   return extended_menuitems (menu->items);
498 }
499 
500 static int
extended_menuitems(const struct menuitem * menuitems)501 extended_menuitems (const struct menuitem *menuitems)
502 {
503   const struct menuitem *mi;
504 
505   for (mi = menuitems; mi != NULL; mi = mi->next)
506     {
507       if (mi->help != 0 || mi->state != 0)
508 	return 1;
509       if (mi->popup != NULL && mi->id != 0)
510 	return 1;
511       if ((mi->type
512 	   & ~ (MENUITEM_CHECKED
513 		| MENUITEM_GRAYED
514 		| MENUITEM_HELP
515 		| MENUITEM_INACTIVE
516 		| MENUITEM_MENUBARBREAK
517 		| MENUITEM_MENUBREAK))
518 	  != 0)
519 	return 1;
520       if (mi->popup != NULL)
521 	{
522 	  if (extended_menuitems (mi->popup))
523 	    return 1;
524 	}
525     }
526 
527   return 0;
528 }
529 
530 /* Convert a string to a format type, or exit if it can't be done.  */
531 
532 static enum res_format
format_from_name(const char * name,int exit_on_error)533 format_from_name (const char *name, int exit_on_error)
534 {
535   const struct format_map *m;
536 
537   for (m = format_names; m->name != NULL; m++)
538     if (strcasecmp (m->name, name) == 0)
539       break;
540 
541   if (m->name == NULL && exit_on_error)
542     {
543       non_fatal (_("unknown format type `%s'"), name);
544       fprintf (stderr, _("%s: supported formats:"), program_name);
545       for (m = format_names; m->name != NULL; m++)
546 	fprintf (stderr, " %s", m->name);
547       fprintf (stderr, "\n");
548       xexit (1);
549     }
550 
551   return m->format;
552 }
553 
554 /* Work out a format type given a file name.  If INPUT is non-zero,
555    it's OK to look at the file itself.  */
556 
557 static enum res_format
format_from_filename(const char * filename,int input)558 format_from_filename (const char *filename, int input)
559 {
560   const char *ext;
561   FILE *e;
562   unsigned char b1, b2, b3, b4, b5;
563   int magic;
564 
565   /* If we have an extension, see if we recognize it as implying a
566      particular format.  */
567   ext = strrchr (filename, '.');
568   if (ext != NULL)
569     {
570       const struct format_map *m;
571 
572       ++ext;
573       for (m = format_fileexts; m->name != NULL; m++)
574 	if (strcasecmp (m->name, ext) == 0)
575 	  return m->format;
576     }
577 
578   /* If we don't recognize the name of an output file, assume it's a
579      COFF file.  */
580   if (! input)
581     return RES_FORMAT_COFF;
582 
583   /* Read the first few bytes of the file to see if we can guess what
584      it is.  */
585   e = fopen (filename, FOPEN_RB);
586   if (e == NULL)
587     fatal ("%s: %s", filename, strerror (errno));
588 
589   b1 = getc (e);
590   b2 = getc (e);
591   b3 = getc (e);
592   b4 = getc (e);
593   b5 = getc (e);
594 
595   fclose (e);
596 
597   /* A PE executable starts with 0x4d 0x5a.  */
598   if (b1 == 0x4d && b2 == 0x5a)
599     return RES_FORMAT_COFF;
600 
601   /* A COFF .o file starts with a COFF magic number.  */
602   magic = (b2 << 8) | b1;
603   switch (magic)
604     {
605     case 0x14c: /* i386 */
606     case 0x166: /* MIPS */
607     case 0x184: /* Alpha */
608     case 0x268: /* 68k */
609     case 0x1f0: /* PowerPC */
610     case 0x290: /* PA */
611       return RES_FORMAT_COFF;
612     }
613 
614   /* A RES file starts with 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0.  */
615   if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 && b5 == 0x20)
616     return RES_FORMAT_RES;
617 
618   /* If every character is printable or space, assume it's an RC file.  */
619   if ((ISPRINT (b1) || ISSPACE (b1))
620       && (ISPRINT (b2) || ISSPACE (b2))
621       && (ISPRINT (b3) || ISSPACE (b3))
622       && (ISPRINT (b4) || ISSPACE (b4))
623       && (ISPRINT (b5) || ISSPACE (b5)))
624     return RES_FORMAT_RC;
625 
626   /* Otherwise, we give up.  */
627   fatal (_("can not determine type of file `%s'; use the -J option"),
628 	 filename);
629 
630   /* Return something to silence the compiler warning.  */
631   return RES_FORMAT_UNKNOWN;
632 }
633 
634 /* Print a usage message and exit.  */
635 
636 static void
usage(FILE * stream,int status)637 usage (FILE *stream, int status)
638 {
639   fprintf (stream, _("Usage: %s [option(s)] [input-file] [output-file]\n"),
640 	   program_name);
641   fprintf (stream, _(" The options are:\n\
642   -i --input=<file>            Name input file\n\
643   -o --output=<file>           Name output file\n\
644   -J --input-format=<format>   Specify input format\n\
645   -O --output-format=<format>  Specify output format\n\
646   -F --target=<target>         Specify COFF target\n\
647      --preprocessor=<program>  Program to use to preprocess rc file\n\
648   -I --include-dir=<dir>       Include directory when preprocessing rc file\n\
649   -D --define <sym>[=<val>]    Define SYM when preprocessing rc file\n\
650   -U --undefine <sym>          Undefine SYM when preprocessing rc file\n\
651   -v --verbose                 Verbose - tells you what it's doing\n\
652   -l --language=<val>          Set language when reading rc file\n\
653      --use-temp-file           Use a temporary file instead of popen to read\n\
654                                the preprocessor output\n\
655      --no-use-temp-file        Use popen (default)\n"));
656 #ifdef YYDEBUG
657   fprintf (stream, _("\
658      --yydebug                 Turn on parser debugging\n"));
659 #endif
660   fprintf (stream, _("\
661   -r                           Ignored for compatibility with rc\n\
662   @<file>                      Read options from <file>\n\
663   -h --help                    Print this help message\n\
664   -V --version                 Print version information\n"));
665   fprintf (stream, _("\
666 FORMAT is one of rc, res, or coff, and is deduced from the file name\n\
667 extension if not specified.  A single file name is an input file.\n\
668 No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"));
669 
670   list_supported_targets (program_name, stream);
671 
672   if (status == 0)
673     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
674 
675   exit (status);
676 }
677 
678 /* Quote characters that will confuse the shell when we run the preprocessor.  */
679 
680 static const char *
quot(const char * string)681 quot (const char *string)
682 {
683   static char *buf = 0;
684   static int buflen = 0;
685   int slen = strlen (string);
686   const char *src;
687   char *dest;
688 
689   if ((buflen < slen * 2 + 2) || !buf)
690     {
691       buflen = slen * 2 + 2;
692       if (buf)
693 	free (buf);
694       buf = (char *) xmalloc (buflen);
695     }
696 
697   for (src=string, dest=buf; *src; src++, dest++)
698     {
699       if (*src == '(' || *src == ')' || *src == ' ')
700 	*dest++ = '\\';
701       *dest = *src;
702     }
703   *dest = 0;
704   return buf;
705 }
706 
707 /* Long options.  */
708 
709 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
710 
711 #define OPTION_PREPROCESSOR	150
712 #define OPTION_USE_TEMP_FILE	(OPTION_PREPROCESSOR + 1)
713 #define OPTION_NO_USE_TEMP_FILE	(OPTION_USE_TEMP_FILE + 1)
714 #define OPTION_YYDEBUG		(OPTION_NO_USE_TEMP_FILE + 1)
715 
716 static const struct option long_options[] =
717 {
718   {"input", required_argument, 0, 'i'},
719   {"output", required_argument, 0, 'o'},
720   {"input-format", required_argument, 0, 'J'},
721   {"output-format", required_argument, 0, 'O'},
722   {"target", required_argument, 0, 'F'},
723   {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
724   {"include-dir", required_argument, 0, 'I'},
725   {"define", required_argument, 0, 'D'},
726   {"undefine", required_argument, 0, 'U'},
727   {"verbose", no_argument, 0, 'v'},
728   {"language", required_argument, 0, 'l'},
729   {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
730   {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
731   {"yydebug", no_argument, 0, OPTION_YYDEBUG},
732   {"version", no_argument, 0, 'V'},
733   {"help", no_argument, 0, 'h'},
734   {0, no_argument, 0, 0}
735 };
736 
737 /* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes.  */
738 int main (int, char **);
739 
740 /* The main function.  */
741 
742 int
main(int argc,char ** argv)743 main (int argc, char **argv)
744 {
745   int c;
746   char *input_filename;
747   char *output_filename;
748   enum res_format input_format;
749   enum res_format input_format_tmp;
750   enum res_format output_format;
751   char *target;
752   char *preprocessor;
753   char *preprocargs;
754   const char *quotedarg;
755   int language;
756   struct res_directory *resources;
757   int use_temp_file;
758 
759 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
760   setlocale (LC_MESSAGES, "");
761 #endif
762 #if defined (HAVE_SETLOCALE)
763   setlocale (LC_CTYPE, "");
764 #endif
765   bindtextdomain (PACKAGE, LOCALEDIR);
766   textdomain (PACKAGE);
767 
768   program_name = argv[0];
769   xmalloc_set_program_name (program_name);
770 
771   expandargv (&argc, &argv);
772 
773   bfd_init ();
774   set_default_bfd_target ();
775 
776   res_init ();
777 
778   input_filename = NULL;
779   output_filename = NULL;
780   input_format = RES_FORMAT_UNKNOWN;
781   output_format = RES_FORMAT_UNKNOWN;
782   target = NULL;
783   preprocessor = NULL;
784   preprocargs = NULL;
785   language = 0x409;   /* LANG_ENGLISH, SUBLANG_ENGLISH_US.  */
786   use_temp_file = 0;
787 
788   while ((c = getopt_long (argc, argv, "f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
789 			   (int *) 0)) != EOF)
790     {
791       switch (c)
792 	{
793 	case 'i':
794 	  input_filename = optarg;
795 	  break;
796 
797 	case 'f':
798 	  /* For compatibility with rc we accept "-fo <name>" as being the
799 	     equivalent of "-o <name>".  We do not advertise this fact
800 	     though, as we do not want users to use non-GNU like command
801 	     line switches.  */
802 	  if (*optarg != 'o')
803 	    fatal (_("invalid option -f\n"));
804 	  optarg++;
805 	  if (* optarg == 0)
806 	    {
807 	      if (optind == argc)
808 		fatal (_("No filename following the -fo option.\n"));
809 	      optarg = argv [optind++];
810 	    }
811 	  /* Fall through.  */
812 
813 	case 'o':
814 	  output_filename = optarg;
815 	  break;
816 
817 	case 'J':
818 	  input_format = format_from_name (optarg, 1);
819 	  break;
820 
821 	case 'O':
822 	  output_format = format_from_name (optarg, 1);
823 	  break;
824 
825 	case 'F':
826 	  target = optarg;
827 	  break;
828 
829 	case OPTION_PREPROCESSOR:
830 	  preprocessor = optarg;
831 	  break;
832 
833 	case 'D':
834 	case 'U':
835 	  if (preprocargs == NULL)
836 	    {
837 	      quotedarg = quot (optarg);
838 	      preprocargs = xmalloc (strlen (quotedarg) + 3);
839 	      sprintf (preprocargs, "-%c%s", c, quotedarg);
840 	    }
841 	  else
842 	    {
843 	      char *n;
844 
845 	      quotedarg = quot (optarg);
846 	      n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
847 	      sprintf (n, "%s -%c%s", preprocargs, c, quotedarg);
848 	      free (preprocargs);
849 	      preprocargs = n;
850 	    }
851 	  break;
852 
853 	case 'r':
854 	  /* Ignored for compatibility with rc.  */
855 	  break;
856 
857 	case 'v':
858 	  verbose ++;
859 	  break;
860 
861 	case 'I':
862 	  /* For backward compatibility, should be removed in the future.  */
863 	  input_format_tmp = format_from_name (optarg, 0);
864 	  if (input_format_tmp != RES_FORMAT_UNKNOWN)
865 	    {
866 	      fprintf (stderr, _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
867 	      input_format = input_format_tmp;
868 	      break;
869 	    }
870 
871 	  if (preprocargs == NULL)
872 	    {
873 	      quotedarg = quot (optarg);
874 	      preprocargs = xmalloc (strlen (quotedarg) + 3);
875 	      sprintf (preprocargs, "-I%s", quotedarg);
876 	    }
877 	  else
878 	    {
879 	      char *n;
880 
881 	      quotedarg = quot (optarg);
882 	      n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 4);
883 	      sprintf (n, "%s -I%s", preprocargs, quotedarg);
884 	      free (preprocargs);
885 	      preprocargs = n;
886 	    }
887 
888 	  {
889 	    struct include_dir *n, **pp;
890 
891 	    n = (struct include_dir *) xmalloc (sizeof *n);
892 	    n->next = NULL;
893 	    n->dir = optarg;
894 
895 	    for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
896 	      ;
897 	    *pp = n;
898 	  }
899 
900 	  break;
901 
902 	case 'l':
903 	  language = strtol (optarg, (char **) NULL, 16);
904 	  break;
905 
906 	case OPTION_USE_TEMP_FILE:
907 	  use_temp_file = 1;
908 	  break;
909 
910 	case OPTION_NO_USE_TEMP_FILE:
911 	  use_temp_file = 0;
912 	  break;
913 
914 #ifdef YYDEBUG
915 	case OPTION_YYDEBUG:
916 	  yydebug = 1;
917 	  break;
918 #endif
919 
920 	case 'h':
921 	case 'H':
922 	  usage (stdout, 0);
923 	  break;
924 
925 	case 'V':
926 	  print_version ("windres");
927 	  break;
928 
929 	default:
930 	  usage (stderr, 1);
931 	  break;
932 	}
933     }
934 
935   if (input_filename == NULL && optind < argc)
936     {
937       input_filename = argv[optind];
938       ++optind;
939     }
940 
941   if (output_filename == NULL && optind < argc)
942     {
943       output_filename = argv[optind];
944       ++optind;
945     }
946 
947   if (argc != optind)
948     usage (stderr, 1);
949 
950   if (input_format == RES_FORMAT_UNKNOWN)
951     {
952       if (input_filename == NULL)
953 	input_format = RES_FORMAT_RC;
954       else
955 	input_format = format_from_filename (input_filename, 1);
956     }
957 
958   if (output_format == RES_FORMAT_UNKNOWN)
959     {
960       if (output_filename == NULL)
961 	output_format = RES_FORMAT_RC;
962       else
963 	output_format = format_from_filename (output_filename, 0);
964     }
965 
966   /* Read the input file.  */
967   switch (input_format)
968     {
969     default:
970       abort ();
971     case RES_FORMAT_RC:
972       resources = read_rc_file (input_filename, preprocessor, preprocargs,
973 				language, use_temp_file);
974       break;
975     case RES_FORMAT_RES:
976       resources = read_res_file (input_filename);
977       break;
978     case RES_FORMAT_COFF:
979       resources = read_coff_rsrc (input_filename, target);
980       break;
981     }
982 
983   if (resources == NULL)
984     fatal (_("no resources"));
985 
986   /* Sort the resources.  This is required for COFF, convenient for
987      rc, and unimportant for res.  */
988   resources = sort_resources (resources);
989 
990   /* Write the output file.  */
991   reswr_init ();
992 
993   switch (output_format)
994     {
995     default:
996       abort ();
997     case RES_FORMAT_RC:
998       write_rc_file (output_filename, resources);
999       break;
1000     case RES_FORMAT_RES:
1001       write_res_file (output_filename, resources);
1002       break;
1003     case RES_FORMAT_COFF:
1004       write_coff_file (output_filename, target, resources);
1005       break;
1006     }
1007 
1008   xexit (0);
1009   return 0;
1010 }
1011