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