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