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