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