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