Update FSF address
[external/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
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 \f
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
134 res_init (void)
135 {
136   obstack_init (&res_obstack);
137 }
138
139 /* Allocate space on the resource building obstack.  */
140
141 void *
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
155 reswr_init (void)
156 {
157   obstack_init (&reswr_obstack);
158 }
159
160 /* Allocate space on the resource writing obstack.  */
161
162 void *
163 reswr_alloc (size_t bytes)
164 {
165   return (void *) obstack_alloc (&reswr_obstack, bytes);
166 }
167 \f
168 /* Open a file using the include directory search list.  */
169
170 FILE *
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 \f
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
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
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
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
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 *
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 *
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
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 *
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 \f
474 /* Return whether the dialog resource DIALOG is a DIALOG or a
475    DIALOGEX.  */
476
477 int
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
495 extended_menu (const struct menu *menu)
496 {
497   return extended_menuitems (menu->items);
498 }
499
500 static int
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 \f
530 /* Convert a string to a format type, or exit if it can't be done.  */
531
532 static enum res_format
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
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
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   -h --help                    Print this help message\n\
663   -V --version                 Print version information\n"));
664   fprintf (stream, _("\
665 FORMAT is one of rc, res, or coff, and is deduced from the file name\n\
666 extension if not specified.  A single file name is an input file.\n\
667 No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"));
668
669   list_supported_targets (program_name, stream);
670
671   if (status == 0)
672     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
673
674   exit (status);
675 }
676
677 /* Quote characters that will confuse the shell when we run the preprocessor.  */
678
679 static const char *
680 quot (const char *string)
681 {
682   static char *buf = 0;
683   static int buflen = 0;
684   int slen = strlen (string);
685   const char *src;
686   char *dest;
687
688   if ((buflen < slen * 2 + 2) || !buf)
689     {
690       buflen = slen * 2 + 2;
691       if (buf)
692         free (buf);
693       buf = (char *) xmalloc (buflen);
694     }
695
696   for (src=string, dest=buf; *src; src++, dest++)
697     {
698       if (*src == '(' || *src == ')' || *src == ' ')
699         *dest++ = '\\';
700       *dest = *src;
701     }
702   *dest = 0;
703   return buf;
704 }
705
706 /* Long options.  */
707
708 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
709
710 #define OPTION_PREPROCESSOR     150
711 #define OPTION_USE_TEMP_FILE    (OPTION_PREPROCESSOR + 1)
712 #define OPTION_NO_USE_TEMP_FILE (OPTION_USE_TEMP_FILE + 1)
713 #define OPTION_YYDEBUG          (OPTION_NO_USE_TEMP_FILE + 1)
714
715 static const struct option long_options[] =
716 {
717   {"input", required_argument, 0, 'i'},
718   {"output", required_argument, 0, 'o'},
719   {"input-format", required_argument, 0, 'J'},
720   {"output-format", required_argument, 0, 'O'},
721   {"target", required_argument, 0, 'F'},
722   {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
723   {"include-dir", required_argument, 0, 'I'},
724   {"define", required_argument, 0, 'D'},
725   {"undefine", required_argument, 0, 'U'},
726   {"verbose", no_argument, 0, 'v'},
727   {"language", required_argument, 0, 'l'},
728   {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
729   {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
730   {"yydebug", no_argument, 0, OPTION_YYDEBUG},
731   {"version", no_argument, 0, 'V'},
732   {"help", no_argument, 0, 'h'},
733   {0, no_argument, 0, 0}
734 };
735
736 /* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes.  */
737 int main (int, char **);
738
739 /* The main function.  */
740
741 int
742 main (int argc, char **argv)
743 {
744   int c;
745   char *input_filename;
746   char *output_filename;
747   enum res_format input_format;
748   enum res_format input_format_tmp;
749   enum res_format output_format;
750   char *target;
751   char *preprocessor;
752   char *preprocargs;
753   const char *quotedarg;
754   int language;
755   struct res_directory *resources;
756   int use_temp_file;
757
758 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
759   setlocale (LC_MESSAGES, "");
760 #endif
761 #if defined (HAVE_SETLOCALE)
762   setlocale (LC_CTYPE, "");
763 #endif
764   bindtextdomain (PACKAGE, LOCALEDIR);
765   textdomain (PACKAGE);
766
767   program_name = argv[0];
768   xmalloc_set_program_name (program_name);
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 }