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