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